diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 130aa023..1cbbf35a 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -13,7 +13,7 @@ android:glEsVersion="0x00020000"/> @@ -22,14 +22,17 @@ android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:theme="@android:style/Theme.NoTitleBar.Fullscreen" - android:allowBackup="false"> + android:allowBackup="false" + android:largeHeap="true" + > + diff --git a/assets/buffs.png b/assets/buffs.png index d4006417..4c8e79a5 100644 Binary files a/assets/buffs.png and b/assets/buffs.png differ diff --git a/assets/firerabbit.png b/assets/firerabbit.png index 39d03f62..277b7063 100644 Binary files a/assets/firerabbit.png and b/assets/firerabbit.png differ diff --git a/assets/items.png b/assets/items.png index 3bae5985..77507b85 100644 Binary files a/assets/items.png and b/assets/items.png differ diff --git a/assets/large_buffs.png b/assets/large_buffs.png index 800a36ae..02e283bc 100644 Binary files a/assets/large_buffs.png and b/assets/large_buffs.png differ diff --git a/assets/painter.png b/assets/painter.png index 9d96421e..498ff441 100644 Binary files a/assets/painter.png and b/assets/painter.png differ diff --git a/assets/ranger.png b/assets/ranger.png index 625c3817..3be4b636 100644 Binary files a/assets/ranger.png and b/assets/ranger.png differ diff --git a/assets/status_pane.png b/assets/status_pane.png index c6d7ce8e..9e464875 100644 Binary files a/assets/status_pane.png and b/assets/status_pane.png differ diff --git a/java/com/hmdzl/spspd/Assets.java b/java/com/hmdzl/spspd/Assets.java new file mode 100644 index 00000000..b3fe49a2 --- /dev/null +++ b/java/com/hmdzl/spspd/Assets.java @@ -0,0 +1,347 @@ +/* + * 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 + */ +package com.hmdzl.spspd; + +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 PUDDING_CUP = "pudding_cup.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 SHADOW = "shadow.png"; + + public static final String PIXELFONT = "pixel_font.png"; + public static final String FONT1X = "font1x(2).png"; + public static final String FONT2X = "font2x(2).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 PERFORMER = "performer.png"; + public static final String SOLDIER = "soldier.png"; + public static final String FOLLOWER = "follower.png"; + public static final String AVATARS = "avatars.png"; + public static final String PET = "pet.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 GNOLLARCHER = "gnollarcher.png"; + public static final String CRAB = "crab.png"; + public static final String GOO = "goo.png"; + public static final String POISONGOO = "poisongoo.png"; + public static final String SWARM = "swarm.png"; + public static final String SKELETON = "skeleton.png"; + public static final String MOSSYSKELETON = "mossyskeleton.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 SOKOBANSHEEP = "sokobansheep.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 BLUEWRAITH = "bluewraith.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 ALBINOPIRANHA = "albinopiranha.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 PINNING = "pinning_fist.png"; + public static final String INFECTING = "infecting_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 BEE = "bee.png"; + public static final String MIMIC = "mimic.png"; + public static final String RATBOSS = "ratboss.png"; + public static final String ASSASSIN = "assassin.png"; + public static final String MONSTERBOX = "monsterbox.png"; + public static final String BROKENROBOT = "robot.png"; + public static final String TOWER = "tower.png"; + public static final String DWARFLICH = "dwarflich.png"; + public static final String DEMONGOO = "demongoo.png"; + public static final String BANDITKING = "banditking.png"; + public static final String DWARFKINGTOMB = "dwarfkingtomb.png"; + public static final String FLYINGPROTECTOR = "flyingprotector.png"; + public static final String SENTINEL = "sentinel.png"; + public static final String ONI = "oni.png"; + public static final String SHADOWYOG = "shadowyog.png"; + public static final String SPECTRALRAT = "shadowghost.png"; + public static final String REDWRAITH = "redwraith.png"; + public static final String GOLDTHIEF = "goldthief.png"; + public static final String MRDESTRUCTO = "mrdestructo.png"; + public static final String MRDESTRUCTO2 = "mrdestructo2.png"; + public static final String GREYONI = "greyoni.png"; + public static final String TINKERER1 = "tinkerer.png"; + public static final String DEWPROTECTOR = "dewprotector.png"; + public static final String ORBOFZOT = "orbofzot.png"; + public static final String SEEKINGBOMB = "seekingbomb.png"; + public static final String CRABKING = "crabking.png"; + public static final String HERMITCRAB = "hermitcrab.png"; + public static final String SHELL = "shell.png"; + public static final String GUARD = "guard.png"; + public static final String THIEFKING = "thiefking.png"; + public static final String SKELETONKING = "skeletonkingskull.png"; + public static final String SKELETONHAND1 = "skeletonhand1.png"; + public static final String SKELETONHAND2 = "skeletonhand2.png"; + public static final String PETDRAGON = "petreddragon.png"; + public static final String VELOCIROOSTER = "velocirooster.png"; + public static final String FAIRY = "fairy.png"; + public static final String BUNNY = "rabbit.png"; + public static final String OTILUKESTONE = "otilukestone.png"; + public static final String OTILUKE = "otiluke.png"; + public static final String ZOT = "zot.png"; + public static final String ZOTPHASE = "zotphase.png"; + public static final String MAGICEYE = "magiceye.png"; + public static final String DRAGON = "adultdragon.png"; + + public static final String ITEMS = "items.png"; + public static final String PLANTS = "plants.png"; + public static final String TRAPS = "traps.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 TILES_PUZZLE = "tiles5.png"; + public static final String TILES_SEAL = "tiles_magic_cave.png"; + public static final String TILES_BEACH = "tiles_beach.png"; + public static final String TILES_SKELETON = "tiles_skeleton.png"; + public static final String TILES_VAULT = "tiles_vault.png"; + public static final String TILES_FOREST = "tiles_forest.png"; + public static final String TILES_TOWN = "tiles_town.png"; + public static final String TILES_SP = "tiles_sp.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 WEAK_FLOOR = "custom_tiles/weak_floor.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 CONS_ICONS = "consumable_icons.png"; + public static final String CONS_ICONS2 = "consumable_icons2.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"; + public static final String SND_BEE = "snd_bee.mp3"; + public static final String SND_DEGRADE = "snd_degrade.mp3"; + public static final String SND_MIMIC = "snd_mimic.mp3"; + + public static final String GNOLLKING = "gnollking.png"; + public static final String DRAGONKING = "dragonking.png"; + public static final String UDAWOS = "udawos.png"; + public static final String TYPEDSCROLL = "typedscroll.png"; + public static final String G2159687 = "g2159687.png"; + public static final String CONSIDEREDHAMSTER = "consideredhamster.png"; + public static final String EVAN = "evan.png"; + public static final String NYRDS = "NYRDS.png"; + public static final String BILBOLDEV = "bilboldev.png"; + public static final String WATABOU = "watabou.png"; + public static final String HBB = "HBB.png"; + public static final String SFB = "SFB.png"; + public static final String HEXA = "HeXA.png"; + public static final String RUSTYBLADE = "rustyblade.png"; + public static final String JINKELOID = "jinkeloid.png"; + public static final String SP931 = "SP931.png"; + public static final String LYN = "Lyn.png"; + public static final String COCONUT = "coconut.png"; + public static final String LOCASTAN = "locastan.png"; + public static final String DACHHACK = "dachhack.png"; + public static final String TEMPEST102 = "tempest102.png"; + public static final String ERROR = "error.png"; + public static final String SAR = "stormandrain.png"; + public static final String MOS = "memoryofsand.png"; + public static final String HS = "hatesokoban.png"; + public static final String FRUITCAT = "fruitcat.png"; + public static final String LAJI = "laji.png"; + public static final String RAIN = "rain.png"; + public static final String LYNN = "lynn.png"; + public static final String JUH9870 = "juh9870.png"; + public static final String SADSALTAN ="sadsaltan.png"; + public static final String OLDNEWSTWIST = "oldnewstwist.png"; + + public static final String KLIKS = "kliks.png"; + public static final String SNAKE = "snakes.png"; + public static final String MUSKETEER ="musketeer.png"; + public static final String THIEFIMP = "thiefimp.png"; + public static final String LIVEMOSS = "livemoss.png"; + public static final String TROLLWARRIOR = "trollwarrior.png"; + + public static final String SCARECROW = "scarecrow.png"; + + public static final String UGOO = "ugoo.png"; + public static final String GENTLECRAB = "gentlecrab.png"; + + public static final String XAVIER = "xavier251998.png"; + public static final String REN = "ren.png"; + + public static final String SEWER_HEART = "sewer_heart.png"; + public static final String SEWER_LASHER = "sewer_lasher.png"; + + public static final String T_CLOUD = "tcloud.png"; + + public static final String PLAGUEDOCTOR = "plaguedoctor.png"; + + public static final String PRISONWANDER = "prisonwander.png"; + + public static final String SANDMOB = "sandmob.png"; + public static final String SPIDERBOT = "spiderbot.png"; + public static final String ZOMBIE = "zombie.png"; + public static final String TANK = "tank.png"; + public static final String SUFFERER = "sufferer.png"; + public static final String DEMONFLOWER = "demonflower.png"; + public static final String SPIDERQUEEN = "spider_queen.png"; + public static final String SPIDERWORKER = "spider_worker.png"; + public static final String SPIDERMIND = "spider_mind.png"; + public static final String SPIDEREGG = "spider_egg.png"; + + public static final String KOSTIS = "kostis12345.png"; + public static final String NOODLEMIRE = "noodlemire.png"; + public static final String RAVEBWOLF = "ravenwolf.png"; + public static final String HMDZL = "hmdzl001.png"; + public static final String NEW_PLAYER = "newplayer.png"; + public static final String THANK_LIST = "thanklist.png"; + + public static final String CELL_MOB = "cellmob.png"; + public static final String MOBILE = "mobile.png"; + public static final String HYBRID = "hybrid.png"; + + public static final String OBELISK = "obelisk.png"; + public static final String ELDER_AVATAR = "elderavatar.png"; + + public static final String M_AMD_W = "mandw.png"; + public static final String UNCLE_S = "sibaoluodeti.png"; + + public static final String GOBLIN_PLAYER = "goblinplayer.png"; + public static final String SAID_BY_SUN = "saidbysun.png"; + public static final String MILLILITRE = "millilitre.png"; + public static final String APOSTLE = "apostle.png"; + public static final String SHOWER = "shower.png"; + public static final String HONEY_POOOOT = "honeypoooot.png"; + public static final String XIXIZERO = "cat_lix.png"; + public static final String A_FLY = "npcalfred.png"; + public static final String PAINTER= "painter.png"; + public static final String DREAMPLAYER = "dreamplayer.png"; + public static final String PLANT_KING = "plantking.png"; + public static final String OMICRONRG9 = "omicronrg9.png"; + + + public static final String LICH_DANCER = "boss_lich.png"; + public static final String BATTERYTOMB = "batterytomb.png"; + + public static final String PATROLUAV = "patroluav.png"; + public static final String ICE13 = "ice13.png"; + + public static final String FIRERABBIT = "firerabbit.png"; + public static final String MANY_SKELETON = "manyskeleton.png"; + public static final String BEAST_YEAR = "beastyear.png"; + +} + diff --git a/java/com/hmdzl/spspd/Badges.java b/java/com/hmdzl/spspd/Badges.java new file mode 100644 index 00000000..31a02b62 --- /dev/null +++ b/java/com/hmdzl/spspd/Badges.java @@ -0,0 +1,1079 @@ +/* + * 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 + */ +package com.hmdzl.spspd; + +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.hmdzl.spspd.actors.mobs.Acidic; +import com.hmdzl.spspd.actors.mobs.Albino; +import com.hmdzl.spspd.actors.mobs.Bandit; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.actors.mobs.Senior; +import com.hmdzl.spspd.actors.mobs.Shielded; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.artifacts.Artifact; +import com.hmdzl.spspd.items.bags.PotionBandolier; +import com.hmdzl.spspd.items.bags.ScrollHolder; +import com.hmdzl.spspd.items.bags.SeedPouch; +import com.hmdzl.spspd.items.bags.WandHolster; +import com.hmdzl.spspd.items.potions.Potion; +import com.hmdzl.spspd.items.rings.Ring; +import com.hmdzl.spspd.items.scrolls.Scroll; +import com.hmdzl.spspd.scenes.PixelScene; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.noosa.Game; +import com.watabou.utils.Bundle; +import com.watabou.utils.Callback; +import com.hmdzl.spspd.messages.Messages; + +public class Badges { + + public /*static*/ enum Badge { + MONSTERS_SLAIN_1(0), + MONSTERS_SLAIN_2(1), + MONSTERS_SLAIN_3(2), + MONSTERS_SLAIN_4(3), + GOLD_COLLECTED_1(4), + GOLD_COLLECTED_2(5), + GOLD_COLLECTED_3(6), + GOLD_COLLECTED_4(7), + LEVEL_REACHED_1(8), + LEVEL_REACHED_2(9), + LEVEL_REACHED_3(10), + LEVEL_REACHED_4(11), + ALL_POTIONS_IDENTIFIED(16), + ALL_SCROLLS_IDENTIFIED(17), + ALL_RINGS_IDENTIFIED(18), + ALL_WANDS_IDENTIFIED(19), + ALL_ITEMS_IDENTIFIED(35, true), + BAG_BOUGHT_SEED_POUCH, BAG_BOUGHT_SCROLL_HOLDER, BAG_BOUGHT_POTION_BANDOLIER, BAG_BOUGHT_WAND_HOLSTER, ALL_BAGS_BOUGHT(23), + DEATH_FROM_FIRE(24), + DEATH_FROM_POISON(25), + DEATH_FROM_GAS(26), + DEATH_FROM_HUNGER(27), + DEATH_FROM_GLYPH(57), + DEATH_FROM_FALLING(59), + YASD(34, true), + BOSS_SLAIN_1_WARRIOR, BOSS_SLAIN_1_MAGE, BOSS_SLAIN_1_ROGUE, BOSS_SLAIN_1_HUNTRESS, BOSS_SLAIN_1_PERFORMER,BOSS_SLAIN_1_SOLDIER,BOSS_SLAIN_1_FOLLOWER, BOSS_SLAIN_1(12), + BOSS_SLAIN_2(13), + BOSS_SLAIN_3(14), + BOSS_SLAIN_4(15), + BOSS_SLAIN_1_ALL_CLASSES(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_SUPERSTAR,BOSS_SLAIN_3_JOKER, BOSS_SLAIN_3_ALL_SUBCLASSES(33, true), + RING_OF_HAGGLER(20), + RING_OF_THORNS(21), + STRENGTH_ATTAINED_1(40), + STRENGTH_ATTAINED_2(41), + STRENGTH_ATTAINED_3(42), + STRENGTH_ATTAINED_4(43), + FOOD_EATEN_1(44), + FOOD_EATEN_2(45), + FOOD_EATEN_3(46), + FOOD_EATEN_4(47), + MASTERY_WARRIOR, MASTERY_MAGE, MASTERY_ROGUE, MASTERY_HUNTRESS, MASTERY_PERFORMER, MASTERY_SOLDIER,MASTERY_FOLLOWER, + ITEM_LEVEL_1(48), + ITEM_LEVEL_2(49), + ITEM_LEVEL_3(50), + ITEM_LEVEL_4(51), + RARE_ALBINO, RARE_BANDIT, RARE_SHIELDED, RARE_SENIOR, RARE_ACIDIC, RARE(37, true), + VICTORY_WARRIOR, VICTORY_MAGE, VICTORY_ROGUE, VICTORY_HUNTRESS, VICTORY_PERFORMER, VICTORY_SOLDIER,VICTORY_FOLLOWER,VICTORY(22), + VICTORY_ALL_CLASSES(36, true), + MASTERY_COMBO(56), + POTIONS_COOKED_1(52), + POTIONS_COOKED_2(53), + POTIONS_COOKED_3(54), + POTIONS_COOKED_4(55), + NO_MONSTERS_SLAIN(28), + GRIM_WEAPON(29), + PIRANHAS(30), + NIGHT_HUNTER(58), + GAMES_PLAYED_1(60, true), + GAMES_PLAYED_2(61, true), + GAMES_PLAYED_3(62, true), + GAMES_PLAYED_4(63, true), + HAPPY_END(38), + CHAMPION(39, true), + SUPPORTER(31, true), + ORB(68), + OTILUKE(65), + TRI(66), + EGG_BREAK_1(69), + EGG_BREAK_2(70), + EGG_BREAK_3(71); + + public boolean meta; + + public int image; + + private Badge(int image) { + this(image, false); + } + + Badge( int image, boolean meta ) { + this.image = image; + this.meta = meta; + } + + public String desc(){ + return Messages.get(this, name()); + } + + Badge() { + this( -1 ); + } + + } + + private static HashSet global; + private static HashSet local = new HashSet(); + + private static boolean saveNeeded = false; + + public static Callback loadingListener = null; + + public static void reset() { + local.clear(); + loadGlobal(); + } + + private static final String BADGES_FILE = "badges.dat"; + private static final String BADGES = "badges"; + + private static HashSet restore(Bundle bundle) { + HashSet badges = new HashSet(); + + 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 badges) { + int count = 0; + String names[] = new String[badges.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 (Exception e) { + global = new HashSet(); + } + } + } + + 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 >= 10) { + badge = Badge.LEVEL_REACHED_1; + local.add(badge); + } + if (!local.contains(Badge.LEVEL_REACHED_2) && Dungeon.hero.lvl >= 20) { + badge = Badge.LEVEL_REACHED_2; + local.add(badge); + } + if (!local.contains(Badge.LEVEL_REACHED_3) && Dungeon.hero.lvl >= 30) { + badge = Badge.LEVEL_REACHED_3; + local.add(badge); + } + if (!local.contains(Badge.LEVEL_REACHED_4) && Dungeon.hero.lvl >= 40) { + 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 validateEggBreak() { + Badge badge = null; + + if (!local.contains(Badge.EGG_BREAK_1) && Statistics.eggBreak >= 1) { + badge = Badge.EGG_BREAK_1; + local.add(badge); + } + if (!local.contains(Badge.EGG_BREAK_2) && Statistics.eggBreak >= 2) { + badge = Badge.EGG_BREAK_2; + local.add(badge); + } + if (!local.contains(Badge.EGG_BREAK_3) && Statistics.eggBreak >= 5) { + badge = Badge.EGG_BREAK_3; + 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 + + // Note that artifacts should never trigger this badge as they are + // alternatively upgraded + if (!item.levelKnown || item instanceof Artifact) { + 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) + ) { + + 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 PotionBandolier) { + badge = Badge.BAG_BOUGHT_POTION_BANDOLIER; + } 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_SEED_POUCH) + && local.contains(Badge.BAG_BOUGHT_SCROLL_HOLDER) + && local.contains(Badge.BAG_BOUGHT_POTION_BANDOLIER) + && 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; + case PERFORMER: + badge = Badge.BOSS_SLAIN_1_PERFORMER; + break; + case SOLDIER: + badge = Badge.BOSS_SLAIN_1_SOLDIER; + break; + case FOLLOWER: + badge = Badge.BOSS_SLAIN_1_FOLLOWER; + 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; + case SUPERSTAR: + badge = Badge.BOSS_SLAIN_3_SUPERSTAR; + break; + case JOKER: + badge = Badge.BOSS_SLAIN_3_JOKER; + 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) + && global.contains(Badge.BOSS_SLAIN_3_SUPERSTAR) + && global.contains(Badge.BOSS_SLAIN_3_JOKER)) { + + badge = Badge.BOSS_SLAIN_3_ALL_SUBCLASSES; + if (!global.contains(badge)) { + displayBadge(badge); + global.add(badge); + saveNeeded = true; + } + } + } + } + } + + public static void validateOrbObtained() { + Badge badge = Badge.ORB; + local.add(badge); + displayBadge(badge); + if (!global.contains(Badge.ORB)) { + global.add(badge); + } + } + + public static boolean checkOrbObtained() { + return global.contains(Badge.ORB); + } + + + + public static boolean checkOtilukeRescued() { + return local.contains(Badge.OTILUKE); + } + + public static boolean checkCoconutRescued() { + return local.contains(Badge.MONSTERS_SLAIN_4); + } + + public static boolean checkSARRescued() { + return local.contains(Badge.ALL_RINGS_IDENTIFIED); + } + + public static boolean checkMOSRescued() { + return local.contains(Badge.FOOD_EATEN_4); + } + + public static boolean checkItemRescued() { + return local.contains(Badge.ITEM_LEVEL_4); + } + + public static boolean checkFishRescued() { + return local.contains(Badge.BOSS_SLAIN_3); + } + + public static boolean checkEggRescued() { + return local.contains(Badge.EGG_BREAK_3); + } + + public static boolean checkTombRescued() { + return local.contains(Badge.BOSS_SLAIN_4); + } + + public static boolean checkRainRescued() { + return local.contains(Badge.LEVEL_REACHED_4); + } + + public static boolean checkUncleRescued() { + return local.contains(Badge.POTIONS_COOKED_1); + } + + 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; + case PERFORMER: + badge = Badge.MASTERY_PERFORMER; + break; + case SOLDIER: + badge = Badge.MASTERY_SOLDIER; + break; + case FOLLOWER: + badge = Badge.MASTERY_FOLLOWER; + 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); + } + } + + // TODO: Replace this badge, delayed until an eventual badge rework + public static void validateRingOfHaggler() { + if (!local.contains(Badge.RING_OF_HAGGLER)/* + * && new + * RingOfThorns().isKnown() + */) { + Badge badge = Badge.RING_OF_HAGGLER; + local.add(badge); + displayBadge(badge); + } + } + + // TODO: Replace this badge, delayed until an eventual badge rework + 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; + case PERFORMER: + badge = Badge.VICTORY_PERFORMER; + 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) + && global.contains(Badge.VICTORY_PERFORMER) + && global.contains(Badge.VICTORY_SOLDIER) + && global.contains(Badge.VICTORY_FOLLOWER)) { + + 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 validateOtilukeRescued() { + if (!local.contains(Badge.OTILUKE)) { + Badge badge = Badge.OTILUKE; + 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); + } + + public static void validateChampion() { + displayBadge(Badge.CHAMPION); + } + + private static void displayBadge(Badge badge) { + + if (badge == null) { + return; + } + + if (global.contains(badge)) { + + if (!badge.meta) { + GLog.h(Messages.get(Badges.class, "endorsed", badge.desc())); + } + + } else { + + global.add(badge); + saveNeeded = true; + + if (badge.meta) { + GLog.h( Messages.get(Badges.class, "new_super", badge.desc()) ); + } else { + GLog.h( Messages.get(Badges.class, "new", badge.desc()) ); + } + 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 filtered(boolean global) { + + HashSet filtered = new HashSet(global ? Badges.global + : Badges.local); + + if (!global) { + Iterator 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.EGG_BREAK_1, Badge.EGG_BREAK_2, + Badge.EGG_BREAK_3); + 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 list = new ArrayList(filtered); + Collections.sort(list); + + return list; + } + + private static void leaveBest(HashSet 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; + } + } + } +} diff --git a/java/com/hmdzl/spspd/Challenges.java b/java/com/hmdzl/spspd/Challenges.java new file mode 100644 index 00000000..917b109c --- /dev/null +++ b/java/com/hmdzl/spspd/Challenges.java @@ -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 + */ +package com.hmdzl.spspd; + +public class Challenges { + + public static final int ITEM_PHOBIA = 1; + public static final int LISTLESS = 2; + public static final int NIGHTMARE_VIRUS = 4; + public static final int ENERGY_LOST = 8; + public static final int DEW_REJECTION = 16; + public static final int DARKNESS = 32; + public static final int ABRASION = 64; + public static final int TEST_TIME = 128; + + public static final String[] NAME_IDS = { + "item_phobia", + "listless", + "nightmare_virus", + "energy_lost", + "dew_rejection", + "darkness", + "abrasion", + "test_time" + }; + + public static final int[] MASKS = { + ITEM_PHOBIA, LISTLESS, NIGHTMARE_VIRUS, + ENERGY_LOST, DEW_REJECTION, DARKNESS, ABRASION, TEST_TIME}; + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/Chrome.java b/java/com/hmdzl/spspd/Chrome.java new file mode 100644 index 00000000..4099c50b --- /dev/null +++ b/java/com/hmdzl/spspd/Chrome.java @@ -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 + */ +package com.hmdzl.spspd; + +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 + }; + + public static NinePatch get(Type type) { + String Asset = Assets.CHROME; + switch (type) { + case WINDOW: + return new NinePatch(Asset, 0, 0, 20, 20, 6); + case TOAST: + return new NinePatch(Asset, 22, 0, 18, 18, 5); + case TOAST_TR: + return new NinePatch(Asset, 40, 0, 18, 18, 5); + case BUTTON: + return new NinePatch(Asset, 58, 0, 4, 4, 1); + case TAG: + return new NinePatch(Asset, 22, 18, 16, 14, 3); + case GEM: + return new NinePatch(Asset, 0, 32, 32, 32, 13); + case SCROLL: + return new NinePatch(Asset, 32, 32, 32, 32, 5, 11, 5, 11); + case TAB_SET: + return new NinePatch(Asset, 64, 0, 20, 20, 6); + case TAB_SELECTED: + return new NinePatch(Asset, 65, 22, 8, 13, 3, 7, 3, 5); + case TAB_UNSELECTED: + return new NinePatch(Asset, 75, 22, 8, 13, 3, 7, 3, 5); + default: + return null; + } + } +} diff --git a/java/com/hmdzl/spspd/Dungeon.java b/java/com/hmdzl/spspd/Dungeon.java new file mode 100644 index 00000000..2d1317bd --- /dev/null +++ b/java/com/hmdzl/spspd/Dungeon.java @@ -0,0 +1,1572 @@ +/* + * 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 + */ +package com.hmdzl.spspd; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Calendar; +import java.util.HashSet; + +import com.hmdzl.spspd.items.artifacts.DriedRose; +import com.hmdzl.spspd.levels.ChaosLevel; +import com.hmdzl.spspd.levels.PotLevel; +import com.hmdzl.spspd.levels.ShadowEaterLevel; +import com.hmdzl.spspd.levels.SokobanSPLevel; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Amok; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Dewcharge; +import com.hmdzl.spspd.actors.buffs.Light; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.hero.HeroClass; +import com.hmdzl.spspd.actors.mobs.npcs.Blacksmith; +import com.hmdzl.spspd.actors.mobs.npcs.Ghost; +import com.hmdzl.spspd.actors.mobs.npcs.Imp; +import com.hmdzl.spspd.actors.mobs.npcs.Wandmaker; +import com.hmdzl.spspd.items.Ankh; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.potions.Potion; +import com.hmdzl.spspd.items.rings.Ring; +import com.hmdzl.spspd.items.scrolls.Scroll; +import com.hmdzl.spspd.levels.BattleLevel; +import com.hmdzl.spspd.levels.CatacombLevel; +import com.hmdzl.spspd.levels.CavesBossLevel; +import com.hmdzl.spspd.levels.CavesLevel; +import com.hmdzl.spspd.levels.ChasmLevel; +import com.hmdzl.spspd.levels.CityBossLevel; +import com.hmdzl.spspd.levels.CityLevel; +import com.hmdzl.spspd.levels.CrabBossLevel; +import com.hmdzl.spspd.levels.DeadEndLevel; +import com.hmdzl.spspd.levels.FieldLevel; +import com.hmdzl.spspd.levels.FieldBossLevel; +import com.hmdzl.spspd.levels.FishingLevel; +import com.hmdzl.spspd.levels.FortressLevel; +import com.hmdzl.spspd.levels.HallsBossLevel; +import com.hmdzl.spspd.levels.HallsLevel; +import com.hmdzl.spspd.levels.InfestBossLevel; +import com.hmdzl.spspd.levels.LastLevel; +import com.hmdzl.spspd.levels.LastShopLevel; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.MinesBossLevel; +import com.hmdzl.spspd.levels.PrisonBossLevel; +import com.hmdzl.spspd.levels.PrisonLevel; +import com.hmdzl.spspd.levels.Room; +import com.hmdzl.spspd.levels.SafeLevel; +import com.hmdzl.spspd.levels.SewerBossLevel; +import com.hmdzl.spspd.levels.SewerLevel; +import com.hmdzl.spspd.levels.SkeletonBossLevel; +import com.hmdzl.spspd.levels.SokobanCastle; +import com.hmdzl.spspd.levels.SokobanIntroLevel; +import com.hmdzl.spspd.levels.SokobanPuzzlesLevel; +import com.hmdzl.spspd.levels.SokobanTeleportLevel; +import com.hmdzl.spspd.levels.TenguDenLevel; +import com.hmdzl.spspd.levels.ThiefBossLevel; +import com.hmdzl.spspd.levels.ThiefCatchLevel; +import com.hmdzl.spspd.levels.BossRushLevel; +import com.hmdzl.spspd.levels.TownLevel; +import com.hmdzl.spspd.levels.VaultLevel; +import com.hmdzl.spspd.levels.ZotBossLevel; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.scenes.StartScene; +import com.hmdzl.spspd.ui.QuickSlotButton; +import com.hmdzl.spspd.utils.BArray; +import com.hmdzl.spspd.utils.GLog; + +import com.hmdzl.spspd.windows.WndResurrect; +import com.watabou.noosa.Game; +import com.watabou.utils.Bundlable; +import com.watabou.utils.Bundle; +import com.watabou.utils.PathFinder; +import com.watabou.utils.Random; +import com.watabou.utils.SparseArray; + +public class Dungeon { + + // enum of items which have limited spawns, records how many have spawned + // could all be their own separate numbers, but this allows iterating, much + // nicer for bundling/initializing. + public static enum limitedDrops { + // limited world drops + strengthPotions, upgradeScrolls, + + //Norn Stones + nornstones, + + // doesn't use Generator, so we have to enforce one armband drop here + spork, sewerkey, prisonkey, caveskey, citykey, potkey, ringofwealth, vaultpage, town, + conchshell, ancientcoin, tengukey, bone, journal, safespotpage, dragoncave, treasuremap, goei, + + // containers + dewVial, seedBag, scrollBag, potionBag, wandBag, shopcart, heartScarecrow, challengebook; + + public int count = 0; + + // for items which can only be dropped once, should directly access + // count otherwise. + public boolean dropped() { + return count != 0; + } + + public void drop() { + count = 1; + } + } + + public static int[] pars; + + public static boolean earlygrass = false; + public static boolean gnollspawned = false; + public static boolean skeletonspawned = false; + public static boolean goldthiefspawned = false; + public static boolean triforce = false; + public static boolean triforceofcourage = false; + public static boolean triforceofpower = false; + public static boolean triforceofwisdom = false; + public static boolean shadowyogkilled = false; + public static boolean crabkingkilled = false; + public static boolean banditkingkilled = false; + public static boolean skeletonkingkilled = false; + public static boolean gnollkingkilled = false; + public static boolean tengudenkilled = false; + public static boolean zotkilled = false; + public static boolean dewDraw = false; + public static boolean dewWater = false; + public static boolean wings = false; + public static boolean dewNorn = false; + public static boolean canSave = false; + public static boolean gnollmission = false; + public static boolean oneDay = false; + public static boolean error = false; + //public static boolean secondQuest = false; + + public static int challenges; + public static int skins; + + public static int ratChests = 0; + public static int sacrifice = 0; + public static boolean sporkAvail = false; + public static boolean challengebookdrop = false; + public static boolean goeidrop = false; + + public static Hero hero; + public static Level level; + + public static QuickSlot quickslot = new QuickSlot(); + + public static int depth = 1; + public static int gold = 0; + + public static String resultDescription; + + public static HashSet chapters; + + // Hero's field of view + public static boolean[] visible = new boolean[Level.getLength()]; + + public static SparseArray> droppedItems; + + public static int version; + + public static void init() { + + version = Game.versionCode; + challenges = ShatteredPixelDungeon.challenges(); + + //Generator.initArtifacts(); + + Actor.clear(); + Actor.resetNextID(); + + PathFinder.setMapSize(Level.getWidth(), Level.HEIGHT); + + Scroll.initLabels(); + Potion.initColors(); + Ring.initGems(); + + Statistics.reset(); + Journal.reset(); + + quickslot.reset(); + QuickSlotButton.reset(); + + depth = 0; + gold = 0; + + droppedItems = new SparseArray>(); + + for (limitedDrops a : limitedDrops.values()) + a.count = 0; + + chapters = new HashSet(); + + Ghost.Quest.reset(); + Wandmaker.Quest.reset(); + Blacksmith.Quest.reset(); + Imp.Quest.reset(); + + Room.shuffleTypes(); + + //Generator.initArtifacts(); + hero = new Hero(); + hero.live(); + + Badges.reset(); + + StartScene.curClass.initHero(hero); + + earlygrass = false; + gnollspawned = false; + skeletonspawned = false; + goldthiefspawned = false; + triforce = false; + triforceofcourage = false; + triforceofpower = false; + triforceofwisdom = false; + shadowyogkilled = false; + crabkingkilled = false; + banditkingkilled = false; + gnollkingkilled = false; + tengudenkilled = false; + skeletonkingkilled = false; + zotkilled = false; + ratChests = 0; + sacrifice = 0 ; + sporkAvail = false; + challengebookdrop = false; + goeidrop = false; + dewDraw = false; + dewWater = false; + wings = false; + dewNorn = false; + canSave = false; + gnollmission = false; + oneDay =false; + error = false; + + pars = new int[100]; + + } + + public static boolean isChallenged(int mask) { + return (challenges & mask) != 0; + } + + public static Level newFieldLevel(){ + + Dungeon.level = null; + Actor.clear(); + depth = 27; + if (depth > Statistics.realdeepestFloor) { + Statistics.realdeepestFloor = depth;} + + Arrays.fill(visible, false); + + Level level; + level = new FieldLevel(); + + level.create(); + + Statistics.qualifiedForNoKilling = !bossLevel(); + + return level; + } + public static Level newBattleLevel(){ + + Dungeon.level = null; + Actor.clear(); + depth = 28; + if (depth > Statistics.realdeepestFloor) { + Statistics.realdeepestFloor = depth;} + + Arrays.fill(visible, false); + + Level level; + level = new BattleLevel(); + + level.create(); + + Statistics.qualifiedForNoKilling = !bossLevel(); + + return level; + } + public static Level newFishLevel(){ + + Dungeon.level = null; + Actor.clear(); + depth = 29; + if (depth > Statistics.realdeepestFloor) { + Statistics.realdeepestFloor = depth;} + + Arrays.fill(visible, false); + + Level level; + level = new FishingLevel(); + + level.create(); + + Statistics.qualifiedForNoKilling = !bossLevel(); + + return level; + } + public static Level newVaultLevel(){ + + Dungeon.level = null; + Actor.clear(); + depth = 30; + if (depth > Statistics.realdeepestFloor) { + Statistics.realdeepestFloor = depth;} + + Arrays.fill(visible, false); + + Level level; + level = new VaultLevel(); + + level.create(); + + Statistics.qualifiedForNoKilling = !bossLevel(); + + return level; + } + + public static Level newCatacombLevel(){ + + + Dungeon.level = null; + Actor.clear(); + depth = 31; + if (depth > Statistics.realdeepestFloor) { + Statistics.realdeepestFloor = depth;} + + Arrays.fill(visible, false); + + Level level; + level = new CatacombLevel(); + + level.create(); + + Statistics.qualifiedForNoKilling = !bossLevel(); + + return level; + } + +public static Level newFortressLevel(){ + + Dungeon.level = null; + Actor.clear(); + depth = 32; + if (depth > Statistics.realdeepestFloor) { + Statistics.realdeepestFloor = depth;} + + Arrays.fill(visible, false); + + Level level; + level = new FortressLevel(); + + level.create(); + + Statistics.qualifiedForNoKilling = !bossLevel(); + + return level; + } + +public static Level newChasmLevel(){ + + Dungeon.level = null; + Actor.clear(); + depth = 33; + if (depth > Statistics.realdeepestFloor) { + Statistics.realdeepestFloor = depth;} + + Arrays.fill(visible, false); + + Level level; + level = new ChasmLevel(); + + level.create(); + + Statistics.qualifiedForNoKilling = !bossLevel(); + + return level; +} + +public static Level newInfestLevel(){ + + Dungeon.level = null; + Actor.clear(); + depth = 35; + if (depth > Statistics.realdeepestFloor) { + Statistics.realdeepestFloor = depth;} + + Arrays.fill(visible, false); + + Level level; + level = new InfestBossLevel(); + + level.create(); + + Statistics.qualifiedForNoKilling = !bossLevel(); + if (Statistics.deepestFloor>24){Statistics.deepestFloor = depth;} + + return level; +} + + + +public static Level newTenguHideoutLevel(){ + + Dungeon.level = null; + Actor.clear(); + depth = 36; + if (depth > Statistics.realdeepestFloor) { + Statistics.realdeepestFloor = depth;} + + Arrays.fill(visible, false); + + Level level; + level = new TenguDenLevel(); + + level.create(); + + Statistics.qualifiedForNoKilling = !bossLevel(); + + return level; +} + +public static Level newSkeletonBossLevel(){ + + Dungeon.level = null; + Actor.clear(); + depth = 37; + if (depth > Statistics.realdeepestFloor) { + Statistics.realdeepestFloor = depth;} + + Arrays.fill(visible, false); + + Level level; + level = new SkeletonBossLevel(); + + level.create(); + + Statistics.qualifiedForNoKilling = !bossLevel(); + + return level; +} + +public static Level newCrabBossLevel(){ + + Dungeon.level = null; + Actor.clear(); + depth = 38; + if (depth > Statistics.realdeepestFloor) { + Statistics.realdeepestFloor = depth;} + + Arrays.fill(visible, false); + + Level level; + level = new CrabBossLevel(); + + level.create(); + + Statistics.qualifiedForNoKilling = !bossLevel(); + + return level; +} + +public static Level newThiefBossLevel(){ + + Dungeon.level = null; + Actor.clear(); + depth = 40; + if (depth > Statistics.realdeepestFloor) { + Statistics.realdeepestFloor = depth;} + + Arrays.fill(visible, false); + + Level level; + level = new ThiefBossLevel(); + + level.create(); + + Statistics.qualifiedForNoKilling = !bossLevel(); + + return level; +} + +public static Level newFieldBossLevel(){ + + Dungeon.level = null; + Actor.clear(); + depth = 43; + if (depth > Statistics.realdeepestFloor) { + Statistics.realdeepestFloor = depth;} + + Arrays.fill(visible, false); + + Level level; + level = new FieldBossLevel(); + + level.create(); + + Statistics.qualifiedForNoKilling = !bossLevel(); + + return level; +} + +public static Level newPotLevel(){ + + Dungeon.level = null; + Actor.clear(); + depth = 45; + if (depth > Statistics.realdeepestFloor) { + Statistics.realdeepestFloor = depth;} + + Arrays.fill(visible, false); + + Level level; + level = new PotLevel(); + + level.create(); + + return level; +} + +public static Level newShadowEaterLevel(){ + + Dungeon.level = null; + Actor.clear(); + depth = 47; + if (depth > Statistics.realdeepestFloor) { + Statistics.realdeepestFloor = depth;} + + Arrays.fill(visible, false); + + Level level; + level = new ShadowEaterLevel(); + + level.create(); + + return level; +} + +public static Level newMineBossLevel(){ + + Dungeon.level = null; + Actor.clear(); + //depth = 67; + depth++; + if (depth > Statistics.realdeepestFloor) { + Statistics.realdeepestFloor = depth;} + + Arrays.fill(visible, false); + + Level level; + level = new MinesBossLevel(); + + level.create(); + + Statistics.qualifiedForNoKilling = !bossLevel(); + + return level; +} + +public static Level newBossRushLevel(){ + + + Dungeon.level = null; + Actor.clear(); + depth = 71; + if (depth > Statistics.realdeepestFloor) { + Statistics.realdeepestFloor = depth;} + + Arrays.fill(visible, false); + + Level level; + level = new BossRushLevel(); + + level.create(); + + Statistics.qualifiedForNoKilling = !bossLevel(); + + return level; + } + + public static Level newChaosLevel(){ + + Dungeon.level = null; + Actor.clear(); + depth = 85; + if (depth > Statistics.realdeepestFloor) { + Statistics.realdeepestFloor = depth;} + + Arrays.fill(visible, false); + + Level level; + level = new ChaosLevel(); + + level.create(); + + Statistics.qualifiedForNoKilling = !bossLevel(); + + return level; + } + +public static Level newZotBossLevel(){ + + Dungeon.level = null; + Actor.clear(); + depth = 99; + if (depth > Statistics.realdeepestFloor) { + Statistics.realdeepestFloor = depth;} + + Arrays.fill(visible, false); + + Level level; + level = new ZotBossLevel(); + + level.create(); + + Statistics.qualifiedForNoKilling = !bossLevel(); + + return level; +} + +public static Level newJournalLevel(int page, Boolean first){ + + Dungeon.level = null; + Actor.clear(); + + depth = 50+page; + + if (page==6){ + depth = 66; + } + + if (page==7){ + depth = 67; + } + + if (depth > Statistics.realdeepestFloor && depth < 68) { + Statistics.realdeepestFloor = depth;} + + Arrays.fill(visible, false); + + Level level; + switch(page){ + case 0: + level = new SafeLevel(); + break; + case 1: + level = new SokobanIntroLevel(); + break; + case 2: + level = new SokobanCastle(); + break; + case 3: + level = new SokobanTeleportLevel(); + break; + case 4: + level = new SokobanPuzzlesLevel(); + break; + case 5: + level = new TownLevel(); + break; + case 6: + level = new SokobanSPLevel(); + break; + case 7: + level = new MinesBossLevel(); + break; + default: + level = Dungeon.newLevel(); + } + + level.first = first; + level.create(); + + Statistics.qualifiedForNoKilling = !bossLevel(); + + return level; +} + +public static Level newChallengeLevel(int list, Boolean first){ + + Dungeon.level = null; + Actor.clear(); + + depth = 26+list; + if (list==0){ + depth = 26; + } + if (list==1 ){ + depth = 27; + } + if (list==2){ + depth = 28; + } + if (list==3){ + depth = 29; + } + if (list==4){ + depth = 30; + } + if (list==5){ + depth = 31; + } + if (list==6){ + depth = 32; + } + if (list==7){ + depth = 33; + } + + if (depth > Statistics.realdeepestFloor && depth < 34) { + Statistics.realdeepestFloor = depth;} + + Arrays.fill(visible, false); + + Level level; + switch(list){ + case 0: + level = Dungeon.newLevel(); + break; + case 1: + level = new FieldLevel(); + break; + case 2: + level = new BattleLevel(); + break; + case 3: + level = new FishingLevel(); + break; + case 4: + level = new VaultLevel(); + break; + case 5: + level = new CatacombLevel(); + break; + case 6: + level = new FortressLevel(); + break; + case 7: + level = new ChasmLevel(); + break; + default: + level = Dungeon.newLevel(); + } + + level.first = first; + level.create(); + + Statistics.qualifiedForNoKilling = !bossLevel(); + + return level; +} + + + public static Level newLevel() { + + Dungeon.level = null; + Actor.clear(); + + depth++; + if (depth > Statistics.realdeepestFloor) { + Statistics.realdeepestFloor = depth;} + + if (depth > Statistics.deepestFloor && depth < 27) { + Statistics.deepestFloor = depth; + + if (Statistics.qualifiedForNoKilling) { + Statistics.completedWithNoKilling = true; + } else { + Statistics.completedWithNoKilling = false; + } + } + + if (depth==6){ + Statistics.sewerKills=Statistics.enemiesSlain; + } + if (depth==10){ + Statistics.prisonKills=Statistics.enemiesSlain-Statistics.sewerKills; + } + + Arrays.fill(visible, false); + + Level level; + switch (depth) { + case 1: + //level = new PrisonBossLevel(); + //level = new SewerLevel(); + //hero.HT=999; + //hero.HP=hero.HT; + //break; + case 2: + //level = new HallsLevel(); + //hero.HT=999; + //hero.HP=hero.HT; + //break; + case 3: + case 4: + //level = new CavesLevel(); + level = new SewerLevel(); + //hero.HT=999; + //hero.HP=hero.HT; + break; + case 5: + level = new SewerBossLevel(); + break; + case 6: + //level = new HallsLevel(); + //hero.HT=999; + //hero.HP=hero.HT; + //break; + 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; + case 41: + level = new ThiefCatchLevel(); + break; + case 67: + level = new MinesBossLevel(); + break; + case 71: + level = new BossRushLevel(); + break; + case 85: + level = new ChaosLevel(); + default: + level = new DeadEndLevel(); + if (depth<27){Statistics.deepestFloor--;} + } + + level.create(); + + Statistics.qualifiedForNoKilling = !bossLevel(); + if (depth<26 && depth!=21 && !Dungeon.bossLevel(depth) && (Dungeon.dewDraw || Dungeon.dewWater)){ + Buff.prolong(Dungeon.hero, Dewcharge.class, Dewcharge.DURATION+(Math.max(Statistics.prevfloormoves,1))); + //GLog.p("You feel the dungeon charge with dew!"); + } + /*if(Dungeon.hero.heroClass == HeroClass.PERFORMER){ + //Buff.prolong(Dungeon.hero,Rhythm.class,50); + Buff.affect(Dungeon.hero,GlassShield.class).turns(3); + } + if(Dungeon.hero.heroClass == HeroClass.PERFORMER && Dungeon.hero.subClass == HeroSubClass.SUPERSTAR){ + Buff.affect(Dungeon.hero,Rhythm.class,50); + Buff.prolong(Dungeon.hero,Rhythm2.class,50); + }*/ + + return level; + } + + public static void resetLevel() { + + Actor.clear(); + + Arrays.fill(visible, false); + + level.reset(); + switchLevel(level, level.entrance); + } + + public static boolean shopOnLevel() { + return depth==1 || 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 || depth == 36 || depth == 41 || depth == 71 ; + } + + public static boolean notClearableLevel(int depth) { + return depth == 1 || depth ==2 ||depth == 5 || depth == 10 || depth == 15 || depth == 20 || depth == 21 + || depth == 25 || depth>25; + } + + public static boolean townCheck(int depth) { + return depth > 54 && depth < 66; + } + + public static boolean growLevel(int depth) { + return depth == 27 || depth == 28 || depth == 32 || depth == 30 || depth == 55; + } + + public static boolean waterLevel(int depth) { + return depth == 29; + } + + public static boolean sokobanLevel(int depth) { + return depth == 51 || depth == 52 || depth == 53 || depth == 54; + } + + //public static boolean dropLevel(int depth) { + //return depth == 40; + //} + + + @SuppressWarnings("deprecation") + public static void switchLevel(final Level level, int pos) { + + Dungeon.level = level; + DriedRose.restoreGhostHero( level, pos ); + Actor.init(); + + Actor respawner = level.respawner(); + if (respawner != null) { + Actor.add(level.respawner()); + } + + Actor regrower = level.regrower(); + if (regrower != null && growLevel(depth)) { + Actor.add(level.regrower()); + } + + Actor waterer = level.waterer(); + if (waterer != null && waterLevel(depth)) { + Actor.add(level.waterer()); + } + + /*Actor floordropper = level.floordropper(); + if (floordropper != null && dropLevel(depth)) { + Actor.add(level.floordropper()); + }*/ + + 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); + + Actor respawnerPet = level.respawnerPet(); + if (respawnerPet != null) { + Actor.add(level.respawnerPet()); + } + + observe(); + try { + saveAll(); + } catch (IOException e) { + /* + * This only catches IO errors. Yes, this means things can go wrong, + * and they can go wrong catastrophically. But when they do the user + * will get a nice 'report this issue' dialogue, and I can fix the + * bug. + */ + } + } + + public static void dropToChasm(Item item) { + int depth = Dungeon.depth + 1; + ArrayList dropped = Dungeon.droppedItems + .get(depth); + if (dropped == null) { + Dungeon.droppedItems.put(depth, dropped = new ArrayList()); + } + dropped.add(item); + } + + public static boolean posNeeded() { + int[] quota = { 4, 2, 9, 4, 14, 6, 19, 8, 24, 10 }; + return chance(quota, limitedDrops.strengthPotions.count); + } + + public static boolean souNeeded() { + int[] quota = { 5, 4, 10, 8, 15, 12, 20, 16, 25, 20 }; + return chance(quota, limitedDrops.upgradeScrolls.count); + } + + 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; + } + + private static final String RG_GAME_FILE = "rogue.dat"; + private static final String RG_DEPTH_FILE = "rogue%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 = "huntress.dat"; + private static final String RN_DEPTH_FILE = "huntress%d.dat"; + + private static final String PE_GAME_FILE = "performer.dat"; + private static final String PE_DEPTH_FILE = "performer%d.dat"; + + private static final String SO_GAME_FILE = "soldier.dat"; + private static final String SO_DEPTH_FILE = "soldier%d.dat"; + + private static final String FO_GAME_FILE = "follower.dat"; + private static final String FO_DEPTH_FILE = "follower%d.dat"; + + private static final String VERSION = "version"; + private static final String SKINS = "skins"; + private static final String CHALLENGES = "challenges"; + private static final String HERO = "hero"; + private static final String GOLD = "gold"; + private static final String DEPTH = "depth"; + private static final String DROPPED = "dropped%d"; + private static final String LEVEL = "level"; + private static final String LIMDROPS = "limiteddrops"; + private static final String DV = "dewVial"; + private static final String CHAPTERS = "chapters"; + private static final String QUESTS = "quests"; + private static final String BADGES = "badges"; + + private static final String SACRIFICE = "sacrifice"; + private static final String RATCHESTS = "ratChests"; + private static final String EARLYGRASS = "earlygrass"; + private static final String GNOLLSPAWN = "gnollspawned"; + private static final String SKELETONSPAWN = "skeletonspawned"; + private static final String THIEFSPAWN = "goldthiefspawned"; + private static final String STRI = "triforce"; + private static final String STRID = "triforceofcourage"; + private static final String STRIL = "triforceofpower"; + private static final String STRIT = "triforceofwisdom"; + private static final String SYOGKILL = "shadowyogkilled"; + private static final String CRABKILL = "crabkingkilled"; + private static final String TENGUDENKILL = "tengudenkilled"; + private static final String SKELETONKILL = "skeletonkingkilled"; + private static final String GNOLLKILL = "gnollkingkilled"; + private static final String BANDITKILL = "banditkingkilled"; + private static final String ZOTKILL = "zotkilled"; + private static final String SPORK = "sporkAvail"; + private static final String CBDROP = "challengebookdrop"; + private static final String GOEIDROP = "goeidrop"; + private static final String DEWDRAW = "dewDraw"; + private static final String DEWWATER = "dewWater"; + private static final String DEWNORN = "dewNorn"; + private static final String CANSAVE = "canSave"; + private static final String GNOLLMISSION = "gnollmission"; + private static final String ONEDAY = "oneDay"; + private static final String ERROR = "error"; + private static final String WINGS = "wings"; + private static final String PARS = "pars"; + + //private static final String SECONDQUEST = "secondQuest"; + + public static String gameFile(HeroClass cl) { + switch (cl) { + case WARRIOR: + return WR_GAME_FILE; + case MAGE: + return MG_GAME_FILE; + case ROGUE: + return RG_GAME_FILE; + case HUNTRESS: + return RN_GAME_FILE; + case PERFORMER: + return PE_GAME_FILE; + case SOLDIER: + return SO_GAME_FILE; + case FOLLOWER: + return FO_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 ROGUE: + return RG_DEPTH_FILE; + case HUNTRESS: + return RN_DEPTH_FILE; + case PERFORMER: + return PE_DEPTH_FILE; + case SOLDIER: + return SO_DEPTH_FILE; + case FOLLOWER: + return FO_DEPTH_FILE; + default: + return RG_DEPTH_FILE; + } + } + + public static void saveGame(String fileName) throws IOException { + try { + Bundle bundle = new Bundle(); + + version = Game.versionCode; + bundle.put(VERSION, Game.versionCode); + bundle.put( SKINS, skins ); + bundle.put(CHALLENGES, challenges); + bundle.put(HERO, hero); + bundle.put(GOLD, gold); + bundle.put(DEPTH, depth); + + //bundle.put(SECONDQUEST, secondQuest); + bundle.put(SACRIFICE, sacrifice); + bundle.put(RATCHESTS, ratChests); + bundle.put(EARLYGRASS, earlygrass); + bundle.put(GNOLLSPAWN, gnollspawned); + bundle.put(SKELETONSPAWN, skeletonspawned); + bundle.put(THIEFSPAWN, goldthiefspawned); + bundle.put(STRI, triforce); + bundle.put(STRID, triforceofcourage); + bundle.put(STRIL, triforceofpower); + bundle.put(STRIT, triforceofwisdom); + bundle.put(SYOGKILL, shadowyogkilled); + bundle.put(CRABKILL, crabkingkilled); + bundle.put(TENGUDENKILL, tengudenkilled); + bundle.put(BANDITKILL, banditkingkilled); + bundle.put(SKELETONKILL, skeletonkingkilled); + bundle.put(GNOLLKILL, gnollkingkilled); + bundle.put(ZOTKILL, zotkilled); + bundle.put(SPORK, sporkAvail); + bundle.put(CBDROP, challengebookdrop); + bundle.put(GOEIDROP, goeidrop); + bundle.put(DEWDRAW, dewDraw); + bundle.put(DEWWATER, dewWater); + bundle.put(WINGS, wings); + bundle.put(DEWNORN, dewNorn); + bundle.put(CANSAVE, canSave); + bundle.put(GNOLLMISSION, gnollmission); + bundle.put(ONEDAY, oneDay); + bundle.put(ERROR, error); + bundle.put(PARS, pars); + + for (int d : droppedItems.keyArray()) { + bundle.put(String.format(DROPPED, d), droppedItems.get(d)); + } + + quickslot.storePlaceholders(bundle); + + int[] dropValues = new int[limitedDrops.values().length]; + for (limitedDrops value : limitedDrops.values()) + dropValues[value.ordinal()] = value.count; + bundle.put(LIMDROPS, dropValues); + + 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); + //Generator.storeInBundle(bundle); + + Scroll.save(bundle); + Potion.save(bundle); + Ring.save(bundle); + + Actor.storeNextID(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 (IOException e) { + + GamesInProgress.setUnknown(hero.heroClass); + } + } + + public static void saveLevel() throws IOException { + Bundle bundle = new Bundle(); + bundle.put(LEVEL, level); + + OutputStream output = Game.instance.openFileOutput( + Messages.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,skins, + challenges != 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 { + try{ + Bundle bundle = gameBundle(fileName); + + version = bundle.getInt(VERSION); + + Generator.reset(); + + Actor.restoreNextID(bundle); + + quickslot.reset(); + QuickSlotButton.reset(); + + Dungeon.challenges = bundle.getInt(CHALLENGES); + Dungeon.skins = bundle.getInt(SKINS); + + Dungeon.level = null; + Dungeon.depth = -1; + + if (fullLoad) { + PathFinder.setMapSize(Level.getWidth(), Level.HEIGHT); + } + + Scroll.restore(bundle); + Potion.restore(bundle); + Ring.restore(bundle); + + quickslot.restorePlaceholders(bundle); + // TODO: adjust this when dropping support for pre-0.2.3 saves + if (bundle.contains(LIMDROPS)) { + int[] dropValues = bundle.getIntArray(LIMDROPS); + for (limitedDrops value : limitedDrops.values()) + value.count = value.ordinal() < dropValues.length ? dropValues[value + .ordinal()] : 0; + + // for pre-0.2.4 saves + if (bundle.getBoolean(DV)) + limitedDrops.dewVial.drop(); + + chapters = new HashSet(); + 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(); + } + + hero = null; + hero = (Hero) bundle.get(HERO); + + gold = bundle.getInt(GOLD); + depth = bundle.getInt(DEPTH); + + sacrifice = bundle.getInt(SACRIFICE); + ratChests = bundle.getInt(RATCHESTS); + earlygrass = bundle.getBoolean(EARLYGRASS); + gnollspawned = bundle.getBoolean(GNOLLSPAWN); + skeletonspawned = bundle.getBoolean(SKELETONSPAWN); + goldthiefspawned = bundle.getBoolean(THIEFSPAWN); + triforce = bundle.getBoolean(STRI); + triforceofcourage = bundle.getBoolean(STRID); + triforceofpower = bundle.getBoolean(STRIL); + triforceofwisdom = bundle.getBoolean(STRIT); + shadowyogkilled = bundle.getBoolean(SYOGKILL); + crabkingkilled = bundle.getBoolean(CRABKILL); + tengudenkilled = bundle.getBoolean(TENGUDENKILL); + banditkingkilled = bundle.getBoolean(BANDITKILL); + skeletonkingkilled = bundle.getBoolean(SKELETONKILL); + gnollkingkilled = bundle.getBoolean(GNOLLKILL); + zotkilled = bundle.getBoolean(ZOTKILL); + sporkAvail = bundle.getBoolean(SPORK); + challengebookdrop = bundle.getBoolean(CBDROP); + goeidrop = bundle.getBoolean(GOEIDROP); + dewDraw = bundle.getBoolean(DEWDRAW); + dewWater = bundle.getBoolean(DEWWATER); + wings = bundle.getBoolean(WINGS); + dewNorn = bundle.getBoolean(DEWNORN); + canSave = bundle.getBoolean(CANSAVE); + gnollmission = bundle.getBoolean(GNOLLMISSION); + oneDay = bundle.getBoolean(ONEDAY); + error = bundle.getBoolean(ERROR); + pars = bundle.getIntArray(PARS); + + Statistics.restoreFromBundle(bundle); + Journal.restoreFromBundle(bundle); + //Generator.restoreFromBundle(bundle); + + droppedItems = new SparseArray>(); + for (int i = 2; i <= Statistics.realdeepestFloor + 1; i++) { + ArrayList dropped = new ArrayList(); + for (Bundlable b : bundle.getCollection(String.format(DROPPED, i))) { + dropped.add((Item) b); + } + if (!dropped.isEmpty()) { + droppedItems.put(i, dropped); + } + } + } + catch (IOException ex) { + GLog.i("Save File corrupt...\n\nthe gremlins have won this round!"); + } + } + + public static Level loadLevel(HeroClass cl) throws IOException { + + Dungeon.level = null; + Actor.clear(); + + InputStream input = Game.instance.openFileInput(Messages.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(Messages.format(depthFile(cl), depth))) { + depth++; + } + for(int i=1; i<200; i++){ + Game.instance.deleteFile(Messages.format(depthFile(cl), i)); + } + } + + 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); + info.challenges = (bundle.getInt(CHALLENGES) != 0); + if (info.depth == -1) { + info.depth = bundle.getInt("maxDepth"); // FIXME + } + 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) { + + hero.belongings.identify(); + + if (challenges != 0) { + Badges.validateChampion(); + } + + resultDescription = desc; + Rankings.INSTANCE.submit( true ); + } + + public static void observe() { + + if (level == null) { + return; + } + + if (level.darkness()){ + level.visited = visible; + level.updateFieldOfView(hero); + System.arraycopy(Level.fieldOfView, 0, visible, 0, visible.length); + BArray.or(level.visited, visible, level.visited); + } else { + + 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.getLength()]; + + + 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.getLength()); + } + + 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.getLength()); + } + + 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); + + } + + public static boolean checkNight(){ + int hour=Calendar.getInstance().get(Calendar.HOUR_OF_DAY); + return (hour > 19 || hour < 7); + } + + public static int getMonth(){ + int month=Calendar.getInstance().get(Calendar.MONTH); + return month; + } + +} diff --git a/java/com/hmdzl/spspd/DungeonTilemap.java b/java/com/hmdzl/spspd/DungeonTilemap.java new file mode 100644 index 00000000..30c85e3e --- /dev/null +++ b/java/com/hmdzl/spspd/DungeonTilemap.java @@ -0,0 +1,99 @@ +/* + * 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 + */ +package com.hmdzl.spspd; + +import com.hmdzl.spspd.levels.Level; +import com.watabou.noosa.Image; +import com.watabou.noosa.TextureFilm; +import com.watabou.noosa.Tilemap; +import com.watabou.noosa.tweeners.AlphaTweener; +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.getWidth()); + + 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.getWidth() && p.y >= 0 && p.y < Level.HEIGHT ? p.x + + p.y * Level.getWidth() + : -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) { + @Override + protected void onComplete() { + tile.killAndErase(); + killAndErase(); + }; + }); + } + + public static PointF tileToWorld(int pos) { + return new PointF(pos % Level.getWidth(), pos / Level.getWidth()).scale(SIZE); + } + + public static PointF tileCenterToWorld(int pos) { + return new PointF((pos % Level.getWidth() + 0.5f) * SIZE, + (pos / Level.getWidth() + 0.5f) * SIZE); + } + + public static Image tile(int index) { + Image img = new Image(instance.texture); + img.frame(instance.tileset.get(index)); + return img; + } + + public static PointF raisedTileCenterToWorld( int pos ) { + return new PointF( + (pos % Dungeon.level.WIDTH + 0.5f) * SIZE, + (pos / Dungeon.level.WIDTH + 0.1f) * SIZE ); + } + + @Override + public boolean overlapsScreenPoint(int x, int y) { + return true; + } +} diff --git a/java/com/hmdzl/spspd/FogOfWar.java b/java/com/hmdzl/spspd/FogOfWar.java new file mode 100644 index 00000000..c7b41618 --- /dev/null +++ b/java/com/hmdzl/spspd/FogOfWar.java @@ -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 + */ +package com.hmdzl.spspd; + +import java.util.Arrays; + +import android.graphics.Bitmap; + +import com.hmdzl.spspd.scenes.GameScene; +import com.watabou.gltextures.SmartTexture; +import com.watabou.gltextures.TextureCache; +import com.watabou.glwrap.Texture; +import com.watabou.noosa.Image; + +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(); + } + } +} diff --git a/java/com/hmdzl/spspd/GamesInProgress.java b/java/com/hmdzl/spspd/GamesInProgress.java new file mode 100644 index 00000000..89f82b01 --- /dev/null +++ b/java/com/hmdzl/spspd/GamesInProgress.java @@ -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 + */ +package com.hmdzl.spspd; + +import java.util.HashMap; + +import com.hmdzl.spspd.actors.hero.HeroClass; +import com.watabou.utils.Bundle; + +public class GamesInProgress { + + //private static HashMap state = new HashMap(); + private static HashMap state = new HashMap<>(); + + 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 skins, + boolean challenges) { + Info info = new Info(); + info.depth = depth; + info.level = level; + info.skins = skins; + info.challenges = challenges; + 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 skins; + public boolean challenges; + } +} diff --git a/java/com/hmdzl/spspd/Journal.java b/java/com/hmdzl/spspd/Journal.java new file mode 100644 index 00000000..385b26d7 --- /dev/null +++ b/java/com/hmdzl/spspd/Journal.java @@ -0,0 +1,123 @@ +/* + * 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 + */ +package com.hmdzl.spspd; + +import java.util.ArrayList; + +import com.hmdzl.spspd.messages.Messages; +import com.watabou.utils.Bundlable; +import com.watabou.utils.Bundle; + +public class Journal { + + public enum Feature { + WELL_OF_HEALTH, + WELL_OF_AWARENESS, + WELL_OF_TRANSMUTATION, + ALCHEMY, + GARDEN, + STATUE, + + GHOST, + WANDMAKER, + TROLL, + IMP, + + MEMORY_FIRE; + + public String desc() { + return Messages.get(this, name()); + } + }; + + public static class Record implements Comparable, 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 records; + + public static void reset() { + records = new ArrayList(); + } + + 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(); + 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; + } + } + } +} diff --git a/java/com/hmdzl/spspd/Preferences.java b/java/com/hmdzl/spspd/Preferences.java new file mode 100644 index 00000000..35628016 --- /dev/null +++ b/java/com/hmdzl/spspd/Preferences.java @@ -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 + */ +package com.hmdzl.spspd; + +import android.content.SharedPreferences; + +import com.watabou.noosa.Game; + +enum Preferences { + + INSTANCE; + + public static final String KEY_LANDSCAPE = "landscape"; + public static final String KEY_IMMERSIVE = "immersive"; + 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_CHALLENGES = "challenges"; + public static final String KEY_QUICKSLOTS = "quickslots"; + public static final String KEY_LANG = "language"; + public static final String KEY_CLASSICFONT = "classic_font"; + public static final String KEY_INTRO = "intro"; + public static final String KEY_BRIGHTNESS = "brightness"; + public static final String KEY_VERSION = "version"; + + 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(); + } +} diff --git a/java/com/hmdzl/spspd/QuickSlot.java b/java/com/hmdzl/spspd/QuickSlot.java new file mode 100644 index 00000000..24b4149a --- /dev/null +++ b/java/com/hmdzl/spspd/QuickSlot.java @@ -0,0 +1,134 @@ +package com.hmdzl.spspd; + +import java.util.ArrayList; +import java.util.Collection; + +import com.hmdzl.spspd.items.Item; +import com.watabou.utils.Bundlable; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +/** + * Created by debenhame on 16/01/2015. + */ +public class QuickSlot { + + /** + * Slots contain objects which are also in a player's inventory. The one + * exception to this is when quantity is 0, which can happen for a stackable + * item that has been 'used up', these are refered to a placeholders. + */ + + // note that the current max size is coded at 4, due to UI constraints, but + // it could be much much bigger with no issue. + public static int SIZE = 6; + private Item[] slots = new Item[SIZE]; + + // direct array interaction methods, everything should build from these + // methods. + public void setSlot(int slot, Item item) { + clearItem(item); // we don't want to allow the same item in multiple + // slots. + slots[slot] = item; + } + + public void clearSlot(int slot) { + slots[slot] = null; + } + + public void reset() { + slots = new Item[SIZE]; + } + + public Item getItem(int slot) { + return slots[slot]; + } + + // utility methods, for easier use of the internal array. + public int getSlot(Item item) { + for (int i = 0; i < SIZE; i++) + if (getItem(i) == item) + return i; + return -1; + } + + public Boolean isPlaceholder(int slot) { + return getItem(slot) != null && getItem(slot).quantity() == 0; + } + + public Boolean isNonePlaceholder(int slot) { + return getItem(slot) != null && getItem(slot).quantity() > 0; + } + + public void clearItem(Item item) { + if (contains(item)) + clearSlot(getSlot(item)); + } + + public boolean contains(Item item) { + return getSlot(item) != -1; + } + + public void replaceSimilar(Item item) { + for (int i = 0; i < SIZE; i++) + if (getItem(i) != null && item.isSimilar(getItem(i))) + setSlot(i, item); + } + + public void convertToPlaceholder(Item item) { + Item placeholder = Item.virtual(item.getClass()); + + if (placeholder != null && contains(item)) + for (int i = 0; i < SIZE; i++) + if (getItem(i) == item) + setSlot(i, placeholder); + } + + public Item randomNonePlaceholder() { + + ArrayList result = new ArrayList(); + for (int i = 0; i < SIZE; i++) + if (getItem(i) != null && !isPlaceholder(i)) + result.add(getItem(i)); + + return Random.element(result); + } + + private final String PLACEHOLDERS = "placeholders"; + private final String PLACEMENTS = "placements"; + + /** + * Placements array is used as order is preserved while bundling, but exact + * index is not, so if we bundle both the placeholders (which preserves + * their order) and an array telling us where the placeholders are, we can + * reconstruct them perfectly. + */ + + public void storePlaceholders(Bundle bundle) { + ArrayList placeholders = new ArrayList(SIZE); + boolean[] placements = new boolean[SIZE]; + + for (int i = 0; i < SIZE; i++) + if (isPlaceholder(i)) { + placeholders.add(getItem(i)); + placements[i] = true; + } + bundle.put(PLACEHOLDERS, placeholders); + bundle.put(PLACEMENTS, placements); + } + + public void restorePlaceholders(Bundle bundle) { + Collection placeholders = bundle.getCollection(PLACEHOLDERS); + boolean[] placements = bundle.getBooleanArray(PLACEMENTS); + + int i = 0; + for (Bundlable item : placeholders) { + while (!placements[i]) + i++; + setSlot(i, (Item) item); + i++; + } + + } + +} diff --git a/java/com/hmdzl/spspd/Rankings.java b/java/com/hmdzl/spspd/Rankings.java new file mode 100644 index 00000000..dffe00d1 --- /dev/null +++ b/java/com/hmdzl/spspd/Rankings.java @@ -0,0 +1,225 @@ +/* + * 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 + */ +package com.hmdzl.spspd; + +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.hmdzl.spspd.actors.hero.HeroClass; +import com.hmdzl.spspd.messages.Messages; +import com.watabou.noosa.Game; +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 = 11; + + public static final String RANKINGS_FILE = "rankings.dat"; + public static final String DETAILS_FILE = "game_%d.dat"; + + public ArrayList records; + public int lastRecord; + public int totalNumber; + public int wonNumber; + + public void submit(boolean win) { + + load(); + + Record rec = new Record(); + + rec.info = Dungeon.resultDescription; + rec.win = win; + rec.heroClass = Dungeon.hero.heroClass; + rec.skin = 7-Dungeon.skins; + rec.herolevel = Dungeon.hero.lvl; + rec.depth = Dungeon.depth; + rec.score = score(win); + + String gameFile = Messages.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(); + while (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); + } + + size = records.size(); + } + + totalNumber++; + if (win) { + wonNumber++; + } + + Badges.validateGamesPlayed(); + + save(); + } + + private int score(boolean win) { + return (Statistics.goldCollected + Dungeon.hero.lvl + * (win ? 26 : Dungeon.depth) * 100) + * (win ? 2 : 1); + } + + private static final String RECORDS = "records"; + private static final String LATEST = "latest"; + private static final String TOTAL = "total"; + private static final String WON = "won"; + + public void save() { + Bundle bundle = new Bundle(); + bundle.put(RECORDS, records); + bundle.put(LATEST, lastRecord); + bundle.put(TOTAL, totalNumber); + bundle.put(WON, wonNumber); + + try { + OutputStream output = Game.instance.openFileOutput(RANKINGS_FILE, + Game.MODE_PRIVATE); + Bundle.write(bundle, output); + output.close(); + } catch (IOException e) { + } + } + + public void load() { + + if (records != null) { + return; + } + + records = new ArrayList(); + + 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(); + } + + wonNumber = bundle.getInt(WON); + if (wonNumber == 0) { + for (Record rec : records) { + if (rec.win) { + wonNumber++; + } + } + } + + } catch (IOException 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 SKIN = "skin"; + private static final String LEVEL = "level"; + private static final String DEPTH = "depth"; + private static final String GAME = "gameFile"; + + public String info; + public boolean win; + + public HeroClass heroClass; + public int skin; + public int herolevel; + public int depth; + + 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); + skin = bundle.getInt(SKIN); + gameFile = bundle.getString(GAME); + depth = bundle.getInt(DEPTH); + herolevel = bundle.getInt(LEVEL); + + } + + @Override + public void storeInBundle(Bundle bundle) { + + bundle.put(REASON, info); + bundle.put(WIN, win); + bundle.put(SCORE, score); + + heroClass.storeInBundle(bundle); + bundle.put(SKIN, skin); + bundle.put(LEVEL, herolevel); + bundle.put(DEPTH, depth); + + bundle.put(GAME, gameFile); + } + } + + private static final Comparator scoreComparator = new Comparator() { + @Override + public int compare(Record lhs, Record rhs) { + return (int) Math.signum(rhs.score - lhs.score); + } + }; +} diff --git a/java/com/hmdzl/spspd/ResultDescriptions.java b/java/com/hmdzl/spspd/ResultDescriptions.java new file mode 100644 index 00000000..9de71acb --- /dev/null +++ b/java/com/hmdzl/spspd/ResultDescriptions.java @@ -0,0 +1,49 @@ +/* + * 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 + */ +package com.hmdzl.spspd; + +import com.hmdzl.spspd.messages.Messages; + +public class ResultDescriptions { + + // Mobs + public static final String MOB = "MOB"; + public static final String UNIQUE = "UNIQUE"; + public static final String NAMED = "NAMED"; + + // Items + public static final String ITEM = "ITEM"; + public static final String GLYPH = "GLYPH"; + + // Dungeon features + public static final String TRAP = "TRAP"; + + // Debuffs & blobs + public static final String BURNING = "BURNING"; + public static final String HUNGER = "HUNGER"; + public static final String POISON = "POISON"; + public static final String GAS = "GAS"; + public static final String BLEEDING = "BLEEDING"; + public static final String OOZE = "OOZE"; + public static final String FALL = "FALL"; + public static final String COUNTDOWN = "COUNTDOWN"; + public static final String CHEAT = "CHEAT"; + + public static final String WIN = "WIN"; + public static final String WIN2 = "WIN2"; +} diff --git a/java/com/hmdzl/spspd/SPSSettings.java b/java/com/hmdzl/spspd/SPSSettings.java new file mode 100644 index 00000000..55d0f302 --- /dev/null +++ b/java/com/hmdzl/spspd/SPSSettings.java @@ -0,0 +1,129 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2017 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ + +package com.hmdzl.spspd; + +import com.hmdzl.spspd.messages.Languages; +import com.hmdzl.spspd.scenes.GameScene; +import com.watabou.noosa.Game; +import com.watabou.noosa.RenderedText; +import com.watabou.noosa.audio.Music; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.GameSettings; + +import java.util.Locale; + +public class SPSSettings extends GameSettings { + + //Version info + + public static final String KEY_VERSION = "version"; + + public static void version( int value) { + put( KEY_VERSION, value ); + } + + public static int version() { + return getInt( KEY_VERSION, 0 ); + } + + //Graphics + + public static final String KEY_LANDSCAPE = "landscape"; + public static final String KEY_SCALE = "scale"; + public static final String KEY_ZOOM = "zoom"; + + public static boolean landscape() { + return getBoolean(KEY_LANDSCAPE, Game.dispWidth > Game.dispHeight); + } + + public static void scale( int value ) { + put( KEY_SCALE, value ); + } + + public static int scale() { + return getInt( KEY_SCALE, 0 ); + } + + public static void zoom( int value ) { + put( KEY_ZOOM, value ); + } + + public static int zoom() { + return getInt( KEY_ZOOM, 0 ); + } + + //Interface + + //Game State + + public static final String KEY_CHALLENGES = "challenges"; + + public static void challenges( int value ) { + put( KEY_CHALLENGES, value ); + } + + //Audio + + public static final String KEY_MUSIC = "music"; + + public static void music( boolean value ) { + Music.INSTANCE.enable( value ); + put( KEY_MUSIC, value ); + } + + public static boolean music() { + return getBoolean( KEY_MUSIC, true ); + } + + //Languages and Font + + public static final String KEY_LANG = "language"; + public static final String KEY_SYSTEMFONT = "system_font"; + + public static void language(Languages lang) { + put( KEY_LANG, lang.code()); + } + + public static Languages language() { + String code = getString(KEY_LANG, null); + if (code == null){ + return Languages.matchLocale(Locale.getDefault()); + } else { + return Languages.matchCode(code); + } + } + + public static void systemFont(boolean value){ + put(KEY_SYSTEMFONT, value); + if (!value) { + RenderedText.setFont("pixelfont.ttf"); + } else { + RenderedText.setFont( null ); + } + } + + public static boolean systemFont(){ + return getBoolean(KEY_SYSTEMFONT, + (/*language() == Languages.KOREAN ||*/ language() == Languages.CHINESE)); + } + +} diff --git a/java/com/hmdzl/spspd/ShatteredPixelDungeon.java b/java/com/hmdzl/spspd/ShatteredPixelDungeon.java new file mode 100644 index 00000000..ccb89442 --- /dev/null +++ b/java/com/hmdzl/spspd/ShatteredPixelDungeon.java @@ -0,0 +1,334 @@ +/* + * 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 + */ +package com.hmdzl.spspd; + +import javax.microedition.khronos.opengles.GL10; + +import android.annotation.SuppressLint; +import android.content.pm.ActivityInfo; +import android.os.Build; +import android.os.Bundle; +import android.util.DisplayMetrics; +import android.util.Log; +import android.view.View; + +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.scenes.PixelScene; +import com.hmdzl.spspd.scenes.TitleScene; +import com.hmdzl.spspd.scenes.WelcomeScene; +import com.watabou.noosa.Game; +import com.watabou.noosa.audio.Music; +import com.watabou.noosa.audio.Sample; +import com.watabou.noosa.RenderedText; + +public class ShatteredPixelDungeon extends Game { + + public ShatteredPixelDungeon() { + super(WelcomeScene.class); + } + + @SuppressWarnings("deprecation") + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + updateImmersiveMode(); + + DisplayMetrics metrics = new DisplayMetrics(); + instance.getWindowManager().getDefaultDisplay().getMetrics(metrics); + boolean landscape = metrics.widthPixels > metrics.heightPixels; + + if (Preferences.INSTANCE.getBoolean(Preferences.KEY_LANDSCAPE, false) != landscape) { + landscape(!landscape); + } + + Music.INSTANCE.enable(music()); + Sample.INSTANCE.enable(soundFx()); + + Sample.INSTANCE.load(Assets.SND_CLICK, Assets.SND_BADGE, + Assets.SND_GOLD, + + Assets.SND_STEP, Assets.SND_WATER, Assets.SND_OPEN, + Assets.SND_UNLOCK, Assets.SND_ITEM, Assets.SND_DEWDROP, + Assets.SND_HIT, Assets.SND_MISS, + + Assets.SND_DESCEND, Assets.SND_EAT, Assets.SND_READ, + Assets.SND_LULLABY, Assets.SND_DRINK, Assets.SND_SHATTER, + Assets.SND_ZAP, Assets.SND_LIGHTNING, Assets.SND_LEVELUP, + Assets.SND_DEATH, Assets.SND_CHALLENGE, Assets.SND_CURSED, + Assets.SND_EVOKE, Assets.SND_TRAP, Assets.SND_TOMB, + Assets.SND_ALERT, Assets.SND_MELD, Assets.SND_BOSS, + Assets.SND_BLAST, Assets.SND_PLANT, Assets.SND_RAY, + Assets.SND_BEACON, Assets.SND_TELEPORT, Assets.SND_CHARMS, + Assets.SND_MASTERY, Assets.SND_PUFF, Assets.SND_ROCKS, + Assets.SND_BURNING, Assets.SND_FALLING, Assets.SND_GHOST, + Assets.SND_SECRET, Assets.SND_BONES, Assets.SND_BEE, + Assets.SND_DEGRADE, Assets.SND_MIMIC); + + if (!SPSSettings.systemFont()) { + RenderedText.setFont("pixelfont.ttf"); + } else { + RenderedText.setFont( null ); + } + } + + @Override + public void onWindowFocusChanged(boolean hasFocus) { + + super.onWindowFocusChanged(hasFocus); + + if (hasFocus) { + updateImmersiveMode(); + } + } + + public static void switchNoFade(Class c){ + switchNoFade(c, null); + } + + public static void switchNoFade(Class c, SceneChangeCallback callback) { + PixelScene.noFade = true; + switchScene( c, callback ); + } + + /* + * ---> 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); + } + + // *** IMMERSIVE MODE **** + + private static boolean immersiveModeChanged = false; + + @SuppressLint("NewApi") + public static void immerse(boolean value) { + Preferences.INSTANCE.put(Preferences.KEY_IMMERSIVE, value); + + instance.runOnUiThread(new Runnable() { + @Override + public void run() { + updateImmersiveMode(); + immersiveModeChanged = true; + } + }); + } + + @Override + public void onSurfaceChanged(GL10 gl, int width, int height) { + super.onSurfaceChanged(gl, width, height); + + if (immersiveModeChanged) { + requestedReset = true; + immersiveModeChanged = false; + } + } + + private void updateDisplaySize(){ + DisplayMetrics m = new DisplayMetrics(); + if (immersed() && Build.VERSION.SDK_INT >= 19) + getWindowManager().getDefaultDisplay().getRealMetrics( m ); + else + getWindowManager().getDefaultDisplay().getMetrics( m ); + dispHeight = m.heightPixels; + dispWidth = m.widthPixels; + + float dispRatio = dispWidth / (float)dispHeight; + + float renderWidth = dispRatio > 1 ? PixelScene.MIN_WIDTH_L : PixelScene.MIN_WIDTH_P; + float renderHeight = dispRatio > 1 ? PixelScene.MIN_HEIGHT_L : PixelScene.MIN_HEIGHT_P; + + runOnUiThread(new Runnable() { + @Override + public void run() { + view.getHolder().setSizeFromLayout(); + } + }); + + } + + @SuppressLint("NewApi") + public static void updateImmersiveMode() { + if (android.os.Build.VERSION.SDK_INT >= 19) { + try { + // Sometime NullPointerException happens here + instance.getWindow() + .getDecorView() + .setSystemUiVisibility( + immersed() ? 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 + : 0); + } catch (Exception e) { + reportException(e); + } + } + } + + public static boolean immersed() { + return Preferences.INSTANCE + .getBoolean(Preferences.KEY_IMMERSIVE, false); + } + + // ***************************** + + 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 language(Languages lang) { + Preferences.INSTANCE.put( Preferences.KEY_LANG, lang.code()); + if (lang == Languages.RUSSIAN || lang == Languages.CHINESE || lang == Languages.KOREAN) + RenderedText.setFont(null); + else if (classicFont()) + RenderedText.setFont("pixelfont.ttf"); + }*/ + + /*public static Languages language() { + String code = Preferences.INSTANCE.getString(Preferences.KEY_LANG, null); + if (code == null){ + Languages lang = Languages.matchLocale(Locale.getDefault()); + if (lang.status() == Languages.Status.REVIEWED) + return lang; + else + return Languages.ENGLISH; + } + else return Languages.matchCode(code); + }*/ + + /*public static void classicFont(boolean classic){ + Preferences.INSTANCE.put(Preferences.KEY_CLASSICFONT, classic); + if (classic) { + RenderedText.setFont("pixelfont.ttf"); + } else { + RenderedText.setFont( null ); + } + }*/ + + /*public static boolean classicFont(){ + Languages lang = ShatteredPixelDungeon.language(); + if (lang == Languages.RUSSIAN ||lang == Languages.CHINESE || lang == Languages.KOREAN ) + return false; + else + return Preferences.INSTANCE.getBoolean(Preferences.KEY_CLASSICFONT, true); + } */ + + 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 challenges(int value) { + Preferences.INSTANCE.put(Preferences.KEY_CHALLENGES, value); + } + + public static int challenges() { + return Preferences.INSTANCE.getInt(Preferences.KEY_CHALLENGES, 0); + } + + public static void quickSlots(int value) { + Preferences.INSTANCE.put(Preferences.KEY_QUICKSLOTS, value); + } + + public static int quickSlots() { + return Preferences.INSTANCE.getInt(Preferences.KEY_QUICKSLOTS, 1); + } + + 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); + } + + public static void version(int value) { + Preferences.INSTANCE.put(Preferences.KEY_VERSION, value); + } + + public static int version() { + return Preferences.INSTANCE.getInt(Preferences.KEY_VERSION, 0); + } + + /* + * <--- Preferences + */ + + public static void reportException(Throwable tr) { + Log.e("PD", Log.getStackTraceString(tr)); + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/Skins.java b/java/com/hmdzl/spspd/Skins.java new file mode 100644 index 00000000..2e8fa409 --- /dev/null +++ b/java/com/hmdzl/spspd/Skins.java @@ -0,0 +1,37 @@ +/* + * 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 + */ +package com.hmdzl.spspd; + +public class Skins { + + public static final int NORMAL = 0; + public static final int FIRST = 1; + public static final int SECOND = 2; + public static final int THIRD = 3; + + public static final String[] NAME_IDS = { + "normal", + "first", + "second", + "third", + }; + + public static final int[] MASKS = { + NORMAL, FIRST,SECOND,THIRD}; + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/Statistics.java b/java/com/hmdzl/spspd/Statistics.java new file mode 100644 index 00000000..e76f66a3 --- /dev/null +++ b/java/com/hmdzl/spspd/Statistics.java @@ -0,0 +1,197 @@ +/* + * 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 + */ +package com.hmdzl.spspd; + +import com.watabou.utils.Bundle; + +//move target 300 + d3*lvl + +public class Statistics { + + public static int goldCollected; + public static int deepestFloor; + public static int realdeepestFloor; + public static int enemiesSlain; + public static int foodEaten; + public static int eggBreak; + public static int potionsCooked; + public static int piranhasKilled; + public static int archersKilled; + public static int skeletonsKilled; + public static int assassinsKilled; + public static int albinoPiranhasKilled; + public static int goldThievesKilled; + public static int shadowYogsKilled; + public static int nightHunt; + public static int ankhsUsed; + public static int ballsCooked; + public static int waters; + public static int sewerKills; + public static int prisonKills; + public static int petDies; + + public static float duration; + public static int floormoves; + public static int prevfloormoves; + public static int moves; + public static float time; + + + public static boolean qualifiedForNoKilling = false; + public static boolean completedWithNoKilling = false; + + + public static boolean amuletObtained = false; + public static boolean orbObtained = false; + + + public static void reset() { + + goldCollected = 0; + deepestFloor = 0; + realdeepestFloor = 0; + enemiesSlain = 0; + foodEaten = 0; + eggBreak = 0; + potionsCooked = 0; + + piranhasKilled = 0; + archersKilled = 0; + assassinsKilled = 0; + skeletonsKilled = 0; + albinoPiranhasKilled = 0; + goldThievesKilled = 0; + shadowYogsKilled = 0; + nightHunt = 0; + ankhsUsed = 0; + ballsCooked = 0; + waters = 0; + sewerKills = 0; + prisonKills = 0; + petDies = 0; + + duration = 0; + moves = 0; + floormoves = 0; + prevfloormoves = 0; + time = 360; + + qualifiedForNoKilling = false; + + amuletObtained = false; + orbObtained = false; + + } + + private static final String GOLD = "score"; + private static final String DEEPEST = "maxDepth"; + private static final String REALDEEPEST = "maxDepthReal"; + private static final String SLAIN = "enemiesSlain"; + private static final String FOOD = "foodEaten"; + private static final String EGG = "eggBreak"; + private static final String ALCHEMY = "potionsCooked"; + private static final String PIRANHAS = "priranhas"; + private static final String WATERS = "waters"; + + private static final String ARCHERS = "archers"; + private static final String SKELETONS = "skeletons"; + private static final String ASSASSINS = "assassins"; + private static final String APIRANHAS = "apiranhas"; + private static final String THIEVES = "thieves"; + private static final String SYOGS = "syogs"; + private static final String BALLS = "balls"; + private static final String PRISONKILLS = "prisonKills"; + private static final String SEWERKILLS = "sewerKills"; + private static final String PETDIES = "petDies"; + + private static final String NIGHT = "nightHunt"; + private static final String ANKHS = "ankhsUsed"; + private static final String DURATION = "duration"; + private static final String FLOORMOVES = "floormoves"; + private static final String PREVFLOORMOVES = "prevfloormoves"; + private static final String MOVES = "moves"; + private static final String TIME = "time"; + private static final String AMULET = "amuletObtained"; + private static final String ORB = "orbObtained"; + + public static void storeInBundle(Bundle bundle) { + bundle.put(GOLD, goldCollected); + bundle.put(DEEPEST, deepestFloor); + bundle.put(REALDEEPEST, realdeepestFloor); + bundle.put(SLAIN, enemiesSlain); + bundle.put(FOOD, foodEaten); + bundle.put(EGG, eggBreak); + bundle.put(ALCHEMY, potionsCooked); + bundle.put(PIRANHAS, piranhasKilled); + bundle.put(ARCHERS, archersKilled); + bundle.put(SKELETONS, skeletonsKilled); + bundle.put(ASSASSINS, assassinsKilled); + bundle.put(APIRANHAS, albinoPiranhasKilled); + bundle.put(THIEVES, goldThievesKilled); + bundle.put(SYOGS, shadowYogsKilled); + bundle.put(BALLS, ballsCooked); + bundle.put(NIGHT, nightHunt); + bundle.put(ANKHS, ankhsUsed); + bundle.put(DURATION, duration); + bundle.put(FLOORMOVES, floormoves); + bundle.put(PREVFLOORMOVES, prevfloormoves); + bundle.put(MOVES, moves); + bundle.put(TIME, time); + bundle.put(AMULET, amuletObtained); + bundle.put(ORB, orbObtained); + bundle.put(WATERS, waters); + bundle.put(SEWERKILLS, sewerKills); + bundle.put(PRISONKILLS, prisonKills); + bundle.put(PETDIES, petDies); + } + + public static void restoreFromBundle(Bundle bundle) { + goldCollected = bundle.getInt(GOLD); + deepestFloor = bundle.getInt(DEEPEST); + realdeepestFloor = bundle.getInt(REALDEEPEST); + enemiesSlain = bundle.getInt(SLAIN); + foodEaten = bundle.getInt(FOOD); + eggBreak = bundle.getInt(EGG); + potionsCooked = bundle.getInt(ALCHEMY); + piranhasKilled = bundle.getInt(PIRANHAS); + waters = bundle.getInt(WATERS); + sewerKills = bundle.getInt(SEWERKILLS); + prisonKills = bundle.getInt(PRISONKILLS); + petDies = bundle.getInt(PETDIES); + + archersKilled = bundle.getInt(ARCHERS); + skeletonsKilled = bundle.getInt(SKELETONS); + assassinsKilled = bundle.getInt(ASSASSINS); + albinoPiranhasKilled = bundle.getInt(APIRANHAS); + goldThievesKilled = bundle.getInt(THIEVES); + shadowYogsKilled = bundle.getInt(SYOGS); + ballsCooked = bundle.getInt(BALLS); + + nightHunt = bundle.getInt(NIGHT); + ankhsUsed = bundle.getInt(ANKHS); + duration = bundle.getFloat(DURATION); + floormoves = bundle.getInt(FLOORMOVES); + prevfloormoves = bundle.getInt(PREVFLOORMOVES); + moves = bundle.getInt(MOVES); + time = bundle.getInt(TIME); + amuletObtained = bundle.getBoolean(AMULET); + orbObtained = bundle.getBoolean(ORB); + + } + +} diff --git a/java/com/hmdzl/spspd/actors/Actor.java b/java/com/hmdzl/spspd/actors/Actor.java new file mode 100644 index 00000000..6703840b --- /dev/null +++ b/java/com/hmdzl/spspd/actors/Actor.java @@ -0,0 +1,288 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors; + +import java.util.Arrays; +import java.util.HashSet; + +import android.util.SparseArray; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.Statistics; +import com.hmdzl.spspd.actors.blobs.Blob; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.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; + + private int id = 0; + + 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; + } + } + + public float cooldown() { + return time - now; + } + + protected void diactivate() { + time = Float.MAX_VALUE; + } + + protected void onAdd() { + } + + protected void onRemove() { + } + + private static final String TIME = "time"; + private static final String ID = "id"; + + @Override + public void storeInBundle(Bundle bundle) { + bundle.put(TIME, time); + bundle.put(ID, id); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + time = bundle.getFloat(TIME); + id = bundle.getInt(ID); + } + + private static int nextID = 1; + + public int id() { + if (id > 0) { + return id; + } else { + return (id = nextID++); + } + } + + // ********************** + // *** Static members *** + + private static HashSet all = new HashSet(); + private static Actor current; + + private static SparseArray ids = new SparseArray(); + + private static float now = 0; + + private static Char[] chars = new Char[Level.getLength()]; + + public static float now(){ + return now; + } + + public static void clear() { + + now = 0; + + Arrays.fill(chars, null); + all.clear(); + + ids.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; + } + + private static final String NEXTID = "nextid"; + + public static void storeNextID(Bundle bundle) { + bundle.put(NEXTID, nextID); + } + + public static void restoreNextID(Bundle bundle) { + nextID = bundle.getInt(NEXTID); + } + + public static void resetNextID() { + nextID = 1; + } + + public static void occupyCell(Char ch) { + chars[ch.pos] = ch; + } + + public static void freeCell(int pos) { + chars[pos] = null; + } + + /* protected */public void next() { + if (current == this) { + 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) { + // Order of actions when time is equal: + // 1. Hero + // 2. Other Chars + // 3. Other Actors (e.g. blobs) + if (actor.time < now + || (actor instanceof Hero && actor.time == now) + || (actor instanceof Char && actor.time == now && !(current instanceof Hero))) { + now = actor.time; + current = actor; + } + + if (actor instanceof Char) { + Char ch = (Char) actor; + chars[ch.pos] = ch; + } + } + + if (current != null) { + + if (current instanceof Char && ((Char) current).sprite.isMoving) { + // If it's character's turn to act, but its sprite + // is moving, wait till the movement is over + current = null; + break; + } + + 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; + } + + ids.put(actor.id(), actor); + + 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); + //chars.remove( actor ); + actor.onRemove(); + + if (actor.id > 0) { + ids.remove(actor.id); + } + } + } + + public static Char findChar(int pos) { + return chars[pos]; + } + + public static Actor findById(int id) { + return ids.get(id); + } + + public static HashSet all() { + return all; + } +} diff --git a/java/com/hmdzl/spspd/actors/Char.java b/java/com/hmdzl/spspd/actors/Char.java new file mode 100644 index 00000000..22616d20 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/Char.java @@ -0,0 +1,735 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.ResultDescriptions; +import com.hmdzl.spspd.actors.blobs.ToxicGas; +import com.hmdzl.spspd.actors.buffs.ArmorBreak; +import com.hmdzl.spspd.actors.buffs.AttackDown; +import com.hmdzl.spspd.actors.buffs.AttackUp; +import com.hmdzl.spspd.actors.buffs.Bleeding; +import com.hmdzl.spspd.actors.buffs.Bless; +import com.hmdzl.spspd.actors.buffs.BloodAngry; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Burning; +import com.hmdzl.spspd.actors.buffs.Charm; +import com.hmdzl.spspd.actors.buffs.Cold; +import com.hmdzl.spspd.actors.buffs.Cripple; +import com.hmdzl.spspd.actors.buffs.Chill; +import com.hmdzl.spspd.actors.buffs.DamageUp; +import com.hmdzl.spspd.actors.buffs.DefenceUp; +import com.hmdzl.spspd.actors.buffs.Disarm; +import com.hmdzl.spspd.actors.buffs.EarthImbue; +import com.hmdzl.spspd.actors.buffs.FireImbue; +import com.hmdzl.spspd.actors.buffs.Frost; +import com.hmdzl.spspd.actors.buffs.FrostImbue; +import com.hmdzl.spspd.actors.buffs.GlassShield; +import com.hmdzl.spspd.actors.buffs.GrowSeed; +import com.hmdzl.spspd.actors.buffs.Haste; +import com.hmdzl.spspd.actors.buffs.HighAttack; +import com.hmdzl.spspd.actors.buffs.HighVoice; +import com.hmdzl.spspd.actors.buffs.Hot; +import com.hmdzl.spspd.actors.buffs.Hunger; +import com.hmdzl.spspd.actors.buffs.MechArmor; +import com.hmdzl.spspd.actors.buffs.Needling; +import com.hmdzl.spspd.actors.buffs.ParyAttack; +import com.hmdzl.spspd.actors.buffs.Rhythm; +import com.hmdzl.spspd.actors.buffs.Rhythm2; +import com.hmdzl.spspd.actors.buffs.ShieldArmor; +import com.hmdzl.spspd.actors.buffs.Shocked; +import com.hmdzl.spspd.actors.buffs.StoneIce; +import com.hmdzl.spspd.actors.buffs.Tar; +import com.hmdzl.spspd.actors.buffs.MagicalSleep; +import com.hmdzl.spspd.actors.buffs.Paralysis; +import com.hmdzl.spspd.actors.buffs.Poison; +import com.hmdzl.spspd.actors.buffs.Slow; +import com.hmdzl.spspd.actors.buffs.Speed; +import com.hmdzl.spspd.actors.buffs.Vertigo; +import com.hmdzl.spspd.actors.buffs.BloodImbue; +import com.hmdzl.spspd.actors.buffs.Wet; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.hero.HeroClass; +import com.hmdzl.spspd.actors.hero.HeroSubClass; +import com.hmdzl.spspd.actors.mobs.Bestiary; +import com.hmdzl.spspd.effects.Lightning; +import com.hmdzl.spspd.items.wands.WandOfFirebolt; +import com.hmdzl.spspd.items.weapon.enchantments.EnchantmentFire; +import com.hmdzl.spspd.items.weapon.enchantments.EnchantmentFire2; +import com.hmdzl.spspd.items.weapon.missiles.MissileWeapon; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.Terrain; +import com.hmdzl.spspd.levels.features.Door; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.CharSprite; +import com.hmdzl.spspd.utils.GLog; + +import com.watabou.noosa.Camera; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Bundlable; +import com.watabou.utils.Bundle; +import com.watabou.utils.GameMath; +import com.watabou.utils.Random; + +public abstract class Char extends Actor { + + protected static final String TXT_KILL = "%s killed you..."; + + public int pos = 0; + + public CharSprite sprite; + + public String name = "mob"; + + public int HT; + public int HP; + + protected float baseSpeed = 1; + + public int paralysed = 0; + public boolean rooted = false; + public boolean flying = false; + public int invisible = 0; + + public int viewDistance = 8; + + private HashSet buffs = new HashSet(); + + @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); + }*/ + + // FIXME + int dr = enemy.drRoll(); + + if (this instanceof Hero){ + Hero h = (Hero)this; + if ((h.belongings.weapon instanceof MissileWeapon + && h.subClass == HeroSubClass.SNIPER )|| + ( h.heroClass == HeroClass.FOLLOWER && Dungeon.skins == 2) ){ + dr = 0; + } + } + + int dmg = damageRoll(); + + AttackUp atkup = buff(AttackUp.class); + if (atkup != null) { + dmg *=(1f+atkup.level()*0.01f); + } + + AttackDown atkdown = buff(AttackDown.class); + if (atkdown != null) { + dmg *=(1f-atkdown.level()*0.01f); + } + + MechArmor marmor = buff(MechArmor.class); + if (marmor != null) { + dmg *=1.3f; + } + + StoneIce si = buff(StoneIce.class); + if ( si != null){ + dmg *= 1.4; + } + + DamageUp dmgup = buff(DamageUp.class); + if (dmgup != null) { + dmg +=dmgup.level(); + Buff.detach(this,DamageUp.class); + } + + + int effectiveDamage = Math.max(dmg - dr, 1); + + effectiveDamage = attackProc(enemy, effectiveDamage); + effectiveDamage = enemy.defenseProc(this, effectiveDamage); + + if (visibleFight) { + Sample.INSTANCE.play(Assets.SND_HIT, 1, 1, + Random.Float(0.8f, 1.25f)); + } + + // If the enemy is already dead, interrupt the attack. + // This matters as defence procs can sometimes inflict self-damage, + // such as armor glyphs. + if (!enemy.isAlive()) { + return true; + } + + // TODO: consider revisiting this and shaking in more cases. + float shake = 0f; + if (enemy == Dungeon.hero) + shake = effectiveDamage / (enemy.HT / 4); + + if (shake > 1f) + Camera.main.shake(GameMath.gate(1, shake, 5), 0.3f); + + enemy.damage(effectiveDamage, this); + + if (buff(FireImbue.class) != null) + buff(FireImbue.class).proc(enemy); + if (buff(EarthImbue.class) != null) + buff(EarthImbue.class).proc(enemy); + if (buff(BloodImbue.class) != null) + buff(BloodImbue.class).proc(enemy); + if (buff(FrostImbue.class) != null) + buff(FrostImbue.class).proc(enemy); + if (buff(Needling.class) != null) + buff(Needling.class).proc(enemy); + + enemy.sprite.bloodBurstA(sprite.center(), effectiveDamage); + enemy.sprite.flash(); + + if (!enemy.isAlive() && visibleFight) { + if (enemy == Dungeon.hero) { + if (Bestiary.isUnique(this)) { + Dungeon.fail(Messages.format(ResultDescriptions.UNIQUE)); + } else { + Dungeon.fail(Messages.format(ResultDescriptions.MOB)); + } + + } + } + return true; + + } else { + + if (visibleFight) { + String defense = enemy.defenseVerb(); + enemy.sprite.showStatus(CharSprite.NEUTRAL, defense); + Sample.INSTANCE.play(Assets.SND_MISS); + } + + return false; + + } + } + + public static boolean hit(Char attacker, Char defender, boolean magic) { + float acuRoll = Random.Float(attacker.hitSkill(defender)); + float defRoll = Random.Float(defender.evadeSkill(attacker)); + if (attacker.buff(Bless.class) != null) acuRoll *= 1.20f; + if (defender.buff(Bless.class) != null) defRoll *= 1.20f; + if (attacker.buff(Wet.class) != null) acuRoll *= 0.90f; + if (defender.buff(Wet.class) != null) defRoll *= 0.90f; + if (attacker.buff(Rhythm.class) != null) acuRoll *= 3.00f; + if (defender.buff(Rhythm.class) != null) defRoll *= 1.50f; + if (defender.buff(HighAttack.class) != null) defRoll *= 1.20f; + return (magic ? acuRoll * 2 : acuRoll) >= defRoll; + } + + public int hitSkill(Char target) { + return 0; + } + + public int evadeSkill(Char enemy) { + return 0; + } + + public String defenseVerb() { + return Messages.get(this,"def_verb"); + } + + public int drRoll() { + return 0; + } + + public int damageRoll() { + return 1; + } + + public int attackProc(Char enemy, int damage) { + if (buff(Shocked.class)!=null){ + Buff.detach(this,Shocked.class); + Buff.affect(this, Disarm.class,5f); + damage(this.HP/10,this); + ArrayList arcs = new ArrayList<>(); + arcs.add(new Lightning.Arc(pos - Level.WIDTH, pos + Level.WIDTH)); + arcs.add(new Lightning.Arc(pos - 1, pos + 1)); + sprite.parent.add( new Lightning( arcs, null ) ); + } + + return damage; + } + + public int defenseProc(Char enemy, int damage) { + return damage; + } + + public float speed() { + if (buff(Cripple.class) != null){ + return baseSpeed * 0.5f; + } else if (buff(Haste.class) != null){ + return baseSpeed * 2.5f; + } else if (buff(Poison.class) != null) { + return baseSpeed * 0.9f; + } else if (buff(BloodAngry.class) != null) { + return baseSpeed * 1.2f; + } else if (buff(MechArmor.class) != null) { + return baseSpeed * 1.5f; + } else if (buff(StoneIce.class) != null) { + return baseSpeed * 0.8f; + } else{ + return baseSpeed; + } + + + } + + public void damage(int dmg, Object src) { + + if (this.buff(Frost.class) != null) { + Buff.detach(this, Frost.class); + dmg = (int) Math.ceil(dmg *1.5); + } + if (this.buff(MagicalSleep.class) != null) { + Buff.detach(this, MagicalSleep.class); + dmg = (int) Math.ceil(dmg *1.5); + } + + ArmorBreak ab = buff(ArmorBreak.class); + if (buff(ArmorBreak.class) != null){ + dmg= (int) Math.ceil(dmg *(ab.level()*0.01+1)); + } + + ParyAttack paryatk = buff(ParyAttack.class); + if (buff(ParyAttack.class) != null){ + dmg= (int) Math.ceil(dmg *Math.max((1-paryatk.level()*0.02),0.5)); + } + + if (buff(Hot.class) != null){ + dmg = (int) Math.ceil(dmg * 1.2); + } + + DefenceUp drup = buff(DefenceUp.class); + if (buff(DefenceUp.class) != null) { + dmg = (int) Math.ceil(dmg *(-drup.level()*0.01+1)); + } + + if (buff(GrowSeed.class) != null) { + dmg = (int) Math.ceil(dmg *0.8); + } + + ShieldArmor sarmor = buff(ShieldArmor.class); + if (sarmor != null && !(src instanceof Hunger)) { + dmg = sarmor.absorb(dmg); + } + + MechArmor marmor = buff(MechArmor.class); + if (marmor != null && !(src instanceof Hunger)) { + dmg = marmor.absorb(dmg); + } + + if (HP <= 0 || dmg < 0) { + return; + } + + Class srcClass = src.getClass(); + if (immunities().contains(srcClass)) { + dmg = 0; + } else if (resistances().contains(srcClass)) { + dmg = Random.IntRange(0, dmg); + } else if (weakness().contains(srcClass)) { + dmg = Random.IntRange(dmg+1, 2*dmg); + } + + if (buff(Paralysis.class) != null) { + if (Random.Int(dmg) >= Random.Int(HP)) { + Buff.detach(this, Paralysis.class); + if (Dungeon.visible[pos]) { + GLog.i(Messages.get(this,"out_of_paralysis",name)); + } + } + } + + //GlassShield glass = buff(GlassShield.class); + if (buff(GlassShield.class) != null) { + if (dmg >= 10) { + dmg = 10; + Buff.detach(this, GlassShield.class); + } + } + //if (dmg > HP){ + //Buff.detach(this,Corruption.class);} + HP -= dmg; + + + if (dmg > 0 || src instanceof Char) { + sprite.showStatus(HP > HT / 2 ? CharSprite.WARNING + : CharSprite.NEGATIVE, Integer.toString(dmg)); + } + + if (HP <= 0 || HT <= 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 && HT > 0; + } + + @Override + protected void spend(float time) { + + float timeScale = 1f; + if (buff(Slow.class) != null) { + timeScale *= 0.67f; + } else if (buff( Chill.class ) != null) { + timeScale *= buff( Chill.class ).speedFactor(); + } + if (buff(Speed.class) != null) { + timeScale *= 1.5f; + } + /*if (buff(Haste.class) != null) { + timeScale *= 1.5f; + }*/ + if (buff(Cold.class) != null) { + timeScale *= 0.9f; + } + + if (buff(Tar.class) != null) { + timeScale *= 0.8f; + } + if (buff(Burning.class) != null) { + timeScale *= 1.25f; + } + + if (buff(Rhythm2.class) != null) { + timeScale *= 1.2f; + } + + super.spend(time / timeScale); + } + + public HashSet buffs() { + return buffs; + } + + @SuppressWarnings("unchecked") + public HashSet buffs(Class c) { + HashSet filtered = new HashSet(); + for (Buff b : buffs) { + if (c.isInstance(b)) { + filtered.add((T) b); + } + } + return filtered; + } + + @SuppressWarnings("unchecked") + public T buff(Class c) { + for (Buff b : buffs) { + if (c.isInstance(b)) { + return (T) b; + } + } + return null; + } + + public boolean isCharmedBy(Char ch) { + int chID = ch.id(); + for (Buff b : buffs) { + if (b instanceof Charm && ((Charm) b).object == chID) { + return true; + } + } + return false; + } + + public void add(Buff buff) { + + buffs.add(buff); + Actor.add(buff); + + if (sprite != null) + switch(buff.type){ + case POSITIVE: + sprite.showStatus(CharSprite.POSITIVE, buff.toString()); break; + case NEGATIVE: + sprite.showStatus(CharSprite.NEGATIVE, buff.toString());break; + case NEUTRAL: + sprite.showStatus(CharSprite.NEUTRAL, buff.toString()); break; + case SILENT: default: + break; //show nothing + } + + } + + public void remove(Buff buff) { + + buffs.remove(buff); + Actor.remove(buff); + + + } + + public void remove(Class buffClass) { + for (Buff buff : buffs(buffClass)) { + remove(buff); + } + } + + @Override + protected void onRemove() { + for (Buff buff : buffs.toArray(new Buff[buffs.size()])) { + 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 + || buff instanceof CloakOfShadows.cloakStealth) { + sprite.add(CharSprite.State.INVISIBLE); + } else if (buff instanceof Stun || buff instanceof Shieldblock) { + 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); + }*/ + buff.fx( true ); + } + } + + public int stealth() { + return 0; + } + + public int energybase() { + return 0; + } + + public void move(int step) { + + if (Level.adjacent(step, pos) && buff(Vertigo.class) != null) { + step = pos + Level.NEIGHBOURS8[Random.Int(8)]; + if (!(Level.passable[step] || Level.avoid[step]) + || Actor.findChar(step) != null) + return; + } + + 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> EMPTY = new HashSet>(); + + public HashSet> resistances() { + return EMPTY; + } + + public HashSet> immunities() { + return EMPTY; + } + + public HashSet> weakness() { + return EMPTY; + } + + //protected final HashSet resistances = new HashSet<>(); + + //returns percent effectiveness after resistances + //TODO currently resistances reduce effectiveness by a static 50%, and do not stack. + //public float resist( Class effect ){ + //HashSet resists = new HashSet<>(resistances); + // for (Property p : properties()){ + // resists.addAll(p.resistances()); + // } + // for (Buff b : buffs()){ + // resists.addAll(b.resistances()); + // } + + // float result = 1f; + // for (Class c : resists){ + // if (c.isAssignableFrom(effect)){ + // result *= 0.5f; + // } + // } + // return result * RingOfElements.restore(this, effect); + //} + + //protected final HashSet immunities = new HashSet<>(); + + //public boolean isImmune(Class effect ){ + //HashSet immunes = new HashSet<>(immunities); + //for (Property p : properties()){ + //immunes.addAll(p.immunities()); + //} + //for (Buff b : buffs()){ + //immunes.addAll(b.immunities()); + //} + + //for (Class c : immunes){ + //if (c.isAssignableFrom(effect)){ + // return true; + //} + // } + //return false; + //} + + protected HashSet properties = new HashSet<>(); + + public HashSet properties() { return properties; } + + public enum Property{ + BOSS, + MINIBOSS, + IMMOVABLE, + + HUMAN, + ORC, + ELF, + //GNOLL, + DWARF, + TROLL, + DEMONIC, + GOBLIN, + + BEAST, + DRAGON, + PLANT( new HashSet(), + new HashSet( Arrays.asList(Bleeding.class, ToxicGas.class, Poison.class)), + new HashSet( Arrays.asList(Burning.class, WandOfFirebolt.class,EnchantmentFire.class,EnchantmentFire2.class)) + ), + ELEMENT, + + MECH, + UNDEAD, + ALIEN, + UNKNOW; + + private HashSet resistances; + private HashSet immunities; + private HashSet weakness; + + Property(){ + this(new HashSet(), new HashSet(),new HashSet()); + } + + Property( HashSet resistances, HashSet immunities,HashSet weakness){ + this.resistances = resistances; + this.immunities = immunities; + this.weakness = weakness; + } + + public HashSet resistances(){ + return new HashSet<>(resistances); + } + + public HashSet immunities(){ + return new HashSet<>(immunities); + } + public HashSet weakness(){ + return new HashSet<>(weakness); + } + } +} diff --git a/java/com/hmdzl/spspd/actors/animate/WeaponAnimate.java b/java/com/hmdzl/spspd/actors/animate/WeaponAnimate.java new file mode 100644 index 00000000..cb1afa61 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/animate/WeaponAnimate.java @@ -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 + */ +package com.hmdzl.spspd.actors.animate; + +import java.text.DecimalFormat; +import java.util.HashSet; + +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.ui.BuffIndicator; + +public class WeaponAnimate extends Actor { + + @Override + public boolean act() { + return true; + } + + +} diff --git a/java/com/hmdzl/spspd/actors/blobs/Alchemy.java b/java/com/hmdzl/spspd/actors/blobs/Alchemy.java new file mode 100644 index 00000000..0a62e805 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/blobs/Alchemy.java @@ -0,0 +1,74 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.blobs; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.Journal; +import com.hmdzl.spspd.effects.BlobEmitter; +import com.hmdzl.spspd.effects.Speck; +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); + } +} diff --git a/java/com/hmdzl/spspd/actors/blobs/Alter.java b/java/com/hmdzl/spspd/actors/blobs/Alter.java new file mode 100644 index 00000000..f7810c1f --- /dev/null +++ b/java/com/hmdzl/spspd/actors/blobs/Alter.java @@ -0,0 +1,71 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2014 Oleg Dolya + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.actors.blobs; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.effects.BlobEmitter; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.Heap; +import com.hmdzl.spspd.items.weapon.Weapon; +import com.watabou.utils.Bundle; + +public class Alter 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]; + } + + @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) { + + Weapon result = heap.consecrate(); + 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.LIGHT), 0.4f, 0); + } +} diff --git a/java/com/hmdzl/spspd/actors/blobs/Blob.java b/java/com/hmdzl/spspd/actors/blobs/Blob.java new file mode 100644 index 00000000..45bd4b03 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/blobs/Blob.java @@ -0,0 +1,213 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.blobs; + +import java.util.Arrays; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.ShatteredPixelDungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.effects.BlobEmitter; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.utils.BArray; +import com.watabou.utils.Bundle; + +public class Blob extends Actor { + + public static final int WIDTH = Level.getWidth(); + public static final int HEIGHT = Level.HEIGHT; + public static final int LENGTH = Level.getLength(); + + 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.getLength()]; + Arrays.fill(cur, 0); + + int loadedMapSize = Level.loadedMapSize; + for (int i = 0; i < loadedMapSize; i++) { + System.arraycopy(this.cur, i * loadedMapSize, cur, i + * Level.getWidth(), 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 seed(int cell, int amount, Class 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; + } + } +} diff --git a/java/com/hmdzl/spspd/actors/blobs/ConfusionGas.java b/java/com/hmdzl/spspd/actors/blobs/ConfusionGas.java new file mode 100644 index 00000000..a8567148 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/blobs/ConfusionGas.java @@ -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 + */ +package com.hmdzl.spspd.actors.blobs; + +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Locked; +import com.hmdzl.spspd.actors.buffs.Vertigo; +import com.hmdzl.spspd.effects.BlobEmitter; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.messages.Messages; + +public class ConfusionGas 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) { + if (!ch.immunities().contains(this.getClass())) + Buff.prolong(ch, Vertigo.class, 2); + Buff.prolong(ch, Locked.class,2f); + } + } + } + + @Override + public void use(BlobEmitter emitter) { + super.use(emitter); + + emitter.pour(Speck.factory(Speck.CONFUSION), 0.6f); + } + + @Override + public String tileDesc() { + return Messages.get(this, "desc"); + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/blobs/CorruptGas.java b/java/com/hmdzl/spspd/actors/blobs/CorruptGas.java new file mode 100644 index 00000000..29617023 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/blobs/CorruptGas.java @@ -0,0 +1,84 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.blobs; + +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Bleeding; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Cripple; +import com.hmdzl.spspd.actors.buffs.Vertigo; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.BlobEmitter; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.messages.Messages; +import com.watabou.utils.Random; + +public class CorruptGas extends Blob implements Hero.Doom { + + @Override + protected void evolve() { + super.evolve(); + + int levelDamage = 5 + Dungeon.depth/2; + int bleedDamage = 5 + Dungeon.depth/2; + + Char ch; + for (int i = 0; i < LENGTH; i++) { + if (cur[i] > 0 && (ch = Actor.findChar(i)) != null) { + + if (!ch.immunities().contains(ConfusionGas.class)){ + Buff.prolong(ch, Vertigo.class, 2); + } + + if (!ch.immunities().contains(this.getClass())){ + Buff.affect(ch, Bleeding.class).set(bleedDamage); + Buff.prolong(ch, Cripple.class, Cripple.DURATION); + + int damage = (ch.HT/2 + levelDamage) / 40; + if (Random.Int(40) < (ch.HT/2 + levelDamage) % 40) { + damage++; + } + + ch.damage(damage, this); + } + } + } + } + + @Override + public void use(BlobEmitter emitter) { + super.use(emitter); + + emitter.pour(Speck.factory(Speck.CORRUPT), 0.6f); + } + + @Override + public String tileDesc() { + return Messages.get(this, "desc"); + } + + @Override + public void onDeath() { + + Badges.validateDeathFromGas(); + + } +} diff --git a/java/com/hmdzl/spspd/actors/blobs/DarkGas.java b/java/com/hmdzl/spspd/actors/blobs/DarkGas.java new file mode 100644 index 00000000..8c2a1e5b --- /dev/null +++ b/java/com/hmdzl/spspd/actors/blobs/DarkGas.java @@ -0,0 +1,54 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.blobs; + +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Blindness; +import com.hmdzl.spspd.effects.BlobEmitter; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.messages.Messages; + +public class DarkGas 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) { + if (!ch.immunities().contains(this.getClass())) + Buff.prolong(ch, Blindness.class, 2); + } + } + } + + @Override + public void use(BlobEmitter emitter) { + super.use(emitter); + + emitter.pour(Speck.factory(Speck.DARKNESS), 0.6f); + } + + @Override + public String tileDesc() { + return Messages.get(this, "desc"); + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/blobs/ElectriShock.java b/java/com/hmdzl/spspd/actors/blobs/ElectriShock.java new file mode 100644 index 00000000..ccae19b7 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/blobs/ElectriShock.java @@ -0,0 +1,104 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.blobs; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.ResultDescriptions; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Paralysis; +import com.hmdzl.spspd.effects.BlobEmitter; +import com.hmdzl.spspd.effects.particles.EnergyParticle; +import com.hmdzl.spspd.items.Heap; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.messages.Messages; +import com.watabou.utils.Random; + +public class ElectriShock extends Blob { + + @Override + protected void evolve() { + + //boolean[] shockable = Level.shockable; + + int from = WIDTH + 1; + int to = Level.getLength() - WIDTH - 1; + + + for (int pos = from; pos < to; pos++) { + + int shock; + boolean shelf = false; + + if (cur[pos] > 0) { + + shocking(pos); + + shock = cur[pos] - 1; + + if (shock <= 0){ } + } else { + shock = 0; + } + + volume += (off[pos] = shock); + } + + } + + private void shocking(int pos) { + Char ch = Actor.findChar(pos); + if (ch != null ) { + //Buff.detach(ch,Corruption.class); + ch.damage( Math.max( 1, Random.Int( ch.HP / 100, ch.HP / 50 ) ), this ); + Buff.prolong(ch, Paralysis.class,1f); + + } + Heap heap = Dungeon.level.heaps.get(pos); + if (heap != null) { + heap.lit(); + } + + } + + @Override + public void seed(int cell, int amount) { + if (cur[cell] == 0) { + volume += amount; + cur[cell] = amount; + /*} else { + volume += amount - cur[cell]; + cur[cell] = amount;*/ + } + } + + @Override + public void use(BlobEmitter emitter) { + super.use(emitter); + emitter.start(EnergyParticle.FACTORY, 0.03f, 0); + } + @Override + public String tileDesc() { + return Messages.get(this, "desc"); + } + + public void onDeath() { + Dungeon.fail(Messages.format(ResultDescriptions.GAS)); + } +} diff --git a/java/com/hmdzl/spspd/actors/blobs/Fire.java b/java/com/hmdzl/spspd/actors/blobs/Fire.java new file mode 100644 index 00000000..2af6160e --- /dev/null +++ b/java/com/hmdzl/spspd/actors/blobs/Fire.java @@ -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 + */ +package com.hmdzl.spspd.actors.blobs; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Burning; +import com.hmdzl.spspd.effects.BlobEmitter; +import com.hmdzl.spspd.effects.particles.FlameParticle; +import com.hmdzl.spspd.items.Heap; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.Terrain; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.items.Generator; +import com.watabou.utils.Random; + +public class Fire extends Blob { + + @Override + protected void evolve() { + + boolean[] flamable = Level.flamable; + + int from = WIDTH + 1; + int to = Level.getLength() - WIDTH - 1; + + boolean observe = false; + + for (int pos = from; pos < to; pos++) { + + int fire; + boolean shelf = false; + + Blob blob = Dungeon.level.blobs.get( TarGas.class ); + + if (blob != null) { + + int par[] = blob.cur; + + for (int i=0; i < LENGTH; i++) { + + if (cur[i] > 0) { + blob.volume -= par[i]; + par[i] = 0; + } + } + } + + if (cur[pos] > 0) { + + burn(pos); + + fire = cur[pos] - 1; + if (fire <= 0 && flamable[pos]) { + + if(Dungeon.level.map[pos]==Terrain.BOOKSHELF){ + shelf=true; + } + + int oldTile = Dungeon.level.map[pos]; + Level.set(pos, Terrain.EMBERS); + + if (shelf && Random.Float()<.10){ + Dungeon.level.drop(Generator.random(Generator.Category.SCROLL), pos); + } + + 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(); + } + + if( Dungeon.level.map[pos] == Terrain.SECRET_DOOR) { + + GameScene.discoverTile( pos, Dungeon.level.map[pos] ); + + Level.set( pos, Terrain.DOOR); + + GameScene.updateMap( pos ); + } + } + + @Override + public void seed(int cell, int amount) { + if (cur[cell] == 0) { + volume += amount; + cur[cell] = amount; + /*} else { + volume += amount - cur[cell]; + cur[cell] = amount;*/ + } + } + + @Override + public void use(BlobEmitter emitter) { + super.use(emitter); + emitter.start(FlameParticle.FACTORY, 0.1f, 0); + } + @Override + public String tileDesc() { + return Messages.get(this, "desc"); + } +} diff --git a/java/com/hmdzl/spspd/actors/blobs/Foliage.java b/java/com/hmdzl/spspd/actors/blobs/Foliage.java new file mode 100644 index 00000000..13e39f45 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/blobs/Foliage.java @@ -0,0 +1,87 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.blobs; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.Journal; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Shadows; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.BlobEmitter; +import com.hmdzl.spspd.effects.particles.ShaftParticle; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.Terrain; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.GameScene; + +public class Foliage extends Blob { + + @Override + protected void evolve() { + + int from = WIDTH + 1; + int to = Level.getLength() - 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 Messages.get(this, "desc"); + } +} diff --git a/java/com/hmdzl/spspd/actors/blobs/Freezing.java b/java/com/hmdzl/spspd/actors/blobs/Freezing.java new file mode 100644 index 00000000..f49bf2cc --- /dev/null +++ b/java/com/hmdzl/spspd/actors/blobs/Freezing.java @@ -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 + */ +package com.hmdzl.spspd.actors.blobs; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Frost; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.particles.SnowParticle; +import com.hmdzl.spspd.items.Heap; +import com.hmdzl.spspd.levels.Level; +import com.watabou.utils.Random; + +public class Freezing { + + // Returns true, if this cell is visible + public static boolean affect(int cell, Fire fire) { + + Char ch = Actor.findChar(cell); + if (ch != null) { + if (Level.water[ch.pos]) { + Buff.prolong(ch, Frost.class, + Frost.duration(ch) * Random.Float(5f, 7.5f)); + } else { + 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); + return true; + } else { + return false; + } + } +} diff --git a/java/com/hmdzl/spspd/actors/blobs/FrostGas.java b/java/com/hmdzl/spspd/actors/blobs/FrostGas.java new file mode 100644 index 00000000..428c3b9d --- /dev/null +++ b/java/com/hmdzl/spspd/actors/blobs/FrostGas.java @@ -0,0 +1,99 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.blobs; + +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Chill; +import com.hmdzl.spspd.actors.buffs.Frost; +import com.hmdzl.spspd.effects.BlobEmitter; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.effects.particles.SnowParticle; +import com.hmdzl.spspd.items.Heap; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.messages.Messages; + +public class FrostGas extends Blob { + + @Override + protected void evolve() { + + int from = WIDTH + 1; + int to = Level.getLength() - WIDTH - 1; + + for (int pos = from; pos < to; pos++) { + + int ice; + + + if (cur[pos] > 0) { + + ice(pos); + + ice = cur[pos] - 1; + if (ice <= 0){ } + } else { + ice = 0; + } + + volume += (off[pos] = ice); + + } + + } + + private void ice(int pos) { + Char ch = Actor.findChar( pos ); + if (ch != null && !ch.immunities().contains(this.getClass())) { + if (ch.buff(Frost.class) != null){ + Buff.affect(ch, Frost.class, 2f); + } else { + Buff.affect(ch, Chill.class, 3f); + Chill chill = ch.buff(Chill.class); + if (chill != null && chill.cooldown() >= 10f){ + Buff.affect(ch, Frost.class, 5f); + } + } + } + + Heap heap = Dungeon.level.heaps.get( pos ); + if (heap != null) heap.freeze(); + } + + @Override + public void seed(int cell, int amount) { + if (cur[cell] == 0) { + volume += amount; + cur[cell] = amount; + /*} else { + volume += amount - cur[cell]; + cur[cell] = amount;*/ + } + } + + @Override + public void use(BlobEmitter emitter) { + super.use(emitter); + emitter.start(SnowParticle.FACTORY, 0.05f, 0); + } + @Override + public String tileDesc() { + return Messages.get(this, "desc"); + } +} diff --git a/java/com/hmdzl/spspd/actors/blobs/GooWarn.java b/java/com/hmdzl/spspd/actors/blobs/GooWarn.java new file mode 100644 index 00000000..f6100a9d --- /dev/null +++ b/java/com/hmdzl/spspd/actors/blobs/GooWarn.java @@ -0,0 +1,53 @@ +package com.hmdzl.spspd.actors.blobs; + +import com.hmdzl.spspd.effects.BlobEmitter; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.GooSprite; + +/** + * Created by Evan on 29/09/2014. + */ +public class GooWarn extends Blob { + + // cosmetic blob, used to warn noobs that goo's pump up should, infact, be + // avoided. + + // Thanks to Watabou for the much better particle effect, I was lazy and + // just re-colored flames initially + + protected int pos; + + @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; + } + } + + } + + @Override + public void seed(int cell, int amount) { + int diff = amount - cur[cell]; + if (diff > 0) { + cur[cell] = amount; + volume += diff; + } + } + + @Override + public void use(BlobEmitter emitter) { + super.use(emitter); + emitter.pour(GooSprite.GooParticle.FACTORY, 0.03f); + } + + @Override + public String tileDesc() { + return Messages.get(this, "desc"); + } +} diff --git a/java/com/hmdzl/spspd/actors/blobs/HealLight.java b/java/com/hmdzl/spspd/actors/blobs/HealLight.java new file mode 100644 index 00000000..c91e679b --- /dev/null +++ b/java/com/hmdzl/spspd/actors/blobs/HealLight.java @@ -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 + */ + +package com.hmdzl.spspd.actors.blobs; + +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.effects.BlobEmitter; +import com.hmdzl.spspd.effects.particles.ShaftParticle; + +public class HealLight extends Blob implements Hero.Doom{ + + @Override + protected void evolve() { + + super.evolve(); + + Char ch; + for (int i = 0; i < LENGTH; i++) { + if (cur[i] > 0 && (ch = Actor.findChar(i)) != null) { + if (ch.HP + */ +package com.hmdzl.spspd.actors.blobs; + +import com.hmdzl.spspd.effects.particles.MemoryParticle; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.LoadSaveScene; +import com.watabou.noosa.Game; +import com.watabou.noosa.audio.Sample; +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.Journal; +import com.hmdzl.spspd.Journal.Feature; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.effects.BlobEmitter; +import com.watabou.utils.Bundle; + +import java.io.IOException; + +public class MemoryFire 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]; + Char ch = Actor.findChar( pos ); + MemoryFire fire = (MemoryFire)Dungeon.level.blobs.get( MemoryFire.class ); + if (ch != null && ch == Dungeon.hero) { + if (Dungeon.visible[pos]) { + Sample.INSTANCE.play( Assets.SND_BURNING ); + fire.seed( fire.pos, 0 ); + Journal.remove( Feature.MEMORY_FIRE ); + try { + Dungeon.saveAll(); + } catch (IOException e) { + // + } + Dungeon.canSave=true; + Game.switchScene(LoadSaveScene.class); + //GameScene.show(new WndMemory()); + } + } + if (Dungeon.visible[pos]) { + Journal.add( Feature.MEMORY_FIRE ); + } + } + + @Override + public void seed( int cell, int amount ) { + cur[pos] = 0; + pos = cell; + volume = cur[pos] = amount; + } + + @Override + public void use( BlobEmitter emitter ) { + super.use( emitter ); + + emitter.pour( MemoryParticle.FACTORY, 0.04f ); + } + + @Override + public String tileDesc() { + return Messages.get(this, "desc"); + } + + + /*public class WndMemory extends Window { + + private static final int WIDTH = 120; + private static final int MARGIN = 2; + private static final int BUTTON_WIDTH = WIDTH - MARGIN * 2; + private static final int BUTTON_HEIGHT = 20; + + public WndMemory() { + super(); + + IconTitle titlebar = new IconTitle(); + titlebar.setRect(0, 0, WIDTH, 0); + add(titlebar); + + RenderedTextMultiline tfMesage = PixelScene.renderMultiline( Messages.get(this, "SorN"), 8 ); + tfMesage.maxWidth(WIDTH - MARGIN * 2); + tfMesage.setPos(MARGIN, titlebar.bottom() + MARGIN); + add( tfMesage ); + + RedButton btnSave = new RedButton(Messages.get(MemoryFire.class,"save")) { + @Override + protected void onClick() { + Game.switchScene(LoadSaveScene.class); + } + }; + btnSave.setRect(MARGIN, pos + MARGIN, BUTTON_WIDTH, + BUTTON_HEIGHT); + add( btnSave ); + + RedButton btnNosave = new RedButton(Messages.get(MemoryFire.class,"no_save")) { + @Override + protected void onClick() { + hide(); + } + }; + btnNosave.setRect(MARGIN, pos + MARGIN, BUTTON_WIDTH, BUTTON_HEIGHT); + add(btnNosave); + + resize(WIDTH, (int) btnNosave.bottom()); + } + }*/ + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/blobs/ParalyticGas.java b/java/com/hmdzl/spspd/actors/blobs/ParalyticGas.java new file mode 100644 index 00000000..1d873705 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/blobs/ParalyticGas.java @@ -0,0 +1,54 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.blobs; + +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Paralysis; +import com.hmdzl.spspd.effects.BlobEmitter; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.messages.Messages; + +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) { + if (!ch.immunities().contains(this.getClass())) + 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 Messages.get(this, "desc"); + } +} diff --git a/java/com/hmdzl/spspd/actors/blobs/Portal.java b/java/com/hmdzl/spspd/actors/blobs/Portal.java new file mode 100644 index 00000000..80097983 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/blobs/Portal.java @@ -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 + */ +package com.hmdzl.spspd.actors.blobs; + +import com.hmdzl.spspd.effects.BlobEmitter; +import com.hmdzl.spspd.effects.particles.ShaftParticle; +import com.watabou.utils.Bundle; + +public class Portal 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]; + } + + @Override + public void seed(int cell, int amount) { + cur[pos] = 0; + pos = cell; + volume = cur[pos] = amount; + } + + + @Override + public void use(BlobEmitter emitter) { + super.use(emitter); + emitter.start(ShaftParticle.FACTORY, 0.9f, 0); + } +} diff --git a/java/com/hmdzl/spspd/actors/blobs/Regrowth.java b/java/com/hmdzl/spspd/actors/blobs/Regrowth.java new file mode 100644 index 00000000..66634c1c --- /dev/null +++ b/java/com/hmdzl/spspd/actors/blobs/Regrowth.java @@ -0,0 +1,78 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.blobs; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Roots; +import com.hmdzl.spspd.effects.BlobEmitter; +import com.hmdzl.spspd.effects.particles.LeafParticle; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.Terrain; +import com.hmdzl.spspd.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); + } +} diff --git a/java/com/hmdzl/spspd/actors/blobs/ShockWeb.java b/java/com/hmdzl/spspd/actors/blobs/ShockWeb.java new file mode 100644 index 00000000..d73f6946 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/blobs/ShockWeb.java @@ -0,0 +1,72 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.blobs; + +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Roots; +import com.hmdzl.spspd.effects.BlobEmitter; +import com.hmdzl.spspd.effects.particles.ShockWebParticle; +import com.hmdzl.spspd.messages.Messages; + +public class ShockWeb 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) { + int damage = 5; + ch.damage(damage, this); + Buff.prolong(ch, Roots.class, TICK); + } + } + } + } + + @Override + public void use(BlobEmitter emitter) { + super.use(emitter); + + emitter.pour(ShockWebParticle.FACTORY, 0.4f); + } + + @Override + 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 Messages.get(this, "desc"); + } +} diff --git a/java/com/hmdzl/spspd/actors/blobs/SlowWeb.java b/java/com/hmdzl/spspd/actors/blobs/SlowWeb.java new file mode 100644 index 00000000..d6f1b993 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/blobs/SlowWeb.java @@ -0,0 +1,71 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2014 Oleg Dolya + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.actors.blobs; + +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Roots; +import com.hmdzl.spspd.actors.buffs.Slow; +import com.hmdzl.spspd.effects.BlobEmitter; +import com.hmdzl.spspd.effects.particles.WebParticle; +import com.hmdzl.spspd.messages.Messages; + +public class SlowWeb 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, Slow.class, TICK); + } + } + } + } + + @Override + public void use(BlobEmitter emitter) { + super.use(emitter); + + emitter.pour(WebParticle.FACTORY, 0.4f); + } + + @Override + 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 Messages.get(this, "desc"); + } +} diff --git a/java/com/hmdzl/spspd/actors/blobs/StenchGas.java b/java/com/hmdzl/spspd/actors/blobs/StenchGas.java new file mode 100644 index 00000000..0a7a6503 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/blobs/StenchGas.java @@ -0,0 +1,40 @@ +package com.hmdzl.spspd.actors.blobs; + +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Ooze; +import com.hmdzl.spspd.effects.BlobEmitter; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.messages.Messages; + +/** + * Created by debenhame on 08/10/2014. + */ +public class StenchGas 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) { + if (!ch.immunities().contains(this.getClass())) + Buff.affect(ch, Ooze.class); + } + } + } + + @Override + public void use(BlobEmitter emitter) { + super.use(emitter); + + emitter.pour(Speck.factory(Speck.STENCH), 0.6f); + } + + @Override + public String tileDesc() { + return Messages.get(this, "desc"); + } +} diff --git a/java/com/hmdzl/spspd/actors/blobs/TarGas.java b/java/com/hmdzl/spspd/actors/blobs/TarGas.java new file mode 100644 index 00000000..3b80b08b --- /dev/null +++ b/java/com/hmdzl/spspd/actors/blobs/TarGas.java @@ -0,0 +1,85 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.blobs; + +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Burning; +import com.hmdzl.spspd.effects.BlobEmitter; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.buffs.Tar; +import com.hmdzl.spspd.messages.Messages; +import com.watabou.utils.Random; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.scenes.GameScene; + + +public class TarGas 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) { + if (!ch.immunities().contains(this.getClass())) + Buff.affect(ch,Tar.class); + if ( ch.buff( Burning.class ) != null ) {GameScene.add(Blob.seed(ch.pos, 2, Fire.class)); + } + } + } + + Blob blob = Dungeon.level.blobs.get( Fire.class ); + if (blob != null) { + + for (int pos=0; pos < LENGTH; pos++) { + + if ( cur[pos] > 0 && blob.cur[ pos ] < 2 ) { + + int flammability = 0; + + for (int n : Level.NEIGHBOURS8) { + if ( blob.cur[ pos + n ] > 0 ) { + flammability++; + } + } + if( Random.Int( 4 ) < flammability ) { + blob.volume += ( blob.cur[ pos ] = 2 ); + volume -= ( cur[pos] / 2 ); + cur[pos] -=( cur[pos] / 2 ); + } + } + } + } + } + + @Override + public void use(BlobEmitter emitter) { + super.use(emitter); + + emitter.pour(Speck.factory(Speck.TARGAS,true ), 0.6f); + } + + @Override + public String tileDesc() { + return Messages.get(this, "desc"); + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/blobs/ToxicGas.java b/java/com/hmdzl/spspd/actors/blobs/ToxicGas.java new file mode 100644 index 00000000..a9163512 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/blobs/ToxicGas.java @@ -0,0 +1,73 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.blobs; + +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.ResultDescriptions; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.BlobEmitter; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.messages.Messages; +import com.watabou.utils.Random; + +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 (Random.Int(40) < (ch.HT + levelDamage) % 40) { + damage++; + } + + ch.damage(damage, this); + } + } + } + + @Override + public void use(BlobEmitter emitter) { + super.use(emitter); + + emitter.pour(Speck.factory(Speck.TOXIC), 0.6f); + } + + @Override + public String tileDesc() { + return Messages.get(this, "desc"); + } + + @Override + public void onDeath() { + + Badges.validateDeathFromGas(); + + Dungeon.fail(Messages.format(ResultDescriptions.GAS)); + //GLog.n("You died from a toxic gas.."); + } +} diff --git a/java/com/hmdzl/spspd/actors/blobs/VenomGas.java b/java/com/hmdzl/spspd/actors/blobs/VenomGas.java new file mode 100644 index 00000000..6deeb651 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/blobs/VenomGas.java @@ -0,0 +1,83 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2015 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.actors.blobs; + +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Venom; +import com.hmdzl.spspd.effects.BlobEmitter; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.messages.Messages; +import com.watabou.utils.Bundle; + +public class VenomGas extends Blob { + + private int strength = 0; + + @Override + protected void evolve() { + super.evolve(); + + if (volume == 0){ + strength = 0; + } else { + Char ch; + for (int i = 0; i < LENGTH; i++) { + if (cur[i] > 0 && (ch = Actor.findChar(i)) != null) { + if (!ch.immunities().contains(this.getClass())) + Buff.affect(ch, Venom.class).set(2f, strength); + } + } + } + } + + public void setStrength(int str){ + if (str > strength) + strength = str; + } + + private static final String STRENGTH = "strength"; + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + strength = bundle.getInt( STRENGTH ); + } + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put( STRENGTH, strength ); + } + + @Override + public void use( BlobEmitter emitter ) { + super.use( emitter ); + + emitter.pour( Speck.factory(Speck.VENOM), 0.6f ); + } + + @Override + public String tileDesc() { + return Messages.get(this, "desc"); + } +} diff --git a/java/com/hmdzl/spspd/actors/blobs/Water.java b/java/com/hmdzl/spspd/actors/blobs/Water.java new file mode 100644 index 00000000..a0c788ec --- /dev/null +++ b/java/com/hmdzl/spspd/actors/blobs/Water.java @@ -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 + */ +package com.hmdzl.spspd.actors.blobs; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.effects.BlobEmitter; +import com.hmdzl.spspd.effects.particles.LeafParticle; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.Terrain; +import com.hmdzl.spspd.scenes.GameScene; + +public class Water 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; + + } + + } + } + + if (mapUpdated) { + GameScene.updateMap(); + Dungeon.observe(); + } + } + } + + @Override + public void use(BlobEmitter emitter) { + super.use(emitter); + + emitter.start(LeafParticle.LEVEL_SPECIFIC, 0.2f, 0); + } +} diff --git a/java/com/hmdzl/spspd/actors/blobs/WaterOfAwareness.java b/java/com/hmdzl/spspd/actors/blobs/WaterOfAwareness.java new file mode 100644 index 00000000..e96a8335 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/blobs/WaterOfAwareness.java @@ -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 + */ +package com.hmdzl.spspd.actors.blobs; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.DungeonTilemap; +import com.hmdzl.spspd.Journal; +import com.hmdzl.spspd.Journal.Feature; +import com.hmdzl.spspd.actors.buffs.Awareness; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.BlobEmitter; +import com.hmdzl.spspd.effects.Identification; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.Terrain; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.noosa.audio.Sample; + +public class WaterOfAwareness extends WellWater { + + @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.getLength(); i++) { + + int terr = Dungeon.level.map[i]; + if ((Terrain.flags[terr] & Terrain.SECRET) != 0) { + + //Level.set(i, Terrain.discover(terr)); + //GameScene.updateMap(i); + Dungeon.level.discover( i ); + + if (Dungeon.visible[i]) { + GameScene.discoverTile(i, terr); + } + } + } + + Buff.affect(hero, Awareness.class, Awareness.DURATION); + Dungeon.observe(); + + Dungeon.hero.interrupt(); + + GLog.p( Messages.get(this, "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 Messages.get(this, "desc"); + } +} diff --git a/java/com/hmdzl/spspd/actors/blobs/WaterOfHealth.java b/java/com/hmdzl/spspd/actors/blobs/WaterOfHealth.java new file mode 100644 index 00000000..f08116a2 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/blobs/WaterOfHealth.java @@ -0,0 +1,80 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.blobs; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.Journal; +import com.hmdzl.spspd.Journal.Feature; +import com.hmdzl.spspd.actors.buffs.Hunger; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.BlobEmitter; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.effects.particles.ShaftParticle; +import com.hmdzl.spspd.items.DewVial; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.potions.PotionOfHealing; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.noosa.audio.Sample; + +public class WaterOfHealth extends WellWater { + + @Override + protected boolean affectHero(Hero hero) { + + Sample.INSTANCE.play(Assets.SND_DRINK); + + PotionOfHealing.heal(hero); + hero.belongings.uncurseEquipped(); + hero.buff(Hunger.class).satisfy(Hunger.STARVING); + + CellEmitter.get(pos).start(ShaftParticle.FACTORY, 0.2f, 3); + + Dungeon.hero.interrupt(); + + GLog.p( Messages.get(this, "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(); + Journal.remove(Feature.WELL_OF_HEALTH); + return item; + } + Journal.remove(Feature.WELL_OF_HEALTH); + 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 Messages.get(this, "desc"); + } +} diff --git a/java/com/hmdzl/spspd/actors/blobs/WaterOfTransmutation.java b/java/com/hmdzl/spspd/actors/blobs/WaterOfTransmutation.java new file mode 100644 index 00000000..b43d69f2 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/blobs/WaterOfTransmutation.java @@ -0,0 +1,229 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.blobs; + +import com.hmdzl.spspd.Journal; +import com.hmdzl.spspd.Journal.Feature; +import com.hmdzl.spspd.effects.BlobEmitter; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.items.Generator.Category; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.artifacts.Artifact; +import com.hmdzl.spspd.items.potions.Potion; +import com.hmdzl.spspd.items.potions.PotionOfHealing; +import com.hmdzl.spspd.items.potions.PotionOfMending; +import com.hmdzl.spspd.items.potions.PotionOfMight; +import com.hmdzl.spspd.items.potions.PotionOfStrength; +import com.hmdzl.spspd.items.rings.Ring; +import com.hmdzl.spspd.items.scrolls.Scroll; +import com.hmdzl.spspd.items.scrolls.ScrollOfMagicalInfusion; +import com.hmdzl.spspd.items.scrolls.ScrollOfUpgrade; +import com.hmdzl.spspd.items.wands.Wand; +import com.hmdzl.spspd.items.armor.Armor; +import com.hmdzl.spspd.items.weapon.melee.MeleeWeapon; +import com.hmdzl.spspd.messages.Messages; + +public class WaterOfTransmutation extends WellWater { + + @Override + protected Item affectItem(Item item) { + + if (item instanceof MeleeWeapon) { + item = changeWeapon((MeleeWeapon) item); + } else if (item instanceof Armor) { + item = changeArmor((Armor) item); + } else if (item instanceof Scroll) { + item = changeScroll((Scroll) item); + } else if (item instanceof Potion) { + item = changePotion((Potion) item); + } else if (item instanceof Ring) { + item = changeRing((Ring) item); + } else if (item instanceof Wand) { + item = changeWand((Wand) item); + } else if (item instanceof Artifact) { + item = changeArtifact((Artifact) item); + } else { + item = null; + } + + if (item != null) { + Journal.remove(Feature.WELL_OF_TRANSMUTATION); + } + + return item; + + } + + @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; + do { + n = (MeleeWeapon) Generator.random(Category.MELEEWEAPON); + } while (n.getClass() == w.getClass()); + + n.level = 0; + + int level = w.level; + if (level > 0) { + n.upgrade(level); + } else if (level < 0) { + n.degrade(-level); + } + + n.enchantment = w.enchantment; + n.reinforced = w.reinforced; + n.levelKnown = w.levelKnown; + n.cursedKnown = w.cursedKnown; + n.cursed = w.cursed; + + return n; + + } + + private Armor changeArmor(Armor r) { + Armor n; + do { + n = (Armor) Generator.random(Category.ARMOR); + } 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.glyph = r.glyph; + n.reinforced = r.reinforced; + n.levelKnown = r.levelKnown; + n.cursedKnown = r.cursedKnown; + n.cursed = r.cursed; + + return n; + } + + + 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.reinforced = r.reinforced; + n.levelKnown = r.levelKnown; + n.cursedKnown = r.cursedKnown; + n.cursed = r.cursed; + + return n; + } + + private Artifact changeArtifact(Artifact a) { + Artifact n ; + do { + n = (Artifact) Generator.random(Category.ARTIFACT); + } while (n.getClass() == a.getClass()); + + if (n != null) { + n.cursedKnown = a.cursedKnown; + n.cursed = a.cursed; + n.levelKnown = a.levelKnown; + n.transferUpgrade(a.visiblyUpgraded()); + } + + 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.updateLevel(); + n.upgrade(w.level); + + n.reinforced = w.reinforced; + n.levelKnown = w.levelKnown; + n.cursedKnown = w.cursedKnown; + n.cursed = w.cursed; + + return n; + } + + private Scroll changeScroll(Scroll s) { + if (s instanceof ScrollOfUpgrade) { + + return new ScrollOfMagicalInfusion(); + + } else if (s instanceof ScrollOfMagicalInfusion) { + + 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 PotionOfMending){ + + return new PotionOfHealing(); + + } else { + + Potion n; + do { + n = (Potion) Generator.random(Category.POTION); + } while (n.getClass() == p.getClass()); + return n; + } + } + + + @Override + public String tileDesc() { + return Messages.get(this, "desc"); + } +} diff --git a/java/com/hmdzl/spspd/actors/blobs/WaterOfUpgradeEating.java b/java/com/hmdzl/spspd/actors/blobs/WaterOfUpgradeEating.java new file mode 100644 index 00000000..83f89588 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/blobs/WaterOfUpgradeEating.java @@ -0,0 +1,100 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.blobs; + +import com.hmdzl.spspd.effects.BlobEmitter; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.Stylus; +import com.hmdzl.spspd.items.UpgradeBlobRed; +import com.hmdzl.spspd.items.UpgradeBlobViolet; +import com.hmdzl.spspd.items.UpgradeBlobYellow; +import com.hmdzl.spspd.items.potions.Potion; +import com.hmdzl.spspd.items.scrolls.Scroll; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.plants.Seedpod; +import com.watabou.utils.Random; + +public class WaterOfUpgradeEating extends WellWater { + + @Override + protected Item affectItem(Item item) { + + if (item.isUpgradable()) { + item = eatUpgradable((Item) item); + } else if (item instanceof Scroll + || item instanceof Potion + || item instanceof Stylus) { + item = eatStandard((Item) item); + } else { + item = null; + } + + return item; + } + + @Override + public void use(BlobEmitter emitter) { + super.use(emitter); + emitter.start(Speck.factory(Speck.CHANGE), 0.2f, 0); + } + + private Item eatUpgradable(Item w) { + + int ups = w.level; + + Item n = null; + + if (Random.Float()<(ups/10)){ + + n = new UpgradeBlobViolet(); + + } else if (Random.Float()<(ups/5)) { + + n = new UpgradeBlobRed(); + + } else if (Random.Float()<(ups/3)) { + + n = new UpgradeBlobYellow(); + + } else { + + n =new Seedpod.Seed() ; + } + + return n; + } + + private Item eatStandard(Item w) { + + Item n = null; + + if (Random.Float()<0.1f){ + n = new UpgradeBlobYellow(); + } else { + n = new Seedpod.Seed() ; + } + + return n; + } + + @Override + public String tileDesc() { + return Messages.get(this, "desc"); + } +} diff --git a/java/com/hmdzl/spspd/actors/blobs/Web.java b/java/com/hmdzl/spspd/actors/blobs/Web.java new file mode 100644 index 00000000..345ba4d4 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/blobs/Web.java @@ -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 + */ +package com.hmdzl.spspd.actors.blobs; + +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Roots; +import com.hmdzl.spspd.effects.BlobEmitter; +import com.hmdzl.spspd.effects.particles.WebParticle; +import com.hmdzl.spspd.messages.Messages; + +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); + } + + @Override + 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 Messages.get(this, "desc"); + } +} diff --git a/java/com/hmdzl/spspd/actors/blobs/WellWater.java b/java/com/hmdzl/spspd/actors/blobs/WellWater.java new file mode 100644 index 00000000..9a3f438e --- /dev/null +++ b/java/com/hmdzl/spspd/actors/blobs/WellWater.java @@ -0,0 +1,166 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.blobs; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.Journal; +import com.hmdzl.spspd.Journal.Feature; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.items.Heap; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.Terrain; +import com.hmdzl.spspd.scenes.GameScene; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public class WellWater extends Blob { + + public 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; + } + } + } + + public static boolean affectCellPlant(int cell) { + + boolean transmuted = false; + + 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()) { + + GameScene.updateMap(cell); + transmuted = true; + } + } + return transmuted; + } +} diff --git a/java/com/hmdzl/spspd/actors/blobs/weather/WeatherOfDead.java b/java/com/hmdzl/spspd/actors/blobs/weather/WeatherOfDead.java new file mode 100644 index 00000000..aac908a1 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/blobs/weather/WeatherOfDead.java @@ -0,0 +1,55 @@ +package com.hmdzl.spspd.actors.blobs.weather; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.blobs.Blob; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.DeadRaise; +import com.hmdzl.spspd.actors.buffs.Hot; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.BlobEmitter; +import com.hmdzl.spspd.effects.particles.DeadParticle; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.messages.Messages; + +public class WeatherOfDead extends Blob { + + protected int pos; + + @Override + protected void evolve() { + int from = WIDTH + 1; + int to = Level.LENGTH - WIDTH - 1; + + int[] map = Dungeon.level.map; + + for (int pos=from; pos < to; pos++) { + if (cur[pos] > 0) { + + off[pos] = cur[pos]; + volume += off[pos]; + + } else { + off[pos] = 0; + } + } + + Hero hero = Dungeon.hero; + if (hero.isAlive() && cur[hero.pos] > 0) { + Buff.prolong( hero, DeadRaise.class, 2f ); + Buff.detach(hero,Hot.class); + } + + } + + @Override + public void use(BlobEmitter emitter) { + super.use(emitter); + emitter.start(DeadParticle.FACTORY, 0.3f, 0); + } + + @Override + public String tileDesc() { + return Messages.get(this, "desc"); + } + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/blobs/weather/WeatherOfQuite.java b/java/com/hmdzl/spspd/actors/blobs/weather/WeatherOfQuite.java new file mode 100644 index 00000000..9fa1379c --- /dev/null +++ b/java/com/hmdzl/spspd/actors/blobs/weather/WeatherOfQuite.java @@ -0,0 +1,53 @@ +package com.hmdzl.spspd.actors.blobs.weather; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.blobs.Blob; +import com.hmdzl.spspd.actors.buffs.Bless; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.BlobEmitter; +import com.hmdzl.spspd.effects.particles.ShaftParticle; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.messages.Messages; + +public class WeatherOfQuite extends Blob { + + protected int pos; + + @Override + protected void evolve() { + int from = WIDTH + 1; + int to = Level.LENGTH - WIDTH - 1; + + int[] map = Dungeon.level.map; + + for (int pos=from; pos < to; pos++) { + if (cur[pos] > 0) { + + off[pos] = cur[pos]; + volume += off[pos]; + + } else { + off[pos] = 0; + } + } + + Hero hero = Dungeon.hero; + if (hero.isAlive() && cur[hero.pos] > 0) { + Buff.prolong( hero, Bless.class, 5f ); + } + + } + + @Override + public void use(BlobEmitter emitter) { + super.use(emitter); + emitter.start( ShaftParticle.FACTORY, 0.8f, 0); + } + + @Override + public String tileDesc() { + return Messages.get(this, "desc"); + } + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/blobs/weather/WeatherOfRain.java b/java/com/hmdzl/spspd/actors/blobs/weather/WeatherOfRain.java new file mode 100644 index 00000000..884d8c91 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/blobs/weather/WeatherOfRain.java @@ -0,0 +1,55 @@ +package com.hmdzl.spspd.actors.blobs.weather; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.blobs.Blob; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Dry; +import com.hmdzl.spspd.actors.buffs.Wet; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.BlobEmitter; +import com.hmdzl.spspd.effects.particles.RainParticle; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.messages.Messages; + +public class WeatherOfRain extends Blob { + + protected int pos; + + @Override + protected void evolve() { + + int from = WIDTH + 1; + int to = Level.LENGTH - WIDTH - 1; + + int[] map = Dungeon.level.map; + + for (int pos=from; pos < to; pos++) { + if (cur[pos] > 0) { + + off[pos] = cur[pos]; + volume += off[pos]; + + } else { + off[pos] = 0; + } + } + + Hero hero = Dungeon.hero; + if (hero.isAlive() && cur[hero.pos] > 0) { + Buff.prolong( hero, Wet.class, Wet.DURATION ); + Buff.detach(hero,Dry.class); + } + } + + @Override + public void use(BlobEmitter emitter) { + super.use(emitter); + emitter.start(RainParticle.FACTORY, 0.8f, 0); + } + + @Override + public String tileDesc() { + return Messages.get(this, "desc"); + } + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/blobs/weather/WeatherOfSand.java b/java/com/hmdzl/spspd/actors/blobs/weather/WeatherOfSand.java new file mode 100644 index 00000000..50815020 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/blobs/weather/WeatherOfSand.java @@ -0,0 +1,54 @@ +package com.hmdzl.spspd.actors.blobs.weather; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.blobs.Blob; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Dry; +import com.hmdzl.spspd.actors.buffs.Wet; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.BlobEmitter; +import com.hmdzl.spspd.effects.particles.SandParticle; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.messages.Messages; + +public class WeatherOfSand extends Blob { + + protected int pos; + + @Override + protected void evolve() { + int from = WIDTH + 1; + int to = Level.LENGTH - WIDTH - 1; + + int[] map = Dungeon.level.map; + + for (int pos=from; pos < to; pos++) { + if (cur[pos] > 0) { + + off[pos] = cur[pos]; + volume += off[pos]; + + } else { + off[pos] = 0; + } + } + + Hero hero = Dungeon.hero; + if (hero.isAlive() && cur[hero.pos] > 0) { + Buff.prolong( hero, Dry.class, Dry.DURATION ); + Buff.detach(hero,Wet.class); + } + } + + @Override + public void use(BlobEmitter emitter) { + super.use(emitter); + emitter.start(SandParticle.FACTORY, 0.5f, 0); + } + + @Override + public String tileDesc() { + return Messages.get(this, "desc"); + } + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/blobs/weather/WeatherOfSnow.java b/java/com/hmdzl/spspd/actors/blobs/weather/WeatherOfSnow.java new file mode 100644 index 00000000..1fdbed87 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/blobs/weather/WeatherOfSnow.java @@ -0,0 +1,55 @@ +package com.hmdzl.spspd.actors.blobs.weather; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.blobs.Blob; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Cold; +import com.hmdzl.spspd.actors.buffs.Hot; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.BlobEmitter; +import com.hmdzl.spspd.effects.particles.SnowParticle; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.messages.Messages; + +public class WeatherOfSnow extends Blob { + + protected int pos; + + @Override + protected void evolve() { + int from = WIDTH + 1; + int to = Level.LENGTH - WIDTH - 1; + + int[] map = Dungeon.level.map; + + for (int pos=from; pos < to; pos++) { + if (cur[pos] > 0) { + + off[pos] = cur[pos]; + volume += off[pos]; + + } else { + off[pos] = 0; + } + } + + Hero hero = Dungeon.hero; + if (hero.isAlive() && cur[hero.pos] > 0) { + Buff.prolong( hero, Cold.class, Cold.DURATION ); + Buff.detach(hero,Hot.class); + } + + } + + @Override + public void use(BlobEmitter emitter) { + super.use(emitter); + emitter.start(SnowParticle.FACTORY, 0.5f, 0); + } + + @Override + public String tileDesc() { + return Messages.get(this, "desc"); + } + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/blobs/weather/WeatherOfSun.java b/java/com/hmdzl/spspd/actors/blobs/weather/WeatherOfSun.java new file mode 100644 index 00000000..97f57c1e --- /dev/null +++ b/java/com/hmdzl/spspd/actors/blobs/weather/WeatherOfSun.java @@ -0,0 +1,54 @@ +package com.hmdzl.spspd.actors.blobs.weather; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.blobs.Blob; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Cold; +import com.hmdzl.spspd.actors.buffs.Hot; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.BlobEmitter; +import com.hmdzl.spspd.effects.particles.ShaftParticle; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.messages.Messages; + +public class WeatherOfSun extends Blob { + + protected int pos; + + @Override + protected void evolve() { + int from = WIDTH + 1; + int to = Level.LENGTH - WIDTH - 1; + + int[] map = Dungeon.level.map; + + for (int pos=from; pos < to; pos++) { + if (cur[pos] > 0) { + + off[pos] = cur[pos]; + volume += off[pos]; + + } else { + off[pos] = 0; + } + } + + Hero hero = Dungeon.hero; + if (hero.isAlive() && cur[hero.pos] > 0) { + Buff.prolong( hero, Hot.class, Hot.DURATION ); + Buff.detach(hero,Cold.class); + } + } + + @Override + public void use(BlobEmitter emitter) { + super.use(emitter); + emitter.start(ShaftParticle.FACTORY, 0.9f, 0); + } + + @Override + public String tileDesc() { + return Messages.get(this, "desc"); + } + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/buffs/AflyBless.java b/java/com/hmdzl/spspd/actors/buffs/AflyBless.java new file mode 100644 index 00000000..1679fd43 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/AflyBless.java @@ -0,0 +1,49 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2015 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.BuffIndicator; + +public class AflyBless extends FlavourBuff { + + public static final float DURATION = 200f; + + { + type = buffType.POSITIVE; + } + + + @Override + public int icon() { + return BuffIndicator.NO_FUSHIGI; + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public String desc() { + return Messages.get(this, "desc", dispTurns()); + } +} diff --git a/java/com/hmdzl/spspd/actors/buffs/Amok.java b/java/com/hmdzl/spspd/actors/buffs/Amok.java new file mode 100644 index 00000000..52510154 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/Amok.java @@ -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 + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.BuffIndicator; + +public class Amok extends FlavourBuff { + + { + type = buffType.NEGATIVE; + } + + @Override + public int icon() { + return BuffIndicator.AMOK; + } + + @Override + public void detach() { + super.detach(); + if (target instanceof Mob) + ((Mob)target).aggro( null ); + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public String desc() { + return Messages.get(this, "desc", dispTurns()); + } + +} diff --git a/java/com/hmdzl/spspd/actors/buffs/Arcane.java b/java/com/hmdzl/spspd/actors/buffs/Arcane.java new file mode 100644 index 00000000..ed315833 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/Arcane.java @@ -0,0 +1,41 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.BuffIndicator; + +public class Arcane extends FlavourBuff { + + public static final float DURATION = 30f; + + @Override + public int icon() { + return BuffIndicator.ARCANE; + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public String desc() { + return Messages.get(this, "desc", dispTurns()); + } +} diff --git a/java/com/hmdzl/spspd/actors/buffs/ArmorBreak.java b/java/com/hmdzl/spspd/actors/buffs/ArmorBreak.java new file mode 100644 index 00000000..d8599590 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/ArmorBreak.java @@ -0,0 +1,92 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2015 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.BuffIndicator; +import com.watabou.utils.Bundle; + +public class ArmorBreak extends FlavourBuff { + + private int level = 0; + private static final String LEVEL = "level"; + protected float left; + private static final String LEFT = "left"; + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(LEVEL, level); + bundle.put(LEFT, left); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + level = bundle.getInt(LEVEL); + left = bundle.getFloat(LEFT); + } + + public void set(float duration) { + this.left = duration; + }; + public static final float DURATION = 10f; + + { + type = buffType.NEGATIVE; + } + + public boolean act() { + + spend(TICK); + left -= TICK; + if (left <= 0) + detach(); + return true; + + } + + public int level() { + return level; + } + + public void level(int value) { + if (level < value) { + level = value; + } + } + + @Override + public int icon() { + return BuffIndicator.ARMOR_BREAK; + } + + + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public String desc() { + return Messages.get(this, "desc", dispTurns(),level()); + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/buffs/AttackDown.java b/java/com/hmdzl/spspd/actors/buffs/AttackDown.java new file mode 100644 index 00000000..3637893d --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/AttackDown.java @@ -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 + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.items.rings.RingOfElements.Resistance; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.BuffIndicator; +import com.watabou.utils.Bundle; + +public class AttackDown extends FlavourBuff { + + private int level = 0; + private static final String LEVEL = "level"; + protected float left; + private static final String LEFT = "left"; + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(LEVEL, level); + bundle.put(LEFT, left); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + level = bundle.getInt(LEVEL); + left = bundle.getFloat(LEFT); + } + + public void set(float duration) { + this.left = duration; + }; + + { + type = buffType.NEGATIVE; + } + + public boolean act() { + + spend(TICK); + left -= TICK; + if (left <= 0) + detach(); + return true; + + } + @Override + public int icon() { + return BuffIndicator.WEAKNESS; + } + + public int level() { + return level; + } + + public void level(int value) { + if (level < value) { + level = value; + } + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public String desc() { + return Messages.get(this, "desc", dispTurns(),level()); + } + +} diff --git a/java/com/hmdzl/spspd/actors/buffs/AttackUp.java b/java/com/hmdzl/spspd/actors/buffs/AttackUp.java new file mode 100644 index 00000000..2317c3b5 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/AttackUp.java @@ -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 + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.items.rings.RingOfElements.Resistance; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.BuffIndicator; +import com.watabou.utils.Bundle; + +public class AttackUp extends FlavourBuff { + + private int level = 0; + private static final String LEVEL = "level"; + protected float left; + private static final String LEFT = "left"; + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(LEVEL, level); + bundle.put(LEFT, left); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + level = bundle.getInt(LEVEL); + left = bundle.getFloat(LEFT); + } + + public void set(float duration) { + this.left = duration; + }; + + { + type = buffType.POSITIVE; + } + + public boolean act() { + + spend(TICK); + left -= TICK; + if (left <= 0) + detach(); + return true; + + } + @Override + public int icon() { + return BuffIndicator.ATTACK_UP; + } + + public int level() { + return level; + } + + public void level(int value) { + if (level < value) { + level = value; + } + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public String desc() { + return Messages.get(this, "desc", dispTurns(),level()); + } + +} diff --git a/java/com/hmdzl/spspd/actors/buffs/Awareness.java b/java/com/hmdzl/spspd/actors/buffs/Awareness.java new file mode 100644 index 00000000..12e0e25e --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/Awareness.java @@ -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 + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.BuffIndicator; + +public class Awareness extends FlavourBuff { + + public static final float DURATION = 2f; + + { + type = buffType.POSITIVE; + } + + @Override + public int icon() { + return BuffIndicator.MIND_VISION; + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public void detach() { + super.detach(); + Dungeon.observe(); + } + + @Override + public String desc() { + return Messages.get(this, "desc", dispTurns()); + } +} diff --git a/java/com/hmdzl/spspd/actors/buffs/Barkskin.java b/java/com/hmdzl/spspd/actors/buffs/Barkskin.java new file mode 100644 index 00000000..a4197530 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/Barkskin.java @@ -0,0 +1,85 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.BuffIndicator; +import com.watabou.utils.Bundle; + +public class Barkskin extends Buff { + + private int barkleft = 0; + + private static final String BARKLEFT = "barkleft"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(BARKLEFT, barkleft); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + barkleft = bundle.getInt(BARKLEFT); + } + + @Override + public boolean act() { + if (target.isAlive()) { + + spend(TICK); + barkleft = (int)barkleft/2; + if (barkleft <= 1) { + detach(); + } + + } else { + + detach(); + + } + + return true; + } + + public int level() { + return barkleft; + } + + public void level(int value) { + if (barkleft < value) { + barkleft = value; + } + } + + @Override + public int icon() { + return BuffIndicator.BARKSKIN; + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public String desc() { + return Messages.get(this, "desc", barkleft); + } +} diff --git a/java/com/hmdzl/spspd/actors/buffs/BerryRegeneration.java b/java/com/hmdzl/spspd/actors/buffs/BerryRegeneration.java new file mode 100644 index 00000000..cd910de2 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/BerryRegeneration.java @@ -0,0 +1,92 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.hero.HeroSubClass; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.BuffIndicator; +import com.watabou.utils.Bundle; + +public class BerryRegeneration extends Buff { + + private int regenleft = 0; + + private static final String REGENLEFT = "regenleft"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(REGENLEFT, regenleft); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + regenleft = bundle.getInt(REGENLEFT); + } + + public int level() { + return regenleft; + } + + public void level(int value) { + if (regenleft < value) { + regenleft = value; + } + } + + @Override + public int icon() { + return BuffIndicator.REGEN; + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public String desc() { + return Messages.get(this, "desc", regenleft); + } + + @Override + public boolean act() { + if (target.isAlive()) { + if (Dungeon.hero.subClass == HeroSubClass.PASTOR && target.HP < target.HT*1.5){ + target.HP += 2 * (5+Math.round(regenleft/25)); + } else if (target.HP < target.HT) { + target.HP += Math.min(5+Math.round(regenleft/25),(target.HT-target.HP)); + } + + spend(TICK); + if (--regenleft <= 0) { + detach(); + } + + } else { + + detach(); + + } + + return true; + } + +} diff --git a/java/com/hmdzl/spspd/actors/buffs/Bleeding.java b/java/com/hmdzl/spspd/actors/buffs/Bleeding.java new file mode 100644 index 00000000..5cd0fbb3 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/Bleeding.java @@ -0,0 +1,107 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.ResultDescriptions; +import com.hmdzl.spspd.effects.Splash; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.BuffIndicator; +import com.watabou.utils.Bundle; +import com.watabou.utils.PointF; +import com.watabou.utils.Random; + +public class Bleeding extends Buff { + + { + type = buffType.NEGATIVE; + } + + 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 Messages.get(this, "name"); + } + + @Override + public boolean act() { + if (target.isAlive()) { + + if ((level = Random.Int(level / 3, level/2)) > 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(Messages.format(ResultDescriptions.BLEEDING)); + //GLog.n("You bled to death..."); + } + + spend(TICK); + } else { + detach(); + } + + } else { + + detach(); + + } + + return true; + } + + @Override + public String heroMessage() { + return Messages.get(this, "heromsg"); + } + + @Override + public String desc() { + return Messages.get(this, "desc", level); + } +} diff --git a/java/com/hmdzl/spspd/actors/buffs/Bless.java b/java/com/hmdzl/spspd/actors/buffs/Bless.java new file mode 100644 index 00000000..30947fb5 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/Bless.java @@ -0,0 +1,85 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2015 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.actors.blobs.ConfusionGas; +import com.hmdzl.spspd.actors.blobs.CorruptGas; +import com.hmdzl.spspd.actors.blobs.ElectriShock; +import com.hmdzl.spspd.actors.blobs.Fire; +import com.hmdzl.spspd.actors.blobs.Freezing; +import com.hmdzl.spspd.actors.blobs.ParalyticGas; +import com.hmdzl.spspd.actors.blobs.Regrowth; +import com.hmdzl.spspd.actors.blobs.ShockWeb; +import com.hmdzl.spspd.actors.blobs.StenchGas; +import com.hmdzl.spspd.actors.blobs.ToxicGas; +import com.hmdzl.spspd.actors.blobs.VenomGas; +import com.hmdzl.spspd.actors.blobs.weather.WeatherOfRain; +import com.hmdzl.spspd.actors.blobs.weather.WeatherOfSand; +import com.hmdzl.spspd.actors.blobs.weather.WeatherOfSnow; +import com.hmdzl.spspd.actors.blobs.weather.WeatherOfSun; +import com.hmdzl.spspd.actors.blobs.Web; +import com.hmdzl.spspd.levels.traps.LightningTrap; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.BuffIndicator; + +public class Bless extends FlavourBuff { + + public static final float DURATION = 30f; + + @Override + public int icon() { + return BuffIndicator.BLESS; + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + { + immunities.add( ParalyticGas.class ); + immunities.add( ToxicGas.class ); + immunities.add( ConfusionGas.class ); + immunities.add( StenchGas.class ); + immunities.add( VenomGas.class ); + immunities.add( CorruptGas.class ); + immunities.add( Fire.class ); + immunities.add( Freezing.class ); + immunities.add( ElectriShock.class ); + immunities.add( LightningTrap.Electricity.class ); + immunities.add( Regrowth.class ); + immunities.add( Web.class ); + immunities.add( ShockWeb.class ); + immunities.add( Hot.class ); + immunities.add( Cold.class ); + immunities.add( Wet.class ); + immunities.add( Dry.class ); + immunities.add(WeatherOfRain.class); + immunities.add(WeatherOfSand.class); + immunities.add(WeatherOfSnow.class); + immunities.add(WeatherOfSun.class); + } + + @Override + public String desc() { + return Messages.get(this, "desc", dispTurns()); + } +} diff --git a/java/com/hmdzl/spspd/actors/buffs/Blindness.java b/java/com/hmdzl/spspd/actors/buffs/Blindness.java new file mode 100644 index 00000000..f43d099e --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/Blindness.java @@ -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 + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.BuffIndicator; + +public class Blindness extends FlavourBuff { + + { + type = buffType.NEGATIVE; + } + + @Override + public void detach() { + super.detach(); + Dungeon.observe(); + } + + @Override + public int icon() { + return BuffIndicator.BLINDNESS; + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public String heroMessage() { + return Messages.get(this, "heromsg"); + } + + @Override + public String desc() { + return Messages.get(this, "desc", dispTurns()); + } +} diff --git a/java/com/hmdzl/spspd/actors/buffs/BloodAngry.java b/java/com/hmdzl/spspd/actors/buffs/BloodAngry.java new file mode 100644 index 00000000..04ffbf2c --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/BloodAngry.java @@ -0,0 +1,102 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2015 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.actors.blobs.ConfusionGas; +import com.hmdzl.spspd.actors.blobs.CorruptGas; +import com.hmdzl.spspd.actors.blobs.ElectriShock; +import com.hmdzl.spspd.actors.blobs.Fire; +import com.hmdzl.spspd.actors.blobs.Freezing; +import com.hmdzl.spspd.actors.blobs.ParalyticGas; +import com.hmdzl.spspd.actors.blobs.Regrowth; +import com.hmdzl.spspd.actors.blobs.ShockWeb; +import com.hmdzl.spspd.actors.blobs.StenchGas; +import com.hmdzl.spspd.actors.blobs.ToxicGas; +import com.hmdzl.spspd.actors.blobs.VenomGas; +import com.hmdzl.spspd.actors.blobs.weather.WeatherOfRain; +import com.hmdzl.spspd.actors.blobs.weather.WeatherOfSand; +import com.hmdzl.spspd.actors.blobs.weather.WeatherOfSnow; +import com.hmdzl.spspd.actors.blobs.weather.WeatherOfSun; +import com.hmdzl.spspd.actors.blobs.Web; +import com.hmdzl.spspd.levels.traps.LightningTrap; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.BuffIndicator; +import com.watabou.utils.Bundle; + +public class BloodAngry extends Buff { + + public static final float DURATION = 30f; + + private float left; + private static final String LEFT = "left"; + + @Override + public int icon() { + return BuffIndicator.BLOODANGRY; + } + + @Override + public boolean act() { + + if (target.HP > target.HT/3){ + target.HP = Math.max(target.HT/3, target.HP - 1); + } + spend(TICK); + left -= TICK; + if (left <= 0){ + detach(); + } else + if (target.HP < target.HT/3){ + target.HP = Math.max(target.HT/3, target.HP + 1); + } + spend(TICK); + left -= TICK; + if (left <= 0){ + detach(); + } + return true; + } + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(LEFT, left); + + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + left = bundle.getInt(LEFT); + } + public void set(float left){ + this.left = left; + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public String desc() { + return Messages.get(this, "desc", left); + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/buffs/BloodImbue.java b/java/com/hmdzl/spspd/actors/buffs/BloodImbue.java new file mode 100644 index 00000000..bc19f6f4 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/BloodImbue.java @@ -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 + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.BuffIndicator; +import com.watabou.utils.Random; + +/** + * Created by debenhame on 19/11/2014. + */ +public class BloodImbue extends FlavourBuff { + + public static final float DURATION = 10f; + + { + type = buffType.POSITIVE; + } + + + public void proc(Char enemy) { + switch (Random.Int(4)){ + case 0: + Buff.affect(enemy, Cripple.class,3); + break; + case 1: + Buff.affect(enemy, Roots.class,3); + break; + case 2: + Buff.affect(enemy, Paralysis.class,3); + break; + case 3: + break; + } + } + + @Override + public int icon() { + return BuffIndicator.PBLOOD; + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public String desc() { + return Messages.get(this, "desc", dispTurns()); + } + + { + immunities.add(Paralysis.class); + immunities.add(Roots.class); + immunities.add(Slow.class); + immunities.add(Bleeding.class); + immunities.add(Weakness.class); + } + +} diff --git a/java/com/hmdzl/spspd/actors/buffs/BoxStar.java b/java/com/hmdzl/spspd/actors/buffs/BoxStar.java new file mode 100644 index 00000000..597acab9 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/BoxStar.java @@ -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 + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.items.rings.RingOfElements.Resistance; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.CharSprite; +import com.hmdzl.spspd.ui.BuffIndicator; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public class BoxStar extends FlavourBuff { + + { + type = buffType.POSITIVE; + } + + public int proc(int damage, Char attacker) { + + damage = 0; + return damage; + } + + public int icon() { + return BuffIndicator.UNKNOW_BOX; + } + + //@Override + //public void fx(boolean on) { + //if (on) target.sprite.add(CharSprite.State.ILLUMINATED); + //else target.sprite.remove(CharSprite.State.ILLUMINATED); + //} + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public String desc() { + return Messages.get(this, "desc", dispTurns()); + } + +} diff --git a/java/com/hmdzl/spspd/actors/buffs/Buff.java b/java/com/hmdzl/spspd/actors/buffs/Buff.java new file mode 100644 index 00000000..4f1e17d0 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/Buff.java @@ -0,0 +1,136 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.buffs; + +import java.text.DecimalFormat; +import java.util.HashSet; + +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.ui.BuffIndicator; + +public class Buff extends Actor { + + public Char target; + + public enum buffType {POSITIVE, NEGATIVE, NEUTRAL, SILENT}; + public buffType type = buffType.SILENT; + + public HashSet> resistances = new HashSet>(); + + public HashSet> immunities = new HashSet>(); + + public boolean attachTo(Char target) { + + if (target.immunities().contains(getClass())) { + return false; + } + + this.target = target; + target.add(this); + + if (target.buffs().contains(this)){ + if (target.sprite != null) fx( true ); + return true; + } else + return false; + } + + public void detach() { + fx( false ); + target.remove(this); + } + + @Override + public boolean act() { + diactivate(); + return true; + } + + public int icon() { + return BuffIndicator.NONE; + } + + public void fx(boolean on) { + //do nothing by default + }; + + public String heroMessage(){ + return null; + } + + public String desc(){ + return ""; + } + + //to handle the common case of showing how many turns are remaining in a buff description. + protected String dispTurns(float input){ + return new DecimalFormat("#.##").format(input); + } + + public static T append(Char target, Class buffClass) { + try { + T buff = buffClass.newInstance(); + buff.attachTo(target); + return buff; + } catch (Exception e) { + //ShatteredPixelDungeon.reportException(e); + return null; + } + } + + public static T append(Char target, + Class buffClass, float duration) { + T buff = append(target, buffClass); + buff.spend(duration); + return buff; + } + + public static T affect(Char target, Class buffClass) { + T buff = target.buff(buffClass); + if (buff != null) { + return buff; + } else { + return append(target, buffClass); + } + } + + public static T affect(Char target, + Class buffClass, float duration) { + T buff = affect(target, buffClass); + buff.spend(duration); + return buff; + } + + public static T prolong(Char target, + Class 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 cl) { + detach(target.buff(cl)); + } +} diff --git a/java/com/hmdzl/spspd/actors/buffs/Burning.java b/java/com/hmdzl/spspd/actors/buffs/Burning.java new file mode 100644 index 00000000..6c9dbbb4 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/Burning.java @@ -0,0 +1,189 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.ResultDescriptions; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.Blob; +import com.hmdzl.spspd.actors.blobs.Fire; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.mobs.Thief; +import com.hmdzl.spspd.effects.particles.ElmoParticle; +import com.hmdzl.spspd.items.Heap; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.food.meatfood.ChargrilledMeat; +import com.hmdzl.spspd.items.food.meatfood.MysteryMeat; +import com.hmdzl.spspd.items.rings.RingOfElements.Resistance; +import com.hmdzl.spspd.items.scrolls.Scroll; +import com.hmdzl.spspd.items.scrolls.ScrollOfMagicalInfusion; +import com.hmdzl.spspd.items.scrolls.ScrollOfUpgrade; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.CharSprite; +import com.hmdzl.spspd.ui.BuffIndicator; +import com.hmdzl.spspd.utils.GLog; +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"; + + { + type = buffType.NEGATIVE; + } + + @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, Math.min(1000,target.HT/20)), this); + Buff.detach( target, Chill.class); + + if (target instanceof Hero) { + + Hero hero = (Hero) target; + Item item = hero.belongings.randomUnequipped(); + if (item instanceof Scroll + && !(item instanceof ScrollOfUpgrade || item instanceof ScrollOfMagicalInfusion)){ + + item = item.detach(hero.belongings.backpack); + GLog.w(Messages.get(this, "burnsup", item.toString())); + + Heap.burnFX(hero.pos); + + } else if (item instanceof MysteryMeat) { + + item = item.detach(hero.belongings.backpack); + ChargrilledMeat steak = new ChargrilledMeat(); + if (!steak.collect(hero.belongings.backpack)) { + Dungeon.level.drop(steak, hero.pos).sprite.drop(); + } + GLog.w(Messages.get(this, "burnsup", item.toString())); + + Heap.burnFX(hero.pos); + + } + + } else if (target instanceof Thief) { + + Item item = ((Thief) target).item; + + if (item instanceof Scroll && + !(item instanceof ScrollOfUpgrade || item instanceof ScrollOfMagicalInfusion)) { + target.sprite.emitter().burst( ElmoParticle.FACTORY, 6 ); + ((Thief)target).item = null; + } + + } + + } else { + detach(); + } + + if (Level.flamable[target.pos]) { + GameScene.add(Blob.seed(target.pos, 4, Fire.class)); + } + + spend(TICK); + left -= TICK; + + if (left <= 0 || (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 void fx(boolean on) { + if (on) target.sprite.add(CharSprite.State.BURNING); + else target.sprite.remove(CharSprite.State.BURNING); + } + + + @Override + public String heroMessage() { + return Messages.get(this, "heromsg"); + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + public static float duration(Char ch) { + Resistance r = ch.buff(Resistance.class); + Tar tar = ch.buff(Tar.class); + if (ch.isAlive() && tar!=null){ + return DURATION; + } else return r != null ? r.durationFactor() * DURATION : DURATION; + + } + + @Override + public String desc() { + return Messages.get(this, "desc", dispTurns(left)); + } + + @Override + public void onDeath() { + + Badges.validateDeathFromFire(); + + Dungeon.fail(Messages.format(ResultDescriptions.BURNING)); + //GLog.n(TXT_BURNED_TO_DEATH); + } +} diff --git a/java/com/hmdzl/spspd/actors/buffs/Charm.java b/java/com/hmdzl/spspd/actors/buffs/Charm.java new file mode 100644 index 00000000..8731fee1 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/Charm.java @@ -0,0 +1,72 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.items.rings.RingOfElements.Resistance; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.BuffIndicator; +import com.watabou.utils.Bundle; + +public class Charm extends FlavourBuff { + + public int object = 0; + + private static final String OBJECT = "object"; + + { + type = buffType.NEGATIVE; + } + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(OBJECT, object); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + object = bundle.getInt(OBJECT); + } + + @Override + public int icon() { + return BuffIndicator.HEART; + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + public static float durationFactor(Char ch) { + Resistance r = ch.buff(Resistance.class); + return r != null ? r.durationFactor() : 1; + } + + @Override + public String heroMessage() { + return Messages.get(this, "heromsg"); + } + + @Override + public String desc() { + return Messages.get(this, "desc", dispTurns()); + } +} diff --git a/java/com/hmdzl/spspd/actors/buffs/Chill.java b/java/com/hmdzl/spspd/actors/buffs/Chill.java new file mode 100644 index 00000000..81ab6899 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/Chill.java @@ -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 + */ + +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.mobs.Thief; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.food.meatfood.FrozenCarpaccio; +import com.hmdzl.spspd.items.food.meatfood.MysteryMeat; +import com.hmdzl.spspd.items.potions.Potion; +import com.hmdzl.spspd.items.potions.PotionOfMight; +import com.hmdzl.spspd.items.potions.PotionOfStrength; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.CharSprite; +import com.hmdzl.spspd.ui.BuffIndicator; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Random; + +import java.text.DecimalFormat; + +public class Chill extends FlavourBuff { + + { + type = buffType.NEGATIVE; + } + + @Override + public boolean attachTo(Char target) { + //can't chill what's frozen! + if (target.buff(Frost.class) != null) return false; + + if (super.attachTo(target)){ + Burning.detach( target, Burning.class ); + + //chance of potion breaking is the same as speed factor. + if (Random.Float(1f) > speedFactor() && target instanceof Hero) { + + Hero hero = (Hero)target; + Item item = hero.belongings.randomUnequipped(); + if (item instanceof Potion + && !(item instanceof PotionOfStrength || item instanceof PotionOfMight)) { + + item = item.detach( hero.belongings.backpack ); + GLog.w(Messages.get(this, "freezes", item.toString())); + ((Potion) item).shatter(hero.pos); + + } else 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(); + } + GLog.w(Messages.get(this, "freezes", item.toString())); + + } + } else if (target instanceof Thief) { + + Item item = ((Thief) target).item; + + if (item instanceof Potion && !(item instanceof PotionOfStrength || item instanceof PotionOfMight)) { + ((Potion) ((Thief) target).item).shatter(target.pos); + ((Thief) target).item = null; + } + + } + return true; + } else { + return false; + } + } + + //reduces speed by 10% for every turn remaining, capping at 50% + public float speedFactor(){ + return Math.max(0.5f, 1 - cooldown()*0.1f); + } + + @Override + public int icon() { + return BuffIndicator.FROST; + } + + //@Override + public void fx(boolean on) { + if (on) target.sprite.add(CharSprite.State.CHILLED); + else target.sprite.remove(CharSprite.State.CHILLED); + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public String desc() { + return Messages.get(this, "desc", dispTurns(), new DecimalFormat("#.##").format((1f-speedFactor())*100f)); + } + +} diff --git a/java/com/hmdzl/spspd/actors/buffs/Cold.java b/java/com/hmdzl/spspd/actors/buffs/Cold.java new file mode 100644 index 00000000..c3f52a0e --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/Cold.java @@ -0,0 +1,48 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2015 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.BuffIndicator; + +public class Cold extends FlavourBuff { + + public static final float DURATION = 10f; + + { + type = buffType.NEGATIVE; + } + + @Override + public int icon() { + return BuffIndicator.COLD; + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public String desc() { + return Messages.get(this, "desc", dispTurns()); + } +} diff --git a/java/com/hmdzl/spspd/actors/buffs/Combo.java b/java/com/hmdzl/spspd/actors/buffs/Combo.java new file mode 100644 index 00000000..c0cdecde --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/Combo.java @@ -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 + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.BuffIndicator; +import com.hmdzl.spspd.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 Messages.get(this, "name"); + } + + public int hit(Char enemy, int damage) { + + count++; + + if (count >= 3) { + + Badges.validateMasteryCombo(count); + + GLog.p( Messages.get(this, "combo", count)); + postpone(1.41f - Math.min(0.8f,count / 20f)); + return (int) (damage * (count - 2) / 10f); + + } else { + + postpone(1.1f); + return 0; + + } + } + + @Override + public boolean act() { + detach(); + return true; + } + + @Override + public String desc() { + return Messages.get(this, "desc") + + (count <= 2 ? + Messages.get(this, "notenough") : + Messages.get(this, "bonusdmg", ((count - 2) * 20f))); + } + +} diff --git a/java/com/hmdzl/spspd/actors/buffs/Corruption.java b/java/com/hmdzl/spspd/actors/buffs/Corruption.java new file mode 100644 index 00000000..a3fd2e0d --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/Corruption.java @@ -0,0 +1,72 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2019 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ + +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.CharSprite; +import com.hmdzl.spspd.ui.BuffIndicator; + +public class Corruption extends Buff { + + { + type = buffType.NEGATIVE; + } + + private float buildToDamage = 0f; + + @Override + public boolean act() { + buildToDamage += target.HT/200f; + + int damage = (int)buildToDamage; + buildToDamage -= damage; + + if (damage > 0 && damage < target.HP) + target.damage(damage, this); + + spend(TICK); + + return true; + } + + @Override + public void fx(boolean on) { + if (on) target.sprite.add( CharSprite.State.DARKENED ); + else if (target.invisible == 0) target.sprite.remove( CharSprite.State.DARKENED ); + } + + @Override + public int icon() { + return BuffIndicator.CORRUPT; + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public String desc() { + return Messages.get(this, "desc"); + } +} diff --git a/java/com/hmdzl/spspd/actors/buffs/CountDown.java b/java/com/hmdzl/spspd/actors/buffs/CountDown.java new file mode 100644 index 00000000..3b6d74aa --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/CountDown.java @@ -0,0 +1,85 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.ResultDescriptions; +import com.hmdzl.spspd.effects.particles.ShadowParticle; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.BuffIndicator; +import com.watabou.utils.Bundle; + +public class CountDown extends Buff { + + private int ticks = 0; + + private static final String TICKS = "ticks"; + + { + type = buffType.NEGATIVE; + } + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(TICKS, ticks); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + ticks = bundle.getInt(TICKS); + } + + + @Override + public int icon() { + return BuffIndicator.COUNTDOWN; + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public String desc() { + return Messages.get(this, "desc", ticks); + } + + @Override + public boolean act() { + if (target.isAlive()) { + ticks++; + if (ticks>5){ + target.sprite.emitter().burst(ShadowParticle.CURSE, 6); + target.damage(Math.round(target.HT / 4), this); + detach(); + } + } + + if (!target.isAlive() && target == Dungeon.hero) { + Dungeon.fail(Messages.format(ResultDescriptions.COUNTDOWN)); + //GLog.n(TXT_HERO_KILLED, toString()); + } + + spend(TICK); + + return true; + } +} diff --git a/java/com/hmdzl/spspd/actors/buffs/Cripple.java b/java/com/hmdzl/spspd/actors/buffs/Cripple.java new file mode 100644 index 00000000..54d68e33 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/Cripple.java @@ -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 + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.BuffIndicator; + +public class Cripple extends FlavourBuff { + + public static final float DURATION = 10f; + + { + type = buffType.NEGATIVE; + } + + @Override + public int icon() { + return BuffIndicator.CRIPPLE; + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public String heroMessage() { + return Messages.get(this, "heromsg"); + } + + @Override + public String desc() { + return Messages.get(this, "desc", dispTurns()); + } +} diff --git a/java/com/hmdzl/spspd/actors/buffs/DamageUp.java b/java/com/hmdzl/spspd/actors/buffs/DamageUp.java new file mode 100644 index 00000000..9e08955d --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/DamageUp.java @@ -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 + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.items.rings.RingOfElements.Resistance; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.BuffIndicator; +import com.watabou.utils.Bundle; + +public class DamageUp extends FlavourBuff { + + private int level = 0; + private static final String LEVEL = "level"; + protected float left; + @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); + } + + { + type = buffType.POSITIVE; + } + + public boolean act() { + spend(TICK); + return true; + } + @Override + public int icon() { + return BuffIndicator.ATTACK_UP; + } + + public int level() { + return level; + } + + public void level(int value) { + if (level < value) { + level = value; + } + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public String desc() { + return Messages.get(this, "desc",level()); + } + +} diff --git a/java/com/hmdzl/spspd/actors/buffs/DeadRaise.java b/java/com/hmdzl/spspd/actors/buffs/DeadRaise.java new file mode 100644 index 00000000..f1de81fc --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/DeadRaise.java @@ -0,0 +1,48 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2015 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.BuffIndicator; + +public class DeadRaise extends FlavourBuff { + + public static final float DURATION = 5f; + + { + type = buffType.NEGATIVE; + } + + @Override + public int icon() { + return BuffIndicator.TERROR; + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public String desc() { + return Messages.get(this, "desc", dispTurns()); + } +} diff --git a/java/com/hmdzl/spspd/actors/buffs/DefenceUp.java b/java/com/hmdzl/spspd/actors/buffs/DefenceUp.java new file mode 100644 index 00000000..894865ef --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/DefenceUp.java @@ -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 + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.items.rings.RingOfElements.Resistance; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.BuffIndicator; +import com.watabou.utils.Bundle; + +public class DefenceUp extends FlavourBuff { + + private int level = 0; + private static final String LEVEL = "level"; + protected float left; + private static final String LEFT = "left"; + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(LEVEL, level); + bundle.put(LEFT, left); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + level = bundle.getInt(LEVEL); + left = bundle.getFloat(LEFT); + } + + public void set(float duration) { + this.left = duration; + }; + + { + type = buffType.POSITIVE; + } + + private static final float DURATION = 20f; + + public boolean act() { + + spend(TICK); + left -= TICK; + if (left <= 0) + detach(); + return true; + + } + + @Override + public int icon() { + return BuffIndicator.ARMOR; + } + + public int level() { + return level; + } + + public void level(int value) { + if (level < value) { + level = value; + } + } + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public String desc() { + return Messages.get(this, "desc", dispTurns(),level()); + } + +} diff --git a/java/com/hmdzl/spspd/actors/buffs/Dewcharge.java b/java/com/hmdzl/spspd/actors/buffs/Dewcharge.java new file mode 100644 index 00000000..81e7afc1 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/Dewcharge.java @@ -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 + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.BuffIndicator; + +public class Dewcharge extends FlavourBuff { + + public static final float DURATION = 300f; + + @Override + public int icon() { + return BuffIndicator.DEWCHARGE; + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public String desc() { + return Messages.get(this, "desc", dispTurns(cooldown()+1)); + } + +} diff --git a/java/com/hmdzl/spspd/actors/buffs/Disarm.java b/java/com/hmdzl/spspd/actors/buffs/Disarm.java new file mode 100644 index 00000000..6ad8c9e5 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/Disarm.java @@ -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 + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.items.rings.RingOfElements.Resistance; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.BuffIndicator; + +public class Disarm extends FlavourBuff { + + { + type = buffType.NEGATIVE; + } + + private static final float DURATION = 5f; + + @Override + public int icon() { + return BuffIndicator.DISARM; + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public String desc() { + return Messages.get(this, "desc", dispTurns()); + } + + public static float duration(Char ch) { + Resistance r = ch.buff(Resistance.class); + return r != null ? r.durationFactor() * DURATION : DURATION; + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/buffs/Drowsy.java b/java/com/hmdzl/spspd/actors/buffs/Drowsy.java new file mode 100644 index 00000000..eba176f6 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/Drowsy.java @@ -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 + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.BuffIndicator; +import com.watabou.utils.Random; + +public class Drowsy extends Buff { + + { + type = buffType.NEUTRAL; + } + + + @Override + public int icon() { + return BuffIndicator.DROWSY; + } + + @Override + public boolean attachTo(Char target) { + if (!target.immunities().contains(Sleep.class) + && super.attachTo(target)) { + if (cooldown() == 0) + spend(Random.Int(3, 6)); + return true; + } + return false; + } + + @Override + public boolean act() { + Buff.affect(target, MagicalSleep.class); + + detach(); + return true; + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public String desc() { + return Messages.get(this, "desc", dispTurns(cooldown()+1)); + } +} diff --git a/java/com/hmdzl/spspd/actors/buffs/Dry.java b/java/com/hmdzl/spspd/actors/buffs/Dry.java new file mode 100644 index 00000000..5a6e23fc --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/Dry.java @@ -0,0 +1,48 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2015 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.BuffIndicator; + +public class Dry extends FlavourBuff { + + public static final float DURATION = 10f; + + { + type = buffType.NEGATIVE; + } + + @Override + public int icon() { + return BuffIndicator.DRY; + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public String desc() { + return Messages.get(this, "desc", dispTurns()); + } +} diff --git a/java/com/hmdzl/spspd/actors/buffs/EarthImbue.java b/java/com/hmdzl/spspd/actors/buffs/EarthImbue.java new file mode 100644 index 00000000..a482c2c6 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/EarthImbue.java @@ -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 + */ + +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.particles.EarthParticle; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.BuffIndicator; + +/** + * Created by debenhame on 19/11/2014. + */ +public class EarthImbue extends FlavourBuff { + + public static final float DURATION = 30f; + + public void proc(Char enemy) { + Buff.affect(enemy, Roots.class, 2); + CellEmitter.bottom(enemy.pos).start(EarthParticle.FACTORY, 0.05f, 8); + } + + @Override + public int icon() { + return BuffIndicator.PEARTH; + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public String desc() { + return Messages.get(this, "desc", dispTurns()); + } + + { + immunities.add(Paralysis.class); + immunities.add(Roots.class); + immunities.add(Slow.class); + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/buffs/ExitFind.java b/java/com/hmdzl/spspd/actors/buffs/ExitFind.java new file mode 100644 index 00000000..502a473e --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/ExitFind.java @@ -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 + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.messages.Messages; + +public class ExitFind extends FlavourBuff { + + public static final float DURATION = 1f; + + { + type = buffType.POSITIVE; + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public void detach() { + super.detach(); + Dungeon.observe(); + } + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/buffs/Feed.java b/java/com/hmdzl/spspd/actors/buffs/Feed.java new file mode 100644 index 00000000..e94e33f0 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/Feed.java @@ -0,0 +1,61 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2015 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.actors.blobs.ConfusionGas; +import com.hmdzl.spspd.actors.blobs.CorruptGas; +import com.hmdzl.spspd.actors.blobs.ElectriShock; +import com.hmdzl.spspd.actors.blobs.Fire; +import com.hmdzl.spspd.actors.blobs.Freezing; +import com.hmdzl.spspd.actors.blobs.ParalyticGas; +import com.hmdzl.spspd.actors.blobs.Regrowth; +import com.hmdzl.spspd.actors.blobs.ShockWeb; +import com.hmdzl.spspd.actors.blobs.StenchGas; +import com.hmdzl.spspd.actors.blobs.ToxicGas; +import com.hmdzl.spspd.actors.blobs.VenomGas; +import com.hmdzl.spspd.actors.blobs.weather.WeatherOfRain; +import com.hmdzl.spspd.actors.blobs.weather.WeatherOfSand; +import com.hmdzl.spspd.actors.blobs.weather.WeatherOfSnow; +import com.hmdzl.spspd.actors.blobs.weather.WeatherOfSun; +import com.hmdzl.spspd.actors.blobs.Web; +import com.hmdzl.spspd.levels.traps.LightningTrap; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.BuffIndicator; + +public class Feed extends FlavourBuff { + + public static final float DURATION = 30f; + + @Override + public int icon() { + return BuffIndicator.FEED; + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public String desc() { + return Messages.get(this, "desc", dispTurns()); + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/buffs/FireImbue.java b/java/com/hmdzl/spspd/actors/buffs/FireImbue.java new file mode 100644 index 00000000..789daf07 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/FireImbue.java @@ -0,0 +1,100 @@ +/* + * 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 + */ + +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.effects.particles.FlameParticle; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.Terrain; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.ui.BuffIndicator; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +/** + * Created by debenhame on 19/11/2014. + */ +public class FireImbue extends Buff { + + public static final float DURATION = 30f; + + 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 boolean act() { + if (Dungeon.level.map[target.pos] == Terrain.GRASS) { + Level.set(target.pos, Terrain.EMBERS); + GameScene.updateMap(target.pos); + } + + spend(TICK); + left -= TICK; + if (left <= 0) + detach(); + + return true; + } + + public void proc(Char enemy) { + if (Random.Int(2) == 0) + Buff.affect(enemy, Burning.class).reignite(enemy); + + enemy.sprite.emitter().burst(FlameParticle.FACTORY, 2); + } + + @Override + public int icon() { + return BuffIndicator.PFIRE; + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public String desc() { + return Messages.get(this, "desc", dispTurns(left)); + } + + { + immunities.add(Burning.class); + } +} diff --git a/java/com/hmdzl/spspd/actors/buffs/FlavourBuff.java b/java/com/hmdzl/spspd/actors/buffs/FlavourBuff.java new file mode 100644 index 00000000..2dac2e99 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/FlavourBuff.java @@ -0,0 +1,36 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.buffs; + +import java.text.DecimalFormat; + +//buff whose only logic is to wait and detach after a time. +public class FlavourBuff extends Buff { + + @Override + public boolean act() { + detach(); + return true; + } + + //flavour buffs can all just rely on cooldown() + protected String dispTurns() { + //add one turn as buffs act last, we want them to end at 1 visually, even if they end at 0 internally. + return dispTurns(cooldown()+1f); + } +} diff --git a/java/com/hmdzl/spspd/actors/buffs/ForeverShadow.java b/java/com/hmdzl/spspd/actors/buffs/ForeverShadow.java new file mode 100644 index 00000000..b45f415b --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/ForeverShadow.java @@ -0,0 +1,93 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2015 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.ConfusionGas; +import com.hmdzl.spspd.actors.blobs.CorruptGas; +import com.hmdzl.spspd.actors.blobs.ElectriShock; +import com.hmdzl.spspd.actors.blobs.Fire; +import com.hmdzl.spspd.actors.blobs.Freezing; +import com.hmdzl.spspd.actors.blobs.ParalyticGas; +import com.hmdzl.spspd.actors.blobs.Regrowth; +import com.hmdzl.spspd.actors.blobs.ShockWeb; +import com.hmdzl.spspd.actors.blobs.StenchGas; +import com.hmdzl.spspd.actors.blobs.ToxicGas; +import com.hmdzl.spspd.actors.blobs.VenomGas; +import com.hmdzl.spspd.actors.blobs.weather.WeatherOfRain; +import com.hmdzl.spspd.actors.blobs.weather.WeatherOfSand; +import com.hmdzl.spspd.actors.blobs.weather.WeatherOfSnow; +import com.hmdzl.spspd.actors.blobs.weather.WeatherOfSun; +import com.hmdzl.spspd.actors.blobs.Web; +import com.hmdzl.spspd.levels.traps.LightningTrap; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.CharSprite; +import com.hmdzl.spspd.ui.BuffIndicator; + +public class ForeverShadow extends FlavourBuff { + + public static final float DURATION = 30f; + + { + type = buffType.POSITIVE; + } + + @Override + public boolean attachTo(Char target) { + if (super.attachTo(target)) { + target.invisible++; + return true; + } else { + return false; + } + } + + @Override + public void detach() { + if (target.invisible > 0) + target.invisible--; + super.detach(); + } + + @Override + public void fx(boolean on) { + if (on) target.sprite.add( CharSprite.State.INVISIBLE ); + else if (target.invisible == 0) target.sprite.remove( CharSprite.State.INVISIBLE ); + } + + @Override + public int icon() { + return BuffIndicator.BLESS; + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + + + + @Override + public String desc() { + return Messages.get(this, "desc", dispTurns()); + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/buffs/Frost.java b/java/com/hmdzl/spspd/actors/buffs/Frost.java new file mode 100644 index 00000000..d2df6c5d --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/Frost.java @@ -0,0 +1,135 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.Freezing; +import com.hmdzl.spspd.actors.blobs.FrostGas; +import com.hmdzl.spspd.actors.blobs.weather.WeatherOfSnow; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.mobs.Thief; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.food.meatfood.FrozenCarpaccio; +import com.hmdzl.spspd.items.food.meatfood.MysteryMeat; +import com.hmdzl.spspd.items.potions.Potion; +import com.hmdzl.spspd.items.potions.PotionOfMight; +import com.hmdzl.spspd.items.potions.PotionOfStrength; +import com.hmdzl.spspd.items.rings.RingOfElements.Resistance; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.BuffIndicator; +import com.hmdzl.spspd.sprites.CharSprite; +import com.hmdzl.spspd.utils.GLog; + +public class Frost extends FlavourBuff { + + private static final float DURATION = 5f; + + { + type = buffType.NEGATIVE; + } + + @Override + public boolean attachTo(Char target) { + if (super.attachTo(target)) { + + target.paralysed++; + Buff.detach( target, Burning.class ); + Buff.detach( target, Chill.class ); + + if (target instanceof Hero) { + + Hero hero = (Hero) target; + Item item = hero.belongings.randomUnequipped(); + if (item instanceof Potion + && !(item instanceof PotionOfStrength || item instanceof PotionOfMight)){ + + item = item.detach(hero.belongings.backpack); + GLog.w( Messages.get(this, "freezes", item.toString())); + ((Potion) item).shatter(hero.pos); + + } else 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(); + } + GLog.w( Messages.get(this, "freezes", item.toString())); + + } + } else if (target instanceof Thief){ + Item item = ((Thief) target).item; + + if (item instanceof Potion && !(item instanceof PotionOfStrength || item instanceof PotionOfMight)) { + ((Potion) ((Thief) target).item).shatter(target.pos); + ((Thief) target).item = null; + } + } + + return true; + } else { + return false; + } + } + + @Override + public void detach() { + super.detach(); + if (target.paralysed > 0) + target.paralysed--; + if (Level.water[target.pos]) + Buff.prolong(target, Chill.class, 4f); + } + + @Override + public int icon() { + return BuffIndicator.FROST; + } + + //@Override + public void fx(boolean on) { + if (on) target.sprite.add(CharSprite.State.FROZEN); + else target.sprite.remove(CharSprite.State.FROZEN); + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public String desc() { + return Messages.get(this, "desc", dispTurns()); + } + + public static float duration(Char ch) { + Resistance r = ch.buff(Resistance.class); + return r != null ? r.durationFactor() * DURATION : DURATION; + } + + { + immunities.add( Chill.class ); + immunities.add( FrostGas.class ); + immunities.add( Freezing.class ); + immunities.add( Cold.class ); + immunities.add(WeatherOfSnow.class); + } + +} diff --git a/java/com/hmdzl/spspd/actors/buffs/FrostImbue.java b/java/com/hmdzl/spspd/actors/buffs/FrostImbue.java new file mode 100644 index 00000000..a0e1abe8 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/FrostImbue.java @@ -0,0 +1,62 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2019 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ + +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.effects.particles.SnowParticle; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.BuffIndicator; +import com.watabou.noosa.Image; + +public class FrostImbue extends FlavourBuff { + + { + type = buffType.POSITIVE; + } + + public static final float DURATION = 50f; + + public void proc(Char enemy){ + Buff.affect(enemy, Chill.class, 2f); + enemy.sprite.emitter().burst( SnowParticle.FACTORY, 2 ); + } + + @Override + public int icon() { + return BuffIndicator.FROST; + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public String desc() { + return Messages.get(this, "desc", dispTurns()); + } + + { + immunities.add( Frost.class ); + immunities.add( Chill.class ); + } +} diff --git a/java/com/hmdzl/spspd/actors/buffs/FullMoonStrength.java b/java/com/hmdzl/spspd/actors/buffs/FullMoonStrength.java new file mode 100644 index 00000000..871e01ad --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/FullMoonStrength.java @@ -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 + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.Statistics; +import com.hmdzl.spspd.messages.Messages; +import com.watabou.utils.Bundle; + +public class FullMoonStrength extends Buff { + + public static float LEVEL = 0.4f; + + private int hits = (Dungeon.checkNight() ? Math.max(8, Math.round(Statistics.deepestFloor/5)+9) : Math.max(2, Math.round(Statistics.deepestFloor/5)+3)); + + + private static final String HITS = "hits"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(HITS, hits); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + hits = bundle.getInt(HITS); + } + + //private int hits = Math.max(2, Math.round(Statistics.deepestFloor/5)+3); + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public String heroMessage() { + return Messages.get(this, "heromsg"); + } + + @Override + public String desc() { + return Messages.get(this, "desc"); + } + + @Override + public void detach() { + hits--; + if(hits==0){ + super.detach(); + } + } + +} diff --git a/java/com/hmdzl/spspd/actors/buffs/Fury.java b/java/com/hmdzl/spspd/actors/buffs/Fury.java new file mode 100644 index 00000000..7a7812cd --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/Fury.java @@ -0,0 +1,57 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.BuffIndicator; + +public class Fury extends Buff { + + public static float LEVEL = 0.5f; + + @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 Messages.get(this, "name"); + } + + @Override + public String heroMessage() { + return Messages.get(this, "heromsg"); + } + + @Override + public String desc() { + return Messages.get(this, "desc"); + } +} diff --git a/java/com/hmdzl/spspd/actors/buffs/GasesImmunity.java b/java/com/hmdzl/spspd/actors/buffs/GasesImmunity.java new file mode 100644 index 00000000..23c4011d --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/GasesImmunity.java @@ -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 + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.actors.blobs.ConfusionGas; +import com.hmdzl.spspd.actors.blobs.DarkGas; +import com.hmdzl.spspd.actors.blobs.ParalyticGas; +import com.hmdzl.spspd.actors.blobs.StenchGas; +import com.hmdzl.spspd.actors.blobs.TarGas; +import com.hmdzl.spspd.actors.blobs.ToxicGas; +import com.hmdzl.spspd.actors.blobs.weather.WeatherOfDead; +import com.hmdzl.spspd.actors.blobs.weather.WeatherOfRain; +import com.hmdzl.spspd.actors.blobs.weather.WeatherOfSand; +import com.hmdzl.spspd.actors.blobs.weather.WeatherOfSnow; +import com.hmdzl.spspd.actors.blobs.weather.WeatherOfSun; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.BuffIndicator; + +public class GasesImmunity extends FlavourBuff { + + public static final float DURATION = 15f; + + @Override + public int icon() { + return BuffIndicator.IMMUNITY; + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + { + immunities.add(ParalyticGas.class); + immunities.add(ToxicGas.class); + immunities.add(ConfusionGas.class); + immunities.add(StenchGas.class); + immunities.add(DarkGas.class); + immunities.add(TarGas.class); + immunities.add(Locked.class); + immunities.add(WeatherOfDead.class); + immunities.add(WeatherOfRain.class); + immunities.add(WeatherOfSun.class); + immunities.add(WeatherOfSnow.class); + immunities.add(WeatherOfSand.class); + } + + @Override + public String desc() { + return Messages.get(this, "desc", dispTurns()); + } +} diff --git a/java/com/hmdzl/spspd/actors/buffs/GlassShield.java b/java/com/hmdzl/spspd/actors/buffs/GlassShield.java new file mode 100644 index 00000000..b9c79f63 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/GlassShield.java @@ -0,0 +1,81 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.items.rings.RingOfElements.Resistance; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.BuffIndicator; +import com.watabou.utils.Bundle; + +public class GlassShield extends Buff { + + { + type = buffType.POSITIVE; + } + + private int turns = 0; + + @Override + public int icon() { + return BuffIndicator.GLASS_SHIELD; + } + + @Override + public void detach() { + turns--; + if(turns<=0){ + super.detach(); + } + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public String desc() { + return Messages.get(this, "desc",turns()); + } + + private static final String TURNS = "turns"; + + public int turns() { + return turns; + } + + public void turns(int value) { + if (turns< value) { + turns = value; + } + } + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(TURNS, turns); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + turns = bundle.getInt(TURNS); + } + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/buffs/GoldTouch.java b/java/com/hmdzl/spspd/actors/buffs/GoldTouch.java new file mode 100644 index 00000000..b6f8bcb8 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/GoldTouch.java @@ -0,0 +1,62 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2015 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.actors.blobs.ConfusionGas; +import com.hmdzl.spspd.actors.blobs.CorruptGas; +import com.hmdzl.spspd.actors.blobs.ElectriShock; +import com.hmdzl.spspd.actors.blobs.Fire; +import com.hmdzl.spspd.actors.blobs.Freezing; +import com.hmdzl.spspd.actors.blobs.ParalyticGas; +import com.hmdzl.spspd.actors.blobs.Regrowth; +import com.hmdzl.spspd.actors.blobs.ShockWeb; +import com.hmdzl.spspd.actors.blobs.StenchGas; +import com.hmdzl.spspd.actors.blobs.ToxicGas; +import com.hmdzl.spspd.actors.blobs.VenomGas; +import com.hmdzl.spspd.actors.blobs.weather.WeatherOfRain; +import com.hmdzl.spspd.actors.blobs.weather.WeatherOfSand; +import com.hmdzl.spspd.actors.blobs.weather.WeatherOfSnow; +import com.hmdzl.spspd.actors.blobs.weather.WeatherOfSun; +import com.hmdzl.spspd.actors.blobs.Web; +import com.hmdzl.spspd.levels.traps.LightningTrap; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.BuffIndicator; + +public class GoldTouch extends FlavourBuff { + + public static final float DURATION = 30f; + + @Override + public int icon() { + return BuffIndicator.GOLDTOUCH; + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + + @Override + public String desc() { + return Messages.get(this, "desc", dispTurns()); + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/buffs/GrowSeed.java b/java/com/hmdzl/spspd/actors/buffs/GrowSeed.java new file mode 100644 index 00000000..25909034 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/GrowSeed.java @@ -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 + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.ResultDescriptions; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.items.rings.RingOfElements.Resistance; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.CharSprite; +import com.hmdzl.spspd.ui.BuffIndicator; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public class GrowSeed extends Buff implements Hero.Doom { + + { + type = buffType.NEGATIVE; + } + + private static final float DURATION = 10f; + + 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()) { + + int dmg = Random.Int(1, target.HT/20); + + target.damage(dmg, this); + + int p = target.pos; + for (int n : Level.NEIGHBOURS8) { + Char ch = Actor.findChar(n+p); + if (ch != null && ch != target && ch.isAlive()) { + ch.HP +=Random.Int( Math.min(dmg,ch.HT - ch.HP)); + } + } + + + } else { + detach(); + } + + + spend(TICK); + left -= TICK; + + if (left <= 0) { + + detach(); + } + + return true; + } + + public void reignite(Char ch) { + left = duration(ch); + } + + @Override + public int icon() { + return BuffIndicator.GROW_SEED; + } + + @Override + public void fx(boolean on) { + if (on) target.sprite.add(CharSprite.State.REGROW); + else target.sprite.remove(CharSprite.State.REGROW); + } + + @Override + public String heroMessage() { + return Messages.get(this, "heromsg"); + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public String desc() { + return Messages.get(this, "desc", dispTurns(left)); + } + + public static float duration(Char ch) { + Resistance r = ch.buff(Resistance.class); + return r != null ? r.durationFactor() * DURATION : DURATION; + } + + @Override + public void onDeath() { + Dungeon.fail(Messages.format(ResultDescriptions.ITEM)); + } +} diff --git a/java/com/hmdzl/spspd/actors/buffs/Haste.java b/java/com/hmdzl/spspd/actors/buffs/Haste.java new file mode 100644 index 00000000..791bf797 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/Haste.java @@ -0,0 +1,43 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.items.rings.RingOfElements.Resistance; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.BuffIndicator; + +public class Haste extends FlavourBuff { + + public static final float DURATION = 10f; + + @Override + public int icon() { + return BuffIndicator.HASTE; + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public String desc() { + return Messages.get(this, "desc", dispTurns()); + } + +} diff --git a/java/com/hmdzl/spspd/actors/buffs/HighAttack.java b/java/com/hmdzl/spspd/actors/buffs/HighAttack.java new file mode 100644 index 00000000..2c039547 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/HighAttack.java @@ -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 + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.Terrain; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.BuffIndicator; +import com.watabou.utils.Bundle; + +public class HighAttack extends Buff { + + public static final float DURATION = 30f; + + private int level = 0; + private static final String LEVEL = "level"; + public static boolean nearwall = false; + + @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); + } + + + + { + type = buffType.POSITIVE; + } + + @Override + public boolean attachTo(Char target) { + if (super.attachTo(target)) { + return true; + } else { + return false; + } + } + + public boolean act() { + + if (target.isAlive()) { + for (int i = 0; i < Level.NEIGHBOURS8.length; i++) { + final int pos = target.pos + Level.NEIGHBOURS8[i]; + if (Dungeon.level.map[pos] == Terrain.WALL || + Dungeon.level.map[pos] == Terrain.WALL_DECO || + Dungeon.level.map[pos] == Terrain.UNBREAK_WALL || + Dungeon.level.map[pos] == Terrain.CHASM_WALL || + Dungeon.level.map[pos] == Terrain.DOOR || + Dungeon.level.map[pos] == Terrain.OPEN_DOOR|| + Dungeon.level.map[pos] == Terrain.SECRET_DOOR|| + Dungeon.level.map[pos] == Terrain.BARRICADE || + Dungeon.level.map[pos] == Terrain.BOOKSHELF + ) { + nearwall = true; + } + } + if (nearwall == false){ + detach(); + } else { + level++; + spend(TICK); + nearwall = false; + } + + } else { + detach(); + } + + return true; + } + + @Override + public void detach() { + super.detach(); + } + + @Override + public int icon() { + return BuffIndicator.HIGH_ATTACK; + } + + public int level() { + return level; + } + + public void level(int value) { + if (level < value) { + level = value; + } + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public String desc() { + return Messages.get(this, "desc",level); + } +} diff --git a/java/com/hmdzl/spspd/actors/buffs/HighLight.java b/java/com/hmdzl/spspd/actors/buffs/HighLight.java new file mode 100644 index 00000000..5143aaf5 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/HighLight.java @@ -0,0 +1,64 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.CharSprite; +import com.hmdzl.spspd.ui.BuffIndicator; + +public class HighLight extends FlavourBuff { + + public static final float DURATION = 500f; + public static final int DISTANCE = 10; + + @Override + public boolean attachTo(Char target) { + if (super.attachTo(target)) { + return true; + } else { + return false; + } + } + + @Override + public void detach() { + super.detach(); + } + + @Override + public int icon() { + return BuffIndicator.LIGHT; + } + + @Override + public void fx(boolean on) { + if (on) target.sprite.add(CharSprite.State.ILLUMINATED); + else target.sprite.remove(CharSprite.State.ILLUMINATED); + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public String desc() { + return Messages.get(this, "desc", dispTurns()); + } +} diff --git a/java/com/hmdzl/spspd/actors/buffs/HighVoice.java b/java/com/hmdzl/spspd/actors/buffs/HighVoice.java new file mode 100644 index 00000000..d4305d6c --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/HighVoice.java @@ -0,0 +1,90 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.BuffIndicator; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public class HighVoice extends FlavourBuff { + + public static final float DURATION = 10f; + + @Override + public int icon() { + return BuffIndicator.VOICE_UP; + } + + 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 boolean act() { + if (target.isAlive()) { + if (target.buff(HighVoice.class) != null && Random.Int(8) == 0) { + if (target.HP > target.HT*0.75 ){ + Buff.affect(target,Haste.class,5f); + GLog.p(Messages.get(this,"speed",Dungeon.hero.givenName())); + } else { + target.HP += (int)(target.HT/4); + GLog.p(Messages.get(this,"heal",Dungeon.hero.givenName())); + } + } + left -= TICK; + if (left <= 2) + detach(); + spend(TICK); + + + } else { + + detach(); + + } + + return true; + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public String desc() { + return Messages.get(this, "desc", dispTurns()); + } + +} diff --git a/java/com/hmdzl/spspd/actors/buffs/Hot.java b/java/com/hmdzl/spspd/actors/buffs/Hot.java new file mode 100644 index 00000000..3208298f --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/Hot.java @@ -0,0 +1,48 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2015 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.BuffIndicator; + +public class Hot extends FlavourBuff { + + public static final float DURATION = 10f; + + { + type = buffType.NEGATIVE; + } + + @Override + public int icon() { + return BuffIndicator.HOT; + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public String desc() { + return Messages.get(this, "desc", dispTurns()); + } +} diff --git a/java/com/hmdzl/spspd/actors/buffs/Hunger.java b/java/com/hmdzl/spspd/actors/buffs/Hunger.java new file mode 100644 index 00000000..61fbab21 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/Hunger.java @@ -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 + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.Challenges; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.ResultDescriptions; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.items.artifacts.Artifact; +import com.hmdzl.spspd.items.artifacts.HornOfPlenty; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.BuffIndicator; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Bundle; + +public class Hunger extends Buff implements Hero.Doom { + + private static final float STEP = 10f; + + public static final float OVERFED = 150f; + public static final float HUNGRY = 600f; + public static final float STARVING = 800f; + + private float level; + private float partialDamage; + + private static final String LEVEL = "level"; + private static final String PARTIALDAMAGE = "partialDamage"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(LEVEL, level); + bundle.put( PARTIALDAMAGE, partialDamage ); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + level = bundle.getFloat(LEVEL); + partialDamage = bundle.getFloat(PARTIALDAMAGE); + } + + @Override + public boolean act() { + if (target.isAlive()) { + + Hero hero = (Hero) target; + + if (isStarving()) { + + partialDamage += target.HT/100f; + + if (partialDamage > 1){ + target.damage( (int)partialDamage, this); + partialDamage -= (int)partialDamage; + } + + } else { + + float newLevel = level + STEP; + boolean statusUpdated = false; + if (newLevel <= OVERFED && level > OVERFED) { + + GLog.n(Messages.get(this, "onoverfed")); + statusUpdated = true; + + } else if (newLevel >= OVERFED && level < OVERFED) { + + statusUpdated = true; + + } else if (newLevel >= STARVING) { + + GLog.n(Messages.get(this, "onstarving")); + //hero.resting = false; + hero.damage(1, this); + statusUpdated = true; + + hero.interrupt(); + + } else if (newLevel >= HUNGRY && level < HUNGRY) { + + GLog.w(Messages.get(this, "onhungry")); + statusUpdated = true; + + } + level = newLevel; + + if (statusUpdated) { + BuffIndicator.refreshHero(); + } + + } + spend(target.buff(Shadows.class) == null ? STEP : STEP * 1.5f); + + } else { + + diactivate(); + + } + + return true; + } + + public void satisfy(float energy) { + Artifact.ArtifactBuff buff = target + .buff(HornOfPlenty.hornRecharge.class); + if (buff != null && buff.isCursed()) { + energy = Math.round(energy * 0.75f); + GLog.n(Messages.get(this, "cursedhorn")); + } + if (level>=800f) { + energy = Math.round(energy * 1.5f); + } + if(Dungeon.isChallenged(Challenges.ENERGY_LOST)){ + energy = Math.round(energy * 0.4f); + } + + reduceHunger( energy ); + + } + + public void reduceHunger( float energy ) { + + level -= energy; + if (level < 0) { + level = 0; + } else if (level > STARVING) { + level = STARVING; + } + + BuffIndicator.refreshHero(); + } + + public boolean isStarving() { + return level >= STARVING; + } + + public boolean isOverfed() { + return level <= OVERFED; + } + + public boolean isHungry() { + return (level >= HUNGRY && level < STARVING); + } + + public int hungerLevel() { + return (int) level; + } + + @Override + public int icon() { + if (level < OVERFED) { + return BuffIndicator.OVERFED; + } else if (level < HUNGRY) { + return BuffIndicator.NONE; + } else if (level < STARVING) { + return BuffIndicator.HUNGER; + } else { + return BuffIndicator.STARVATION; + } + } + + @Override + public String toString() { + if (level < OVERFED) { + return Messages.get(this, "overfed"); + } else if (level < HUNGRY) { + return Messages.get(this, "normal"); + } else if (level < STARVING) { + return Messages.get(this, "hungry"); + } else { + return Messages.get(this, "starving"); + } + } + + @Override + public String desc() { + String result; + if (level < OVERFED) { + result = Messages.get(this, "desc_intro_overfed"); + } else if (level < HUNGRY) { + result = Messages.get(this, "desc_intro_normal"); + } else if (level < STARVING) { + result = Messages.get(this, "desc_intro_hungry"); + } else { + result = Messages.get(this, "desc_intro_starving"); + } + + result += Messages.get(this, "desc"); + + return result; + } + + @Override + public void onDeath() { + + Badges.validateDeathFromHunger(); + + Dungeon.fail(Messages.format(ResultDescriptions.HUNGER)); + //GLog.n(TXT_DEATH); + } +} diff --git a/java/com/hmdzl/spspd/actors/buffs/Invisibility.java b/java/com/hmdzl/spspd/actors/buffs/Invisibility.java new file mode 100644 index 00000000..f3e9295f --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/Invisibility.java @@ -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 + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.items.artifacts.CloakOfShadows; +import com.hmdzl.spspd.items.artifacts.TimekeepersHourglass; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.CharSprite; +import com.hmdzl.spspd.ui.BuffIndicator; + +public class Invisibility extends FlavourBuff { + + public static final float DURATION = 15f; + + { + type = buffType.POSITIVE; + } + + @Override + public boolean attachTo(Char target) { + if (super.attachTo(target)) { + target.invisible++; + return true; + } else { + return false; + } + } + + @Override + public void detach() { + if (target.invisible > 0) + target.invisible--; + super.detach(); + } + + @Override + public int icon() { + return BuffIndicator.INVISIBLE; + } + + @Override + public void fx(boolean on) { + if (on) target.sprite.add( CharSprite.State.INVISIBLE ); + else if (target.invisible == 0) target.sprite.remove( CharSprite.State.INVISIBLE ); + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public String desc() { + return Messages.get(this, "desc", dispTurns()); + } + + public static void dispel() { + Invisibility buff = Dungeon.hero.buff(Invisibility.class); + if (buff != null) { + buff.detach(); + } + CloakOfShadows.cloakStealth cloakBuff = Dungeon.hero + .buff(CloakOfShadows.cloakStealth.class); + if (cloakBuff != null) { + cloakBuff.act(); + cloakBuff.detach(); + } + // this isn't a form of invisibilty, but it is meant to dispel at the + // same time as it. + TimekeepersHourglass.timeFreeze timeFreeze = Dungeon.hero + .buff(TimekeepersHourglass.timeFreeze.class); + if (timeFreeze != null) { + timeFreeze.detach(); + } + } +} diff --git a/java/com/hmdzl/spspd/actors/buffs/Levitation.java b/java/com/hmdzl/spspd/actors/buffs/Levitation.java new file mode 100644 index 00000000..9494cbc7 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/Levitation.java @@ -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 + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.CharSprite; +import com.hmdzl.spspd.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; + Buff.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 void fx(boolean on) { + if (on) target.sprite.add(CharSprite.State.LEVITATING); + else target.sprite.remove(CharSprite.State.LEVITATING); + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public String desc() { + return Messages.get(this, "desc", dispTurns()); + } +} diff --git a/java/com/hmdzl/spspd/actors/buffs/Light.java b/java/com/hmdzl/spspd/actors/buffs/Light.java new file mode 100644 index 00000000..cbda0228 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/Light.java @@ -0,0 +1,72 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.CharSprite; +import com.hmdzl.spspd.ui.BuffIndicator; + +public class Light extends FlavourBuff { + + public static final float DURATION = 300f; + public static final int DISTANCE = 6; + + @Override + public boolean attachTo(Char target) { + if (super.attachTo(target)) { + 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 void fx(boolean on) { + if (on) target.sprite.add(CharSprite.State.ILLUMINATED); + else target.sprite.remove(CharSprite.State.ILLUMINATED); + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public String desc() { + return Messages.get(this, "desc", dispTurns()); + } +} diff --git a/java/com/hmdzl/spspd/actors/buffs/Locked.java b/java/com/hmdzl/spspd/actors/buffs/Locked.java new file mode 100644 index 00000000..95417523 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/Locked.java @@ -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 + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.items.rings.RingOfElements.Resistance; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.BuffIndicator; + +public class Locked extends FlavourBuff { + + { + type = buffType.NEGATIVE; + } + + private static final float DURATION = 10f; + + @Override + public int icon() { + return BuffIndicator.LOCKED_FLOOR; + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public String desc() { + return Messages.get(this, "desc", dispTurns()); + } + + public static float duration(Char ch) { + Resistance r = ch.buff(Resistance.class); + return r != null ? r.durationFactor() * DURATION : DURATION; + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/buffs/LokisPoison.java b/java/com/hmdzl/spspd/actors/buffs/LokisPoison.java new file mode 100644 index 00000000..479a3c1f --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/LokisPoison.java @@ -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 + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.ResultDescriptions; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.particles.PoisonParticle; +import com.hmdzl.spspd.items.rings.RingOfElements.Resistance; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.BuffIndicator; +import com.watabou.utils.Bundle; + +public class LokisPoison extends Buff implements Hero.Doom { + + protected float left; + + private static final String LEFT = "left"; + + { + type = buffType.NEGATIVE; + } + + @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 Messages.get(this, "name"); + } + + @Override + public String heroMessage() { + return Messages.get(this, "heromsg"); + } + + @Override + public String desc() { + return Messages.get(this, "desc", dispTurns(left)); + } + + + @Override + public boolean attachTo(Char target) { + if (super.attachTo(target) && target.sprite != null){ + CellEmitter.center(target.pos).burst( PoisonParticle.SPLASH, 5 ); + return true; + } else + return false; + } + + @Override + public boolean act() { + if (target.isAlive()) { + + target.damage((int) (left / 2) + 1, 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(Messages.format(ResultDescriptions.POISON)); + //GLog.n("You died from poison..."); + } +} diff --git a/java/com/hmdzl/spspd/actors/buffs/MagicImmunity.java b/java/com/hmdzl/spspd/actors/buffs/MagicImmunity.java new file mode 100644 index 00000000..12530abf --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/MagicImmunity.java @@ -0,0 +1,74 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.buffs; + +import java.util.HashSet; + +import com.hmdzl.spspd.actors.blobs.ConfusionGas; +import com.hmdzl.spspd.actors.blobs.CorruptGas; +import com.hmdzl.spspd.actors.blobs.ParalyticGas; +import com.hmdzl.spspd.actors.blobs.StenchGas; +import com.hmdzl.spspd.actors.blobs.ToxicGas; +import com.hmdzl.spspd.actors.mobs.BrokenRobot; +import com.hmdzl.spspd.actors.mobs.Eye; +import com.hmdzl.spspd.actors.mobs.Warlock; +import com.hmdzl.spspd.actors.mobs.Yog; +import com.hmdzl.spspd.levels.traps.LightningTrap; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.BuffIndicator; + +public class MagicImmunity extends FlavourBuff { + + public static final float DURATION = 10f; + + { + type = buffType.POSITIVE; + } + + @Override + public int icon() { + return BuffIndicator.DISPEL; + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public String desc() { + return Messages.get(this, "desc", dispTurns()); + } + + { + immunities.add(ParalyticGas.class); + immunities.add(ToxicGas.class); + immunities.add(ConfusionGas.class); + immunities.add(StenchGas.class); + immunities.add(Burning.class); + immunities.add(ToxicGas.class); + immunities.add(Poison.class); + immunities.add(LightningTrap.Electricity.class); + immunities.add(Warlock.class); + immunities.add(Eye.class); + immunities.add(Yog.BurningFist.class); + immunities.add(BrokenRobot.class); + immunities.add(CorruptGas.class); + } +} + diff --git a/java/com/hmdzl/spspd/actors/buffs/MagicalSleep.java b/java/com/hmdzl/spspd/actors/buffs/MagicalSleep.java new file mode 100644 index 00000000..1c1ec546 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/MagicalSleep.java @@ -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 + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.BuffIndicator; +import com.hmdzl.spspd.utils.GLog; + +public class MagicalSleep extends Buff { + + private static final float STEP = 1f; + public static final float SWS = 1.5f; + + @Override + public boolean attachTo(Char target) { + if (super.attachTo(target) + && !target.immunities().contains(Sleep.class)) { + + if (target instanceof Hero) + if (target.HP == target.HT) { + GLog.i(Messages.get(this, "toohealthy")); + detach(); + return true; + } else { + GLog.i(Messages.get(this, "fallasleep")); + } + else if (target instanceof Mob) + ((Mob) target).state = ((Mob) target).SLEEPING; + + target.paralysed++; + + return true; + } else { + return false; + } + } + + @Override + public boolean act() { + if (target instanceof Hero) { + target.HP = Math.min(target.HP + 1, target.HT); + ((Hero) target).restoreHealth = true; + if (target.HP == target.HT) { + GLog.p(Messages.get(this, "wakeup")); + detach(); + } + } + spend(STEP); + return true; + } + + @Override + public void detach() { + if (target.paralysed > 0) + target.paralysed--; + if (target instanceof Hero) + ((Hero) target).restoreHealth = false; + super.detach(); + } + + @Override + public int icon() { + return BuffIndicator.MAGIC_SLEEP; + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public String desc() { + return Messages.get(this, "desc"); + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/buffs/MechArmor.java b/java/com/hmdzl/spspd/actors/buffs/MechArmor.java new file mode 100644 index 00000000..6c87d472 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/MechArmor.java @@ -0,0 +1,88 @@ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.CharSprite; +import com.hmdzl.spspd.ui.BuffIndicator; +import com.watabou.utils.Bundle; + +public class MechArmor extends Buff { + + private static final float STEP = 1f; + + private int level; + + + @Override + public boolean act() { + + if (target.isAlive()) { + spend(TICK); + level --; + if (level <= 1) { + detach(); + Buff.detach( target, ShieldArmor.class ); + } + + } else { + + detach(); + + } + + return true; + //spend(STEP); + //return true; + } + + public int absorb(int damage) { + if (level <= damage) { + detach(); + return damage - level; + } else { + level -= damage; + return 0; + } + } + + public void level(int value) { + if (level < value) { + level = value; + } + } + + @Override + public int icon() { + return BuffIndicator.MECHARMOR; + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public String desc() { + return Messages.get(this, "desc", 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); + } + + //@Override + public void fx(boolean on) { + if (on) target.sprite.add(CharSprite.State.ILLUMINATED); + else target.sprite.remove(CharSprite.State.ILLUMINATED); + } + } \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/buffs/MindVision.java b/java/com/hmdzl/spspd/actors/buffs/MindVision.java new file mode 100644 index 00000000..a43f24da --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/MindVision.java @@ -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 + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.BuffIndicator; + +public class MindVision extends FlavourBuff { + + public static final float DURATION = 40f; + + public int distance = 2; + + @Override + public int icon() { + return BuffIndicator.MIND_VISION; + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public void detach() { + super.detach(); + Dungeon.observe(); + } + + @Override + public String desc() { + return Messages.get(this, "desc", dispTurns()); + } +} diff --git a/java/com/hmdzl/spspd/actors/buffs/MirrorShield.java b/java/com/hmdzl/spspd/actors/buffs/MirrorShield.java new file mode 100644 index 00000000..8008616a --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/MirrorShield.java @@ -0,0 +1,64 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.items.rings.RingOfElements.Resistance; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.CharSprite; +import com.hmdzl.spspd.ui.BuffIndicator; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public class MirrorShield extends FlavourBuff { + + { + type = buffType.POSITIVE; + } + + public int proc(int damage, Char attacker) { + + int deflected = Random.NormalIntRange(damage/2, damage); + damage = 0; + + attacker.damage(deflected, this); + + return damage; + } + + public int icon() { + return BuffIndicator.MIRROR_SHIELD; + } + + @Override + public void fx(boolean on) { + if (on) target.sprite.add(CharSprite.State.ILLUMINATED); + else target.sprite.remove(CharSprite.State.ILLUMINATED); + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public String desc() { + return Messages.get(this, "desc", dispTurns()); + } + +} diff --git a/java/com/hmdzl/spspd/actors/buffs/Muscle.java b/java/com/hmdzl/spspd/actors/buffs/Muscle.java new file mode 100644 index 00000000..5edc7634 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/Muscle.java @@ -0,0 +1,49 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2015 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.BuffIndicator; + +public class Muscle extends FlavourBuff { + + public static final float DURATION = 200f; + + { + type = buffType.POSITIVE; + } + + + @Override + public int icon() { + return BuffIndicator.PBLOOD; + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public String desc() { + return Messages.get(this, "desc", dispTurns()); + } +} diff --git a/java/com/hmdzl/spspd/actors/buffs/Needling.java b/java/com/hmdzl/spspd/actors/buffs/Needling.java new file mode 100644 index 00000000..5689508c --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/Needling.java @@ -0,0 +1,80 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2015 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.ConfusionGas; +import com.hmdzl.spspd.actors.blobs.CorruptGas; +import com.hmdzl.spspd.actors.blobs.ElectriShock; +import com.hmdzl.spspd.actors.blobs.Fire; +import com.hmdzl.spspd.actors.blobs.Freezing; +import com.hmdzl.spspd.actors.blobs.ParalyticGas; +import com.hmdzl.spspd.actors.blobs.Regrowth; +import com.hmdzl.spspd.actors.blobs.ShockWeb; +import com.hmdzl.spspd.actors.blobs.StenchGas; +import com.hmdzl.spspd.actors.blobs.ToxicGas; +import com.hmdzl.spspd.actors.blobs.VenomGas; +import com.hmdzl.spspd.actors.blobs.weather.WeatherOfRain; +import com.hmdzl.spspd.actors.blobs.weather.WeatherOfSand; +import com.hmdzl.spspd.actors.blobs.weather.WeatherOfSnow; +import com.hmdzl.spspd.actors.blobs.weather.WeatherOfSun; +import com.hmdzl.spspd.actors.blobs.Web; +import com.hmdzl.spspd.levels.traps.LightningTrap; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.BuffIndicator; +import com.watabou.utils.Random; + +public class Needling extends FlavourBuff { + + public static final float DURATION = 30f; + + { + type = buffType.POSITIVE; + } + + public void proc(Char enemy) { + switch (Random.Int(2)){ + case 0: + Buff.affect(enemy, ArmorBreak.class,5f).level(50); + break; + case 1: + Buff.affect(enemy, Bleeding.class).set(10); + break; + } + } + + + @Override + public int icon() { + return BuffIndicator.NEEDLING; + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + + @Override + public String desc() { + return Messages.get(this, "desc", dispTurns()); + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/buffs/NewCombo.java b/java/com/hmdzl/spspd/actors/buffs/NewCombo.java new file mode 100644 index 00000000..d56df304 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/NewCombo.java @@ -0,0 +1,306 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2019 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ + +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.effects.Pushing; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.CellSelector; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.ui.ActionIndicator; +import com.hmdzl.spspd.ui.AttackIndicator; +import com.hmdzl.spspd.ui.BuffIndicator; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.noosa.Image; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Bundle; +import com.watabou.utils.Callback; +import com.watabou.utils.Random; + +public class NewCombo extends Buff implements ActionIndicator.Action { + + private int count = 0; + private float comboTime = 0f; + private int misses = 0; + + @Override + public int icon() { + return BuffIndicator.COMBO; + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + public void hit() { + + count++; + comboTime = 4f; + misses = 0; + + if (count >= 2) { + + ActionIndicator.setAction( this ); + GLog.p( Messages.get(this, "combo", count) ); + + } + + } + + public void miss(){ + misses++; + comboTime = 4f; + if (misses >= 2){ + detach(); + } + } + + @Override + public void detach() { + super.detach(); + ActionIndicator.clearAction(this); + } + + @Override + public boolean act() { + comboTime-=TICK; + spend(TICK); + if (comboTime <= 0) { + detach(); + } + return true; + } + + @Override + public String desc() { + String desc = Messages.get(this, "desc"); + + if (count >= 8)desc += "\n\n" + Messages.get(this, "crush_desc"); + else if (count >= 6)desc += "\n\n" + Messages.get(this, "slam_desc"); + else if (count >= 4)desc += "\n\n" + Messages.get(this, "cleave_desc"); + else if (count >= 2)desc += "\n\n" + Messages.get(this, "clobber_desc"); + + return desc; + } + + private static final String COUNT = "count"; + private static final String TIME = "combotime"; + private static final String MISSES= "misses"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(COUNT, count); + bundle.put(TIME, comboTime); + bundle.put(MISSES, misses); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + count = bundle.getInt( COUNT ); + if (count >= 2) ActionIndicator.setAction(this); + comboTime = bundle.getFloat( TIME ); + misses = bundle.getInt( MISSES ); + } + + @Override + public Image getIcon() { + Image icon; + + icon = new ItemSprite(new Item(){ {image = ItemSpriteSheet.ERROR_WEAPON; }}); + + if (count >= 8)icon.tint(0xFFFFCC00); + else if (count >= 6)icon.tint(0xFFFFFF00); + else if (count >= 4)icon.tint(0xFFCCFF00); + else icon.tint(0xFF00FF00); + + return icon; + } + + @Override + public void doAction() { + GameScene.selectCell(finisher); + } + + private enum finisherType{ + CLOBBER, CLEAVE, SLAM, CRUSH; + } + + private CellSelector.Listener finisher = new CellSelector.Listener() { + + private finisherType type; + + @Override + public void onSelect(Integer cell) { + if (cell == null) return; + final Char enemy = Actor.findChar( cell ); + if (enemy == null || !((Hero)target).canAttack(enemy) || target.isCharmedBy( enemy )){ + GLog.w( Messages.get(NewCombo.class, "bad_target") ); + } else { + target.sprite.attack(cell, new Callback() { + @Override + public void call() { + if (count >= 8)type = finisherType.CRUSH; + else if (count >= 6)type = finisherType.SLAM; + else if (count >= 4)type = finisherType.CLEAVE; + else type = finisherType.CLOBBER; + doAttack(enemy); + } + }); + } + } + + private void doAttack(final Char enemy){ + + AttackIndicator.target(enemy); + + int dmg = target.damageRoll(); + + //variance in damage dealt + switch(type){ + case CLOBBER: + dmg = Math.round(dmg*0.6f); + break; + case CLEAVE: + dmg = Math.round(dmg*1.5f); + break; + case SLAM: + //rolls 2 times, takes the highest roll + int dmgReroll = target.damageRoll(); + if (dmgReroll > dmg) dmg = dmgReroll; + dmg = Math.round(dmg*1.6f); + break; + case CRUSH: + //rolls 4 times, takes the highest roll + for (int i = 1; i < 4; i++) { + dmgReroll = target.damageRoll(); + if (dmgReroll > dmg) dmg = dmgReroll; + } + dmg = Math.round(dmg*2.5f); + break; + } + + dmg -= Random.IntRange( 0, enemy.drRoll() ); + dmg = target.attackProc(enemy, dmg); + dmg = enemy.defenseProc(target, dmg); + enemy.damage( dmg, this ); + + //special effects + switch (type){ + case CLOBBER: + if (enemy.isAlive()){ + if (!enemy.properties().contains(Char.Property.IMMOVABLE)){ + for (int i = 0; i < Level.NEIGHBOURS8.length; i++) { + int ofs = Level.NEIGHBOURS8[i]; + if (enemy.pos - target.pos == ofs) { + int newPos = enemy.pos + ofs; + if ((Level.passable[newPos] || Level.avoid[newPos]) && Actor.findChar( newPos ) == null) { + + Actor.addDelayed( new Pushing( enemy, enemy.pos, newPos ), -1 ); + + enemy.pos = newPos; + // FIXME + if (enemy instanceof Mob) { + Dungeon.level.mobPress( (Mob)enemy ); + } else { + Dungeon.level.press( newPos, enemy ); + } + + } + break; + } + } + } + Buff.prolong(enemy, Vertigo.class, Random.NormalIntRange(1, 4)); + } + break; + case SLAM: + Buff.affect(target,ShieldArmor.class).level((int)(dmg/5)); + break; + default: + //nothing + break; + } + + if (target.buff(FireImbue.class) != null) + target.buff(FireImbue.class).proc(enemy); + if (target.buff(EarthImbue.class) != null) + target.buff(EarthImbue.class).proc(enemy); + if (target.buff(FrostImbue.class) != null) + target.buff(FrostImbue.class).proc(enemy); + if (target.buff(BloodImbue.class) != null) + target.buff(BloodImbue.class).proc(enemy); + + Sample.INSTANCE.play( Assets.SND_HIT, 1, 1, Random.Float( 0.8f, 1.25f ) ); + enemy.sprite.bloodBurstA( target.sprite.center(), dmg ); + enemy.sprite.flash(); + + if (!enemy.isAlive()){ + GLog.i( Messages.capitalize(Messages.get(Char.class, "defeat", enemy.name)) ); + } + + Hero hero = (Hero)target; + + //Post-attack behaviour + switch(type) { + case CLEAVE: + if (!enemy.isAlive()) { + //combo isn't reset, but rather increments with a cleave kill, and grants more time. + hit(); + comboTime = 10f; + } else { + detach(); + ActionIndicator.clearAction(NewCombo.this); + } + hero.spendAndNext(hero.attackDelay()); + break; + + default: + detach(); + ActionIndicator.clearAction(NewCombo.this); + hero.spendAndNext(hero.attackDelay()); + break; + } + + } + + @Override + public String prompt() { + if (count >= 8)return Messages.get(NewCombo.class, "crush_prompt"); + else if (count >= 6)return Messages.get(NewCombo.class, "slam_prompt"); + else if (count >= 4)return Messages.get(NewCombo.class, "cleave_prompt"); + else return Messages.get(NewCombo.class, "clobber_prompt"); + } + }; + } + diff --git a/java/com/hmdzl/spspd/actors/buffs/Notice.java b/java/com/hmdzl/spspd/actors/buffs/Notice.java new file mode 100644 index 00000000..44dfcc2f --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/Notice.java @@ -0,0 +1,63 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2015 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.actors.blobs.ConfusionGas; +import com.hmdzl.spspd.actors.blobs.CorruptGas; +import com.hmdzl.spspd.actors.blobs.ElectriShock; +import com.hmdzl.spspd.actors.blobs.Fire; +import com.hmdzl.spspd.actors.blobs.Freezing; +import com.hmdzl.spspd.actors.blobs.ParalyticGas; +import com.hmdzl.spspd.actors.blobs.Regrowth; +import com.hmdzl.spspd.actors.blobs.ShockWeb; +import com.hmdzl.spspd.actors.blobs.StenchGas; +import com.hmdzl.spspd.actors.blobs.ToxicGas; +import com.hmdzl.spspd.actors.blobs.VenomGas; +import com.hmdzl.spspd.actors.blobs.weather.WeatherOfRain; +import com.hmdzl.spspd.actors.blobs.weather.WeatherOfSand; +import com.hmdzl.spspd.actors.blobs.weather.WeatherOfSnow; +import com.hmdzl.spspd.actors.blobs.weather.WeatherOfSun; +import com.hmdzl.spspd.actors.blobs.Web; +import com.hmdzl.spspd.levels.traps.LightningTrap; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.BuffIndicator; + +public class Notice extends FlavourBuff { + + public static final float DURATION = 30f; + + @Override + public int icon() { + return BuffIndicator.NOTICE; + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + + + @Override + public String desc() { + return Messages.get(this, "desc", dispTurns()); + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/buffs/Ooze.java b/java/com/hmdzl/spspd/actors/buffs/Ooze.java new file mode 100644 index 00000000..8b8b0e20 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/Ooze.java @@ -0,0 +1,71 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2014 Oleg Dolya + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.ResultDescriptions; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.BuffIndicator; +import com.watabou.utils.Random; + +public class Ooze extends Buff { + + { + type = buffType.NEGATIVE; + } + + @Override + public int icon() { + return BuffIndicator.OOZE; + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public String heroMessage() { + return Messages.get(this, "heromsg"); + } + + @Override + public String desc() { + return Messages.get(this, "desc"); + } + + @Override + public boolean act() { + if (target.isAlive()) { + if (Dungeon.depth > 4) + target.damage(Dungeon.depth / 5, this); + else if (Random.Int(2) == 0) + target.damage(1, this); + if (!target.isAlive() && target == Dungeon.hero) { + Dungeon.fail(Messages.format(ResultDescriptions.OOZE)); + //GLog.n(TXT_HERO_KILLED, toString()); + } + spend(TICK); + } + if (Level.water[target.pos]) { + detach(); + } + return true; + } +} diff --git a/java/com/hmdzl/spspd/actors/buffs/Paralysis.java b/java/com/hmdzl/spspd/actors/buffs/Paralysis.java new file mode 100644 index 00000000..4130a313 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/Paralysis.java @@ -0,0 +1,81 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.items.rings.RingOfElements.Resistance; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.CharSprite; +import com.hmdzl.spspd.ui.BuffIndicator; + +public class Paralysis extends FlavourBuff { + + private static final float DURATION = 10f; + + { + type = buffType.NEGATIVE; + } + + @Override + public boolean attachTo(Char target) { + if (super.attachTo(target)) { + target.paralysed++; + return true; + } else { + return false; + } + } + + @Override + public void detach() { + super.detach(); + if (target.paralysed > 0) + target.paralysed--; + } + + @Override + public int icon() { + return BuffIndicator.PARALYSIS; + } + + @Override + public void fx(boolean on) { + if (on) target.sprite.add(CharSprite.State.PARALYSED); + else target.sprite.remove(CharSprite.State.PARALYSED); + } + + @Override + public String heroMessage() { + return Messages.get(this, "heromsg"); + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public String desc() { + return Messages.get(this, "desc", dispTurns()); + } + + public static float duration(Char ch) { + Resistance r = ch.buff(Resistance.class); + return r != null ? r.durationFactor() * DURATION : DURATION; + } +} diff --git a/java/com/hmdzl/spspd/actors/buffs/ParyAttack.java b/java/com/hmdzl/spspd/actors/buffs/ParyAttack.java new file mode 100644 index 00000000..cb244278 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/ParyAttack.java @@ -0,0 +1,104 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.BuffIndicator; +import com.watabou.utils.Bundle; + +public class ParyAttack extends Buff { + + private int pos; + private int level = 0; + private static final String LEVEL = "level"; + private static final String POS = "pos"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(POS, pos); + bundle.put(LEVEL, level); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + pos = bundle.getInt(POS); + level = bundle.getInt(LEVEL); + } + + { + type = buffType.POSITIVE; + } + + + @Override + public boolean attachTo(Char target) { + pos = target.pos; + return super.attachTo(target); + } + + public boolean act() { + + if (target.isAlive()) { + + if (target.pos != pos) { + detach(); + } + + level++; + spend(TICK); + + } else { + detach(); + } + + return true; + } + + @Override + public void detach() { + super.detach(); + } + + @Override + public int icon() { + return BuffIndicator.BLESS; + } + + public int level() { + return level; + } + + public void level(int value) { + if (level < value) { + level = value; + } + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public String desc() { + return Messages.get(this, "desc",level/2.5); + } +} diff --git a/java/com/hmdzl/spspd/actors/buffs/PinCushion.java b/java/com/hmdzl/spspd/actors/buffs/PinCushion.java new file mode 100644 index 00000000..0c30d261 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/PinCushion.java @@ -0,0 +1,45 @@ +package com.hmdzl.spspd.actors.buffs; + +import java.util.ArrayList; +import java.util.Collection; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.weapon.missiles.MissileWeapon; +import com.watabou.utils.Bundle; + +/** + * Created by debenhame on 06/02/2015. + */ +public class PinCushion extends Buff { + + private ArrayList items = new ArrayList(); + + public void stick(MissileWeapon item) { + items.add(item); + } + + @Override + public void detach() { + for (Item item : items) + Dungeon.level.drop(item, target.pos).sprite.drop(); + super.detach(); + } + + private static final String ITEMS = "items"; + + @Override + public void storeInBundle(Bundle bundle) { + bundle.put(ITEMS, items); + super.storeInBundle(bundle); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + items = new ArrayList( + (Collection) ((Collection) bundle + .getCollection(ITEMS))); + super.restoreFromBundle(bundle); + } + +} diff --git a/java/com/hmdzl/spspd/actors/buffs/Poison.java b/java/com/hmdzl/spspd/actors/buffs/Poison.java new file mode 100644 index 00000000..beebf50c --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/Poison.java @@ -0,0 +1,116 @@ +/* +` * 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 + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.ResultDescriptions; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.particles.PoisonParticle; +import com.hmdzl.spspd.items.rings.RingOfElements.Resistance; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.BuffIndicator; +import com.watabou.utils.Bundle; + +public class Poison extends Buff implements Hero.Doom { + + 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 Messages.get(this, "name"); + } + + @Override + public String heroMessage() { + return Messages.get(this, "heromsg"); + } + + @Override + public String desc() { + return Messages.get(this, "desc", dispTurns(left)); + } + + @Override + public boolean attachTo(Char target) { + if (super.attachTo(target) && target.sprite != null){ + CellEmitter.center(target.pos).burst( PoisonParticle.SPLASH, 5 ); + return true; + } else + return false; + } + + @Override + public boolean act() { + if (target.isAlive()) { + + target.damage((int) (left / 2) + 1, 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(Messages.format(ResultDescriptions.POISON)); + //GLog.n("You died from poison..."); + } +} diff --git a/java/com/hmdzl/spspd/actors/buffs/Recharging.java b/java/com/hmdzl/spspd/actors/buffs/Recharging.java new file mode 100644 index 00000000..88191b1e --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/Recharging.java @@ -0,0 +1,53 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2015 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.BuffIndicator; + +public class Recharging extends FlavourBuff { + + public static final float DURATION = 40f; + + @Override + public int icon() { + return BuffIndicator.RECHARGING; + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + //want to process partial turns for this buff, and not count it when it's expiring. + //firstly, if this buff has half a turn left, should give out half the benefit. + //secondly, recall that buffs execute in random order, so this can cause a problem where we can't simply check + //if this buff is still attached, must instead directly check its remaining time, and act accordingly. + //otherwise this causes inconsistent behaviour where this may detach before, or after, a wand charger acts. + public float remainder() { + return Math.min(1f, this.cooldown()); + } + + @Override + public String desc() { + return Messages.get(this, "desc", dispTurns()); + } +} diff --git a/java/com/hmdzl/spspd/actors/buffs/Regeneration.java b/java/com/hmdzl/spspd/actors/buffs/Regeneration.java new file mode 100644 index 00000000..e6dd6522 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/Regeneration.java @@ -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 + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.hero.HeroClass; +import com.hmdzl.spspd.actors.hero.HeroSubClass; +import com.hmdzl.spspd.items.artifacts.ChaliceOfBlood; + +public class Regeneration extends Buff { + + private static final float REGENERATION_DELAY = 25; + + @Override + public boolean act() { + if (target.isAlive()) { + if (!((Hero) target).isStarving()){ + if (Dungeon.hero.subClass == HeroSubClass.PASTOR && target.HP < target.HT*1.5){ + target.HP += 2*Math.max(1,(int)(Dungeon.hero.lvl/5)); + } else if (target.HP < target.HT) { + target.HP += Math.min((target.HT - target.HP),Math.max(1,(int)(Dungeon.hero.lvl/5))); + } + } + + ChaliceOfBlood.chaliceRegen regenBuff = Dungeon.hero + .buff(ChaliceOfBlood.chaliceRegen.class); + + if (regenBuff != null) { + if (regenBuff.isCursed()) { + spend(REGENERATION_DELAY * 2f); + } else { + spend(Math.max(REGENERATION_DELAY - 2*regenBuff.level(), 5f)); + } + } else if (Dungeon.hero.heroClass== HeroClass.PERFORMER && Dungeon.skins == 2) { + spend(REGENERATION_DELAY*0.6f); + } else { spend(REGENERATION_DELAY);} + + } else { + + diactivate(); + + } + + return true; + } +} diff --git a/java/com/hmdzl/spspd/actors/buffs/Rhythm.java b/java/com/hmdzl/spspd/actors/buffs/Rhythm.java new file mode 100644 index 00000000..d5365df6 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/Rhythm.java @@ -0,0 +1,43 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.items.rings.RingOfElements.Resistance; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.BuffIndicator; + +public class Rhythm extends FlavourBuff { + + public static final float DURATION = 10f; + + @Override + public int icon() { + return BuffIndicator.RHYTHM; + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public String desc() { + return Messages.get(this, "desc", dispTurns()); + } + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/buffs/Rhythm2.java b/java/com/hmdzl/spspd/actors/buffs/Rhythm2.java new file mode 100644 index 00000000..7ad51d7c --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/Rhythm2.java @@ -0,0 +1,43 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.items.rings.RingOfElements.Resistance; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.BuffIndicator; + +public class Rhythm2 extends FlavourBuff { + + public static final float DURATION = 10f; + + @Override + public int icon() { + return BuffIndicator.RHYTHM2; + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public String desc() { + return Messages.get(this, "desc", dispTurns()); + } + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/buffs/Roots.java b/java/com/hmdzl/spspd/actors/buffs/Roots.java new file mode 100644 index 00000000..5d9c08e1 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/Roots.java @@ -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 + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.BuffIndicator; + +public class Roots extends FlavourBuff { + + { + type = buffType.NEGATIVE; + } + + @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 Messages.get(this, "name"); + } + + @Override + public String heroMessage() { + return Messages.get(this, "heromsg"); + } + + @Override + public String desc() { + return Messages.get(this, "desc", dispTurns()); + } +} diff --git a/java/com/hmdzl/spspd/actors/buffs/Shadows.java b/java/com/hmdzl/spspd/actors/buffs/Shadows.java new file mode 100644 index 00000000..8204e2ec --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/Shadows.java @@ -0,0 +1,106 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.BuffIndicator; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Bundle; + +public class Shadows extends Invisibility { + + protected float left; + + private static final String LEFT = "left"; + + { + type = buffType.SILENT; + } + + @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 Messages.get(this, "name"); + } + + @Override + public String desc() { + return Messages.get(this, "desc"); + } + +} diff --git a/java/com/hmdzl/spspd/actors/buffs/Shield.java b/java/com/hmdzl/spspd/actors/buffs/Shield.java new file mode 100644 index 00000000..660a103b --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/Shield.java @@ -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 + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.Statistics; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.BuffIndicator; + +public class Shield extends Buff { + + public static float LEVEL = 0.4f; + + private int hits = (Dungeon.checkNight() ? Math.max(8, Math.round(Statistics.deepestFloor/5)+9) : Math.max(2, Math.round(Statistics.deepestFloor/5)+3)); + //private int hits = Math.max(2, Math.round(Statistics.deepestFloor/5)+3); + + { + type = buffType.POSITIVE; + } + + @Override + public int icon() { + return BuffIndicator.DISPEL; + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public String desc() { + return Messages.get(this, "desc"); + } + + @Override + public void detach() { + hits--; + if(hits==0){ + super.detach(); + } + } + +} diff --git a/java/com/hmdzl/spspd/actors/buffs/ShieldArmor.java b/java/com/hmdzl/spspd/actors/buffs/ShieldArmor.java new file mode 100644 index 00000000..3949dc36 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/ShieldArmor.java @@ -0,0 +1,65 @@ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.BuffIndicator; +import com.watabou.utils.Bundle; + +public class ShieldArmor extends Buff { + + private static final float STEP = 1f; + + private int level; + + + @Override + public boolean act() { + spend(STEP); + return true; + } + + public int absorb(int damage) { + if (level <= damage) { + detach(); + return damage - level; + } else { + level -= damage; + return 0; + } + } + + public void level(int value) { + if (level < value) { + level = value; + } + } + + @Override + public int icon() { + return BuffIndicator.ARMOR; + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public String desc() { + return Messages.get(this, "desc", 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); + } + } \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/buffs/Shieldblock.java b/java/com/hmdzl/spspd/actors/buffs/Shieldblock.java new file mode 100644 index 00000000..f70dcff6 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/Shieldblock.java @@ -0,0 +1,73 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.items.rings.RingOfElements.Resistance; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.CharSprite; +import com.hmdzl.spspd.ui.BuffIndicator; + +public class Shieldblock extends FlavourBuff { + + private static final float DURATION = 10f; + + @Override + public boolean attachTo(Char target) { + if (super.attachTo(target)) { + target.paralysed ++ ; + return true; + } else { + return false; + } + } + + @Override + public void detach() { + super.detach(); + if (target.paralysed > 0) + target.paralysed--; + } + + @Override + public int icon() { + return BuffIndicator.SHIELDBLOCK; + } + + @Override + public void fx(boolean on) { + if (on) target.sprite.add(CharSprite.State.PARALYSED); + else target.sprite.remove(CharSprite.State.PARALYSED); + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public String desc() { + return Messages.get(this, "desc", dispTurns()); + } + + public static float duration(Char ch) { + Resistance r = ch.buff(Resistance.class); + return r != null ? r.durationFactor() * DURATION : DURATION; + } + +} diff --git a/java/com/hmdzl/spspd/actors/buffs/Shocked.java b/java/com/hmdzl/spspd/actors/buffs/Shocked.java new file mode 100644 index 00000000..be81e3a4 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/Shocked.java @@ -0,0 +1,109 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Yet Another Pixel Dungeon + * Copyright (C) 2015-2016 Considered Hamster + * + * 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 + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.BuffIndicator; + +public class Shocked extends FlavourBuff { + + //private static final String TXT_DISARMED = "Sudden shock have made you drop your %s on the ground!"; + public static final float DURATION = 5f; + + { + type = buffType.NEGATIVE; + } + + @Override + public int icon() { + return BuffIndicator.SHOCKED; + } + + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public String desc() { + return Messages.get(this, "desc", dispTurns()); + } + + /*@Override + public boolean act(){ + + Wet wet = target.buff(Wet.class); + + + if( target.isAlive()){ + if( !target.flying && Level.water[ target.pos ] || wet!= null){ + discharge(); + } else spend(TICK); + } + + if (Level.flamable[target.pos] && !target.flying) { + detach(); + } + return super.act(); + } + + public void discharge() { + + target.damage(Random.IntRange(target.HT/4,target.HT/6),this); + +// target.sprite.showStatus( CharSprite.NEGATIVE, "ZAP!"); + + if( target instanceof Hero ) { + + Camera.main.shake( 2, 0.3f ); + + Hero hero = (Hero)target; + EquipableItem weapon = hero.belongings.weapon; + + if( weapon != null && !(weapon instanceof Knuckles || weapon instanceof FightGloves) + && !weapon.cursed) { + GLog.w(Messages.get(this, "knock",weapon.name())); + weapon.doDrop(hero); + + } + + } else { + Buff.prolong(target,Paralysis.class,2f ); + } + + /*if (target.sprite.visible) { + target.sprite.centerEmitter().burst( SparkParticle.FACTORY, (int)Math.ceil( duration ) + 1 ); + } + + detach(); + }; + + @Override + public void onDeath() { + + //Badges.validateDeathFromFire(); + + Dungeon.fail(Messages.format(ResultDescriptions.POISON)); + //GLog.n(TXT_BURNED_TO_DEATH); + }*/ + +} diff --git a/java/com/hmdzl/spspd/actors/buffs/Silent.java b/java/com/hmdzl/spspd/actors/buffs/Silent.java new file mode 100644 index 00000000..ad235d6e --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/Silent.java @@ -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 + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.items.rings.RingOfElements.Resistance; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.BuffIndicator; + +public class Silent extends FlavourBuff { + + { + type = buffType.NEGATIVE; + } + + private static final float DURATION = 5f; + + @Override + public int icon() { + return BuffIndicator.SILENT; + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public String desc() { + return Messages.get(this, "desc", dispTurns()); + } + + public static float duration(Char ch) { + Resistance r = ch.buff(Resistance.class); + return r != null ? r.durationFactor() * DURATION : DURATION; + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/buffs/Sleep.java b/java/com/hmdzl/spspd/actors/buffs/Sleep.java new file mode 100644 index 00000000..f6a7e292 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/Sleep.java @@ -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 + */ +package com.hmdzl.spspd.actors.buffs; + +public class Sleep extends FlavourBuff { + + public static final float SWS = 1.5f; + +} diff --git a/java/com/hmdzl/spspd/actors/buffs/Slow.java b/java/com/hmdzl/spspd/actors/buffs/Slow.java new file mode 100644 index 00000000..bad42534 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/Slow.java @@ -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 + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.items.rings.RingOfElements.Resistance; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.BuffIndicator; + +public class Slow extends FlavourBuff { + + { + type = buffType.NEGATIVE; + } + + private static final float DURATION = 10f; + + @Override + public int icon() { + return BuffIndicator.SLOW; + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public String desc() { + return Messages.get(this, "desc", dispTurns()); + } + + public static float duration(Char ch) { + Resistance r = ch.buff(Resistance.class); + return r != null ? r.durationFactor() * DURATION : DURATION; + } +} diff --git a/java/com/hmdzl/spspd/actors/buffs/SnipersMark.java b/java/com/hmdzl/spspd/actors/buffs/SnipersMark.java new file mode 100644 index 00000000..eef33234 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/SnipersMark.java @@ -0,0 +1,57 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.BuffIndicator; +import com.watabou.utils.Bundle; + +public class SnipersMark extends FlavourBuff { + + public int object = 0; + + private static final String OBJECT = "object"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(OBJECT, object); + + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + object = bundle.getInt(OBJECT); + } + + @Override + public int icon() { + return BuffIndicator.MARK; + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public String desc() { + return Messages.get(this, "desc"); + } +} diff --git a/java/com/hmdzl/spspd/actors/buffs/SoulBless.java b/java/com/hmdzl/spspd/actors/buffs/SoulBless.java new file mode 100644 index 00000000..88547b7d --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/SoulBless.java @@ -0,0 +1,62 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2015 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.actors.blobs.ConfusionGas; +import com.hmdzl.spspd.actors.blobs.CorruptGas; +import com.hmdzl.spspd.actors.blobs.ElectriShock; +import com.hmdzl.spspd.actors.blobs.Fire; +import com.hmdzl.spspd.actors.blobs.Freezing; +import com.hmdzl.spspd.actors.blobs.ParalyticGas; +import com.hmdzl.spspd.actors.blobs.Regrowth; +import com.hmdzl.spspd.actors.blobs.ShockWeb; +import com.hmdzl.spspd.actors.blobs.StenchGas; +import com.hmdzl.spspd.actors.blobs.ToxicGas; +import com.hmdzl.spspd.actors.blobs.VenomGas; +import com.hmdzl.spspd.actors.blobs.weather.WeatherOfRain; +import com.hmdzl.spspd.actors.blobs.weather.WeatherOfSand; +import com.hmdzl.spspd.actors.blobs.weather.WeatherOfSnow; +import com.hmdzl.spspd.actors.blobs.weather.WeatherOfSun; +import com.hmdzl.spspd.actors.blobs.Web; +import com.hmdzl.spspd.levels.traps.LightningTrap; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.BuffIndicator; + +public class SoulBless extends FlavourBuff { + + public static final float DURATION = 30f; + + @Override + public int icon() { + return BuffIndicator.BLESS; + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + + @Override + public String desc() { + return Messages.get(this, "desc", dispTurns()); + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/buffs/SoulMark.java b/java/com/hmdzl/spspd/actors/buffs/SoulMark.java new file mode 100644 index 00000000..8928455d --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/SoulMark.java @@ -0,0 +1,54 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2015 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.CharSprite; +import com.hmdzl.spspd.ui.BuffIndicator; + +public class SoulMark extends FlavourBuff { + + public static final float DURATION = 10f; + + { + type = buffType.NEGATIVE; + } + + @Override + public int icon() { + return BuffIndicator.CORRUPT; + } + + public void fx(boolean on) { + if (on) target.sprite.add(CharSprite.State.MARKED); + else target.sprite.remove(CharSprite.State.MARKED); + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public String desc() { + return Messages.get(this, "desc", dispTurns()); + } +} diff --git a/java/com/hmdzl/spspd/actors/buffs/SpAttack.java b/java/com/hmdzl/spspd/actors/buffs/SpAttack.java new file mode 100644 index 00000000..85dc0b75 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/SpAttack.java @@ -0,0 +1,44 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2015 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.BuffIndicator; + +public class SpAttack extends FlavourBuff { + + public static final float DURATION = 30f; + + @Override + public int icon() { + return BuffIndicator.SMASH; + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public String desc() { + return Messages.get(this, "desc", dispTurns()); + } +} diff --git a/java/com/hmdzl/spspd/actors/buffs/Speed.java b/java/com/hmdzl/spspd/actors/buffs/Speed.java new file mode 100644 index 00000000..6612dc72 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/Speed.java @@ -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 + */ +package com.hmdzl.spspd.actors.buffs; + +public class Speed extends FlavourBuff { + + public static final float DURATION = 10f; + +} diff --git a/java/com/hmdzl/spspd/actors/buffs/StoneIce.java b/java/com/hmdzl/spspd/actors/buffs/StoneIce.java new file mode 100644 index 00000000..2c35efc8 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/StoneIce.java @@ -0,0 +1,136 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.ResultDescriptions; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.items.rings.RingOfElements; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.CharSprite; +import com.hmdzl.spspd.ui.BuffIndicator; +import com.watabou.utils.Bundle; + +public class StoneIce extends Buff { + + private int pos; + private float left; + private static final String LEFT = "left"; + private static final String POS = "pos"; + private static final float DURATION = 8f; + + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(POS, pos); + bundle.put(LEFT, left); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + pos = bundle.getInt(POS); + left = bundle.getInt(LEFT); + } + + { + type = buffType.NEGATIVE; + } + + + @Override + public boolean attachTo(Char target) { + pos = target.pos; + return super.attachTo(target); + } + + public boolean act() { + + if (target.isAlive()) { + + if (target.pos != pos) { + pos = 0; + if (target.pos != -1) pos = target.pos; + target.damage(Math.min(1000,target.HT/20),this); + } + + Buff.detach( target, Burning.class); + + } else { + detach(); + } + + spend(TICK); + left -= TICK; + + if (left <= 0 ) { + detach(); + } + + return true; + } + + public void reignite(Char ch) { + left = duration(ch); + } + + @Override + public int icon() { + return BuffIndicator.STONE_ICE; + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public String desc() { + return Messages.get(this, "desc",left); + } + + public void set(float duration) { + this.left = duration; + }; + + public float level() { return left; } + + public void level(int value) { + if (left < value) { + left = value; + } + } + + public static float duration(Char ch) { + if (ch.isAlive() && (Level.water[ch.pos] && !ch.flying)){ + return DURATION; + } else return DURATION; + + } + + public void onDeath() { + + Badges.validateDeathFromFire(); + Dungeon.fail(Messages.format(ResultDescriptions.BURNING)); + + } + +} diff --git a/java/com/hmdzl/spspd/actors/buffs/Strength.java b/java/com/hmdzl/spspd/actors/buffs/Strength.java new file mode 100644 index 00000000..fb29363f --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/Strength.java @@ -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 + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.BuffIndicator; + +public class Strength extends Buff { + + public static float LEVEL = 0.4f; + + @Override + public int icon() { + return BuffIndicator.MOON_FURY; + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public String desc() { + return Messages.get(this, "desc"); + } + + @Override + public void detach() { + + Buff buff = Dungeon.hero.buff(FullMoonStrength.class); + if (buff != null){ + + buff.detach(); + } else { + super.detach(); + } + + } +} diff --git a/java/com/hmdzl/spspd/actors/buffs/Tar.java b/java/com/hmdzl/spspd/actors/buffs/Tar.java new file mode 100644 index 00000000..48dfc687 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/Tar.java @@ -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 + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.BuffIndicator; + +public class Tar extends Buff { + + { + type = buffType.NEGATIVE; + } + + @Override + public int icon() { + return BuffIndicator.TAR; + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public String heroMessage() { + return Messages.get(this, "heromsg"); + } + + @Override + public String desc() { + return Messages.get(this, "desc"); + } + + @Override + public boolean act() { + if (target.isAlive()) { + Burning burning = target.buff(Burning.class); + if (target.isAlive() && burning!=null){ + Buff.affect(target,Burning.class).reignite(target); + } + spend(TICK); + } + if (Level.water[target.pos] && !target.flying) { + detach(); + } + + return true; + } +} diff --git a/java/com/hmdzl/spspd/actors/buffs/TargetShoot.java b/java/com/hmdzl/spspd/actors/buffs/TargetShoot.java new file mode 100644 index 00000000..a7d10d4f --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/TargetShoot.java @@ -0,0 +1,41 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.BuffIndicator; + +public class TargetShoot extends FlavourBuff { + + public static final float DURATION = 30f; + + @Override + public int icon() { + return BuffIndicator.MARK; + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public String desc() { + return Messages.get(this, "desc", dispTurns()); + } +} diff --git a/java/com/hmdzl/spspd/actors/buffs/Taunt.java b/java/com/hmdzl/spspd/actors/buffs/Taunt.java new file mode 100644 index 00000000..b589bdbb --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/Taunt.java @@ -0,0 +1,41 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.items.rings.RingOfElements.Resistance; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.BuffIndicator; +import com.watabou.utils.Bundle; + +public class Taunt extends Buff { + + { + type = buffType.NEGATIVE; + } + + @Override + public boolean act() { + if (target.isAlive()) { + spend(TICK); + } + return true; + } + +} diff --git a/java/com/hmdzl/spspd/actors/buffs/Terror.java b/java/com/hmdzl/spspd/actors/buffs/Terror.java new file mode 100644 index 00000000..f4c2db7a --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/Terror.java @@ -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 + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.BuffIndicator; +import com.watabou.utils.Bundle; + +public class Terror extends FlavourBuff { + + public static final float DURATION = 10f; + + public int object = 0; + + private static final String OBJECT = "object"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(OBJECT, object); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + object = bundle.getInt(OBJECT); + } + + @Override + public int icon() { + return BuffIndicator.TERROR; + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public String desc() { + return Messages.get(this, "desc", dispTurns()); + } + + public static void recover(Char target) { + Terror terror = target.buff(Terror.class); + if (terror != null && terror.cooldown() < DURATION) { + target.remove(terror); + } + } +} diff --git a/java/com/hmdzl/spspd/actors/buffs/ToxicImbue.java b/java/com/hmdzl/spspd/actors/buffs/ToxicImbue.java new file mode 100644 index 00000000..4f96c8a6 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/ToxicImbue.java @@ -0,0 +1,87 @@ +/* + * 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 + */ + +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.actors.blobs.Blob; +import com.hmdzl.spspd.actors.blobs.ToxicGas; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.ui.BuffIndicator; +import com.watabou.utils.Bundle; + +/** + * Created by debenhame on 19/11/2014. + */ +public class ToxicImbue extends Buff { + + public static final float DURATION = 30f; + + 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 boolean act() { + GameScene.add(Blob.seed(target.pos, 50, ToxicGas.class)); + + spend(TICK); + left -= TICK; + if (left <= 0) + detach(); + + return true; + } + + @Override + public int icon() { + return BuffIndicator.PTOXIC; + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public String desc() { + return Messages.get(this, "desc", dispTurns(left)); + } + + { + immunities.add(ToxicGas.class); + immunities.add(Poison.class); + } +} diff --git a/java/com/hmdzl/spspd/actors/buffs/Venom.java b/java/com/hmdzl/spspd/actors/buffs/Venom.java new file mode 100644 index 00000000..93e82959 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/Venom.java @@ -0,0 +1,91 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2015 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.BuffIndicator; +import com.watabou.utils.Bundle; + +public class Venom extends Poison implements Hero.Doom { + + private int damage = 1; + + private static final String DAMAGE = "damage"; + + { + type = buffType.NEGATIVE; + } + + @Override + public void storeInBundle( Bundle bundle ) { + super.storeInBundle( bundle ); + bundle.put( DAMAGE, damage ); + + } + + @Override + public void restoreFromBundle( Bundle bundle ) { + super.restoreFromBundle( bundle ); + damage = bundle.getInt( DAMAGE ); + } + + public void set(float duration, int damage) { + set(duration); + this.damage = damage; + } + + @Override + public int icon() { + return BuffIndicator.POISON; + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public String desc() { + return Messages.get(this, "desc", dispTurns(left), damage); + } + + @Override + public boolean act() { + if (target.isAlive()) { + target.damage(damage, this); + if (damage < ((Dungeon.depth+1)/2)+1) + damage++; + + //want it to act after the cloud of venom it came from. + spend( TICK+0.1f ); + if ((left -= TICK) <= 0) { + detach(); + } + } else { + detach(); + } + + return true; + } + +} diff --git a/java/com/hmdzl/spspd/actors/buffs/Vertigo.java b/java/com/hmdzl/spspd/actors/buffs/Vertigo.java new file mode 100644 index 00000000..1770e246 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/Vertigo.java @@ -0,0 +1,51 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.items.rings.RingOfElements.Resistance; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.BuffIndicator; + +public class Vertigo extends FlavourBuff { + + public static final float DURATION = 10f; + + { + type = buffType.NEGATIVE; + } + + @Override + public int icon() { + return BuffIndicator.VERTIGO; + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public String desc() { + return Messages.get(this, "desc", dispTurns()); + } + + public static float duration(Char ch) { + Resistance r = ch.buff(Resistance.class); + return r != null ? r.durationFactor() * DURATION : DURATION; + } +} diff --git a/java/com/hmdzl/spspd/actors/buffs/WarGroove.java b/java/com/hmdzl/spspd/actors/buffs/WarGroove.java new file mode 100644 index 00000000..00a75d11 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/WarGroove.java @@ -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 + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.BuffIndicator; + +public class WarGroove extends Buff { + + @Override + public int icon() { + return BuffIndicator.WARGROOVE; + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public String desc() { + return Messages.get(this, "desc"); + } + + @Override + public void detach() { + super.detach(); + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/buffs/Weakness.java b/java/com/hmdzl/spspd/actors/buffs/Weakness.java new file mode 100644 index 00000000..00759a12 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/Weakness.java @@ -0,0 +1,80 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.items.rings.RingOfElements.Resistance; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.BuffIndicator; + +public class Weakness extends FlavourBuff { + + private static final float DURATION = 40f; + + { + type = buffType.NEGATIVE; + } + + @Override + public int icon() { + return BuffIndicator.WEAKNESS; + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public boolean attachTo(Char target) { + if (super.attachTo(target) && target==Dungeon.hero) { + Hero hero = (Hero) target; + hero.weakened = true; + hero.belongings.discharge(); + + return true; + } else { + return false; + } + } + + @Override + public void detach() { + super.detach(); + if (target==Dungeon.hero){ + ((Hero) target).weakened = false; + } + } + + public static float duration(Char ch) { + Resistance r = ch.buff(Resistance.class); + return r != null ? r.durationFactor() * DURATION : DURATION; + } + + @Override + public String heroMessage() { + return Messages.get(this, "heromsg"); + } + + @Override + public String desc() { + return Messages.get(this, "desc", dispTurns()); + } +} diff --git a/java/com/hmdzl/spspd/actors/buffs/Wet.java b/java/com/hmdzl/spspd/actors/buffs/Wet.java new file mode 100644 index 00000000..bfb079ef --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/Wet.java @@ -0,0 +1,48 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2015 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.actors.buffs; + +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.BuffIndicator; + +public class Wet extends FlavourBuff { + + public static final float DURATION = 10f; + + { + type = buffType.NEGATIVE; + } + + @Override + public int icon() { + return BuffIndicator.WET; + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public String desc() { + return Messages.get(this, "desc", dispTurns()); + } +} diff --git a/java/com/hmdzl/spspd/actors/buffs/armorbuff/GlyphDark.java b/java/com/hmdzl/spspd/actors/buffs/armorbuff/GlyphDark.java new file mode 100644 index 00000000..c72c4d9b --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/armorbuff/GlyphDark.java @@ -0,0 +1,27 @@ +package com.hmdzl.spspd.actors.buffs.armorbuff; + +import com.hmdzl.spspd.actors.blobs.weather.WeatherOfDead; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.CountDown; +import com.hmdzl.spspd.actors.buffs.DeadRaise; +import com.hmdzl.spspd.actors.buffs.Silent; +import com.hmdzl.spspd.actors.buffs.Weakness; +import com.hmdzl.spspd.actors.mobs.DwarfLich; +import com.hmdzl.spspd.actors.mobs.Fiend; +import com.hmdzl.spspd.actors.mobs.Warlock; + +public class GlyphDark extends Buff { + + { + immunities.add( Weakness.class ); + immunities.add( CountDown.class ); + immunities.add( DeadRaise.class ); + immunities.add( Silent.class ); + immunities.add( WeatherOfDead.class ); + + resistances.add( DwarfLich.class ); + resistances.add( Warlock.class ); + resistances.add( Fiend.class ); + } + + } \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/buffs/armorbuff/GlyphEarth.java b/java/com/hmdzl/spspd/actors/buffs/armorbuff/GlyphEarth.java new file mode 100644 index 00000000..3092dc4b --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/armorbuff/GlyphEarth.java @@ -0,0 +1,22 @@ +package com.hmdzl.spspd.actors.buffs.armorbuff; + +import com.hmdzl.spspd.actors.blobs.weather.WeatherOfSand; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Ooze; +import com.hmdzl.spspd.actors.buffs.Poison; +import com.hmdzl.spspd.actors.buffs.Roots; +import com.hmdzl.spspd.actors.buffs.Weakness; +import com.hmdzl.spspd.actors.mobs.DwarfLich; +import com.hmdzl.spspd.actors.mobs.Fiend; +import com.hmdzl.spspd.actors.mobs.Warlock; + + public class GlyphEarth extends Buff { + + { + immunities.add( Roots.class ); + immunities.add( Ooze.class ); + immunities.add( Poison.class ); + immunities.add(WeatherOfSand.class ); + } + + } \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/buffs/armorbuff/GlyphElectricity.java b/java/com/hmdzl/spspd/actors/buffs/armorbuff/GlyphElectricity.java new file mode 100644 index 00000000..275e7465 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/armorbuff/GlyphElectricity.java @@ -0,0 +1,29 @@ +package com.hmdzl.spspd.actors.buffs.armorbuff; + +import com.hmdzl.spspd.actors.blobs.ElectriShock; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Locked; +import com.hmdzl.spspd.actors.buffs.Shocked; +import com.hmdzl.spspd.actors.buffs.Weakness; +import com.hmdzl.spspd.actors.mobs.DwarfLich; +import com.hmdzl.spspd.actors.mobs.Fiend; +import com.hmdzl.spspd.actors.mobs.GnollShaman; +import com.hmdzl.spspd.actors.mobs.Shell; +import com.hmdzl.spspd.actors.mobs.Warlock; +import com.hmdzl.spspd.items.wands.WandOfLightning; +import com.hmdzl.spspd.levels.traps.LightningTrap; + +public class GlyphElectricity extends Buff { + + { + resistances.add( Shell.class ); + resistances.add( GnollShaman.class ); + + immunities.add( WandOfLightning.class ); + immunities.add( Shocked.class ); + immunities.add( ElectriShock.class ); + immunities.add( Locked.class ); + immunities.add( LightningTrap.Electricity.class ); + } + + } \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/buffs/armorbuff/GlyphFire.java b/java/com/hmdzl/spspd/actors/buffs/armorbuff/GlyphFire.java new file mode 100644 index 00000000..680781ef --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/armorbuff/GlyphFire.java @@ -0,0 +1,29 @@ +package com.hmdzl.spspd.actors.buffs.armorbuff; + +import com.hmdzl.spspd.actors.blobs.Fire; +import com.hmdzl.spspd.actors.blobs.TarGas; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Burning; +import com.hmdzl.spspd.actors.buffs.Hot; +import com.hmdzl.spspd.actors.buffs.Tar; +import com.hmdzl.spspd.actors.buffs.Weakness; +import com.hmdzl.spspd.actors.mobs.DwarfLich; +import com.hmdzl.spspd.actors.mobs.Fiend; +import com.hmdzl.spspd.actors.mobs.FireElemental; +import com.hmdzl.spspd.actors.mobs.Warlock; +import com.hmdzl.spspd.actors.mobs.Yog; + +public class GlyphFire extends Buff { + + { + immunities.add( Burning.class ); + resistances.add( FireElemental.class ); + resistances.add( Yog.BurningFist.class ); + immunities.add( Fire.class ); + immunities.add( Tar.class ); + immunities.add( TarGas.class ); + + immunities.add( Hot.class ); + } + + } \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/buffs/armorbuff/GlyphIce.java b/java/com/hmdzl/spspd/actors/buffs/armorbuff/GlyphIce.java new file mode 100644 index 00000000..0f56b4ed --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/armorbuff/GlyphIce.java @@ -0,0 +1,24 @@ + +package com.hmdzl.spspd.actors.buffs.armorbuff; + +import com.hmdzl.spspd.actors.blobs.weather.WeatherOfSnow; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Chill; +import com.hmdzl.spspd.actors.buffs.Cold; +import com.hmdzl.spspd.actors.buffs.Frost; +import com.hmdzl.spspd.actors.buffs.Weakness; +import com.hmdzl.spspd.actors.mobs.DwarfLich; +import com.hmdzl.spspd.actors.mobs.Fiend; +import com.hmdzl.spspd.actors.mobs.Warlock; + +public class GlyphIce extends Buff { + + { + immunities.add( Frost.class ); + immunities.add( Cold.class ); + immunities.add( Chill.class ); + immunities.add(WeatherOfSnow.class ); + + } + + } \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/buffs/armorbuff/GlyphLight.java b/java/com/hmdzl/spspd/actors/buffs/armorbuff/GlyphLight.java new file mode 100644 index 00000000..0830f055 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/armorbuff/GlyphLight.java @@ -0,0 +1,23 @@ +package com.hmdzl.spspd.actors.buffs.armorbuff; + +import com.hmdzl.spspd.actors.blobs.weather.WeatherOfSun; +import com.hmdzl.spspd.actors.buffs.Blindness; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Charm; +import com.hmdzl.spspd.actors.buffs.Vertigo; +import com.hmdzl.spspd.actors.buffs.Weakness; +import com.hmdzl.spspd.actors.mobs.DwarfLich; +import com.hmdzl.spspd.actors.mobs.Fiend; +import com.hmdzl.spspd.actors.mobs.SewerHeart; +import com.hmdzl.spspd.actors.mobs.Warlock; + + public class GlyphLight extends Buff { + + { + immunities.add( Blindness.class ); + immunities.add( Vertigo.class ); + immunities.add( Charm.class ); + immunities.add(WeatherOfSun.class ); + } + + } \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/buffs/faithbuff/BalanceFaith.java b/java/com/hmdzl/spspd/actors/buffs/faithbuff/BalanceFaith.java new file mode 100644 index 00000000..540958b7 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/faithbuff/BalanceFaith.java @@ -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 + */ +package com.hmdzl.spspd.actors.buffs.faithbuff; + +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.BuffIndicator; + +public class BalanceFaith extends Buff { + + @Override + public int icon() { + return BuffIndicator.BALANCE_FAITH; + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public String desc() { + return Messages.get(this, "desc"); + } + + @Override + public boolean act() { + if (target.isAlive()) { + spend(TICK); + } + return true; + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/buffs/faithbuff/DemonFaith.java b/java/com/hmdzl/spspd/actors/buffs/faithbuff/DemonFaith.java new file mode 100644 index 00000000..23fe10d7 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/faithbuff/DemonFaith.java @@ -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 + */ +package com.hmdzl.spspd.actors.buffs.faithbuff; + +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.BuffIndicator; + +public class DemonFaith extends Buff { + + @Override + public int icon() { + return BuffIndicator.DEMON_FAITH; + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public String desc() { + return Messages.get(this, "desc"); + } + + @Override + public boolean act() { + if (target.isAlive()) { + spend(TICK); + } + return true; + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/buffs/faithbuff/HumanFaith.java b/java/com/hmdzl/spspd/actors/buffs/faithbuff/HumanFaith.java new file mode 100644 index 00000000..1cf39972 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/faithbuff/HumanFaith.java @@ -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 + */ +package com.hmdzl.spspd.actors.buffs.faithbuff; + +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.BuffIndicator; + +public class HumanFaith extends Buff { + + @Override + public int icon() { + return BuffIndicator.HUMAN_FAITH; + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public String desc() { + return Messages.get(this, "desc"); + } + + @Override + public boolean act() { + if (target.isAlive()) { + spend(TICK); + } + return true; + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/buffs/faithbuff/LifeFaith.java b/java/com/hmdzl/spspd/actors/buffs/faithbuff/LifeFaith.java new file mode 100644 index 00000000..da6022e7 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/faithbuff/LifeFaith.java @@ -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 + */ +package com.hmdzl.spspd.actors.buffs.faithbuff; + +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.BuffIndicator; + +public class LifeFaith extends Buff { + + @Override + public int icon() { + return BuffIndicator.LIFE_FAITH; + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public String desc() { + return Messages.get(this, "desc"); + } + + @Override + public boolean act() { + if (target.isAlive()) { + spend(TICK); + } + return true; + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/buffs/faithbuff/MechFaith.java b/java/com/hmdzl/spspd/actors/buffs/faithbuff/MechFaith.java new file mode 100644 index 00000000..ffeba214 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/buffs/faithbuff/MechFaith.java @@ -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 + */ +package com.hmdzl.spspd.actors.buffs.faithbuff; + +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.BuffIndicator; + +public class MechFaith extends Buff { + + @Override + public int icon() { + return BuffIndicator.MECH_FAITH; + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public String desc() { + return Messages.get(this, "desc"); + } + + @Override + public boolean act() { + if (target.isAlive()) { + spend(TICK); + } + return true; + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/hero/Belongings.java b/java/com/hmdzl/spspd/actors/hero/Belongings.java new file mode 100644 index 00000000..07f1ebea --- /dev/null +++ b/java/com/hmdzl/spspd/actors/hero/Belongings.java @@ -0,0 +1,355 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.hero; + +import java.util.Iterator; + +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.KindOfArmor; +import com.hmdzl.spspd.items.KindOfWeapon; +import com.hmdzl.spspd.items.KindofMisc; +import com.hmdzl.spspd.items.bags.Bag; +import com.hmdzl.spspd.items.keys.IronKey; +import com.hmdzl.spspd.items.keys.Key; +import com.hmdzl.spspd.items.scrolls.ScrollOfRemoveCurse; +import com.hmdzl.spspd.items.wands.Wand; +import com.hmdzl.spspd.items.weapon.guns.GunWeapon; +import com.hmdzl.spspd.messages.Messages; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public class Belongings implements Iterable { + + public static final int BACKPACK_SIZE = 29; + + private Hero owner; + + public Bag backpack; + + public KindOfWeapon weapon = null; + public KindOfArmor armor = null; + public KindofMisc misc1 = null; + public KindofMisc misc2 = null; + public KindofMisc misc3 = null; + + public Belongings(Hero owner) { + this.owner = owner; + + backpack = new Bag() { + { + name = Messages.get(Bag.class, "name"); + size = BACKPACK_SIZE; + } + }; + backpack.owner = owner; + } + + private static final String WEAPON = "weapon"; + private static final String ARMOR = "armor"; + private static final String MISC1 = "misc1"; + private static final String MISC2 = "misc2"; + private static final String MISC3 = "misc3"; + + public void storeInBundle(Bundle bundle) { + + backpack.storeInBundle(bundle); + + bundle.put(WEAPON, weapon); + bundle.put(ARMOR, armor); + bundle.put(MISC1, misc1); + bundle.put(MISC2, misc2); + bundle.put(MISC3, misc3); + } + + public void restoreFromBundle(Bundle bundle) { + + backpack.clear(); + backpack.restoreFromBundle(bundle); + + weapon = (KindOfWeapon) bundle.get(WEAPON); + if (weapon != null) { + weapon.activate(owner); + } + + armor = (KindOfArmor) bundle.get(ARMOR); + if (armor != null) { + armor.activate(owner); + } + //armor = (Armor) bundle.get(ARMOR); + + misc1 = (KindofMisc) bundle.get(MISC1); + if (misc1 != null) { + misc1.activate(owner); + } + + misc2 = (KindofMisc) bundle.get(MISC2); + if (misc2 != null) { + misc2.activate(owner); + } + + misc3 = (KindofMisc) bundle.get(MISC3); + if (misc3 != null) { + misc3.activate(owner); + } + + } + + @SuppressWarnings("unchecked") + public T getItem(Class itemClass) { + + for (Item item : this) { + if (itemClass.isInstance(item)) { + return (T) item; + } + } + + return null; + } + + @SuppressWarnings("unchecked") + public T getKey(Class kind, int depth) { + + for (Item item : backpack) { + if (item.getClass() == kind && ((Key) item).depth == depth) { + return (T) item; + } + } + + return null; + } + + public void countIronKeys() { + + IronKey.curDepthQuantity = 0; + + for (Item item : backpack) { + if (item instanceof IronKey + && ((IronKey) item).depth == Dungeon.depth) { + IronKey.curDepthQuantity += item.quantity(); + } + } + } + + 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 (misc1 != null) { + misc1.identify(); + Badges.validateItemLevelAquired(misc1); + } + if (misc2 != null) { + misc2.identify(); + Badges.validateItemLevelAquired(misc2); + } + if (misc3 != null) { + misc3.identify(); + Badges.validateItemLevelAquired(misc3); + } + for (Item item : backpack) { + item.cursedKnown = true; + } + } + + public void observeS() { + for (Item item : backpack) { + item.cursedKnown = true; + } + } + + public void uncurseEquipped() { + ScrollOfRemoveCurse.uncurse(owner, armor, weapon, misc1, misc2, misc3); + } + + 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) { + item.detachAll(backpack); + //you keep the bag itself, not its contents. + if (item instanceof Bag){ + ((Bag)item).clear(); + } + item.collect(); + } else if (!item.isEquipped( owner )) { + item.detachAll( backpack ); + } + } + + if (weapon != null) { + weapon.cursed = false; + weapon.activate(owner); + } + + if (armor != null) { + armor.cursed = false; + armor.activate(owner); + } + + if (misc1 != null) { + misc1.cursed = false; + misc1.activate(owner); + } + if (misc2 != null) { + misc2.cursed = false; + misc2.activate(owner); + } + if (misc3 != null) { + misc3.cursed = false; + misc3.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 relord() { + + int count = 0; + + for (Item item : this) { + if (item instanceof GunWeapon) { + GunWeapon gunweapon = (GunWeapon) item; + gunweapon.charge = gunweapon.charge + 1; + count++; + gunweapon.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 iterator() { + return new ItemIterator(); + } + + private class ItemIterator implements Iterator { + + private int index = 0; + + private Iterator backpackIterator = backpack.iterator(); + + private Item[] equipped = { weapon, armor, misc1, misc2 ,misc3 }; + 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] = misc1 = null; + break; + case 3: + equipped[3] = misc2 = null; + break; + case 4: + equipped[4] = misc3 = null; + break; + default: + backpackIterator.remove(); + } + } + } +} diff --git a/java/com/hmdzl/spspd/actors/hero/Hero.java b/java/com/hmdzl/spspd/actors/hero/Hero.java new file mode 100644 index 00000000..3e58c032 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/hero/Hero.java @@ -0,0 +1,2394 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.hero; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; + +import com.hmdzl.spspd.Challenges; +import com.hmdzl.spspd.actors.buffs.AflyBless; +import com.hmdzl.spspd.actors.buffs.Arcane; +import com.hmdzl.spspd.actors.buffs.ArmorBreak; +import com.hmdzl.spspd.actors.buffs.AttackUp; +import com.hmdzl.spspd.actors.buffs.BloodAngry; +import com.hmdzl.spspd.actors.buffs.BoxStar; +import com.hmdzl.spspd.actors.buffs.Burning; +import com.hmdzl.spspd.actors.buffs.Charm; +import com.hmdzl.spspd.actors.buffs.DamageUp; +import com.hmdzl.spspd.actors.buffs.DeadRaise; +import com.hmdzl.spspd.actors.buffs.Disarm; +import com.hmdzl.spspd.actors.buffs.Dry; +import com.hmdzl.spspd.actors.buffs.GlassShield; +import com.hmdzl.spspd.actors.buffs.GoldTouch; +import com.hmdzl.spspd.actors.buffs.Haste; +import com.hmdzl.spspd.actors.buffs.HighAttack; +import com.hmdzl.spspd.actors.buffs.HighLight; +import com.hmdzl.spspd.actors.buffs.HighVoice; +import com.hmdzl.spspd.actors.buffs.Locked; +import com.hmdzl.spspd.actors.buffs.MirrorShield; +import com.hmdzl.spspd.actors.buffs.Muscle; +import com.hmdzl.spspd.actors.buffs.NewCombo; +import com.hmdzl.spspd.actors.buffs.Notice; +import com.hmdzl.spspd.actors.buffs.ParyAttack; +import com.hmdzl.spspd.actors.buffs.Rhythm; +import com.hmdzl.spspd.actors.buffs.Rhythm2; +import com.hmdzl.spspd.actors.buffs.Shocked; +import com.hmdzl.spspd.actors.buffs.Silent; +import com.hmdzl.spspd.actors.buffs.Terror; +import com.hmdzl.spspd.actors.buffs.WarGroove; +import com.hmdzl.spspd.actors.buffs.faithbuff.BalanceFaith; +import com.hmdzl.spspd.actors.buffs.faithbuff.DemonFaith; +import com.hmdzl.spspd.actors.buffs.faithbuff.HumanFaith; +import com.hmdzl.spspd.actors.buffs.faithbuff.LifeFaith; +import com.hmdzl.spspd.actors.buffs.faithbuff.MechFaith; +import com.hmdzl.spspd.actors.mobs.SommonSkeleton; +import com.hmdzl.spspd.effects.Lightning; +import com.hmdzl.spspd.items.DolyaSlate; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.items.KindOfArmor; +import com.hmdzl.spspd.items.armor.glyphs.Iceglyph; +import com.hmdzl.spspd.items.artifacts.AlienBag; +import com.hmdzl.spspd.items.artifacts.EtherealChains; +import com.hmdzl.spspd.items.artifacts.Pylon; +import com.hmdzl.spspd.items.misc.AttackShield; +import com.hmdzl.spspd.items.misc.BShovel; +import com.hmdzl.spspd.items.misc.CopyBall; +import com.hmdzl.spspd.items.misc.DanceLion; +import com.hmdzl.spspd.items.misc.FourClover; +import com.hmdzl.spspd.items.misc.GunOfSoldier; +import com.hmdzl.spspd.items.misc.HealBag; +import com.hmdzl.spspd.items.misc.HorseTotem; +import com.hmdzl.spspd.items.misc.JumpF; +import com.hmdzl.spspd.items.misc.JumpP; +import com.hmdzl.spspd.items.misc.JumpS; +import com.hmdzl.spspd.items.misc.PotionOfMage; +import com.hmdzl.spspd.items.misc.RangeBag; +import com.hmdzl.spspd.items.misc.SavageHelmet; +import com.hmdzl.spspd.items.misc.Shovel; +import com.hmdzl.spspd.items.rings.RingOfMagic; +import com.hmdzl.spspd.items.wands.WandOfFlow; +import com.hmdzl.spspd.items.misc.MissileShield; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.GamesInProgress; +import com.hmdzl.spspd.ResultDescriptions; +import com.hmdzl.spspd.Statistics; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Barkskin; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Combo; +import com.hmdzl.spspd.actors.buffs.Dewcharge; +import com.hmdzl.spspd.actors.buffs.Drowsy; +import com.hmdzl.spspd.actors.buffs.Fury; +import com.hmdzl.spspd.actors.buffs.Hunger; +import com.hmdzl.spspd.actors.buffs.Invisibility; +import com.hmdzl.spspd.actors.buffs.Light; +import com.hmdzl.spspd.actors.buffs.Paralysis; +import com.hmdzl.spspd.actors.buffs.Regeneration; +import com.hmdzl.spspd.actors.buffs.SnipersMark; +import com.hmdzl.spspd.actors.buffs.Strength; +import com.hmdzl.spspd.actors.buffs.Vertigo; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.actors.mobs.npcs.NPC; +import com.hmdzl.spspd.actors.mobs.pets.PET; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.CheckedCell; +import com.hmdzl.spspd.effects.Flare; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.Amulet; +import com.hmdzl.spspd.items.Ankh; +import com.hmdzl.spspd.items.Dewdrop; +import com.hmdzl.spspd.items.eggs.Egg; +import com.hmdzl.spspd.items.Heap; +import com.hmdzl.spspd.items.Heap.Type; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.KindOfWeapon; +import com.hmdzl.spspd.items.artifacts.CapeOfThorns; +import com.hmdzl.spspd.items.artifacts.DriedRose; +import com.hmdzl.spspd.items.artifacts.TalismanOfForesight; +import com.hmdzl.spspd.items.artifacts.TimekeepersHourglass; +import com.hmdzl.spspd.items.keys.GoldenKey; +import com.hmdzl.spspd.items.keys.GoldenSkeletonKey; +import com.hmdzl.spspd.items.keys.IronKey; +import com.hmdzl.spspd.items.keys.Key; +import com.hmdzl.spspd.items.keys.SkeletonKey; +import com.hmdzl.spspd.items.misc.AutoPotion.AutoHealPotion; +import com.hmdzl.spspd.items.potions.Potion; +import com.hmdzl.spspd.items.potions.PotionOfHealing; +import com.hmdzl.spspd.items.potions.PotionOfMight; +import com.hmdzl.spspd.items.potions.PotionOfStrength; +import com.hmdzl.spspd.items.rings.RingOfElements; +import com.hmdzl.spspd.items.rings.RingOfForce; +import com.hmdzl.spspd.items.rings.RingOfFuror; +import com.hmdzl.spspd.items.rings.RingOfHaste; +import com.hmdzl.spspd.items.rings.RingOfMight; +import com.hmdzl.spspd.items.rings.RingOfTenacity; +import com.hmdzl.spspd.items.scrolls.Scroll; +import com.hmdzl.spspd.items.scrolls.ScrollOfMagicMapping; +import com.hmdzl.spspd.items.scrolls.ScrollOfMagicalInfusion; +import com.hmdzl.spspd.items.scrolls.ScrollOfUpgrade; +import com.hmdzl.spspd.items.weapon.melee.MeleeWeapon; +import com.hmdzl.spspd.items.misc.Jumpshoes; +import com.hmdzl.spspd.items.misc.JumpW; +import com.hmdzl.spspd.items.misc.JumpM; +import com.hmdzl.spspd.items.misc.JumpR; +import com.hmdzl.spspd.items.misc.JumpH; +import com.hmdzl.spspd.items.misc.Ankhshield; +import com.hmdzl.spspd.items.OrbOfZot; +import com.hmdzl.spspd.items.weapon.missiles.MissileWeapon; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.Terrain; +import com.hmdzl.spspd.levels.features.AlchemyPot; +import com.hmdzl.spspd.levels.features.Chasm; +import com.hmdzl.spspd.levels.features.Sign; +import com.hmdzl.spspd.plants.Earthroot; +import com.hmdzl.spspd.plants.Sungrass; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.scenes.InterlevelScene; +import com.hmdzl.spspd.scenes.SurfaceScene; +import com.hmdzl.spspd.sprites.CharSprite; +import com.hmdzl.spspd.sprites.HeroSprite; +import com.hmdzl.spspd.ui.AttackIndicator; +import com.hmdzl.spspd.ui.BuffIndicator; +import com.hmdzl.spspd.ui.QuickSlotButton; +import com.hmdzl.spspd.utils.GLog; +import com.hmdzl.spspd.windows.WndAscend; +import com.hmdzl.spspd.windows.WndDescend; +import com.hmdzl.spspd.windows.WndMessage; +import com.hmdzl.spspd.windows.WndResurrect; +import com.hmdzl.spspd.windows.WndTradeItem; +import com.hmdzl.spspd.utils.BArray; +import com.watabou.noosa.Camera; +import com.watabou.noosa.Game; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.PathFinder; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +import static com.hmdzl.spspd.Dungeon.hero; + +public class Hero extends Char { + + private static final String TXT_VALUE = "%+d"; + + public static final int STARTING_STR = 10; + public static final int STARTING_MAGIC = 0; + + + private static final float TIME_TO_REST = 1f; + private static final float TIME_TO_SEARCH = 2f; + + public HeroClass heroClass = HeroClass.ROGUE; + public HeroSubClass subClass = HeroSubClass.NONE; + + public int hitSkill = 10; + public int evadeSkill = 5; + public int magicSkill = 0; + + public boolean ready = false; + + public boolean haspet = false; + public boolean petfollow = false; + public int petType = 0; + public int petLevel = 0; + public int petHP = 0; + public int petExperience = 0; + public int petCooldown = 0; + + private boolean damageInterrupt = true; + public HeroAction curAction = null; + public HeroAction lastAction = null; + + private Char enemy; + + private Item theKey; + private Item theSkeletonKey; + + public boolean restoreHealth = false; + + public MissileWeapon rangedWeapon = null; + public Belongings belongings; + + public int STR; + public boolean weakened = false; + + public float awareness; + + public int lvl = 1; + public int exp = 0; + + private ArrayList visibleEnemies; + + public Hero() { + super(); + name = Messages.get(this, "name"); + + HP = HT = 30; + STR = STARTING_STR; + magicSkill = STARTING_MAGIC; + + awareness = 0.1f; + + belongings = new Belongings(this); + + visibleEnemies = new ArrayList(); + } + + public int STR() { + int STR = this.STR; + + for (Buff buff : buffs(RingOfMight.Might.class)) { + STR += (int)(((RingOfMight.Might) buff).level/5); + } + + if (buff(Muscle.class)!= null) + STR += 2 ; + + if (buff(AflyBless.class)!= null) + STR += 1 ; + + return weakened ? STR - 3 : STR; + } + + public int magicSkill() { + int magicSkill = this.magicSkill; + + for (Buff buff : buffs(RingOfMagic.Magic.class)) { + magicSkill += Math.min(30,((RingOfMagic.Magic) buff).level); + } + if (subClass == HeroSubClass.BATTLEMAGE) + magicSkill += 5; + if (subClass == HeroSubClass.SUPERSTAR) + magicSkill += 4; + if (buff(Arcane.class)!= null) + magicSkill += 10; + + return magicSkill; + } + + private static final String ATTACK = "hitSkill"; + private static final String DEFENSE = "evadeSkill"; + private static final String MAGIC = "magicSkill"; + private static final String STRENGTH = "STR"; + private static final String LEVEL = "lvl"; + private static final String EXPERIENCE = "exp"; + private static final String HASPET = "haspet"; + private static final String PETFOLLOW = "petfollow"; + private static final String PETTYPE = "petType"; + private static final String PETLEVEL = "petLevel"; + private static final String PETHP = "petHP"; + private static final String PETEXP = "petExperience"; + private static final String PETCOOLDOWN = "petCooldown"; + + @Override + public void storeInBundle(Bundle bundle) { + + super.storeInBundle(bundle); + + heroClass.storeInBundle(bundle); + subClass.storeInBundle(bundle); + + bundle.put(ATTACK, hitSkill); + bundle.put(DEFENSE, evadeSkill); + bundle.put(MAGIC, magicSkill); + + bundle.put(STRENGTH, STR); + + bundle.put(LEVEL, lvl); + bundle.put(EXPERIENCE, exp); + bundle.put(HASPET, haspet); + bundle.put(PETFOLLOW, petfollow); + bundle.put(PETTYPE, petType); + bundle.put(PETLEVEL, petLevel); + bundle.put(PETHP, petHP); + bundle.put(PETEXP, petExperience); + bundle.put(PETCOOLDOWN, petCooldown); + + belongings.storeInBundle(bundle); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + + heroClass = HeroClass.restoreInBundle(bundle); + subClass = HeroSubClass.restoreInBundle(bundle); + + hitSkill = bundle.getInt(ATTACK); + evadeSkill = bundle.getInt(DEFENSE); + magicSkill = bundle.getInt(MAGIC); + + STR = bundle.getInt(STRENGTH); + updateAwareness(); + + lvl = bundle.getInt(LEVEL); + exp = bundle.getInt(EXPERIENCE); + haspet = bundle.getBoolean(HASPET); + petfollow = bundle.getBoolean(PETFOLLOW); + petType = bundle.getInt(PETTYPE); + petLevel = bundle.getInt(PETLEVEL); + petHP = bundle.getInt(PETHP); + petExperience = bundle.getInt(PETEXP); + petCooldown = bundle.getInt(PETCOOLDOWN); + + belongings.restoreFromBundle(bundle); + } + + public static void preview(GamesInProgress.Info info, Bundle bundle) { + info.level = bundle.getInt(LEVEL); + } + + public String className() { + return subClass == null || subClass == HeroSubClass.NONE ? heroClass + .title() : subClass.title(); + } + + public String givenName() { + return name.equals(Messages.get(this, "name")) ? className() : name; + } + + public void live() { + Buff.affect(this, Regeneration.class); + Buff.affect(this, Hunger.class); + } + + public int useskin() { + return belongings.armor == null ? 0 : 7 - Dungeon.skins; + } + + public boolean shoot(Char enemy, MissileWeapon wep) { + + rangedWeapon = wep; + boolean result = attack(enemy); + Invisibility.dispel(); + rangedWeapon = null; + + return result; + } + + @Override + public int hitSkill(Char target) { + float accuracy = 1; + + KindOfWeapon wep = rangedWeapon != null ? rangedWeapon + : belongings.weapon; + if (wep != null) { + return (int) (hitSkill * accuracy * wep.acuracyFactor(this)); + } else { + return (int) (hitSkill * accuracy); + } + } + + @Override + public int evadeSkill(Char enemy) { + float evasion = 1; + if (paralysed > 0) { + evasion /= 2; + } + KindOfArmor arm = belongings.armor; + if (arm != null) { + return (int) (evadeSkill * evasion * arm.dexterityFactor(this)); + } else { + return (int) (evadeSkill * evasion); + } + } + + @Override + public int drRoll() { + KindOfArmor arm = belongings.armor; + int dr; + //int bonus = 0; + //for (Buff buff : buffs(RingOfForce.Force.class)) { + //bonus += ((RingOfForce.Force) buff).level; + //} + Barkskin barkskin = buff(Barkskin.class); + if (arm != null) { + dr = arm.drRoll(this); + } else { + //int str = 6; + //dr = bonus == 0 ? str > 1 ? Random.NormalIntRange(1, str) : 1 + //: bonus > 0 ? str > 0 ? Random.NormalIntRange(str / 2 + //+ bonus, (int) (str * 0.5f * bonus) + str * 2) : 1 + //: 0; + dr = 0; + } + + //if (bonus > 0){ dr *= Math.min(3f,(1f + (bonus/15)*1f));} + + if (dr < 0) + dr = 0; + if (barkskin != null) { + dr += barkskin.level(); + } + if (Dungeon.hero.heroClass == HeroClass.SOLDIER && Dungeon.skins == 2) { + dr += Dungeon.hero.lvl; + } + return (int)dr; + } + + @Override + public int damageRoll() { + KindOfWeapon wep = rangedWeapon != null ? rangedWeapon + : belongings.weapon; + int dmg; + int bonus = 0; + for (Buff buff : buffs(RingOfForce.Force.class)) { + bonus += ((RingOfForce.Force) buff).level; + } + + if (wep != null) { + dmg = wep.damageRoll(this); + } else { + int str = 6; + dmg = bonus == 0 ? str > 1 ? Random.NormalIntRange(1, str) : 1 + : bonus > 0 ? str > 0 ? Random.NormalIntRange(str / 2 + + bonus, (int) (str * 0.5f * bonus) + str * 2) : 1 + : 0; + } + if (bonus > 0){ dmg *= Math.min(3f,(1f + (bonus*1.00/10)*1f));} + + if (dmg < 0) + dmg = 0; + + if (buff(Fury.class) != null){ dmg *= 1.30f; } + + if (buff(Strength.class) != null){ dmg *= 3f; Buff.detach(this, Strength.class);} + + HighAttack hatk = buff(HighAttack.class); + if (buff(HighAttack.class) != null){ + dmg *= hatk.level(); + Buff.detach(this, HighAttack.class); + } + + ParyAttack paryatk = buff(ParyAttack.class); + if (buff(ParyAttack.class) != null){ + dmg *= (1+paryatk.level()*0.4); + } + + + if (buff(WarGroove.class) != null){ dmg *= 1.5f; Buff.detach(this, WarGroove.class);} + + if (buff(Dry.class) != null){ dmg *= 0.80f; } + + if (buff(BloodAngry.class) != null){ dmg *= 1.50f; } + + if (buff(Rhythm2.class) != null){ dmg *= 1.20f; } + /*AttackUp atkup = buff(AttackUp.class); + if (atkup != null) { + dmg *=(1f+atkup.level()*0.01f); + } + + AttackDown atkdown = buff(AttackDown.class); + if (atkdown != null) { + dmg *=(1f-atkdown.level()*0.01f); + }*/ + + Hunger hunger = buff(Hunger.class); + if (hunger != null && hunger.isStarving()) { dmg *= 0.8f;} + if (hunger != null && hunger.isHungry()) { dmg *= 0.9f;} + if (hunger != null && hunger.isOverfed()) { dmg *= 1.2f; } + + return (int) dmg; + + } + + + @Override + public float speed() { + + float speed = super.speed(); + + int hasteLevel = 0; + for (Buff buff : buffs(RingOfHaste.Haste.class)) { + hasteLevel += ((RingOfHaste.Haste) buff).level; + } + + + if (hasteLevel != 0) { + if (hasteLevel < 30){ + speed *= (1+(hasteLevel*1.00/10)); + } + else speed *=4; + } + + if (hero.heroClass == HeroClass.HUNTRESS && Dungeon.skins == 2) { + speed += 0.5f; + + } + + return ((HeroSprite) sprite).sprint(subClass == HeroSubClass.FREERUNNER && !isStarving()) ? invisible > 0 ? 2.5f * speed + : 1.5f * speed : speed; + + + } + + public boolean canAttack(Char enemy){ + if (enemy == null || pos == enemy.pos) + return false; + + //can always attack adjacent enemies + if (Dungeon.level.adjacent(pos, enemy.pos)) + return true; + + KindOfWeapon wep = hero.belongings.weapon; + + if (wep != null && Dungeon.level.distance( pos, enemy.pos ) <= wep.reachFactor(this)){ + + boolean[] passable = BArray.not(Level.solid, null); + for (Mob m : Dungeon.level.mobs) + passable[m.pos] = false; + + PathFinder.buildDistanceMap(enemy.pos, passable, wep.reachFactor(this)); + + return PathFinder.distance[pos] <= wep.reachFactor(this); + + } else { + return false; + } + } + + + public float attackDelay() { + KindOfWeapon wep = rangedWeapon != null ? rangedWeapon + : belongings.weapon; + if (wep != null) { + + return wep.speedFactor(this); + + } else { + // Normally putting furor speed on unarmed attacks would be + // unnecessary + // But there's going to be that one guy who gets a furor+force ring + // combo + // This is for that one guy, you shall get your fists of fury! + int bonus = 0; + for (Buff buff : buffs(RingOfFuror.Furor.class)) { + bonus += ((RingOfFuror.Furor) buff).level; + } + return (float) ( 1 / Math.min( 4, 1 + bonus * 1.00 / 10) ); + } + } + + @Override + public void spend(float time) { + justMoved = false; + TimekeepersHourglass.timeFreeze freeze = buff(TimekeepersHourglass.timeFreeze.class); + if (freeze != null) { + freeze.processTime(time); + return; + } else if (Statistics.time < 1440 ) { + Statistics.time += time; + Dungeon.observe(); + } else if ( Statistics.time > 1440 ) { + Statistics.time += time; + Statistics.time -= 1440; + //Dungeon.observe(); + } else { + Statistics.time = 0; + //Dungeon.observe(); + } + + super.spend(time); + }; + + public void spendAndNext(float time) { + busy(); + spend(time); + next(); + } + + @Override + public boolean act() { + + super.act(); + + Statistics.moves++; + + Light light = buff(Light.class); + if (buff(HighLight.class) != null){ + viewDistance = 8; + Dungeon.observe(); + } else if ((Statistics.time > 360 && Statistics.time <601 ) || (Statistics.time > 840 && Statistics.time < 1081 )) { + viewDistance = 6; + Dungeon.observe(); + } else if (Statistics.time < 841 && Statistics.time > 600) { + viewDistance = 8; + Dungeon.observe(); + } else if (Statistics.time > 1080 && light == null) { + viewDistance = 4; + Dungeon.observe(); + } else if (Statistics.time < 361 && light == null) { + viewDistance = 2; + Dungeon.observe(); + } else {viewDistance = 5; + Dungeon.observe();} + + + if(Dungeon.dewDraw || Dungeon.dewWater){ Dungeon.level.currentmoves++;} + + if (paralysed > 0) { + + curAction = null; + + spendAndNext(TICK); + return false; + } + + Egg egg = belongings.getItem(Egg.class); + if (egg!=null){ + egg.moves++; + } + + DolyaSlate journal = belongings.getItem(DolyaSlate.class); + if (journal!=null && (Dungeon.depth < 26) + && (journal.level>1 || journal.rooms[0]) + && journal.charge spawnPoints = new ArrayList(); + 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) { + SommonSkeleton.spawnAt(Random.element(spawnPoints)); + Sample.INSTANCE.play(Assets.SND_CURSED); + } + } + + + /* + Heap heap = Dungeon.level.heaps.get(pos); + if (heap != null){ + heap.dewcollect(); + } + */ + + checkVisibleMobs(); + + if (curAction == null) { + + if (restoreHealth) { + spend(TIME_TO_REST); + next(); + return false; + } + + ready(); + return false; + + } else { + + restoreHealth = false; + + ready = false; + + if (curAction instanceof HeroAction.Move) { + + return actMove((HeroAction.Move) curAction); + + } else if (curAction instanceof HeroAction.Interact) { + + return actInteract((HeroAction.Interact) curAction); + + } else if (curAction instanceof HeroAction.InteractPet) { + + return actInteractPet((HeroAction.InteractPet) curAction); + + } else if (curAction instanceof HeroAction.Buy) { + + return actBuy((HeroAction.Buy) curAction); + + } else if (curAction instanceof HeroAction.PickUp) { + + return actPickUp((HeroAction.PickUp) curAction); + + } else if (curAction instanceof HeroAction.OpenChest) { + + return actOpenChest((HeroAction.OpenChest) curAction); + + } else if (curAction instanceof HeroAction.Unlock) { + + return actUnlock((HeroAction.Unlock) curAction); + + } else if (curAction instanceof HeroAction.Descend) { + + return actDescend((HeroAction.Descend) curAction); + + } else if (curAction instanceof HeroAction.Ascend) { + + return actAscend((HeroAction.Ascend) curAction); + + } else if (curAction instanceof HeroAction.Attack) { + + return actAttack((HeroAction.Attack) curAction); + + /*} else if (curAction instanceof HeroAction.Cook) { + + return actCook( (HeroAction.Cook)curAction );*/ + + } + } + + return false; + } + + public void busy() { + ready = false; + } + + private void ready() { + sprite.idle(); + curAction = null; + damageInterrupt = true; + ready = true; + + AttackIndicator.updateState(); + + GameScene.ready(); + } + + public void interrupt() { + if (isAlive() && curAction != null + && curAction instanceof HeroAction.Move && curAction.dst != pos) { + lastAction = curAction; + } + curAction = null; + } + + public void resume() { + curAction = lastAction; + lastAction = null; + damageInterrupt = false; + act(); + } + + + public boolean justMoved = false; + + private boolean actMove(HeroAction.Move action) { + + if (getCloser(action.dst)) { + justMoved = true; + return true; + + } else { + if (Dungeon.level.map[pos] == Terrain.SIGN && pos != Dungeon.level.pitSign) { + Sign.read(pos); + } else if (Dungeon.level.map[pos] == Terrain.SIGN && pos == Dungeon.level.pitSign){ + Sign.readPit(pos); + } else if (Dungeon.level.map[pos] == Terrain.ALCHEMY){ + AlchemyPot.cook(pos); + } + ready(); + + return false; + } + } + + private boolean actInteract(HeroAction.Interact action) { + + NPC npc = action.npc; + + if (Level.adjacent(pos, npc.pos)) { + + ready(); + sprite.turnTo(pos, npc.pos); + //npc.interact(); + //return false; + return npc.interact(); + + } else { + + if (Level.fieldOfView[npc.pos] && getCloser(npc.pos)) { + + return true; + + } else { + ready(); + return false; + } + + } + } + + private boolean actInteractPet(HeroAction.InteractPet action) { + + PET pet = action.pet; + + if (Level.adjacent(pos, pet.pos)) { + + ready(); + sprite.turnTo(pos, pet.pos); + //pet.interact(); + //return false; + return pet.interact(); + + } else { + + if (Level.fieldOfView[pet.pos] && getCloser(pet.pos)) { + + return true; + + } else { + ready(); + return false; + } + + } + } + + private boolean actBuy(HeroAction.Buy action) { + int dst = action.dst; + if (pos == dst || Level.adjacent(pos, dst)) { + + ready(); + + Heap heap = Dungeon.level.heaps.get(dst); + if (heap != null && heap.type == Type.FOR_SALE && heap.size() == 1) { + GameScene.show(new WndTradeItem(heap, true)); + } + + return false; + + } else if (getCloser(dst)) { + + return true; + + } else { + ready(); + return false; + } + } + + /*private boolean actAlchemy( HeroAction.Alchemy action ) { + int dst = action.dst; + if (Dungeon.level.distance(dst, pos) <= 1) { + + ready(); + GameScene.show(new WndAlchemy()); + return false; + + } else if (getCloser( dst )) { + + return true; + + } else { + ready(); + return false; + } + }*/ + + private boolean actPickUp(HeroAction.PickUp action) { + int dst = action.dst; + if (pos == dst) { + + Heap heap = Dungeon.level.heaps.get(pos); + if (heap != null) { + Item item = heap.pickUp(); + if (item.doPickUp(this)) { + + if (item instanceof Dewdrop + || item instanceof TimekeepersHourglass.sandBag + || item instanceof DriedRose.Petal) { + // Do Nothing + } else { + + boolean important = ((item instanceof ScrollOfUpgrade || item instanceof ScrollOfMagicalInfusion) && ((Scroll) item) + .isKnown()) + || ((item instanceof PotionOfStrength || item instanceof PotionOfMight) && ((Potion) item) + .isKnown()); + if (important) { + GLog.p(Messages.get(this, "you_now_have", item.name())); + } else { + GLog.i(Messages.get(this, "you_now_have", item.name())); + } + + // Alright, if anyone complains about not knowing the + // vial doesn't revive + // after this... I'm done, I'm just done. + } + + curAction = null; + } else { + Dungeon.level.drop(item, pos).sprite.drop(); + ready(); + } + } else { + ready(); + } + + return false; + + } else if (getCloser(dst)) { + + return true; + + } else { + ready(); + return false; + } + } + + private boolean actOpenChest(HeroAction.OpenChest action) { + int dst = action.dst; + if (Level.adjacent(pos, dst) || pos == dst) { + + Heap heap = Dungeon.level.heaps.get(dst); + if (heap != null + && (heap.type != Type.HEAP && heap.type != Type.FOR_SALE)) { + + theKey = null; + theSkeletonKey = null; + + if (heap.type == Type.LOCKED_CHEST + || heap.type == Type.CRYSTAL_CHEST + //|| heap.type == Type.MONSTERBOX + ) { + + theKey = belongings.getKey(GoldenKey.class, Dungeon.depth); + theSkeletonKey = belongings.getKey(GoldenSkeletonKey.class, 0); + + if (theKey == null && theSkeletonKey == null) { + GLog.w( Messages.get(this, "locked_chest")); + ready(); + return false; + } + } + + switch (heap.type) { + case TOMB: + Sample.INSTANCE.play(Assets.SND_TOMB); + Camera.main.shake(1, 0.5f); + break; + case SKELETON: + case REMAINS: + break; + default: + Sample.INSTANCE.play(Assets.SND_UNLOCK); + } + + spend(Key.TIME_TO_UNLOCK); + sprite.operate(dst); + + } else { + ready(); + } + + return false; + + } else if (getCloser(dst)) { + + return true; + + } else { + ready(); + return false; + } + } + + private boolean actUnlock(HeroAction.Unlock action) { + int doorCell = action.dst; + if (Level.adjacent(pos, doorCell)) { + + theKey = null; + int door = Dungeon.level.map[doorCell]; + + if (door == Terrain.LOCKED_DOOR) { + + theKey = belongings.getKey(IronKey.class, Dungeon.depth); + + } else if (door == Terrain.LOCKED_EXIT) { + + theKey = belongings.getKey(SkeletonKey.class, Dungeon.depth); + + } + + if (theKey != null) { + + spend(Key.TIME_TO_UNLOCK); + sprite.operate(doorCell); + + Sample.INSTANCE.play(Assets.SND_UNLOCK); + + } else { + GLog.w( Messages.get(Hero.class, "locked_door")); + ready(); + } + + return false; + + } else if (getCloser(doorCell)) { + + return true; + + } else { + ready(); + return false; + } + } + + private PET checkpet(){ + for (Mob mob : Dungeon.level.mobs) { + if(mob instanceof PET) { + return (PET) mob; + } + } + return null; + } + + private boolean checkpetNear(){ + for (int n : Level.NEIGHBOURS8) { + int c = pos + n; + if (Actor.findChar(c) instanceof PET) { + return true; + } + } + return false; + } + + private boolean actDescend(HeroAction.Descend action) { + int stairs = action.dst; + + if (!Dungeon.level.forcedone && ( Dungeon.dewDraw || Dungeon.dewWater ) + && (Dungeon.level.checkdew()>0 + || hero.buff(Dewcharge.class) != null)) + { + GameScene.show(new WndDescend()); + ready(); + return false; + } + + if (!Dungeon.level.forcedone && + ( Dungeon.dewDraw || Dungeon.dewWater ) && + !Dungeon.level.cleared && + !Dungeon.notClearableLevel(Dungeon.depth)) + { + GameScene.show(new WndDescend()); + ready(); + return false; + } + + + if (pos == stairs && pos == Dungeon.level.exit && !Dungeon.level.sealedlevel){ + + curAction = null; + + if(Dungeon.dewDraw || Dungeon.dewWater) { + + for (int i = 0; i < Level.LENGTH; i++) { + + if (!Dungeon.level.cleared && (Dungeon.dewDraw || Dungeon.dewWater) && !Dungeon.notClearableLevel(Dungeon.depth)) { + Dungeon.level.cleared = true; + Statistics.prevfloormoves = 0; + } + } + } + + PET pet = checkpet(); + if(pet!=null && checkpetNear()){ + hero.petType=pet.type; + hero.petLevel=pet.level; + hero.petHP=pet.HP; + hero.petExperience=pet.experience; + hero.petCooldown=pet.cooldown; + pet.destroy(); + petfollow=true; + } else if (hero.haspet && hero.petfollow) { + petfollow=true; + } else { + petfollow=false; + } + + Buff buff = buff(TimekeepersHourglass.timeFreeze.class); + if (buff != null) buff.detach(); + + InterlevelScene.mode = InterlevelScene.Mode.DESCEND; + Game.switchScene(InterlevelScene.class); + + return false; + + } else if (getCloser(stairs)) { + + return true; + + } else { + ready(); + return false; + } + } + + private boolean actAscend(HeroAction.Ascend action) { + int stairs = action.dst; + if (pos == stairs && pos == Dungeon.level.entrance) { + + if (Dungeon.depth == 1) { + + if (belongings.getItem(Amulet.class) == null) { + GameScene.show(new WndMessage(Messages.get(this, "leave"))); + ready(); + + } else if (Dungeon.level.forcedone){ + Dungeon.win(Messages.format(ResultDescriptions.WIN)); + Dungeon.deleteGame(hero.heroClass, true); + Game.switchScene(SurfaceScene.class); + } else { + GameScene.show(new WndAscend()); + ready(); + } + + } else if (Dungeon.depth == 34) { + curAction = null; + + Hunger hunger = buff(Hunger.class); + if (hunger != null && !hunger.isStarving()) { + hunger.satisfy(-Hunger.STARVING / 10); + } + + PET pet = checkpet(); + if(pet!=null && checkpetNear()){ + hero.petType=pet.type; + hero.petLevel=pet.level; + hero.petHP=pet.HP; + hero.petExperience=pet.experience; + hero.petCooldown=pet.cooldown; + pet.destroy(); + petfollow=true; + } else if (hero.haspet && hero.petfollow) { + petfollow=true; + } else { + petfollow=false; + } + + Buff buff = buff(TimekeepersHourglass.timeFreeze.class); + if (buff != null) + buff.detach(); + + for (Mob mob : Dungeon.level.mobs.toArray(new Mob[0])) + if (mob instanceof DriedRose.GhostHero) + mob.destroy(); + + InterlevelScene.mode = InterlevelScene.Mode.ASCEND; + Game.switchScene(InterlevelScene.class); + + + } else if (Dungeon.depth == 41) { + curAction = null; + + Hunger hunger = buff(Hunger.class); + if (hunger != null && !hunger.isStarving()) { + hunger.satisfy(-Hunger.STARVING / 10); + } + + PET pet = checkpet(); + if(pet!=null && checkpetNear()){ + hero.petType=pet.type; + hero.petLevel=pet.level; + hero.petHP=pet.HP; + hero.petExperience=pet.experience; + hero.petCooldown=pet.cooldown; + pet.destroy(); + petfollow=true; + } else if (hero.haspet && hero.petfollow) { + petfollow=true; + } else { + petfollow=false; + } + + Buff buff = buff(TimekeepersHourglass.timeFreeze.class); + if (buff != null) + buff.detach(); + + for (Mob mob : Dungeon.level.mobs.toArray(new Mob[0])) + if (mob instanceof DriedRose.GhostHero) + mob.destroy(); + + InterlevelScene.mode = InterlevelScene.Mode.ASCEND; + Game.switchScene(InterlevelScene.class); + + } else if (Dungeon.depth > 26 && !Dungeon.townCheck(Dungeon.depth)){ + ready(); + } else if (Dungeon.depth == 55 || Dungeon.depth == 99){ + ready(); + } else if (Dungeon.depth > 55 && Dungeon.level.locked){ + ready(); + } else { + + curAction = null; + + Hunger hunger = buff(Hunger.class); + if (hunger != null && !hunger.isStarving()) { + hunger.satisfy(-Hunger.STARVING / 10); + } + + PET pet = checkpet(); + if(pet!=null && checkpetNear()){ + hero.petType=pet.type; + hero.petLevel=pet.level; + hero.petHP=pet.HP; + hero.petExperience=pet.experience; + hero.petCooldown=pet.cooldown; + pet.destroy(); + petfollow=true; + } else if (hero.haspet && hero.petfollow) { + petfollow=true; + } else { + petfollow=false; + } + + Buff buff = buff(TimekeepersHourglass.timeFreeze.class); + if (buff != null) + buff.detach(); + + for (Mob mob : Dungeon.level.mobs.toArray(new Mob[0])) + if (mob instanceof DriedRose.GhostHero) + mob.destroy(); + + InterlevelScene.mode = InterlevelScene.Mode.ASCEND; + Game.switchScene(InterlevelScene.class); + } + + return false; + + } else if (getCloser(stairs)) { + + return true; + + } else { + ready(); + return false; + } + } + + private boolean actAttack(HeroAction.Attack action) { + + enemy = action.target; + + if (enemy.isAlive() && canAttack( enemy ) && !isCharmedBy( enemy ) && (buff(Disarm.class) == null)) { + + Invisibility.dispel(); + spend( attackDelay()); + sprite.attack( enemy.pos ); + + return false; + + } else { + + if (Level.fieldOfView[enemy.pos] && getCloser( enemy.pos )) { + + return true; + + } else { + ready(); + return false; + } + + } + } + + public Char enemy(){ + return enemy; + } + + public void rest(boolean fullRest) { + //search(true); + spendAndNext(TIME_TO_REST); + if (!fullRest) { + sprite.showStatus(CharSprite.DEFAULT, Messages.get(this, "wait")); + } + restoreHealth = fullRest; + } + + @Override + public int attackProc(Char enemy, int damage) { + KindOfWeapon wep = rangedWeapon != null ? rangedWeapon + : belongings.weapon; + + if (wep != null){ + wep.proc(this, enemy, damage); + } + + AttackShield atkshield = belongings.getItem(AttackShield.class); + if (atkshield!=null && atkshield.charge arcs = new ArrayList<>(); + arcs.add(new Lightning.Arc(pos - Level.WIDTH, pos + Level.WIDTH)); + arcs.add(new Lightning.Arc(pos - 1, pos + 1)); + sprite.parent.add( new Lightning( arcs, null ) ); + } + if (buff(GoldTouch.class)!=null){ + if (rangedWeapon == null && Dungeon.gold < (int)((1000000/(Math.max(1,20-Statistics.deepestFloor))))) { + int earngold = Math.min(1000 * hero.lvl, damage); + Dungeon.gold += earngold; + + hero.sprite.showStatus(CharSprite.NEUTRAL, TXT_VALUE, earngold); + } + } + + if (buff(HighVoice.class)!=null && Random.Int(5) == 0){ + Buff.affect(this, AttackUp.class,8f).level(30); + GLog.p(Messages.get(HighVoice.class,"atkup",Dungeon.hero.givenName())); + } + + if (buff(MechFaith.class)!= null && ((enemy.properties().contains(Property.BEAST)) + || (enemy.properties().contains(Property.PLANT)) + || (enemy.properties().contains(Property.ELEMENT))) ){ + damage=(int)(damage*1.5); + } + + if (buff(LifeFaith.class)!= null && ((enemy.properties().contains(Property.MECH)) + || (enemy.properties().contains(Property.ALIEN)) + || (enemy.properties().contains(Property.GOBLIN))) ){ + damage=(int)(damage*1.5); + } + + if (buff(DemonFaith.class)!= null && ((enemy.properties().contains(Property.HUMAN)) + || (enemy.properties().contains(Property.ORC)) + || (enemy.properties().contains(Property.ELF)) + || (enemy.properties().contains(Property.DWARF)) + || (enemy.properties().contains(Property.TROLL)))){ + damage=(int)(damage*1.5); + } + + if (buff(HumanFaith.class)!= null && ((enemy.properties().contains(Property.DRAGON)) + || (enemy.properties().contains(Property.DEMONIC)) + || (enemy.properties().contains(Property.UNKNOW)) + || (enemy.properties().contains(Property.UNDEAD))) ){ + damage=(int)(damage*1.5); + } + + if (buff(BalanceFaith.class)!= null && ((enemy.properties().contains(Property.BOSS)) + || (enemy.properties().contains(Property.MINIBOSS))) ){ + damage=(int)(damage*1.5); + } + + HorseTotem horseTotem = belongings.getItem(HorseTotem.class); + HorseTotem.HorseTotemBless totembuff = buff(HorseTotem.HorseTotemBless.class); + if (totembuff != null) { + int x = Random.Int(1,damage/3); + damage +=x; + Buff.prolong(this, Haste.class,4f); + } else if (horseTotem!=null && Random.Int(5)==0) { + int x = Random.Int(1,damage/3); + damage +=x; + Buff.prolong(this, Haste.class,4f); + } + + RangeBag.RangeBagBless rangeBless = buff(RangeBag.RangeBagBless.class); + if (rangeBless != null){ + if (enemy.HP <= damage && Random.Int(6) == 0) { + Dungeon.level.drop(Generator.random(Generator.Category.LINKDROP), enemy.pos).sprite.drop(); + } + } + + return damage; + + } + + @Override + public int defenseProc(Char enemy, int damage) { + + KindOfArmor arm = belongings.armor; + + if (buff(HighVoice.class)!=null && Random.Int(5) == 0){ + Buff.affect(this, GlassShield.class).turns(2); + GLog.p(Messages.get(HighVoice.class,"save",Dungeon.hero.givenName())); + } + + CapeOfThorns.Thorns thorns = buff(CapeOfThorns.Thorns.class); + if (thorns != null) { + damage = thorns.proc(damage, enemy); + } + + MirrorShield mirror = buff(MirrorShield.class); + if (mirror != null) { + damage = mirror.proc(damage, enemy); + } + + BoxStar star = buff(BoxStar.class); + if (star != null) { + damage = star.proc(damage, enemy); + } + + Earthroot.Armor earmor = buff(Earthroot.Armor.class); + if (earmor != null) { + damage = earmor.absorb(damage); + } + + Sungrass.Health health = buff(Sungrass.Health.class); + if (health != null) { + health.absorb(damage); + } + + SavageHelmet helmet = belongings.getItem(SavageHelmet.class); + SavageHelmet.SavageHelmetBless helmetbuff = buff(SavageHelmet.SavageHelmetBless.class); + if (helmetbuff != null) { + helmetbuff.absorb(damage); + } else if (helmet!=null && Random.Int(5)==0) { + int x = Random.Int(1,damage/2); + damage -=x; + Buff.affect(this, DamageUp.class).level(x); + } + + if (arm != null) { + arm.proc(enemy, this, damage); + } + + switch (subClass) { + case LEADER: + switch (Random.Int (10)){ + case 0: + int oppositeDefender = enemy.pos + (enemy.pos - pos); + Ballistica trajectory = new Ballistica(enemy.pos, oppositeDefender, Ballistica.MAGIC_BOLT); + WandOfFlow.throwChar(enemy, trajectory, 1); + break; + case 1: + Buff.prolong(enemy,Silent.class,5f); + break; + case 2: + Buff.prolong(enemy,Disarm.class,5f); + break; + case 3: + Buff.prolong(enemy,Terror.class,5f); + break; + case 4: + Buff.prolong(enemy,ArmorBreak.class,5f).level(35); + break; + case 5: + Buff.prolong(enemy,Locked.class,5f); + break; + + default: + break; + + } + } + return damage; + } + + @Override + public void damage(int dmg, Object src) { + if (buff(TimekeepersHourglass.timeStasis.class) != null) + return; + + if (!(src instanceof Hunger || src instanceof Iceglyph.DeferedDamage) + && damageInterrupt){ + interrupt(); + restoreHealth = false; + } + + if (this.buff(Drowsy.class) != null) { + Buff.detach(this, Drowsy.class); + GLog.w(Messages.get(this, "pain_resist")); + } + + if (enemy != null) { + if (buff(LifeFaith.class) != null) { + if ((enemy.properties().contains(Property.BEAST)) + || (enemy.properties().contains(Property.PLANT)) + || (enemy.properties().contains(Property.ELEMENT))) { + dmg = (int) Math.ceil(dmg * 0.75); + } + } + + if (buff(MechFaith.class) != null) { + if ((enemy.properties().contains(Property.MECH)) + || (enemy.properties().contains(Property.ALIEN)) + || (enemy.properties().contains(Property.GOBLIN))) { + dmg = (int) Math.ceil(dmg * 0.75); + } + } + + if (buff(HumanFaith.class) != null) { + if ((enemy.properties().contains(Property.HUMAN)) + || (enemy.properties().contains(Property.ORC)) + || (enemy.properties().contains(Property.ELF)) + || (enemy.properties().contains(Property.DWARF)) + || (enemy.properties().contains(Property.TROLL))) { + dmg = (int) Math.ceil(dmg * 0.75); + } + } + + if (buff(DemonFaith.class) != null) { + if ((enemy.properties().contains(Property.DRAGON)) + || (enemy.properties().contains(Property.DEMONIC)) + || (enemy.properties().contains(Property.UNKNOW)) + || (enemy.properties().contains(Property.UNDEAD))) { + dmg = (int) Math.ceil(dmg * 0.75); + } + } + + if (buff(BalanceFaith.class) != null) { + if ((enemy.properties().contains(Property.BOSS)) + || (enemy.properties().contains(Property.MINIBOSS))) { + dmg = (int) Math.ceil(dmg * 0.75); + } + } + } + + int tenacity = 0; + for (Buff buff : buffs(RingOfTenacity.Tenacity.class)) { + tenacity += ((RingOfTenacity.Tenacity) buff).level; + } + + if (tenacity != 0) // (HT - HP)/HT = heroes current % missing health. + dmg = (int) Math.ceil(dmg * Math.max(0.60, (1- 1.00*tenacity/75))); + + if (buff(Fury.class) != null){dmg = (int) Math.ceil(dmg * 0.75);} + if (buff(BloodAngry.class) != null){dmg = (int) Math.ceil(dmg * 0.80);} + if (buff(Rhythm2.class) != null){dmg = (int) Math.ceil(dmg * 0.90);} + + if (subClass == HeroSubClass.LEADER){dmg = (int) Math.ceil(dmg * 0.80);} + + //if (buff(Hot.class) != null){dmg = (int) Math.ceil(dmg * 1.20);} + + /*DefenceUp drup = buff(DefenceUp.class); + if (buff(DefenceUp.class) != null) { + dmg = (int) Math.ceil(dmg *(-drup.level()*0.01+1)); + }*/ + + /*ArmorBreak ab = buff(ArmorBreak.class); + if (buff(ArmorBreak.class) != null){ + dmg= (int) Math.ceil(dmg *(ab.level()*0.01+1)); + }*/ + + + + super.damage(dmg, src); + + + if (subClass == HeroSubClass.BERSERKER && 0 < HP + && HP <= HT * Fury.LEVEL) { + Buff.affect(this, Fury.class); + } + + if (this.buff(AutoHealPotion.class) != null && ((float) HP / HT)<.1) { + PotionOfHealing pot = hero.belongings.getItem(PotionOfHealing.class); + if (pot != null) { + pot.detach(hero.belongings.backpack,1); + /* + if(!(Dungeon.hero.belongings.getItem(PotionOfHealing.class).quantity() > 0)){ + pot.detachAll(Dungeon.hero.belongings.backpack); + } + */ + GLog.w(Messages.get(this, "auto_potion")); + pot.apply(this); + } + else if (pot==null){ + GLog.w(Messages.get(this, "auto_potion_no")); + } + + } + + } + + private void checkVisibleMobs() { + ArrayList visible = new ArrayList(); + + boolean newMob = false; + Mob closest = null; + + for (Mob m : Dungeon.level.mobs) { + if (Level.fieldOfView[m.pos] && m.hostile) { + visible.add(m); + if (!visibleEnemies.contains(m)) { + newMob = true; + } + if (closest == null){ + closest = m; + } else if (distance(closest) > distance(m)) { + closest = m; + } + } + } + + if (closest != null && (QuickSlotButton.lastTarget == null || + !QuickSlotButton.lastTarget.isAlive() || + !Dungeon.visible[QuickSlotButton.lastTarget.pos])){ + QuickSlotButton.target(closest); + } + + if (newMob) { + interrupt(); + restoreHealth = false; + } + + visibleEnemies = visible; + } + + public int visibleEnemies() { + return visibleEnemies.size(); + } + + public Mob visibleEnemy(int index) { + return visibleEnemies.get(index % visibleEnemies.size()); + } + + private boolean getCloser(final int target) { + + if (rooted) { + Camera.main.shake(1, 1f); + return false; + } + + int step = -1; + + if (Level.adjacent(pos, target)) { + + if (Actor.findChar(target) == null) { + if (Level.pit[target] && !flying && !Chasm.jumpConfirmed) { + if (!Level.solid[target]) { + Chasm.heroJump(this); + interrupt(); + } + return false; + } + if (Level.passable[target] || Level.avoid[target]) { + step = target; + } + } + + } else { + + int len = Level.getLength(); + boolean[] p = Level.passable; + boolean[] v = Dungeon.level.visited; + boolean[] m = Dungeon.level.mapped; + boolean[] passable = new boolean[len]; + for (int i = 0; i < len; i++) { + passable[i] = p[i] && (v[i] || m[i]); + } + + step = Dungeon.findPath(this, pos, target, passable, + Level.fieldOfView); + } + + if (step != -1) { + + int oldPos = pos; + move(step); + sprite.move(oldPos, pos); + spend(1 / speed()); + + return true; + + } else { + + return false; + + } + + } + + public boolean handle(int cell) { + + if (cell == -1) { + return false; + } + + Char ch; + Heap heap; + if (Level.fieldOfView[cell] + && (ch = Actor.findChar(cell)) instanceof Mob) { + + if (ch instanceof NPC) { + curAction = new HeroAction.Interact((NPC) ch); + } else if (ch instanceof PET) { + curAction = new HeroAction.InteractPet((PET) ch); + } else { + curAction = new HeroAction.Attack(ch); + } + + } else if ((heap = Dungeon.level.heaps.get(cell)) != null) { + + switch (heap.type) { + case HEAP: + curAction = new HeroAction.PickUp(cell); + break; + case FOR_SALE: + curAction = heap.size() == 1 && heap.peek().price() > 0 ? new HeroAction.Buy( + cell) : new HeroAction.PickUp(cell); + break; + default: + curAction = new HeroAction.OpenChest(cell); + } + + } else if (Dungeon.level.map[cell] == Terrain.LOCKED_DOOR + || Dungeon.level.map[cell] == Terrain.LOCKED_EXIT) { + + curAction = new HeroAction.Unlock(cell); + + } else if (cell == Dungeon.level.exit && (Dungeon.depth < 26)) { + + curAction = new HeroAction.Descend(cell); + + } else if (cell == Dungeon.level.entrance) { + + curAction = new HeroAction.Ascend(cell); + + } else { + + curAction = new HeroAction.Move(cell); + lastAction = null; + + } + + return act(); + } + + public void earnExp(int exp) { + + this.exp += exp; + + float percent = exp/(float)maxExp(); + + EtherealChains.chainsRecharge chains = buff(EtherealChains.chainsRecharge.class); + if (chains != null) chains.gainExp(percent); + + AlienBag.bagRecharge bags = buff(AlienBag.bagRecharge.class); + if (bags != null) bags.gainExp(percent); + + Pylon.beaconRecharge pylon = buff(Pylon.beaconRecharge.class); + if (pylon != null) pylon.gainExp(percent); + + boolean levelUp = false; + while (this.exp >= maxExp()) { + this.exp -= maxExp(); + lvl++; + + if (Dungeon.isChallenged(Challenges.LISTLESS)){ + HT += 2; + HP += 1; + hitSkill++; + evadeSkill++; + } else if (lvl < 12) { + HT += 4; + HP += 4; + hitSkill++; + evadeSkill++; + } else { + HT += 5; + HP += 5; + hitSkill++; + evadeSkill++;} + FourClover.FourCloverBless fcb = buff(FourClover.FourCloverBless.class); + if (fcb != null){ + HT+=5; + magicSkill++; + Dungeon.gold+=1000; + hero.sprite.showStatus(CharSprite.NEUTRAL, TXT_VALUE, 1000); + + } + if (heroClass == HeroClass.SOLDIER){ + HT+=3; + } + if (lvl < 10) { + updateAwareness(); + } + + levelUp = true; + } + + if (levelUp) { + + GLog.p(Messages.get(this, "new_level"), lvl ); + sprite.showStatus(CharSprite.POSITIVE, Messages.get(Hero.class, "level_up") ); + Sample.INSTANCE.play(Assets.SND_LEVELUP); + + Badges.validateLevelReached(); + + int value = HT - HP; + if (value > 0) { + HP += value; + sprite.emitter().burst(Speck.factory(Speck.HEALING), 1); + } + + buff(Hunger.class).satisfy(10); + if(hero.heroClass == HeroClass.PERFORMER){ + Buff.prolong(hero,Rhythm.class,100); + Buff.affect(hero,GlassShield.class).turns(1); + } + if(hero.subClass == HeroSubClass.SUPERSTAR){ + Buff.prolong(hero,Rhythm2.class,100); + } + } + } + + public int maxExp() { + return 7 + lvl * 8; + } + + void updateAwareness() { + awareness = (float) (1 - Math.pow((heroClass == HeroClass.ROGUE ? 0.85 + : 0.90), (1 + Math.min(lvl, 9)) * 0.5)); + } + + public boolean isStarving() { + return buff(Hunger.class) != null + && buff(Hunger.class).isStarving(); + } + + public boolean isHungry() { + return buff(Hunger.class) != null + && buff(Hunger.class).isHungry(); + } + + public boolean isOverfed() { + return buff(Hunger.class) != null + && buff(Hunger.class).isOverfed(); + } + + @Override + public void add(Buff buff) { + + if (buff(TimekeepersHourglass.timeStasis.class) != null) + return; + + super.add(buff); + + if (sprite != null) { + String msg = buff.heroMessage(); + if (msg != null){ + GLog.w(msg); + } + + if (buff instanceof RingOfMight.Might) { + if (((RingOfMight.Might) buff).level > 0) { + HT += ((RingOfMight.Might) buff).level * 10; + } + } else if (buff instanceof Paralysis || buff instanceof Vertigo) { + interrupt(); + } + + } + BuffIndicator.refreshHero(); + } + + @Override + public void remove(Buff buff) { + super.remove(buff); + if (buff instanceof RingOfMight.Might) { + if (((RingOfMight.Might) buff).level > 0) { + HT -= ((RingOfMight.Might) buff).level * 10; + hero.damage(1, this); + if (!hero.isAlive()) { + Dungeon.fail(Messages.format(ResultDescriptions.ITEM)); + } + + } + } + + BuffIndicator.refreshHero(); + } + + @Override + public int stealth() { + int stealth = super.stealth(); + int shadow = 1; + KindOfArmor arm = belongings.armor; + if (arm != null) { + stealth += shadow * arm.stealthFactor(this); + } else { + stealth += shadow; + } + if (hero.subClass == HeroSubClass.AGENT){ + stealth += 5; + } + if (hero.heroClass == HeroClass.ROGUE && Dungeon.skins == 2){ + stealth += 8; + } + return stealth; + } + + @Override + public int energybase() { + int energybase = super.energybase(); + int energy = 1; + KindOfArmor arm = belongings.armor; + if (arm != null) { + energybase += energy * arm.energyFactor(this); + } else { + energybase += energy; + } + return energybase; + } + + @Override + public void die(Object cause) { + + curAction = null; + + Ankh ankh = null; + + // look for ankhs in player inventory, prioritize ones which are + // blessed. + for (Item item : belongings) { + if (item instanceof Ankh) { + if (ankh == null || ((Ankh) item).isBlessed()) { + ankh = (Ankh) item; + } + } + } + + if (ankh != null && ankh.isBlessed() && this.HT > 0) { + + this.HP = HT; + + Buff.detach(this, Paralysis.class); + spend(-cooldown()); + + new Flare(8, 32).color(0xFFFF66, true).show(sprite, 2f); + CellEmitter.get(this.pos) + .start(Speck.factory(Speck.LIGHT), 0.2f, 3); + + ankh.detach(belongings.backpack); + + Sample.INSTANCE.play(Assets.SND_TELEPORT); + GLog.w(Messages.get(this, "revive")); + Statistics.ankhsUsed++; + return; + } + + Actor.fixTime(); + super.die(cause); + + if (ankh == null) { + reallyDie(cause); + } else { + + //ankh.detach(belongings.backpack); + Dungeon.deleteGame(hero.heroClass, false); + GameScene.show(new WndResurrect(ankh, cause)); + + } + } + + public static void reallyDie(Object cause) { + + int length = Level.getLength(); + int[] map = Dungeon.level.map; + boolean[] visited = Dungeon.level.visited; + boolean[] discoverable = Level.discoverable; + + for (int i = 0; i < length; i++) { + + int terr = map[i]; + + if (discoverable[i]) { + + visited[i] = true; + if ((Terrain.flags[terr] & Terrain.SECRET) != 0) { + //Level.set(i, Terrain.discover(terr)); + //GameScene.updateMap(i); + Dungeon.level.discover( i ); + } + } + } + + Dungeon.observe(); + + hero.belongings.identify(); + + int pos = hero.pos; + + ArrayList passable = new ArrayList(); + for (Integer ofs : Level.NEIGHBOURS8) { + int cell = pos + ofs; + if ((Level.passable[cell] || Level.avoid[cell]) + && Dungeon.level.heaps.get(cell) == null) { + passable.add(cell); + } + } + Collections.shuffle(passable); + + ArrayList items = new ArrayList( + hero.belongings.backpack.items); + for (Integer cell : passable) { + if (items.isEmpty()) { + break; + } + + Item item = Random.element(items); + Dungeon.level.drop(item, cell).sprite.drop(pos); + items.remove(item); + } + + GameScene.gameOver(); + + if (cause instanceof Hero.Doom) { + ((Hero.Doom) cause).onDeath(); + } + + Dungeon.deleteGame(hero.heroClass, true); + } + + @Override + public void move(int step) { + super.move(step); + + if (!flying) { + + if (Level.water[pos]) { + Sample.INSTANCE.play(Assets.SND_WATER, 1, 1, + Random.Float(0.8f, 1.25f)); + } else { + Sample.INSTANCE.play(Assets.SND_STEP); + } + Dungeon.level.press(pos, this); + } + } + + @Override + public void onMotionComplete() { + Dungeon.observe(); + search(false); + + super.onMotionComplete(); + } + + + @Override + public void onAttackComplete() { + + AttackIndicator.target(enemy); + + //attack(enemy); + + boolean hit = attack( enemy ); + + if (buff(AttackShield.LongBuff.class)!=null && belongings.weapon == null){ + if (hit) { + Buff.affect( this, NewCombo.class ).hit(); + } else { + NewCombo newcombo = buff(NewCombo.class); + if (newcombo != null) newcombo.miss(); + } + } + curAction = null; + + Invisibility.dispel(); + + super.onAttackComplete(); + } + + @Override + public void onOperateComplete() { + + if (curAction instanceof HeroAction.Unlock) { + + if (theKey != null) { + theKey.detach(belongings.backpack); + theKey = null; + } + + int doorCell = ((HeroAction.Unlock) curAction).dst; + int door = Dungeon.level.map[doorCell]; + + Level.set(doorCell, door == Terrain.LOCKED_DOOR ? Terrain.DOOR + : Terrain.UNLOCKED_EXIT); + GameScene.updateMap(doorCell); + + } else if (curAction instanceof HeroAction.OpenChest) { + + if (theKey != null) { + theKey.detach(belongings.backpack); + theKey = null; + } else if (theKey == null && theSkeletonKey != null) { + theSkeletonKey.detach(belongings.backpack); + theSkeletonKey = null; + } + + Heap heap = Dungeon.level.heaps + .get(((HeroAction.OpenChest) curAction).dst); + if (heap.type == Type.SKELETON || heap.type == Type.REMAINS) { + Sample.INSTANCE.play(Assets.SND_BONES); + } + heap.open(this); + } + curAction = null; + + super.onOperateComplete(); + } + + public boolean search(boolean intentional) { + + boolean smthFound = false; + + int positive = 0; + int negative = 0; + Light light = buff(Light.class); + if (light != null){ + positive = 1; + } + int distance = 1 + positive + negative; + + + + float level = intentional ? (2 * awareness - awareness * awareness) + : awareness; + if (distance <= 0) { + level /= 2 - distance; + distance = 1; + } + + int cx = pos % Level.getWidth(); + int cy = pos / Level.getWidth(); + int ax = cx - distance; + if (ax < 0) { + ax = 0; + } + int bx = cx + distance; + if (bx >= Level.getWidth()) { + bx = Level.getWidth() - 1; + } + int ay = cy - distance; + if (ay < 0) { + ay = 0; + } + int by = cy + distance; + if (by >= Level.HEIGHT) { + by = Level.HEIGHT - 1; + } + + TalismanOfForesight.Foresight foresight = buff(TalismanOfForesight.Foresight.class); + boolean notice = buff(Notice.class) != null; + // cursed talisman of foresight makes unintentionally finding things + // impossible. + if (foresight != null && foresight.isCursed()) { + level = -1; + } + + for (int y = ay; y <= by; y++) { + for (int x = ax, p = ax + y * Level.getWidth(); x <= bx; x++, p++) { + + if (Dungeon.visible[p]) { + + if (intentional) { + sprite.parent.addToBack(new CheckedCell(p)); + } + + if (Level.secret[p] + && (intentional || Random.Float() < level || notice)) { + + int oldValue = Dungeon.level.map[p]; + + GameScene.discoverTile(p, oldValue); + + //Level.set(p, Terrain.discover(oldValue)); + + //GameScene.updateMap(p); + + Dungeon.level.discover( p ); + + ScrollOfMagicMapping.discover(p); + + smthFound = true; + + if (foresight != null && !foresight.isCursed()) + foresight.charge(); + } + } + } + } + + if (intentional) { + sprite.showStatus(CharSprite.DEFAULT, Messages.get(this, "search")); + sprite.operate(pos); + if (foresight != null && foresight.isCursed()) { + GLog.n(Messages.get(this, "search_distracted")); + spendAndNext(TIME_TO_SEARCH * 3); + } else { + spendAndNext(TIME_TO_SEARCH); + } + + } + + if (smthFound) { + GLog.w(Messages.get(this, "noticed_smth")); + Sample.INSTANCE.play(Assets.SND_SECRET); + interrupt(); + } + + return smthFound; + } + + + public void resurrect(int resetLevel) { + + HP = HT; + Dungeon.gold = 0; + exp = 0; + + belongings.resurrect(resetLevel); + + live(); + } + + @Override + public HashSet> resistances() { + RingOfElements.Resistance r = buff(RingOfElements.Resistance.class); + return r == null ? super.resistances() : r.resistances(); + } + + @Override + public HashSet> immunities() { + HashSet> immunities = new HashSet>(); + for (Buff buff : buffs()) { + for (Class immunity : buff.immunities) + immunities.add(immunity); + } + return immunities; + } + + @Override + public void next() { + super.next(); + } + + public static interface Doom { + public void onDeath(); + } +} diff --git a/java/com/hmdzl/spspd/actors/hero/HeroAction.java b/java/com/hmdzl/spspd/actors/hero/HeroAction.java new file mode 100644 index 00000000..39e7d4bf --- /dev/null +++ b/java/com/hmdzl/spspd/actors/hero/HeroAction.java @@ -0,0 +1,99 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.hero; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.mobs.npcs.NPC; +import com.hmdzl.spspd.actors.mobs.pets.PET; + +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 NPC npc; + + public Interact(NPC npc) { + this.npc = npc; + } + } + + public static class InteractPet extends HeroAction { + public PET pet; + + public InteractPet(PET pet) { + this.pet = pet; + } + } + + 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; + } + } +} diff --git a/java/com/hmdzl/spspd/actors/hero/HeroClass.java b/java/com/hmdzl/spspd/actors/hero/HeroClass.java new file mode 100644 index 00000000..5af1cc16 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/hero/HeroClass.java @@ -0,0 +1,814 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.hero; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.Challenges; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.items.Ankh; +import com.hmdzl.spspd.items.ArmorKit; +import com.hmdzl.spspd.items.DolyaSlate; +import com.hmdzl.spspd.items.Elevator; +import com.hmdzl.spspd.items.ExpOre; +import com.hmdzl.spspd.items.Palantir; +import com.hmdzl.spspd.items.PowerHand; +import com.hmdzl.spspd.items.SaveYourLife; +import com.hmdzl.spspd.items.SoulCollect; +import com.hmdzl.spspd.items.Stylus; +import com.hmdzl.spspd.items.TriForce; +import com.hmdzl.spspd.items.Weightstone; +import com.hmdzl.spspd.items.armor.normalarmor.BaseArmor; +import com.hmdzl.spspd.items.armor.normalarmor.DiscArmor; +import com.hmdzl.spspd.items.armor.normalarmor.LeatherArmor; +import com.hmdzl.spspd.items.armor.normalarmor.LifeArmor; +import com.hmdzl.spspd.items.armor.normalarmor.RubberArmor; +import com.hmdzl.spspd.items.artifacts.AlienBag; +import com.hmdzl.spspd.items.artifacts.EtherealChains; +import com.hmdzl.spspd.items.artifacts.Pylon; +import com.hmdzl.spspd.items.artifacts.TimekeepersHourglass; +import com.hmdzl.spspd.items.bags.PotionBandolier; +import com.hmdzl.spspd.items.bags.SeedPouch; +import com.hmdzl.spspd.items.bags.WandHolster; +import com.hmdzl.spspd.items.bombs.FireBomb; +import com.hmdzl.spspd.items.bombs.IceBomb; +import com.hmdzl.spspd.items.bombs.StormBomb; +import com.hmdzl.spspd.items.challengelists.CaveChallenge; +import com.hmdzl.spspd.items.challengelists.CityChallenge; +import com.hmdzl.spspd.items.challengelists.CourageChallenge; +import com.hmdzl.spspd.items.challengelists.PowerChallenge; +import com.hmdzl.spspd.items.challengelists.PrisonChallenge; +import com.hmdzl.spspd.items.challengelists.SewerChallenge; +import com.hmdzl.spspd.items.challengelists.WisdomChallenge; +import com.hmdzl.spspd.items.journalpages.Vault; +import com.hmdzl.spspd.items.medicine.Hardpill; +import com.hmdzl.spspd.items.medicine.Powerpill; +import com.hmdzl.spspd.items.medicine.Smashpill; +import com.hmdzl.spspd.items.misc.AttackShield; +import com.hmdzl.spspd.items.misc.AttackShoes; +import com.hmdzl.spspd.items.misc.BShovel; +import com.hmdzl.spspd.items.misc.CopyBall; +import com.hmdzl.spspd.items.misc.DanceLion; +import com.hmdzl.spspd.items.misc.DemoScroll; +import com.hmdzl.spspd.items.misc.FaithSign; +import com.hmdzl.spspd.items.misc.GnollMark; +import com.hmdzl.spspd.items.misc.HealBag; +import com.hmdzl.spspd.items.misc.HorseTotem; +import com.hmdzl.spspd.items.misc.JumpF; +import com.hmdzl.spspd.items.misc.MKbox; +import com.hmdzl.spspd.items.misc.MechPocket; +import com.hmdzl.spspd.items.misc.RangeBag; +import com.hmdzl.spspd.items.misc.SavageHelmet; +import com.hmdzl.spspd.items.misc.UndeadBook; +import com.hmdzl.spspd.items.nornstone.BlueNornStone; +import com.hmdzl.spspd.items.nornstone.GreenNornStone; +import com.hmdzl.spspd.items.nornstone.OrangeNornStone; +import com.hmdzl.spspd.items.nornstone.PurpleNornStone; +import com.hmdzl.spspd.items.nornstone.YellowNornStone; +import com.hmdzl.spspd.items.potions.PotionOfHealing; +import com.hmdzl.spspd.items.rings.RingOfForce; +import com.hmdzl.spspd.items.rings.RingOfMight; +import com.hmdzl.spspd.items.scrolls.ScrollOfRegrowth; +import com.hmdzl.spspd.items.scrolls.ScrollOfTerror; +import com.hmdzl.spspd.items.TomeOfMastery; +import com.hmdzl.spspd.items.armor.normalarmor.VestArmor; +import com.hmdzl.spspd.items.armor.normalarmor.WoodenArmor; +import com.hmdzl.spspd.items.bags.ScrollHolder; +import com.hmdzl.spspd.items.bombs.DungeonBomb; +import com.hmdzl.spspd.items.food.Honey; +import com.hmdzl.spspd.items.food.staplefood.NormalRation; +import com.hmdzl.spspd.items.food.staplefood.Pasty; +import com.hmdzl.spspd.items.journalpages.SafeSpotPage; +import com.hmdzl.spspd.items.journalpages.Sokoban2; +import com.hmdzl.spspd.items.journalpages.Sokoban3; +import com.hmdzl.spspd.items.journalpages.Sokoban4; +import com.hmdzl.spspd.items.misc.Ankhshield; +import com.hmdzl.spspd.items.armor.normalarmor.ClothArmor; +import com.hmdzl.spspd.items.artifacts.CloakOfShadows; +import com.hmdzl.spspd.items.bags.KeyRing; +import com.hmdzl.spspd.items.eggs.RandomEgg; +import com.hmdzl.spspd.items.food.completefood.PetFood; +import com.hmdzl.spspd.items.journalpages.Sokoban1; +import com.hmdzl.spspd.items.journalpages.Town; +import com.hmdzl.spspd.items.misc.GunOfSoldier; +import com.hmdzl.spspd.items.misc.JumpP; +import com.hmdzl.spspd.items.misc.JumpS; +import com.hmdzl.spspd.items.misc.PotionOfMage; +import com.hmdzl.spspd.items.misc.Shovel; +import com.hmdzl.spspd.items.potions.PotionOfInvisibility; +import com.hmdzl.spspd.items.potions.PotionOfLiquidFlame; +import com.hmdzl.spspd.items.potions.PotionOfMending; +import com.hmdzl.spspd.items.potions.PotionOfMight; +import com.hmdzl.spspd.items.potions.PotionOfMindVision; +import com.hmdzl.spspd.items.potions.PotionOfPurity; +import com.hmdzl.spspd.items.potions.PotionOfStrength; +import com.hmdzl.spspd.items.reward.SewerReward; +import com.hmdzl.spspd.items.scrolls.ScrollOfIdentify; +import com.hmdzl.spspd.items.scrolls.ScrollOfLullaby; +import com.hmdzl.spspd.items.scrolls.ScrollOfMagicMapping; +import com.hmdzl.spspd.items.scrolls.ScrollOfMagicalInfusion; +import com.hmdzl.spspd.items.scrolls.ScrollOfRage; +import com.hmdzl.spspd.items.scrolls.ScrollOfRemoveCurse; +import com.hmdzl.spspd.items.scrolls.ScrollOfUpgrade; +import com.hmdzl.spspd.items.wands.CannonOfMage; +import com.hmdzl.spspd.items.wands.WandOfDisintegration; +import com.hmdzl.spspd.items.wands.WandOfFirebolt; +import com.hmdzl.spspd.items.wands.WandOfFlock; +import com.hmdzl.spspd.items.wands.WandOfFreeze; +import com.hmdzl.spspd.items.wands.WandOfLightning; +import com.hmdzl.spspd.items.wands.WandOfMagicMissile; +import com.hmdzl.spspd.items.weapon.guns.GunA; +import com.hmdzl.spspd.items.weapon.guns.GunC; +import com.hmdzl.spspd.items.weapon.guns.Sling; +import com.hmdzl.spspd.items.weapon.melee.Dagger; +import com.hmdzl.spspd.items.weapon.melee.Glaive; +import com.hmdzl.spspd.items.weapon.melee.Knuckles; +import com.hmdzl.spspd.items.weapon.melee.Rapier; +import com.hmdzl.spspd.items.weapon.melee.ShortSword; +import com.hmdzl.spspd.items.weapon.melee.MageBook; +import com.hmdzl.spspd.items.weapon.melee.Spear; +import com.hmdzl.spspd.items.weapon.melee.Triangolo; +import com.hmdzl.spspd.items.weapon.melee.Whip; +import com.hmdzl.spspd.items.weapon.melee.WoodenStaff; +import com.hmdzl.spspd.items.weapon.melee.special.DiamondPickaxe; +import com.hmdzl.spspd.items.weapon.melee.special.FireCracker; +import com.hmdzl.spspd.items.weapon.melee.special.LinkSword; +import com.hmdzl.spspd.items.weapon.melee.special.ShadowEater; +import com.hmdzl.spspd.items.weapon.melee.zero.EmptyPotion; +import com.hmdzl.spspd.items.weapon.missiles.Boomerang; +import com.hmdzl.spspd.items.weapon.missiles.EmpBola; +import com.hmdzl.spspd.items.weapon.missiles.ErrorAmmo; +import com.hmdzl.spspd.items.misc.JumpW; +import com.hmdzl.spspd.items.misc.JumpH; +import com.hmdzl.spspd.items.misc.JumpM; +import com.hmdzl.spspd.items.misc.JumpR; +import com.hmdzl.spspd.items.weapon.missiles.EscapeKnive; +import com.hmdzl.spspd.items.misc.MissileShield; +import com.hmdzl.spspd.items.weapon.missiles.ManyKnive; +import com.hmdzl.spspd.items.weapon.missiles.PocketBall; +import com.hmdzl.spspd.items.weapon.missiles.PoisonDart; +import com.hmdzl.spspd.items.weapon.missiles.Skull; +import com.hmdzl.spspd.items.weapon.missiles.Smoke; +import com.hmdzl.spspd.items.weapon.missiles.TaurcenBow; +import com.hmdzl.spspd.items.weapon.spammo.BattleAmmo; +import com.hmdzl.spspd.items.weapon.spammo.GoldAmmo; +import com.hmdzl.spspd.items.weapon.spammo.HeavyAmmo; +import com.hmdzl.spspd.items.weapon.spammo.WoodenAmmo; +import com.hmdzl.spspd.plants.Dewcatcher; +import com.hmdzl.spspd.plants.Seedpod; +import com.watabou.utils.Bundle; +import com.hmdzl.spspd.messages.Messages; + +public enum HeroClass { + + WARRIOR( "warrior" , "warrior_name"), + MAGE( "mage", "mage_name"), + ROGUE( "rogue","rogue_name" ), + HUNTRESS( "huntress", "huntress_name"), + PERFORMER( "performer", "performer_name"), + SOLDIER( "soldier", "soldier_name"), + FOLLOWER( "follower", "follower_name"); + + + private String title; + private String title2; + + private HeroClass(String title, String title2) { + this.title = title; + this.title2 = title2; + } + + + public void initHero(Hero hero) { + + hero.heroClass = this; + + initCommon( hero ); + + switch (this) { + case WARRIOR: + initWarrior( hero ); + break; + + case MAGE: + initMage( hero ); + break; + + case ROGUE: + initRogue( hero ); + break; + + case HUNTRESS: + initHuntress( hero ); + break; + + case PERFORMER: + initPerformer( hero ); + break; + + case SOLDIER: + initSoldier( hero ); + break; + + case FOLLOWER: + initFollower( hero ); + break; + + } + + /*if (Badges.isUnlocked(masteryBadge())) { + new TomeOfMastery().collect(); + }*/ + + hero.updateAwareness(); + } + + private static void initCommon(Hero hero) { + new KeyRing().collect(); + new NormalRation().identify().collect(); + + if (Dungeon.skins != 3) { + new Ankhshield().collect(); + } + if (Dungeon.skins == 3) { + EtherealChains chains = new EtherealChains(); + (hero.belongings.misc3 = chains).identify(); + hero.belongings.misc3.activate(hero); + new EmpBola(7).collect(); + new PoisonDart(7).collect(); + new Smoke(7).collect(); + new Weightstone().collect(); + new Stylus().collect(); + new PotionOfHealing().identify().collect(); + } + + if (Dungeon.skins == 0) { + new RandomEgg().collect(); + new PetFood().collect(); + new PocketBall().collect(); + } + + if (Dungeon.isChallenged(Challenges.ITEM_PHOBIA)){ + Dungeon.gold += 1000; + } + if (Dungeon.isChallenged(Challenges.LISTLESS)){ + new PotionOfMight().collect(); + new PotionOfMight().setKnown(); + new Honey().collect(); + } + if (Dungeon.isChallenged(Challenges.NIGHTMARE_VIRUS)){ + new Ankh().collect(); + } + if (Dungeon.isChallenged(Challenges.ENERGY_LOST)){ + new Pasty().collect(); + } + if (Dungeon.isChallenged(Challenges.DEW_REJECTION)){ + new Dewcatcher.Seed().collect(); + new Dewcatcher.Seed().collect(); + } + if (Dungeon.isChallenged(Challenges.DARKNESS)){ + new ScrollOfMagicMapping().collect(); + new ScrollOfMagicMapping().collect(); + new ScrollOfMagicMapping().setKnown(); + } + if (Dungeon.isChallenged(Challenges.ABRASION)){ + new ScrollOfUpgrade().collect(); + new ScrollOfUpgrade().setKnown(); + new ScrollOfMagicalInfusion().collect(); + new ScrollOfMagicalInfusion().setKnown(); + } + if (Dungeon.isChallenged(Challenges.TEST_TIME)){ + new Elevator().collect(); + new ArmorKit().collect(); + new SafeSpotPage().collect(); + new Town().collect(); + new SewerChallenge().collect(); + new PrisonChallenge().collect(); + new CaveChallenge().collect(); + new CityChallenge().collect(); + new ScrollHolder().collect(); + new SeedPouch().collect(); + new PotionBandolier().collect(); + new WandHolster().collect(); + new Sokoban1().collect(); + new Sokoban2().collect(); + new Sokoban3().collect(); + new Sokoban4().collect(); + new DolyaSlate().collect(); + new Vault().collect(); + new CourageChallenge().collect(); + new PowerChallenge().collect(); + new WisdomChallenge().collect(); + new TriForce().collect(); + new Palantir().collect(); + + new SoulCollect().collect(); + new ErrorAmmo(20).collect(); + new PowerHand().collect(); + new TomeOfMastery().collect(); + new ShadowEater().collect(); + for(int i=0; i<199; i++){ + new ScrollOfMagicalInfusion().identify().collect(); + new ScrollOfUpgrade().identify().collect(); + new ScrollOfIdentify().identify().collect(); + new ScrollOfMagicMapping().identify().collect(); + new ExpOre().collect(); + new Pasty().collect(); + new PotionOfMindVision().identify().collect(); + new PotionOfStrength().identify().collect(); + new YellowNornStone().collect(); + new BlueNornStone().collect(); + new OrangeNornStone().collect(); + new PurpleNornStone().collect(); + new GreenNornStone().collect(); + } + for(int i=0; i<10; i++){ + new Seedpod.Seed().collect(); + new ScrollOfRegrowth().collect(); + } + new WandOfFlock().upgrade(10).identify().collect(); + new SewerReward().collect(); + new SaveYourLife().collect(); + new FireCracker().collect(); + + Dungeon.gold = 10000; + //Dungeon.gold = 10000000; + hero.HT=hero.HP=10000; + //hero.STR = hero.STR + 20; + Dungeon.depth = 1; + + } + } + + public Badges.Badge masteryBadge() { + switch (this) { + case WARRIOR: + return Badges.Badge.MASTERY_WARRIOR; + case MAGE: + return Badges.Badge.MASTERY_MAGE; + case ROGUE: + return Badges.Badge.MASTERY_ROGUE; + case HUNTRESS: + return Badges.Badge.MASTERY_HUNTRESS; + case PERFORMER: + return Badges.Badge.MASTERY_PERFORMER; + case SOLDIER: + return Badges.Badge.MASTERY_SOLDIER; + case FOLLOWER: + return Badges.Badge.MASTERY_FOLLOWER; + } + + return null; + } + + + private static void initWarrior(Hero hero) { + + if (Dungeon.skins == 1) { + (hero.belongings.armor = new VestArmor()).identify().upgrade(1); + RingOfForce force = new RingOfForce(); + (hero.belongings.misc1 = force).identify().upgrade(1); + hero.belongings.misc1.activate(hero); + + RingOfMight might = new RingOfMight(); + (hero.belongings.misc2 = might).identify().upgrade(1); + hero.belongings.misc2.activate(hero); + + new AttackShield().collect(); + new JumpW().collect(); + + } else if (Dungeon.skins == 2) { + hero.HT+=36; + hero.STR -=4; + hero.hitSkill-=4; + hero.evadeSkill+=1; + hero.magicSkill+=6; + (hero.belongings.armor = new BaseArmor()).upgrade(6).identify(); + new WandOfFirebolt().upgrade(6).identify().collect(); + new DemoScroll().collect(); + new PotionOfStrength().collect(); + new PotionOfStrength().collect(); + new PotionOfStrength().collect(); + new PotionOfStrength().collect(); + Dungeon.gold+=666; + new JumpW().collect(); + + } else if (Dungeon.skins == 3) { + + (hero.belongings.weapon = new Spear()).identify(); + (hero.belongings.armor = new DiscArmor()).identify(); + new MissileShield().collect(); + new SavageHelmet().collect(); + + hero.STR += 2; + Dungeon.limitedDrops.strengthPotions.count+=2; + + } else { + (hero.belongings.weapon = new ShortSword()).identify(); + (hero.belongings.armor = new WoodenArmor()).identify(); + new MissileShield().collect(); + new Powerpill().collect(); + new Smashpill().collect(); + new Hardpill().collect(); + new JumpW().collect(); + } + + new PotionOfStrength().setKnown(); + new ScrollOfUpgrade().setKnown(); + + } + + private static void initMage(Hero hero) { + + if (Dungeon.skins == 1) { + hero.STR+=4; + + (hero.belongings.weapon = new Whip()).identify().upgrade(2); + (hero.belongings.armor = new LeatherArmor()).identify().upgrade(1); + + Dungeon.limitedDrops.strengthPotions.count+=4; + new CannonOfMage().identify().collect(); + new JumpM().collect(); + } else if (Dungeon.skins == 2) { + hero.HT-=10; + hero.hitSkill-=5; + hero.evadeSkill+=2; + hero.magicSkill+=3; + (hero.belongings.weapon = new Dagger()).identify(); + (hero.belongings.armor = new VestArmor()).identify(); + new WandOfFirebolt().upgrade(1).identify().collect(); + new WandOfFreeze().upgrade(1).identify().collect(); + new WandOfLightning().upgrade(1).identify().collect(); + new GnollMark().collect(); + new JumpM().collect(); + } else if (Dungeon.skins == 3) { + + (hero.belongings.weapon = new WoodenStaff()).identify(); + (hero.belongings.armor = new VestArmor()).identify(); + + new WandOfFirebolt().identify().collect(); + new WandOfFreeze().identify().collect(); + new GnollMark().collect(); + new PotionOfMage().identify().collect(); + + } else { + (hero.belongings.weapon = new MageBook()).identify(); + (hero.belongings.armor = new ClothArmor()).identify(); + new WandOfMagicMissile().identify().collect(); + new WandOfDisintegration().identify().collect(); + new PotionOfMage().identify().collect(); + new JumpM().collect(); + + } + hero.magicSkill = hero.magicSkill + 3; + new ScrollOfIdentify().setKnown(); + new PotionOfLiquidFlame().setKnown(); + + } + + private static void initRogue(Hero hero) { + if (Dungeon.skins == 1) { + (hero.belongings.weapon = new LinkSword()).identify(); + hero.belongings.weapon.activate(hero); + (hero.belongings.armor = new WoodenArmor()).identify(); + hero.STR += 1; + Dungeon.limitedDrops.strengthPotions.count++; + EtherealChains ec = new EtherealChains(); + (hero.belongings.misc1 = ec).identify(); + hero.belongings.misc1.activate(hero); + new JumpR().collect(); + } else if (Dungeon.skins == 2) { + hero.HT-=20; + hero.evadeSkill+=3; + hero.magicSkill+=3; + (hero.belongings.weapon = new Dagger()).identify(); + (hero.belongings.armor = new ClothArmor()).identify(); + new UndeadBook().collect(); + new Skull(5).collect(); + new JumpR().collect(); + } else if (Dungeon.skins == 3) { + + (hero.belongings.weapon = new Glaive()).identify(); + (hero.belongings.armor = new DiscArmor()).identify(); + + CloakOfShadows cloak = new CloakOfShadows(); + (hero.belongings.misc1 = cloak).identify(); + hero.belongings.misc1.activate(hero); + + new HorseTotem().identify().collect(); + + hero.STR += 4; + Dungeon.limitedDrops.strengthPotions.count+=4; + + } else { + + (hero.belongings.weapon = new Dagger()).identify(); + (hero.belongings.armor = new VestArmor()).identify(); + + CloakOfShadows cloak = new CloakOfShadows(); + (hero.belongings.misc1 = cloak).identify(); + hero.belongings.misc1.activate(hero); + + new Smoke(3).identify().collect(); + new JumpR().collect(); + } + + new ScrollOfMagicMapping().setKnown(); + new PotionOfInvisibility().setKnown(); + } + + private static void initHuntress(Hero hero) { + if (Dungeon.skins == 1) { + hero.STR+=1; + (hero.belongings.weapon = new Dagger()).identify().upgrade(1); + (hero.belongings.armor = new RubberArmor()).identify().upgrade(1); + Dungeon.limitedDrops.strengthPotions.count++; + TimekeepersHourglass th = new TimekeepersHourglass(); + (hero.belongings.misc1 = th).identify(); + hero.belongings.misc1.activate(hero); + + new ManyKnive().upgrade(1).identify().collect(); + + EscapeKnive knife = new EscapeKnive(5); + knife.identify().collect(); + new JumpH().collect(); + } else if (Dungeon.skins == 2) { + hero.HT-=10; + hero.hitSkill+=5; + hero.evadeSkill+=3; + (hero.belongings.weapon = new Knuckles()).identify(); + (hero.belongings.armor = new ClothArmor()).identify(); + new TaurcenBow().identify().collect(); + new JumpH().collect(); + } else if (Dungeon.skins == 3) { + + (hero.belongings.weapon = new Knuckles()).identify(); + (hero.belongings.armor = new ClothArmor()).identify(); + + new TaurcenBow().identify().collect(); + new RangeBag().identify().collect(); + + } else { + (hero.belongings.weapon = new Knuckles()).identify(); + (hero.belongings.armor = new ClothArmor()).identify(); + + Boomerang boomerang = new Boomerang(null); + boomerang.identify().collect(); + EmpBola empbola = new EmpBola(3); + empbola.identify().collect(); + new JumpH().collect(); + } + new PotionOfMindVision().setKnown(); + new ScrollOfRemoveCurse().setKnown(); + } + + private static void initPerformer(Hero hero) { + + if (Dungeon.skins == 1) { + (hero.belongings.weapon = new GunA()).identify().upgrade(2); + (hero.belongings.armor = new VestArmor()).identify().upgrade(1); + new GoldAmmo().collect(); + new WoodenAmmo().collect(); + new BattleAmmo().collect(); + AlienBag alienBag = new AlienBag(); + (hero.belongings.misc1 = alienBag).identify(); + hero.belongings.misc1.activate(hero); + new BShovel().collect(); + new JumpP().collect(); + } else if (Dungeon.skins == 2) { + hero.HT-=10; + hero.magicSkill+=3; + hero.evadeSkill+=5; + (hero.belongings.weapon = new EmptyPotion()).identify(); + (hero.belongings.armor = new BaseArmor()).identify(); + new CopyBall().collect(); + new PotionOfMending().identify().collect(); + new PotionOfHealing().identify().collect(); + new JumpP().collect(); + } else if (Dungeon.skins == 3) { + + (hero.belongings.weapon = new Triangolo()).identify(); + (hero.belongings.armor = new ClothArmor()).identify(); + + new Shovel().identify().collect(); + new DanceLion().identify().collect(); + + } else { + + (hero.belongings.weapon = new Triangolo()).identify(); + (hero.belongings.armor = new ClothArmor()).identify(); + + new Shovel().identify().collect(); + new ScrollOfLullaby().collect(); + new JumpP().collect(); + + new FireBomb().collect(); + new IceBomb().collect(); + new StormBomb().collect(); + new DungeonBomb().collect(); + } + + new DungeonBomb().collect(); + new ScrollOfLullaby().setKnown(); + new PotionOfPurity().setKnown(); + } + + private static void initSoldier(Hero hero) { + if (Dungeon.skins == 1) { + hero.STR += 2; + (hero.belongings.armor = new LeatherArmor()).identify().upgrade(3); + Dungeon.limitedDrops.strengthPotions.count += 2; + + new AttackShoes().collect(); + new MKbox().collect(); + + }else if (Dungeon.skins == 2) { + hero.HT+=5; + hero.STR += 6; + hero.magicSkill+=5; + hero.hitSkill-=10; + hero.evadeSkill-=35; + (hero.belongings.weapon = new GunC()).identify(); + (hero.belongings.armor = new BaseArmor()).identify(); + Dungeon.limitedDrops.strengthPotions.count += 6; + new MechPocket().collect(); + new JumpS().collect(); + + } else if (Dungeon.skins == 3) { + + (hero.belongings.weapon = new GunA()).identify(); + (hero.belongings.armor = new VestArmor()).identify(); + + new HeavyAmmo().collect(); + new GunOfSoldier().identify().collect(); + new HealBag().identify().collect(); + + } else { + + (hero.belongings.weapon = new Sling()).identify(); + (hero.belongings.armor = new VestArmor()).identify(); + + new GunOfSoldier().identify().collect(); + + new JumpS().collect(); + EscapeKnive knife = new EscapeKnive(3); + knife.identify().collect(); + } + + new ScrollOfRage().setKnown(); + new PotionOfMending().setKnown(); + + hero.hitSkill = hero.hitSkill + 4; + hero.evadeSkill = hero.evadeSkill + 2; + } + + private static void initFollower(Hero hero) { + if (Dungeon.skins == 1) { + (hero.belongings.weapon = new DiamondPickaxe()).identify(); + (hero.belongings.armor = new LeatherArmor()).identify(); + hero.STR += 4; + Dungeon.limitedDrops.strengthPotions.count += 4; + new JumpF().collect(); + }else if (Dungeon.skins == 2) { + (hero.belongings.weapon = new Dagger()).upgrade(2).identify(); + (hero.belongings.armor = new VestArmor()).identify(); + Pylon pylon = new Pylon(); + (hero.belongings.misc1 = pylon).identify(); + hero.belongings.misc1.activate(hero); + new JumpF().collect(); + + } else if (Dungeon.skins == 3) { + + (hero.belongings.weapon = new Rapier()).identify(); + (hero.belongings.armor = new VestArmor()).identify(); + + new FaithSign().identify().collect(); + Pylon pylon = new Pylon(); + (hero.belongings.misc1 = pylon).identify(); + hero.belongings.misc1.activate(hero); + + hero.STR += 4; + Dungeon.limitedDrops.strengthPotions.count+=4; + + } else { + + (hero.belongings.weapon = new WoodenStaff()).identify(); + (hero.belongings.armor = new ClothArmor()).identify(); + new PotionOfHealing().identify().collect(); + new FaithSign().identify().collect(); + new JumpF().collect(); + } + + new ScrollOfTerror().setKnown(); + new PotionOfHealing().setKnown(); + + } + + public String title() { + return Messages.get(HeroClass.class, title); + } + + public String title2() { + return Messages.get(HeroClass.class, title2); + } + + + 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; + case PERFORMER: + return Assets.PERFORMER; + case SOLDIER: + return Assets.SOLDIER; + case FOLLOWER: + return Assets.FOLLOWER; + } + + return null; + } + + public String[] perks() { + + switch (this) { + case WARRIOR: + return new String[]{ + Messages.get(HeroClass.class, "warrior_desc_item"), + Messages.get(HeroClass.class, "warrior_desc_loadout"), + Messages.get(HeroClass.class, "warrior_desc_misc"), + }; + case MAGE: + return new String[]{ + Messages.get(HeroClass.class, "mage_desc_item"), + Messages.get(HeroClass.class, "mage_desc_loadout"), + Messages.get(HeroClass.class, "mage_desc_misc"), + }; + case ROGUE: + return new String[]{ + Messages.get(HeroClass.class, "rogue_desc_item"), + Messages.get(HeroClass.class, "rogue_desc_loadout"), + Messages.get(HeroClass.class, "rogue_desc_misc"), + }; + case HUNTRESS: + return new String[]{ + Messages.get(HeroClass.class, "huntress_desc_item"), + Messages.get(HeroClass.class, "huntress_desc_loadout"), + Messages.get(HeroClass.class, "huntress_desc_misc"), + }; + case PERFORMER: + return new String[]{ + Messages.get(HeroClass.class, "performer_desc_item"), + Messages.get(HeroClass.class, "performer_desc_loadout"), + Messages.get(HeroClass.class, "performer_desc_misc"), + }; + case SOLDIER: + return new String[]{ + Messages.get(HeroClass.class, "soldier_desc_item"), + Messages.get(HeroClass.class, "soldier_desc_loadout"), + Messages.get(HeroClass.class, "soldier_desc_misc"), + }; + case FOLLOWER: + return new String[]{ + Messages.get(HeroClass.class, "follower_desc_item"), + Messages.get(HeroClass.class, "follower_desc_loadout"), + Messages.get(HeroClass.class, "follower_desc_misc"), + }; + } + 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; + } + + +} diff --git a/java/com/hmdzl/spspd/actors/hero/HeroSubClass.java b/java/com/hmdzl/spspd/actors/hero/HeroSubClass.java new file mode 100644 index 00000000..a4835b5a --- /dev/null +++ b/java/com/hmdzl/spspd/actors/hero/HeroSubClass.java @@ -0,0 +1,72 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.hero; + +import com.hmdzl.spspd.messages.Messages; +import com.watabou.utils.Bundle; + +public enum HeroSubClass { + + NONE( null ), + + GLADIATOR( "gladiator" ), + BERSERKER( "berserker" ), + + WARLOCK( "warlock" ), + BATTLEMAGE( "battlemage" ), + + ASSASSIN( "assassin" ), + FREERUNNER( "freerunner" ), + + SNIPER( "sniper" ), + WARDEN( "warden" ), + + SUPERSTAR( "superstar" ), + JOKER( "joker" ), + + AGENT( "agent" ), + LEADER( "leader" ), + + PASTOR("pastor"), + ARTISAN("artisan"); + + private String title; + + HeroSubClass( String title ) { + this.title = title; + } + + public String title() { + return Messages.get(this, title); + } + + public String desc() { + return Messages.get(this, title+"_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 ); + return valueOf( value ); + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/Acidic.java b/java/com/hmdzl/spspd/actors/mobs/Acidic.java new file mode 100644 index 00000000..8976d1cb --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/Acidic.java @@ -0,0 +1,71 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2014 Oleg Dolya + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.actors.mobs; + +import java.util.HashSet; + +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.Blob; +import com.hmdzl.spspd.actors.blobs.StenchGas; +import com.hmdzl.spspd.sprites.AcidicSprite; +import com.hmdzl.spspd.scenes.GameScene; +import com.watabou.utils.Random; + +public class Acidic extends Scorpio { + + { + spriteClass = AcidicSprite.class; + + properties.add(Property.BEAST); + properties.add(Property.DEMONIC); + } + + @Override + public boolean act() { + GameScene.add(Blob.seed(pos, 30, StenchGas.class)); + return super.act(); + } + + @Override + public int defenseProc(Char enemy, int damage) { + + int dmg = Random.IntRange(0, damage/2); + if (dmg > 0) { + enemy.damage(dmg, this); + } + + return super.defenseProc(enemy, damage); + } + + @Override + public void die(Object cause) { + super.die(cause); + Badges.validateRare(this); + } + + private static final HashSet> IMMUNITIES = new HashSet>(); + static { + IMMUNITIES.add(StenchGas.class); + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/AdultDragonViolet.java b/java/com/hmdzl/spspd/actors/mobs/AdultDragonViolet.java new file mode 100644 index 00000000..aebde0a3 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/AdultDragonViolet.java @@ -0,0 +1,155 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs; + +import java.util.HashSet; + +import com.hmdzl.spspd.actors.buffs.Silent; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.ToxicGas; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Poison; +import com.hmdzl.spspd.items.BossRush; +import com.hmdzl.spspd.items.weapon.enchantments.EnchantmentDark; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.sprites.AdultDragonVioletSprite; +import com.hmdzl.spspd.sprites.CharSprite; +import com.watabou.utils.Callback; +import com.watabou.utils.Random; + +public class AdultDragonViolet extends Mob implements Callback{ + + private static final int JUMP_DELAY = 20; + private static final float TIME_TO_ZAP = 1f; + + { + spriteClass = AdultDragonVioletSprite.class; + baseSpeed = 1.5f; + + HP = HT = 8000; + EXP = 10; + evadeSkill = 40; + + loot = new BossRush(); + lootChance = 1f; + + properties.add(Property.DRAGON); + properties.add(Property.BOSS); + } + + private int timeToJump = JUMP_DELAY; + + + @Override + public int damageRoll() { + return Random.Int(60, 80); + } + + @Override + public int hitSkill(Char target) { + return 50; + } + + @Override + public int drRoll() { + return Random.NormalIntRange(20, 50); + } + + + @Override + public void die(Object cause) { + + super.die(cause); + + yell(Messages.get(this, "die")); + + } + + @Override + protected boolean canAttack(Char enemy) { + if (buff(Silent.class) != null){ + return Level.adjacent(pos, enemy.pos) && (!isCharmedBy(enemy)); + } else return new Ballistica( pos, enemy.pos, Ballistica.MAGIC_BOLT).collisionPos == enemy.pos; + } + + @Override + 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) { + ((AdultDragonVioletSprite) sprite).zap(enemy.pos); + } else { + zap(); + } + + return !visible; + } + } + + + private void zap() { + spend(TIME_TO_ZAP); + + + yell(Messages.get(this, "atk")); + + if (hit(this, enemy, true)) { + + int dmg = damageRoll(); + enemy.damage(dmg, this); + + Buff.affect(enemy,Poison.class).set(Poison.durationFactor(enemy)); + + } else { + enemy.sprite.showStatus(CharSprite.NEUTRAL, enemy.defenseVerb()); + } + + } + + public void onZapComplete() { + zap(); + next(); + } + + @Override + public void call() { + next(); + } + + private static final HashSet> RESISTANCES = new HashSet>(); + static { + RESISTANCES.add(ToxicGas.class); + RESISTANCES.add(Poison.class); + RESISTANCES.add(EnchantmentDark.class); + + } + + @Override + public HashSet> resistances() { + return RESISTANCES; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/Albino.java b/java/com/hmdzl/spspd/actors/mobs/Albino.java new file mode 100644 index 00000000..43b7b9c6 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/Albino.java @@ -0,0 +1,72 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs; + +import java.util.HashSet; + +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.items.food.meatfood.Meat; +import com.hmdzl.spspd.sprites.AlbinoSprite; +import com.watabou.utils.Random; +import com.hmdzl.spspd.actors.blobs.Blob; +import com.hmdzl.spspd.actors.blobs.CorruptGas; +import com.hmdzl.spspd.actors.buffs.Amok; +import com.hmdzl.spspd.actors.buffs.Terror; +import com.hmdzl.spspd.actors.buffs.Vertigo; +import com.hmdzl.spspd.scenes.GameScene; + +public class Albino extends Rat { + + { + spriteClass = AlbinoSprite.class; + + HP = HT = 10+(Dungeon.depth*Random.NormalIntRange(1, 3)); + + loot = new Meat(); + lootChance = 1f; + + properties.add(Property.BEAST); + properties.add(Property.DEMONIC); + } + + @Override + public void die(Object cause) { + super.die(cause); + Badges.validateRare(this); + } + + @Override + public boolean act() { + GameScene.add(Blob.seed(pos, 15, CorruptGas.class)); + return super.act(); + } + + private static final HashSet> IMMUNITIES = new HashSet>(); + static { + IMMUNITIES.add(Amok.class); + IMMUNITIES.add(Terror.class); + IMMUNITIES.add(CorruptGas.class); + IMMUNITIES.add(Vertigo.class); + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/AlbinoPiranha.java b/java/com/hmdzl/spspd/actors/mobs/AlbinoPiranha.java new file mode 100644 index 00000000..2a66a6a3 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/AlbinoPiranha.java @@ -0,0 +1,203 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs; + +import java.util.HashSet; + +import com.hmdzl.spspd.actors.buffs.Corruption; +import com.hmdzl.spspd.items.food.vegetable.NutVegetable; +import com.hmdzl.spspd.items.food.completefood.GoldenNut; +import com.hmdzl.spspd.items.reward.CaveReward; +import com.hmdzl.spspd.items.scrolls.ScrollOfSacrifice; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.Statistics; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.ToxicGas; +import com.hmdzl.spspd.actors.buffs.Burning; +import com.hmdzl.spspd.actors.buffs.Frost; +import com.hmdzl.spspd.actors.buffs.Paralysis; +import com.hmdzl.spspd.actors.buffs.Roots; +import com.hmdzl.spspd.items.ConchShell; +import com.hmdzl.spspd.items.food.meatfood.Meat; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.sprites.AlbinoPiranhaSprite; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Random; + +public class AlbinoPiranha extends Mob { + + private static final String TXT_KILLCOUNT = "Albino Piranha Kill Count: %s"; + + { + spriteClass = AlbinoPiranhaSprite.class; + + baseSpeed = 1f; + + EXP = 5; + + loot = new Meat(); + lootChance = 0.1f; + + properties.add(Property.BEAST); + } + + public AlbinoPiranha() { + super(); + + HP = HT = 20 + Statistics.albinoPiranhasKilled*2; + evadeSkill = 40 + Statistics.albinoPiranhasKilled/5; + } + + protected boolean checkwater(int cell){ + return Level.water[cell]; + } + + + @Override + protected boolean act() { + + if (!Level.water[pos]) { + die(null); + return true; + + + } else { + // this causes pirahna to move away when a door is closed on them. + Dungeon.level.updateFieldOfView(this); + enemy = chooseEnemy(); + if (state == this.HUNTING + && !(enemy.isAlive() && Level.fieldOfView[enemy.pos] && enemy.invisible <= 0)) { + state = this.WANDERING; + int oldPos = pos; + int i = 0; + do { + i++; + target = Dungeon.level.randomDestination(); + if (i == 100) + return true; + } while (!getCloser(target)); + moveSprite(oldPos, pos); + return true; + } + + return super.act(); + } + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(Statistics.albinoPiranhasKilled/2, 4 + Statistics.albinoPiranhasKilled); + } + + @Override + public int hitSkill(Char target) { + return 20 + Statistics.albinoPiranhasKilled; + } + + @Override + public int drRoll() { + return Statistics.albinoPiranhasKilled; + } + + @Override + public void die(Object cause) { + + super.die(cause); + + Statistics.albinoPiranhasKilled++; + GLog.w(Messages.get(Mob.class,"killcount",Statistics.albinoPiranhasKilled)); + + + explodeDew(pos); + if(Random.Int(105-Math.min(Statistics.albinoPiranhasKilled,100))==0){ + Dungeon.level.drop(new NutVegetable(), pos).sprite.drop(); + } + + if(Statistics.albinoPiranhasKilled == 25) { + Dungeon.limitedDrops.conchshell.drop(); + Dungeon.level.drop(new ConchShell(), pos).sprite.drop(); + } + + if(Statistics.albinoPiranhasKilled == 50) { + Dungeon.level.drop(new ScrollOfSacrifice(), pos).sprite.drop(); + } + + if(Statistics.albinoPiranhasKilled == 100) { + Dungeon.level.drop(new CaveReward(), pos).sprite.drop(); + } + + if (Statistics.goldThievesKilled>99 && Statistics.skeletonsKilled>99 + && Statistics.albinoPiranhasKilled == 100 && Statistics.archersKilled>99){ + Dungeon.level.drop(new GoldenNut(), pos).sprite.drop(); + } + + + + + } + + @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; + } + } + + private static final HashSet> IMMUNITIES = new HashSet>(); + static { + IMMUNITIES.add(Burning.class); + IMMUNITIES.add(Paralysis.class); + IMMUNITIES.add(ToxicGas.class); + IMMUNITIES.add(Roots.class); + IMMUNITIES.add(Frost.class); + IMMUNITIES.add(Corruption.class); + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/Assassin.java b/java/com/hmdzl/spspd/actors/mobs/Assassin.java new file mode 100644 index 00000000..c95f91f6 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/Assassin.java @@ -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 + */ +package com.hmdzl.spspd.actors.mobs; + +import java.util.HashSet; + +import com.hmdzl.spspd.Statistics; +import com.hmdzl.spspd.actors.buffs.Locked; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.items.StoneOre; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.ToxicGas; +import com.hmdzl.spspd.actors.buffs.Poison; +import com.hmdzl.spspd.items.weapon.enchantments.EnchantmentDark; +import com.hmdzl.spspd.items.weapon.melee.special.TekkoKagi; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.AssassinSprite; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Random; + +public class Assassin extends Mob { + + protected static final float SPAWN_DELAY = 2f; + + { + spriteClass = AssassinSprite.class; + baseSpeed = 2f; + + HP = HT = 80+(5*Random.NormalIntRange(2, 5)); + EXP = 10; + maxLvl = 18; + evadeSkill = 15; + + loot = new StoneOre(); + lootChance = 0.2f; + + properties.add(Property.HUMAN); + + } + + + @Override + public int damageRoll() { + return Random.NormalIntRange(10, 23); + } + + @Override + public int hitSkill(Char target) { + return 25; + } + + @Override + public int drRoll() { + return Random.NormalIntRange(0, 5); + } + @Override + protected float attackDelay() { + return 0.75f; + } + + @Override + public void die(Object cause) { + + super.die(cause); + Statistics.assassinsKilled++; + GLog.w(Messages.get(Mob.class,"killcount", Statistics.assassinsKilled)); + + if (Statistics.assassinsKilled == 100){ + Dungeon.level.drop(new TekkoKagi(), pos).sprite.drop(); + } + } + + @Override + protected boolean canAttack(Char enemy) { + if (buff(Locked.class) != null){ + return Level.adjacent(pos, enemy.pos) && (!isCharmedBy(enemy)); + } else + return new Ballistica( pos, enemy.pos, Ballistica.PROJECTILE).collisionPos == enemy.pos; + } + + public static Assassin spawnAt(int pos) { + if (Level.passable[pos] && Actor.findChar(pos) == null) { + + Assassin w = new Assassin(); + w.pos = pos; + w.state = w.HUNTING; + GameScene.add(w, SPAWN_DELAY); + + //w.sprite.alpha(0); + //w.sprite.parent.add(new AlphaTweener(w.sprite, 1, 0.5f)); + + return w; + + } else { + return null; + } + } + + private static final HashSet> RESISTANCES = new HashSet>(); + static { + RESISTANCES.add(ToxicGas.class); + RESISTANCES.add(Poison.class); + RESISTANCES.add(EnchantmentDark.class); + + } + + @Override + public HashSet> resistances() { + return RESISTANCES; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/Bandit.java b/java/com/hmdzl/spspd/actors/mobs/Bandit.java new file mode 100644 index 00000000..adb40e20 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/Bandit.java @@ -0,0 +1,61 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.buffs.Blindness; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Cripple; +import com.hmdzl.spspd.actors.buffs.Poison; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.sprites.BanditSprite; +import com.watabou.utils.Random; + +public class Bandit extends Thief { + + public Item item; + + { + spriteClass = BanditSprite.class; + + // 1 in 30 chance to be a crazy bandit, equates to overall 1/90 chance. + lootChance = 1f; + + properties.add(Property.ELF); + } + + @Override + public int attackProc(Char enemy, int damage) { + + Buff.prolong(enemy, Blindness.class, Random.Int(5, 12)); + Buff.affect(enemy, Poison.class).set( + Random.Int(5, 7) * Poison.durationFactor(enemy)); + Buff.prolong(enemy, Cripple.class, Cripple.DURATION); + Dungeon.observe(); + + return damage; + } + + @Override + public void die(Object cause) { + super.die(cause); + Badges.validateRare(this); + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/BanditKing.java b/java/com/hmdzl/spspd/actors/mobs/BanditKing.java new file mode 100644 index 00000000..b00587b8 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/BanditKing.java @@ -0,0 +1,85 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs; + +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.CountDown; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.weapon.melee.special.Spork; +import com.hmdzl.spspd.sprites.BanditKingSprite; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Random; + +public class BanditKing extends Mob { + + public Item item; + + { + spriteClass = BanditKingSprite.class; + HP = HT = 300; + EXP = 10; + maxLvl = 25; + flying = true; + + // 1 in 30 chance to be a crazy bandit, equates to overall 1/90 chance. + lootChance = 0.2f; + evadeSkill = 20; //20 + if (Dungeon.depth<25){Dungeon.sporkAvail = false;} + + properties.add(Property.ELF); + properties.add(Property.MINIBOSS); + } + + @Override + public int drRoll() { + return Random.NormalIntRange(10, 20); + } + + @Override + public float speed() { + return 2f; + } + + @Override + public int attackProc(Char enemy, int damage) { + if(enemy.buff(CountDown.class) == null){ + Buff.affect(enemy, CountDown.class); + state = FLEEING; + } + + return damage; + } + + @Override + public void die(Object cause) { + super.die(cause); + if (Dungeon.depth<25){ + yell(Messages.get(this, "die")); + GLog.n(Messages.get(this, "dis")); + if (!Dungeon.limitedDrops.spork.dropped()) { + Dungeon.level.drop(new Spork(), pos).sprite.drop(); + Dungeon.limitedDrops.spork.drop(); + Dungeon.sporkAvail = false; + yell(Messages.get(this, "spork")); + } + } + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/Bat.java b/java/com/hmdzl/spspd/actors/mobs/Bat.java new file mode 100644 index 00000000..30801655 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/Bat.java @@ -0,0 +1,103 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2014 Oleg Dolya + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.actors.mobs; + +import java.util.HashSet; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.food.meatfood.Meat; +import com.hmdzl.spspd.items.potions.PotionOfMending; + +import com.hmdzl.spspd.sprites.BatSprite; +import com.watabou.utils.Random; + +public class Bat extends Mob { + + { + spriteClass = BatSprite.class; + + HP = HT = 80+(adj(0)*Random.NormalIntRange(2, 5)); + evadeSkill = 15+adj(0); + baseSpeed = 2f; + + EXP = 9; + maxLvl = 25; + + flying = true; + + loot = new PotionOfMending(); + lootChance = 0.1667f; // by default, see die() + + lootOther = new Meat(); + lootChanceOther = 0.5f; // by default, see die() + + properties.add(Property.BEAST); + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(15, 22+adj(0)); + } + + @Override + public int hitSkill(Char target) { + return 16+adj(0); + } + + @Override + public int drRoll() { + return adj(0); + } + + @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 void die(Object cause) { + super.die(cause); + lootChance = 1f / 6 ; + + } + + @Override + protected Item createLoot() { + return super.createLoot(); + } + + private static final HashSet> RESISTANCES = new HashSet>(); + static { + + } + + @Override + public HashSet> resistances() { + return RESISTANCES; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/Bestiary.java b/java/com/hmdzl/spspd/actors/mobs/Bestiary.java new file mode 100644 index 00000000..01aed40c --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/Bestiary.java @@ -0,0 +1,343 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.watabou.utils.Random; + +public class Bestiary { + + public static Mob mob(int depth) { + @SuppressWarnings("unchecked") + Class cl = (Class) mobClass(depth); + try { + return cl.newInstance(); + } catch (Exception e) { + return null; + } + } + + public static Mob mutable(int depth) { + @SuppressWarnings("unchecked") + Class cl = (Class) 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, 1, 0.02f}; + classes = new Class[]{Rat.class, BrownBat.class, + RatBoss.class}; + break; + case 2: + chances = new float[]{1, 1, 0.7f, 0.5f}; + classes = new Class[]{Rat.class, BrownBat.class, + DustElement.class, LiveMoss.class}; + break; + case 3: + chances = new float[]{1, 1, 0.8f, 0.6f, 0.4f, 0.2f, 0.7f }; + classes = new Class[]{ + Rat.class, BrownBat.class, + DustElement.class, LiveMoss.class, + Swarm.class, Crab.class,PatrolUAV.class}; + break; + case 4: + chances = new float[]{1, 1, 0.9f, 0.7f, 0.5f, 0.3f, 0.02f, 0.02f,0.7f}; + classes = new Class[]{Rat.class, BrownBat.class, + DustElement.class, LiveMoss.class, + Swarm.class, Crab.class, + Gnoll.class, Thief.class,PatrolUAV.class}; + break; + case 5: + if (Random.Int(3) == 1) { + chances = new float[]{ 1 }; + classes = new Class[]{Goo.class}; + } else if (Random.Int(2) == 1) { + chances = new float[]{ 1 }; + classes = new Class[]{SewerHeart.class}; + } else { + chances = new float[]{ 1 }; + classes = new Class[]{PlagueDoctor.class}; + } + break; + + case 6: + chances = new float[]{0.8f, 0.8f, 1, 1,0.5f}; + classes = new Class[]{Swarm.class, Crab.class, + Thief.class, Gnoll.class,PatrolUAV.class}; + break; + case 7: + chances = new float[]{0.6f, 1, 1, 0.4f,0.2f}; + classes = new Class[]{Crab.class, + Thief.class, Gnoll.class, + Guard.class, Zombie.class}; + break; + case 8: + chances = new float[]{1, 1, 0.5f, 0.4f, 0.3f,0.7f,0.5f}; + classes = new Class[]{Thief.class, Gnoll.class, + Guard.class, Assassin.class, TrollWarrior.class, Zombie.class,FireRabbit.class}; + break; + case 9: + if (Dungeon.sporkAvail) { + chances = new float[]{1, 1, 0.1f,1}; + classes = new Class[]{Assassin.class, TrollWarrior.class, BanditKing.class, Zombie.class}; + } else { + chances = new float[]{1, 1, 0.8f, 0.6f, 0.5f, 0.02f, 0.01f,1f,0.8f}; + classes = new Class[]{Thief.class, Gnoll.class, + Guard.class, Assassin.class, TrollWarrior.class, + Bat.class, Brute.class, Zombie.class,FireRabbit.class}; + } + break; + + case 10: + if (Random.Int(3) == 1){ + chances = new float[]{ 1 }; + classes = new Class[]{Tengu.class}; + }else if (Random.Int(2) == 1){ + //}else{ + chances = new float[]{ 1 }; + classes = new Class[]{PrisonWander.class}; + }else{ + chances = new float[] { 1 }; + classes = new Class[] { Tank.class }; + } + break; + + case 11: + chances = new float[] { 0.8f, 0.6f, 1, 0.7f, 0.5f,0.5f }; + classes = new Class[] { Assassin.class, TrollWarrior.class, + Bat.class, Skeleton.class,Brute.class,FireRabbit.class }; + break; + case 12: + chances = new float[] { 1, 0.9f, 0.7f, 0.5f, 0.3f ,0.9f,1 }; + classes = new Class[] { Bat.class, Skeleton.class, Brute.class, + GnollShaman.class,Spinner.class,SandMob.class,BombBug.class }; + break; + case 13: + chances = new float[] { 1, 1, 0.9f, 0.7f, 0.6f, 0.7f,0.4f, 0.02f,1 }; + classes = new Class[] { Bat.class, Skeleton.class, Brute.class, + GnollShaman.class,Spinner.class, BrokenRobot.class,SandMob.class, + FireElemental.class,BombBug.class }; + break; + case 14: + chances = new float[] { 1, 1, 1, 0.9f,0.8f,0.6f,0.6f,0.04f, 0.02f,1 }; + classes = new Class[] { Bat.class, Skeleton.class, Brute.class, + GnollShaman.class,Spinner.class, BrokenRobot.class,SandMob.class, + FireElemental.class, Monk.class,BombBug.class}; + break; + + case 15: + if (Random.Int(3) ==1) { + chances = new float[]{ 1 }; + classes = new Class[] { Hybrid.class }; + } else if (Random.Int(2) == 1){ + chances = new float[]{ 1 }; + classes = new Class[] { DM300.class }; + } else { + chances = new float[]{ 1 }; + classes = new Class[]{SpiderQueen.class}; + } + break; + + case 16: + chances = new float[] { 0.8f, 0.6f, 1, 1, 0.4f }; + classes = new Class[] { GnollShaman.class,BrokenRobot.class, + FireElemental.class, Warlock.class, Monk.class }; + break; + case 17: + chances = new float[] { 1, 1, 0.8f, 0.4f,0.4f ,0.2f }; + classes = new Class[] { FireElemental.class, Warlock.class,Monk.class, + Golem.class,SpiderBot.class, Musketeer.class}; + break; + case 18: + chances = new float[] { 1, 1, 1, 0.8f,0.8f, 0.6f, 0.2f,0.1f }; + classes = new Class[] { FireElemental.class, Warlock.class,Monk.class, + Golem.class, SpiderBot.class,Musketeer.class, DwarfLich.class,ManySkeleton.class }; + break; + case 19: + + chances = new float[] { 1, 1, 1, 1, 1,0.8f, 0.6f, 0.02f,0.3f }; + classes = new Class[] { FireElemental.class, Warlock.class,Monk.class, + Golem.class, SpiderBot.class,Musketeer.class, DwarfLich.class, + Succubus.class,ManySkeleton.class}; + break; + case 20: + if (Random.Int(3) ==1) { + chances = new float[]{ 1 }; + classes = new Class[] { LichDancer.class }; + } else if (Random.Int(2) == 1){ + chances = new float[]{ 1 }; + classes = new Class[] { ElderAvatar.class }; + } else { + chances = new float[] { 1 }; + classes = new Class[] { King.class }; + } + + break; + + case 22: + chances = new float[] { 0.8f,0.8f, 1, 1, 1, 0.2f, 0.2f }; + classes = new Class[] {Musketeer.class, DwarfLich.class, + Succubus.class, Eye.class, DemonGoo.class, DemonFlower.class, Sufferer.class}; + break; + case 23: + chances = new float[] { 1, 1, 1, 0.5f,0.5f, 0.5f,0.5f }; + classes = new Class[] { Succubus.class, Eye.class, DemonGoo.class, + Scorpio.class,ThiefImp.class , DemonFlower.class, Sufferer.class}; + break; + case 24: + chances = new float[] { 1, 1, 1, 1, 1, 1, 1 }; + classes = new Class[] {Succubus.class, Eye.class, DemonGoo.class, + Scorpio.class,ThiefImp.class, DemonFlower.class, Sufferer.class + }; + break; + + case 25: + chances = new float[] { 1 }; + classes = new Class[] { Yog.class }; + break; + + case 27: + chances = new float[] { 1, 0.05f,0.1f }; + classes = new Class[] { GnollArcher.class, ForestProtector.class,Brute.class }; + break; + case 28: + chances = new float[] { 1, 0.05f,0.1f }; + classes = new Class[] { MossySkeleton.class, GraveProtector.class,ManySkeleton.class}; + break; + case 29: + chances = new float[] { 1, 0.05f,0.1f }; + classes = new Class[] { AlbinoPiranha.class, FishProtector.class,Crab.class }; + break; + case 30: + chances = new float[] { 1, 0.05f,0.1f }; + classes = new Class[] { GoldThief.class, VaultProtector.class,Succubus.class}; + break; + + case 31: + chances = new float[] { 1, 0.1f }; + classes = new Class[] { BlueWraith.class, DwarfLich.class}; + break; + + case 32: + chances = new float[] { 1,0.05f }; + classes = new Class[] { Orc.class, GoldOrc.class}; + break; + case 33: + chances = new float[] { 1, 0.2f }; + classes = new Class[] { FlyingProtector.class, FireElemental.class }; + break; + case 35: + chances = new float[] {1, 1 }; + classes = new Class[] {GoldOrc.class, Fiend.class }; + break; + case 36: + chances = new float[] {1}; + classes = new Class[] {TenguDen.class}; + break; + case 41: + chances = new float[] {1}; + classes = new Class[] {BanditKing.class}; + break; + case 45: + chances = new float[] {1 }; + classes = new Class[] {TestMob.class }; + break; + case 71: + chances = new float[] {1}; + classes = new Class[] {Dragonking.class}; + break; + case 85: + chances = new float[] { + 1,1, + 1,1, + 1,1,1, + 1,1, + 1,1,1,1, + 1,1,1, + 1,1,1,1, + 1,1,1, + 1,1,1,1, + 1, + 1,1, + 1,1}; + classes = new Class[] { + Rat.class, BrownBat.class, + DustElement.class, LiveMoss.class, + Swarm.class, Crab.class,PatrolUAV.class, + Thief.class, Gnoll.class, + Guard.class, Assassin.class, TrollWarrior.class, Zombie.class, + Bat.class, Skeleton.class, Brute.class, + GnollShaman.class,Spinner.class, BrokenRobot.class,SandMob.class, + FireElemental.class, Warlock.class,Monk.class, + Golem.class, SpiderBot.class,Musketeer.class, DwarfLich.class, + Succubus.class, Eye.class, DemonGoo.class, + Scorpio.class,ThiefImp.class, DemonFlower.class, Sufferer.class, + BlueWraith.class, + Orc.class,FlyingProtector.class, + GoldOrc.class, Fiend.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.BurningFist + || mob instanceof Yog.RottingFist + || mob instanceof FetidRat + || mob instanceof GnollTrickster + || mob instanceof GreatCrab; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/BlueCat.java b/java/com/hmdzl/spspd/actors/mobs/BlueCat.java new file mode 100644 index 00000000..316cb102 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/BlueCat.java @@ -0,0 +1,172 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Terror; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.items.Amulet; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.items.Gold; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.artifacts.MasterThievesArmband; +import com.hmdzl.spspd.sprites.CharSprite; +import com.hmdzl.spspd.sprites.BanditKingSprite; +import com.hmdzl.spspd.utils.GLog; +import com.hmdzl.spspd.messages.Messages; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public class BlueCat 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."; + protected static final String TXT_RATCHECK1 = "Spork is avail"; + protected static final String TXT_RATCHECK2 = "Spork is not avail"; + + public Item item; + + { + spriteClass = BanditKingSprite.class; + + HP = HT = 20+(adj(0)*Random.NormalIntRange(3, 5)); + evadeSkill = 8+adj(0); + + EXP = 5; + + loot = new MasterThievesArmband().identify(); + lootChance = 0.01f; + + lootOther = Generator.Category.BERRY; + lootChanceOther = 1f; // by default, see die() + + FLEEING = new Fleeing(); + + properties.add(Property.ELF); + } + + 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+adj(0)); + } + + @Override + protected float attackDelay() { + return 0.5f; + } + + @Override + public void die(Object cause) { + + super.die(cause); + + if (item != null) { + Dungeon.level.drop(item, pos).sprite.drop(); + } + } + + @Override + protected Item createLoot() { + return new Gold(Random.NormalIntRange(100, 250)); + } + + @Override + public int hitSkill(Char target) { + return 120; + } + + @Override + public int drRoll() { + return 3; + } + + @Override + public int attackProc(Char enemy, int damage) { + if (item == null && enemy instanceof Hero && steal((Hero) enemy)) { + state = FLEEING; + } + + return damage; + } + + @Override + public int defenseProc(Char enemy, int damage) { + if (state == FLEEING) { + Dungeon.level.drop(new Gold(), pos).sprite.drop(); + } + + return damage; + } + + protected boolean steal(Hero hero) { + + Amulet item = hero.belongings.getItem(Amulet.class); + if (item != null) { + + item.updateQuickslot(); + + GLog.w(Messages.get(BlueCat.class, "stole", item.name()) ); + + this.item = item; + item.detachAll(hero.belongings.backpack); + + + return true; + } else { + return false; + } + } + + @Override + public String description() { + String desc = super.description(); + + if (item != null) { + desc += Messages.get(this, "carries", item.name() ); + } + + return desc; + } + + private class Fleeing extends Mob.Fleeing { + @Override + protected void nowhereToRun() { + if (buff(Terror.class) == null) { + sprite.showStatus(CharSprite.NEGATIVE, Messages.get(Mob.class, "rage")); + state = HUNTING; + } else { + super.nowhereToRun(); + } + } + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/BlueWraith.java b/java/com/hmdzl/spspd/actors/mobs/BlueWraith.java new file mode 100644 index 00000000..58734685 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/BlueWraith.java @@ -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 + */ +package com.hmdzl.spspd.actors.mobs; + +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Terror; +import com.hmdzl.spspd.actors.buffs.Vertigo; +import com.hmdzl.spspd.effects.particles.ShadowParticle; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.BlueWraithSprite; +import com.watabou.noosa.tweeners.AlphaTweener; +import com.watabou.utils.Random; + +public class BlueWraith extends Wraith { + + { + spriteClass = BlueWraithSprite.class; + + HP = HT = 250; + evadeSkill = 24; + baseSpeed = 2f; + + EXP = 20; + + loot = Generator.random(Generator.Category.SEED); + lootChance = 1.0f; // by default, see die() + + properties.add(Property.UNDEAD); + + } + + @Override + public int attackProc(Char enemy, int damage) { + if (Random.Int(10) == 0) { + Buff.affect(enemy, Vertigo.class, Vertigo.duration(enemy)); + Buff.affect(enemy, Terror.class, Terror.DURATION).object = enemy.id(); + } + + return damage; + } + + @Override + public void adjustStats(int level) { + this.level = level; + evadeSkill = 24; + enemySeen = true; + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(20, 90); + } + + @Override + public int hitSkill(Char target) { + return 46; + } + + @Override + public int drRoll() { + return Random.NormalIntRange(10, 25); + } + + @Override + protected boolean canAttack(Char enemy) { + return Dungeon.level.distance( pos, enemy.pos ) <= 2 ; + } + + public static BlueWraith spawnAt(int pos) { + + BlueWraith b = new BlueWraith(); + b.adjustStats(Dungeon.depth); + b.pos = pos; + b.state = b.HUNTING; + GameScene.add(b, SPAWN_DELAY); + + b.sprite.alpha(0); + b.sprite.parent.add(new AlphaTweener(b.sprite, 1, 0.5f)); + + b.sprite.emitter().burst(ShadowParticle.CURSE, 5); + + return b; + + + } + +} diff --git a/java/com/hmdzl/spspd/actors/mobs/BombBug.java b/java/com/hmdzl/spspd/actors/mobs/BombBug.java new file mode 100644 index 00000000..12890c51 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/BombBug.java @@ -0,0 +1,131 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs; + +import java.util.HashSet; + +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Silent; +import com.hmdzl.spspd.actors.buffs.StoneIce; +import com.hmdzl.spspd.items.StoneOre; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.ResultDescriptions; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.weapon.enchantments.EnchantmentDark; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.SkeletonSprite; + +import com.hmdzl.spspd.sprites.SpiderJumpSprite; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public class BombBug extends Mob { + + { + spriteClass = SpiderJumpSprite.class; + + HP = HT = 80+(adj(0)*Random.NormalIntRange(2, 5)); + evadeSkill = 15+adj(0); + baseSpeed = 1.5f; + + EXP = 9; + maxLvl = 25; + + loot = new StoneOre(); + lootChance = 0.3f; + + properties.add(Property.BEAST); + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(15, 20+adj(0)); + } + + + @Override + public void die(Object cause) { + + super.die(cause); + + for (int i = 0; i < Level.NEIGHBOURS8.length; i++) { + Char ch = findChar(pos + Level.NEIGHBOURS8[i]); + if (ch != null && ch.isAlive()) { + Buff.affect(ch,StoneIce.class).level(10); + + } + } + + if (Dungeon.visible[pos]) { + Sample.INSTANCE.play(Assets.SND_BLAST); + } + + + } + + + @Override + public int hitSkill(Char target) { + return 16+adj(0); + } + + @Override + public int drRoll() { + return Random.NormalIntRange(2, 5); + } + + private static final HashSet> IMMUNITIES = new HashSet>(); + static { + IMMUNITIES.add(EnchantmentDark.class); + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } + + 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 BombBug spawnAt(int pos) { + if (Level.passable[pos] && Actor.findChar(pos) == null) { + + BombBug w = new BombBug(); + w.pos = pos; + w.state = w.HUNTING; + GameScene.add(w, 1f); + return w; + + } else { + return null; + } + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/mobs/BrokenRobot.java b/java/com/hmdzl/spspd/actors/mobs/BrokenRobot.java new file mode 100644 index 00000000..50d977e8 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/BrokenRobot.java @@ -0,0 +1,270 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs; + +import java.util.HashSet; + +import com.hmdzl.spspd.items.StoneOre; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.ResultDescriptions; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.ToxicGas; +import com.hmdzl.spspd.actors.blobs.Blob; +import com.hmdzl.spspd.actors.blobs.TarGas; +import com.hmdzl.spspd.actors.buffs.Light; +import com.hmdzl.spspd.actors.buffs.Terror; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.particles.BlastParticle; +import com.hmdzl.spspd.effects.particles.PurpleParticle; +import com.hmdzl.spspd.effects.particles.SmokeParticle; +import com.hmdzl.spspd.items.Heap; +import com.hmdzl.spspd.items.scrolls.ScrollOfRecharging; +import com.hmdzl.spspd.items.weapon.enchantments.EnchantmentDark; + +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.Terrain; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.BrokenRobotSprite; +import com.hmdzl.spspd.sprites.CharSprite; +import com.hmdzl.spspd.utils.GLog; + +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Random; + +public class BrokenRobot extends Mob { + + private static final String TXT_DEATHGAZE_KILLED = "%s's deathray killed you..."; + private static final float SPAWN_DELAY = 2f; + + { + spriteClass = BrokenRobotSprite.class; + + HP = HT = 120+(adj(0)*Random.NormalIntRange(4, 7)); + evadeSkill = 20+adj(1); + viewDistance = Light.DISTANCE; + + EXP = 13; + maxLvl = 25; + + + lootOther = new StoneOre(); + lootChanceOther = 0.25f; + + loot = new ScrollOfRecharging(); + lootChance = 0.25f; // by default, see die() + + properties.add(Property.MECH); + } + + private Ballistica beam; + + @Override + public int drRoll() { + return Random.NormalIntRange(0, 5); + } + + @Override + public boolean act() { + GameScene.add(Blob.seed(pos,30, TarGas.class)); + if(enemySeen){ + switch (Random.Int(50)) { + case 1: + GLog.n(Messages.get(this,"explode") ); + explode(pos); + if (HP<1){destroy();} + break; + } + } + + return super.act(); + } + + + + @Override + protected boolean canAttack(Char enemy) { + + beam = new Ballistica( pos, enemy.pos, Ballistica.STOP_TERRAIN); + + return beam.subPath(1, beam.dist).contains(enemy.pos); + } + + @Override + public int hitSkill(Char target) { + return 20+adj(0); + } + + @Override + protected float attackDelay() { + return 3f; + } + + @Override + protected boolean doAttack(Char enemy) { + + spend(attackDelay()); + + boolean rayVisible = false; + + for (int i : beam.subPath(0, beam.dist)) { + if (Dungeon.visible[i]) { + rayVisible = true; + } + } + + if (rayVisible) { + sprite.attack(beam.collisionPos); + return false; + } else { + attack(enemy); + return true; + } + } + + @Override + public boolean attack(Char enemy) { + + for (int pos : beam.subPath(1, beam.dist)) { + + Char ch = Actor.findChar( pos ); + if (ch == null) { + continue; + } + + if (hit(this, ch, true)) { + ch.damage(Random.NormalIntRange(2, 8+adj(0)), 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(Messages.format(ResultDescriptions.MOB)); + //GLog.n(Messages.get(this, "kill")); + } + } else { + ch.sprite.showStatus(CharSprite.NEUTRAL, ch.defenseVerb()); + } + } + + return true; + } + + 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 BrokenRobot spawnAt(int pos) { + + BrokenRobot b = new BrokenRobot(); + + b.pos = pos; + b.state = b.HUNTING; + GameScene.add(b, SPAWN_DELAY); + + return b; + + } + + + public void explode(int cell) { + // We're blowing up, so no need for a fuse anymore. + + Sample.INSTANCE.play(Assets.SND_BLAST, 2); + + if (Dungeon.visible[cell]) { + CellEmitter.center(cell).burst(BlastParticle.FACTORY, 30); + } + + boolean terrainAffected = false; + for (int n : Level.NEIGHBOURS9) { + int c = cell + n; + if (c >= 0 && c < Level.getLength()) { + if (Dungeon.visible[c]) { + CellEmitter.get(c).burst(SmokeParticle.FACTORY, 4); + } + + if (Level.flamable[c]) { + Level.set(c, Terrain.EMBERS); + GameScene.updateMap(c); + terrainAffected = true; + } + + // destroys items / triggers bombs caught in the blast. + Heap heap = Dungeon.level.heaps.get(c); + if (heap != null) + heap.explode(); + + Char ch = Actor.findChar(c); + if (ch != null) { + // those not at the center of the blast take damage less + // consistently. + int minDamage = c == cell ? Dungeon.depth + 5 : 1; + int maxDamage = 10 + Dungeon.depth * 2; + + int dmg = Random.NormalIntRange(minDamage, maxDamage) + - Math.max(ch.drRoll(),0); + if (dmg > 0) { + ch.damage(dmg, this); + } + + if (ch == this && HP<1){ + die(this); + } + } + } + } + + if (terrainAffected) { + Dungeon.observe(); + } + } + + private static final HashSet> RESISTANCES = new HashSet>(); + static { + RESISTANCES.add(EnchantmentDark.class); + + } + + @Override + public HashSet> resistances() { + return RESISTANCES; + } + + private static final HashSet> IMMUNITIES = new HashSet>(); + static { + IMMUNITIES.add(Terror.class); + IMMUNITIES.add(ToxicGas.class); + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/BrownBat.java b/java/com/hmdzl/spspd/actors/mobs/BrownBat.java new file mode 100644 index 00000000..4cbd94e5 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/BrownBat.java @@ -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 + */ +package com.hmdzl.spspd.actors.mobs; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.items.food.meatfood.Meat; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.BrownBatSprite; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Random; + +public class BrownBat extends Mob { + + { + spriteClass = BrownBatSprite.class; + + HP = HT = 20; + evadeSkill = 1; + baseSpeed = 2f; + + EXP = 1; + maxLvl = 6; + + flying = true; + + loot = new Meat(); + lootChance = 0.5f; // by default, see die() + + lootOther = Generator.Category.BERRY; + lootChanceOther = 0.05f; // by default, see die() + + properties.add(Property.BEAST); + + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(1, 4); + } + + @Override + public int hitSkill(Char target) { + return 5+Dungeon.depth; + } + + + @Override + public int drRoll() { + return 1; + } + + @Override + public void die(Object cause) { + super.die(cause); + + if (Random.Int(5) == 0) { + for (Mob mob : Dungeon.level.mobs.toArray(new Mob[0])) { + if (Random.Int(2) == 0 && enemy!=null){mob.beckon(enemy.pos);} + } + GLog.w(Messages.get(this,"die")); + } + + + } + +} diff --git a/java/com/hmdzl/spspd/actors/mobs/Brute.java b/java/com/hmdzl/spspd/actors/mobs/Brute.java new file mode 100644 index 00000000..a622dbee --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/Brute.java @@ -0,0 +1,116 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs; + +import java.util.HashSet; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.DefenceUp; +import com.hmdzl.spspd.actors.buffs.Terror; +import com.hmdzl.spspd.items.Gold; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.BruteSprite; +import com.hmdzl.spspd.sprites.CharSprite; +import com.hmdzl.spspd.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!"; + + { + spriteClass = BruteSprite.class; + + HP = HT = 120+(adj(0)*Random.NormalIntRange(4, 8)); + evadeSkill = 15+adj(0); + + EXP = 8; + maxLvl = 25; + + loot = Gold.class; + lootChance = 0.5f; + + lootOther = Generator.random(Generator.Category.RANGEWEAPON); + lootChanceOther = 0.5f; // by default, see die() + + properties.add(Property.ORC); + } + + 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(25+adj(0), 60+adj(0)) : Random.NormalIntRange(10+adj(0), 35+adj(0)); + } + + @Override + public int hitSkill(Char target) { + return 20+adj(1); + } + + @Override + protected float attackDelay() { + return 1.2f; + } + @Override + public int drRoll() { + return Random.NormalIntRange(0, 10); + } + + @Override + public void damage(int dmg, Object src) { + super.damage(dmg, src); + + if (isAlive() && !enraged && HP < HT / 4) { + enraged = true; + Buff.affect(this,DefenceUp.class,5f).level(70); + spend(TICK); + if (Dungeon.visible[pos]) { + GLog.w(Messages.get(this, "enraged")); + sprite.showStatus(CharSprite.NEGATIVE, "enraged"); + } + } + } + + /*@Override + protected boolean canAttack(Char enemy) {if (buff(Locked.class) != null){ + return Level.adjacent(pos, enemy.pos) && (!isCharmedBy(enemy)); + } else + return Dungeon.level.distance( pos, enemy.pos ) <= 2 ; + } */ + + private static final HashSet> IMMUNITIES = new HashSet>(); + static { + IMMUNITIES.add(Terror.class); + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/Crab.java b/java/com/hmdzl/spspd/actors/mobs/Crab.java new file mode 100644 index 00000000..8a5afdc6 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/Crab.java @@ -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 + */ +package com.hmdzl.spspd.actors.mobs; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.items.food.meatfood.MysteryMeat; +import com.hmdzl.spspd.sprites.CrabSprite; +import com.watabou.utils.Random; + +public class Crab extends Mob { + + { + spriteClass = CrabSprite.class; + + HP = HT = 50+(adj(0)*Random.NormalIntRange(1, 3)); + evadeSkill = 5+adj(1); + baseSpeed = 2f; + + EXP = 3; + maxLvl = 9; + + loot = new MysteryMeat(); + lootChance = 0.5f; + + properties.add(Property.BEAST); + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(3, 6+adj(0)); + } + + @Override + public int hitSkill(Char target) { + return 12+adj(0); + } + + @Override + public int drRoll() { + return Random.NormalIntRange(0, 4); + } + +} diff --git a/java/com/hmdzl/spspd/actors/mobs/CrabKing.java b/java/com/hmdzl/spspd/actors/mobs/CrabKing.java new file mode 100644 index 00000000..8d0dd032 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/CrabKing.java @@ -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 + */ +package com.hmdzl.spspd.actors.mobs; + +import java.util.HashSet; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.ToxicGas; +import com.hmdzl.spspd.actors.buffs.Locked; +import com.hmdzl.spspd.actors.buffs.Poison; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.AdamantArmor; +import com.hmdzl.spspd.items.Gold; +import com.hmdzl.spspd.items.weapon.enchantments.EnchantmentDark; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.CrabKingSprite; +import com.hmdzl.spspd.utils.GLog; +import com.hmdzl.spspd.messages.Messages; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Random; + +public class CrabKing extends Mob { + + private static final int JUMP_DELAY = 5; + + { + spriteClass = CrabKingSprite.class; + baseSpeed = 2f; + + HP = HT = 1300; + EXP = 20; + evadeSkill = 30; + + properties.add(Property.BEAST); + properties.add(Property.BOSS); + } + + private int timeToJump = JUMP_DELAY; + + + @Override + public int damageRoll() { + return Random.NormalIntRange(20, 50); + } + + @Override + public int hitSkill(Char target) { + return 35; + } + + @Override + public int drRoll() { + return Random.NormalIntRange(5, 10); + } + + @Override + protected boolean act() { + boolean result = super.act(); + + + if (HP < HT) { + sprite.emitter().burst( Speck.factory( Speck.HEALING ), 1 ); + HP = HP + 10; + GLog.n(Messages.get(this,"heal")); + } + return result; + } + + @Override + public void die(Object cause) { + + super.die(cause); + + GameScene.bossSlain(); + + Dungeon.level.drop(new Gold(Random.Int(1900, 4000)), pos).sprite.drop(); + Dungeon.level.drop(new AdamantArmor(), pos).sprite.drop(); + Dungeon.crabkingkilled=true; + + yell(Messages.get(this,"die")); + + } + + @Override + protected boolean getCloser(int target) { + if (Level.fieldOfView[target]) { + jump(); + return true; + } else { + return super.getCloser(target); + } + } + + @Override + protected boolean canAttack(Char enemy) { + if (buff(Locked.class) != null){ + return Level.adjacent(pos, enemy.pos) && (!isCharmedBy(enemy)); + } else + return new Ballistica( pos, enemy.pos, Ballistica.PROJECTILE).collisionPos == 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; + + int newPos; + do { + newPos = Random.Int(Level.getLength()); + } 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(Messages.get(this,"notice")); + } + + private static final HashSet> RESISTANCES = new HashSet>(); + static { + RESISTANCES.add(ToxicGas.class); + RESISTANCES.add(Poison.class); + RESISTANCES.add(EnchantmentDark.class); + + } + + @Override + public HashSet> resistances() { + return RESISTANCES; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/DM300.java b/java/com/hmdzl/spspd/actors/mobs/DM300.java new file mode 100644 index 00000000..ba548f50 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/DM300.java @@ -0,0 +1,443 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs; + +import java.util.HashSet; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.Badges.Badge; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.Blob; +import com.hmdzl.spspd.actors.blobs.ConfusionGas; +import com.hmdzl.spspd.actors.blobs.ToxicGas; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Paralysis; +import com.hmdzl.spspd.actors.buffs.Terror; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.effects.particles.BlastParticle; +import com.hmdzl.spspd.effects.particles.ElmoParticle; +import com.hmdzl.spspd.effects.particles.SmokeParticle; +import com.hmdzl.spspd.effects.particles.SparkParticle; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.items.Gold; +import com.hmdzl.spspd.items.StoneOre; +import com.hmdzl.spspd.items.TomeOfMastery; +import com.hmdzl.spspd.items.artifacts.CapeOfThorns; +import com.hmdzl.spspd.levels.CavesBossLevel; +import com.hmdzl.spspd.levels.traps.LightningTrap; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.items.journalpages.Sokoban3; +import com.hmdzl.spspd.items.keys.SkeletonKey; +import com.hmdzl.spspd.items.weapon.enchantments.EnchantmentDark; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.Terrain; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.DM300Sprite; +import com.hmdzl.spspd.sprites.TowerSprite; +import com.hmdzl.spspd.utils.GLog; + +import com.watabou.noosa.Camera; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Callback; +import com.watabou.utils.PathFinder; +import com.watabou.utils.Random; + +public class DM300 extends Mob implements Callback { + + private static final float TIME_TO_ZAP = 2f; + + { + spriteClass = DM300Sprite.class; + + HP = HT = 800; + EXP = 50; + evadeSkill = 24; + + loot = new CapeOfThorns().identify(); + lootChance = 0.2f; + + lootOther = Generator.Category.NORNSTONE; + lootChanceOther = 1f; + + properties.add(Property.MECH); + properties.add(Property.BOSS); + } + + private int bossAlive = 0; + private int towerAlive = 0; + + @Override + public int damageRoll() { + + return Random.NormalIntRange(15, 19)*towerAlive; + } + + @Override + public int hitSkill(Char target) { + return 35; + } + + @Override + public int drRoll() { + return Random.NormalIntRange(10, 10+(4*towerAlive)); + } + + public void spawnTower() { + Tower a = new Tower(); + Tower b = new Tower(); + + do { + a.pos = pos + PathFinder.NEIGHBOURS8[Random.Int( 8 )]; + b.pos = pos + PathFinder.NEIGHBOURS8[Random.Int( 8 )]; + } while (!Dungeon.level.passable[a.pos] || !Dungeon.level.passable[b.pos] || a.pos == b.pos); + + GameScene.add(a); + GameScene.add(b); + } + + @Override + public boolean act() { + + if (towerAlive < 1){ + spawnTower(); + towerAlive++; + } + + 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(Messages.get(this,"heal")); + } + } + + int[] cells = { step - 1, step + 1, step - Level.getWidth(), + step + Level.getWidth(), step - 1 - Level.getWidth(), + step - 1 + Level.getWidth(), step + 1 - Level.getWidth(), + step + 1 + Level.getWidth() }; + 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); + + for (Mob mob : Dungeon.level.mobs) { + + if (mob instanceof Tower){ + bossAlive++; + } + + } + + if(bossAlive==0){ + + GameScene.bossSlain(); + ((CavesBossLevel) Dungeon.level).unseal(); + Dungeon.level.drop(new SkeletonKey(Dungeon.depth), pos).sprite.drop(); + Badges.validateBossSlain(); + } + + 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; + case PERFORMER: + badgeToCheck = Badge.MASTERY_PERFORMER; + break; + case SOLDIER: + badgeToCheck = Badge.MASTERY_SOLDIER; + break; + case FOLLOWER: + badgeToCheck = Badge.MASTERY_FOLLOWER; + break; + } + + + Dungeon.level.drop(new Sokoban3(), pos).sprite.drop(); + Dungeon.level.drop(new TomeOfMastery(), pos).sprite.drop(); + + yell(Messages.get(this,"die")); + } + + @Override + public void notice() { + super.notice(); + yell(Messages.get(this, "notice")); + } + + @Override + public void call() { + next(); + } + + private static final HashSet> RESISTANCES = new HashSet>(); + static { + RESISTANCES.add(EnchantmentDark.class); + + } + + @Override + public HashSet> resistances() { + return RESISTANCES; + } + + private static final HashSet> IMMUNITIES = new HashSet>(); + static { + IMMUNITIES.add(ToxicGas.class); + IMMUNITIES.add(Terror.class); + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } + +public static class Tower extends Mob implements Callback { + + { + spriteClass = TowerSprite.class; + + HP = HT = 500+(Dungeon.depth*Random.NormalIntRange(2, 5)); + evadeSkill = 0; + + EXP = 25; + + hostile = false; + state = PASSIVE; + + loot = new StoneOre(); + lootChance = 1f; + + properties.add(Property.MECH); + properties.add(Property.BOSS); + } + + @Override + public void beckon(int cell) { + // Do nothing + } + + private int bossAlive = 0; + + @Override + public int damageRoll() { + return 0; + } + + @Override + public void damage(int dmg, Object src) { + + for (Mob mob : Dungeon.level.mobs) { + mob.beckon(Dungeon.hero.pos); + } + + GLog.w(Messages.get(this,"alert")); + CellEmitter.center(pos).start( + Speck.factory(Speck.SCREAM), 0.3f, 3); + Sample.INSTANCE.play(Assets.SND_CHALLENGE); + + super.damage(dmg, src); + } + + @Override + public int hitSkill(Char target) { + return 0; + } + + @Override + public int drRoll() { + return 0; + } + + @Override + protected boolean act() { + + switch (Random.Int(4)) { + case 1: + for (Mob mob : Dungeon.level.mobs) { + if (mob instanceof Tower && mob != this) { + mob.sprite.centerEmitter().burst(SparkParticle.FACTORY, 3); + mob.sprite.flash(); + } + } + break; + case 2: + if (Dungeon.level.mobs.size()<10){ + BrokenRobot.spawnAround(pos); + GLog.n(Messages.get(this,"robots")); + } + break; + } + + return super.act(); + } + + @Override + public void call() { + next(); + } + + public void explode(int cell) { + // We're blowing up, so no need for a fuse anymore. + + Sample.INSTANCE.play(Assets.SND_BLAST, 2); + + if (Dungeon.visible[cell]) { + CellEmitter.center(cell).burst(BlastParticle.FACTORY, 30); + } + + boolean terrainAffected = false; + for (int n : Level.NEIGHBOURS8) { + int c = cell + n; + if (c >= 0 && c < Level.getLength()) { + if (Dungeon.visible[c]) { + CellEmitter.get(c).burst(SmokeParticle.FACTORY, 4); + } + + if (Level.flamable[c]) { + Level.set(c, Terrain.EMBERS); + GameScene.updateMap(c); + terrainAffected = true; + } + + Char ch = Actor.findChar(c); + if (ch != null) { + // those not at the center of the blast take damage less + // consistently. + int minDamage = c == cell ? Dungeon.depth + 5 : 1; + int maxDamage = 10 + Dungeon.depth * 2; + + int dmg = Random.NormalIntRange(minDamage, maxDamage) + - Math.max(ch.drRoll(),0); + if (dmg > 0) { + ch.damage(dmg, this); + } + } + } + } + + if (terrainAffected) { + Dungeon.observe(); + } + } + + + @Override + public void add(Buff buff) { + } + + @Override + public void die(Object cause) { + + super.die(cause); + + explode(pos); + + for (Mob mob : Dungeon.level.mobs) { + + if (mob instanceof Tower || mob instanceof DM300){ + bossAlive++; + } + + } + + if(bossAlive==0){ + + GameScene.bossSlain(); + ((CavesBossLevel) Dungeon.level).unseal(); + Dungeon.level.drop(new SkeletonKey(Dungeon.depth), pos).sprite.drop(); + Dungeon.level.drop(new Gold(Random.Int(3000, 6000)), pos).sprite.drop(); + + Badges.validateBossSlain(); + } + explodeDew(pos); + } + + private static final HashSet> RESISTANCES = new HashSet>(); + static { + RESISTANCES.add(EnchantmentDark.class); + + RESISTANCES.add(LightningTrap.Electricity.class); + } + + @Override + public HashSet> resistances() { + return RESISTANCES; + } + + private static final HashSet> IMMUNITIES = new HashSet>(); + static { + IMMUNITIES.add(ToxicGas.class); + IMMUNITIES.add(Terror.class); + IMMUNITIES.add(ConfusionGas.class); + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } + + +} + +} diff --git a/java/com/hmdzl/spspd/actors/mobs/DemonFlower.java b/java/com/hmdzl/spspd/actors/mobs/DemonFlower.java new file mode 100644 index 00000000..ffe90d29 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/DemonFlower.java @@ -0,0 +1,148 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs; + +import java.util.HashSet; + +import com.hmdzl.spspd.actors.buffs.ArmorBreak; +import com.hmdzl.spspd.actors.buffs.AttackDown; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Burning; +import com.hmdzl.spspd.actors.buffs.DefenceUp; +import com.hmdzl.spspd.actors.buffs.GrowSeed; +import com.hmdzl.spspd.actors.buffs.Silent; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.ToxicGas; +import com.hmdzl.spspd.actors.buffs.Poison; +import com.hmdzl.spspd.items.weapon.enchantments.EnchantmentDark; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.sprites.DemonflowerSprite; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Random; + +public class DemonFlower extends Mob { + + private static final int DEBUFF_DELAY = 6; + + { + spriteClass = DemonflowerSprite.class; + + HP = HT = 450; + EXP = 25; + maxLvl = 35; + evadeSkill = 5; + + properties.add(Property.PLANT); + properties.add(Property.DEMONIC); + + loot = Generator.Category.SEED; + lootChance = 0.5f; + + } + + private int addDebuff = DEBUFF_DELAY; + + + @Override + public int damageRoll() { + return Random.NormalIntRange(26, 37); + } + + @Override + public int hitSkill(Char target) { + return 35+adj(1); + } + + @Override + protected float attackDelay() { + return 0.33f; + } + + @Override + public int drRoll() { + return Random.NormalIntRange(0, 5); + } + + @Override + protected boolean doAttack(Char enemy) { + addDebuff--; + if (addDebuff <= 0 && Level.adjacent(pos, enemy.pos) && (buff(Silent.class) == null)) { + debuffadd(); + return true; + } else { + return super.doAttack(enemy); + } + } + + @Override + public int defenseProc(Char enemy, int damage) { + + int dmg = damage; + if (dmg < HT/9 && buff(DefenceUp.class) == null) { + Buff.affect(this,DefenceUp.class,3f).level(dmg); + } + + return super.defenseProc(enemy, damage); + } + + private void debuffadd() { + addDebuff = DEBUFF_DELAY; + + int pos = enemy.pos; + Char ch; + if ((ch = Actor.findChar(pos)) != null) { + Buff.prolong(ch, AttackDown.class,5f).level(30); + Buff.prolong(ch, ArmorBreak.class,5f).level(30); + } + GLog.n(Messages.get(this,"debuff")); + + spend(1f); + } + + private static final HashSet> RESISTANCES = new HashSet>(); + private static final HashSet> WEAKNESS = new HashSet>(); + private static final HashSet> IMMUNITIES = new HashSet>(); + static { + WEAKNESS.add(Burning.class); + + RESISTANCES.add(ToxicGas.class); + RESISTANCES.add(Poison.class); + RESISTANCES.add(EnchantmentDark.class); + + IMMUNITIES.add(GrowSeed.class); + + } + + @Override + public HashSet> resistances() { + return RESISTANCES; + } + + @Override + public HashSet> weakness() { + return WEAKNESS; + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/DemonGoo.java b/java/com/hmdzl/spspd/actors/mobs/DemonGoo.java new file mode 100644 index 00000000..cfdf9c16 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/DemonGoo.java @@ -0,0 +1,213 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs; + +import java.util.ArrayList; +import java.util.HashSet; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.ToxicGas; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Burning; +import com.hmdzl.spspd.actors.buffs.Light; +import com.hmdzl.spspd.actors.buffs.Ooze; +import com.hmdzl.spspd.actors.buffs.Poison; +import com.hmdzl.spspd.actors.buffs.Roots; +import com.hmdzl.spspd.effects.Pushing; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.StoneOre; +import com.hmdzl.spspd.items.weapon.enchantments.EnchantmentDark; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.Terrain; +import com.hmdzl.spspd.levels.features.Door; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.DemonGooSprite; +import com.hmdzl.spspd.utils.GLog; +import com.hmdzl.spspd.messages.Messages; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public class DemonGoo extends Mob { + +protected static final float SPAWN_DELAY = 2f; + +private int demonGooGeneration = 0; + +private static final String DEMONGOOGENERATION = "demonGooGeneration"; + + { + HP = HT = 300+(adj(0)*Random.NormalIntRange(4, 7)); + EXP = 10; + maxLvl = 35; + evadeSkill = 10+adj(1); + //10 + spriteClass = DemonGooSprite.class; + baseSpeed = 2f; + viewDistance = Light.DISTANCE; + + loot = new StoneOre(); + lootChance = 1f; + + properties.add(Property.ELEMENT); + properties.add(Property.DEMONIC); + } + + private static final float SPLIT_DELAY = 1f; + + @Override + protected boolean act() { + boolean result = super.act(); + + if (Level.water[pos] && HP < HT) { + sprite.emitter().burst( Speck.factory( Speck.HEALING ), 1 ); + HP++; + } else if(Level.water[pos] && HP == HT && HT < 200){ + sprite.emitter().burst( Speck.factory( Speck.HEALING ), 1 ); + HT=HT+5; + HP=HT; + } + return result; + } + + + @Override + public int damageRoll() { + return Random.NormalIntRange(30+adj(1), 60+adj(1)); + } + + @Override + public int hitSkill(Char target) { + return 35+adj(1); + } + + @Override + public int drRoll() { + return Random.NormalIntRange(10, 15); + //10 + } + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(DEMONGOOGENERATION, demonGooGeneration); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + demonGooGeneration = bundle.getInt(DEMONGOOGENERATION); + } + + @Override + public int defenseProc(Char enemy, int damage) { + + if (HP >= damage + 2) { + ArrayList candidates = new ArrayList(); + boolean[] passable = Level.passable; + + int[] neighbours = { pos + 1, pos - 1, pos + Level.getWidth(), + pos - Level.getWidth() }; + for (int n : neighbours) { + if (passable[n] && Actor.findChar(n) == null) { + candidates.add(n); + } + } + + if (candidates.size() > 0) { + GLog.n(Messages.get(this, "divide")); + DemonGoo clone = split(); + clone.HP = (HP - damage) / 2; + clone.pos = Random.element(candidates); + clone.state = clone.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; + } + + + private DemonGoo split() { + DemonGoo clone = new DemonGoo(); + clone.demonGooGeneration = demonGooGeneration + 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 + public int attackProc(Char enemy, int damage) { + if (Random.Int(3) == 0) { + Buff.affect(enemy, Ooze.class); + enemy.sprite.burst(0x000000, 5); + } + return damage; + } + + @Override + public void notice() { + super.notice(); + //yell(Messages.get(this, "notice")); + } + + @Override + public void die(Object cause) { + + super.die(cause); + //yell(Messages.get(this, "die")); + } + + private static final HashSet> RESISTANCES = new HashSet>(); + static { + RESISTANCES.add(ToxicGas.class); + RESISTANCES.add(EnchantmentDark.class); + + } + + @Override + public HashSet> resistances() { + return RESISTANCES; + } + + private static final HashSet> IMMUNITIES = new HashSet>(); + + static { + IMMUNITIES.add(Roots.class); + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } + + +} diff --git a/java/com/hmdzl/spspd/actors/mobs/Dragonking.java b/java/com/hmdzl/spspd/actors/mobs/Dragonking.java new file mode 100644 index 00000000..67b68fab --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/Dragonking.java @@ -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 + */ +package com.hmdzl.spspd.actors.mobs; + +import java.util.HashSet; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.Blob; +import com.hmdzl.spspd.actors.blobs.ToxicGas; +import com.hmdzl.spspd.actors.buffs.Poison; +import com.hmdzl.spspd.items.keys.SkeletonKey; +import com.hmdzl.spspd.items.weapon.enchantments.EnchantmentDark; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.DragonkingSprite; +import com.watabou.utils.Random; +import com.hmdzl.spspd.actors.blobs.ShockWeb; + + +public class Dragonking extends Mob { + { + spriteClass = DragonkingSprite.class; + baseSpeed = 1f; + + HP = HT = 100; + EXP = 1; + evadeSkill = 0; + + properties.add(Property.DRAGON); + properties.add(Property.BOSS); + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(0, 1); + } + + @Override + public int hitSkill(Char target) { + return 1; + } + + @Override + public int drRoll() { + return 0; + } + + @Override + public void die(Object cause) { + + super.die(cause); + GameScene.bossSlain(); + Dungeon.level.drop(new SkeletonKey(Dungeon.depth), pos).sprite.drop(); + UGoo.spawnAt(pos); + + } + + @Override + public void move(int step) { + GameScene.add(Blob.seed(pos, Random.Int(5, 7), ShockWeb.class)); + super.move(step); + } + + @Override + protected boolean doAttack(Char enemy) { + + return super.doAttack(enemy); + + } + + private static final HashSet> RESISTANCES = new HashSet>(); + static { + RESISTANCES.add(ToxicGas.class); + RESISTANCES.add(Poison.class); + RESISTANCES.add(EnchantmentDark.class); + + } + + @Override + public HashSet> resistances() { + return RESISTANCES; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/DustElement.java b/java/com/hmdzl/spspd/actors/mobs/DustElement.java new file mode 100644 index 00000000..87ad37d4 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/DustElement.java @@ -0,0 +1,73 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs; + +import com.hmdzl.spspd.actors.buffs.Blindness; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.sprites.DustElementSprite; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Random; + +public class DustElement extends Mob { + + { + spriteClass = DustElementSprite.class; + + HP = HT = 35+(Dungeon.depth*Random.NormalIntRange(1, 3)); + evadeSkill = 4+(Math.round((Dungeon.depth)/2)); + + EXP = 2; + maxLvl = 8; + + loot = Generator.random(Generator.Category.SEED); + lootChance = 0.5f; + + properties.add(Property.ELEMENT); + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(2, 5+(Dungeon.depth)); + } + + @Override + public int hitSkill(Char target) { + return 11+(Dungeon.depth); + } + + @Override + public int attackProc(Char enemy, int damage) { + if (Random.Int(10) == 0) { + Buff.prolong(enemy, Blindness.class, Random.Int(3, 10)); + GLog.w(Messages.get(this,"blind")); + Dungeon.observe(); + } + + return damage; + } + + @Override + public int drRoll() { + return Random.NormalIntRange(0, 2); + } + +} diff --git a/java/com/hmdzl/spspd/actors/mobs/DwarfLich.java b/java/com/hmdzl/spspd/actors/mobs/DwarfLich.java new file mode 100644 index 00000000..0c6f4859 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/DwarfLich.java @@ -0,0 +1,123 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs; + +import java.util.HashSet; + +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Poison; +import com.hmdzl.spspd.items.food.fruit.Blackberry; +import com.hmdzl.spspd.items.potions.PotionOfHealing; + +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.DwarfLichSprite; +import com.watabou.utils.Random; + +public class DwarfLich extends Mob { + + private static final float SPAWN_DELAY = 2f; + + { + spriteClass = DwarfLichSprite.class; + + HP = HT = 120+(adj(0)*Random.NormalIntRange(7, 5)); + evadeSkill = 24+adj(1); + + EXP = 14; + maxLvl = 30; + + loot = new PotionOfHealing(); + lootChance = 0.3f; + + lootOther = new Blackberry(); + lootChanceOther = 0.3f; + + properties.add(Property.UNDEAD); + properties.add(Property.DWARF); + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(20, 32); + } + + @Override + public int hitSkill(Char target) { + return 36+adj(1); + } + + @Override + public int drRoll() { + return Random.NormalIntRange(5, 15); + } + + @Override + protected boolean canAttack(Char enemy) { + Ballistica attack = new Ballistica( pos, enemy.pos, Ballistica.MAGIC_BOLT); + return !Level.adjacent( pos, enemy.pos ) && attack.collisionPos == enemy.pos; + } + + @Override + protected boolean getCloser(int target) { + if (state == HUNTING) { + return enemySeen && getFurther(target); + } else { + return super.getCloser(target); + } + } + @Override + public void die(Object cause) { + RedWraith.spawnAt(this.pos); + super.die(cause); + } + + 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 DwarfLich spawnAt(int pos) { + + DwarfLich d = new DwarfLich(); + + d.pos = pos; + d.state = d.HUNTING; + GameScene.add(d, SPAWN_DELAY); + + return d; + + } + + private static final HashSet> RESISTANCES = new HashSet>(); + static { + + RESISTANCES.add(Poison.class); + } + + @Override + public HashSet> resistances() { + return RESISTANCES; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/ElderAvatar.java b/java/com/hmdzl/spspd/actors/mobs/ElderAvatar.java new file mode 100644 index 00000000..600a19a5 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/ElderAvatar.java @@ -0,0 +1,775 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs; + +import java.util.HashSet; + +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.Challenges; +import com.hmdzl.spspd.actors.blobs.DarkGas; +import com.hmdzl.spspd.actors.blobs.ElectriShock; +import com.hmdzl.spspd.actors.buffs.Amok; +import com.hmdzl.spspd.actors.buffs.ArmorBreak; +import com.hmdzl.spspd.actors.buffs.AttackDown; +import com.hmdzl.spspd.actors.buffs.Blindness; +import com.hmdzl.spspd.actors.buffs.Burning; +import com.hmdzl.spspd.actors.buffs.Charm; +import com.hmdzl.spspd.actors.buffs.Chill; +import com.hmdzl.spspd.actors.buffs.Disarm; +import com.hmdzl.spspd.actors.buffs.Frost; +import com.hmdzl.spspd.actors.buffs.GlassShield; +import com.hmdzl.spspd.actors.buffs.GrowSeed; +import com.hmdzl.spspd.actors.buffs.ShieldArmor; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.items.DolyaSlate; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.items.Gold; +import com.hmdzl.spspd.items.KindOfArmor; +import com.hmdzl.spspd.items.StoneOre; +import com.hmdzl.spspd.items.armor.normalarmor.NormalArmor; +import com.hmdzl.spspd.items.armor.normalarmor.RubberArmor; +import com.hmdzl.spspd.items.armor.normalarmor.WoodenArmor; +import com.hmdzl.spspd.items.artifacts.AlienBag; +import com.hmdzl.spspd.items.bombs.DangerousBomb; +import com.hmdzl.spspd.items.keys.SkeletonKey; +import com.hmdzl.spspd.levels.Terrain; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.ToxicGas; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Paralysis; +import com.hmdzl.spspd.actors.buffs.Vertigo; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.journalpages.Sokoban4; +import com.hmdzl.spspd.items.wands.WandOfDisintegration; +import com.hmdzl.spspd.levels.CityBossLevel; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ElderAvatarSprite; +import com.hmdzl.spspd.sprites.GolemSprite; +import com.hmdzl.spspd.sprites.MonkSprite; +import com.hmdzl.spspd.sprites.MusketeerSprite; +import com.hmdzl.spspd.sprites.ObeliskSprite; +import com.hmdzl.spspd.sprites.WarlockSprite; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public class ElderAvatar extends Mob { + + { + spriteClass = ElderAvatarSprite.class; + + HP = HT = 600; + EXP = 50; + evadeSkill = 25; + baseSpeed = 1f; + + loot = new AlienBag().identify(); + lootChance = 0.2f; + + lootOther = Generator.Category.GUNWEAPON; + lootChanceOther = 1f; + + properties.add(Property.ALIEN); + properties.add(Property.BOSS); + } + + private int orbAlive = 0; + private int waves = 0; + public static int breaks = 0; + + private static final String WAVES = "waves"; + private static final String BREAKS = "breaks"; + private static final String ORBALIVE = "orbAlive"; + + @Override + public void storeInBundle( Bundle bundle ) { + super.storeInBundle(bundle); + bundle.put( WAVES, waves ); + bundle.put( BREAKS, breaks ); + bundle.put( ORBALIVE, orbAlive ); + } + + @Override + public void restoreFromBundle( Bundle bundle ) { + super.restoreFromBundle(bundle); + waves = bundle.getInt( WAVES ); + breaks = bundle.getInt( BREAKS ); + orbAlive = bundle.getInt( ORBALIVE ); + } + + + public void spawnObe() { + Obelisk a = new Obelisk(); + + a.pos = Terrain.EMPTY_WELL; + do { + a.pos = Random.Int(Dungeon.level.randomRespawnCellMob()); + } while (Dungeon.level.map[a.pos] != Terrain.EMPTY_WELL + || Actor.findChar(a.pos) != null); + GameScene.add(a); + } + + @Override + public int damageRoll() { + return Dungeon.isChallenged(Challenges.TEST_TIME) ? Random.NormalIntRange(0, 1) : Random.NormalIntRange(25, 40); + } + + @Override + public int hitSkill(Char target) { + return 58; + } + + @Override + public int drRoll() { + return Random.NormalIntRange(8, 12); + } + + @Override + protected boolean canAttack(Char enemy) { + if (HP > 49) return Dungeon.level.distance(pos, enemy.pos) <= 3; + else return Dungeon.level.distance(pos, enemy.pos) <= 0; + } + + @Override + public int attackProc(Char enemy, int damage) { + if (Random.Int(5) == 0) { + new DangerousBomb().explode(enemy.pos); + } + if (Random.Int(8) == 0) { + Buff.affect(enemy, Charm.class, Charm.durationFactor(enemy) + * Random.IntRange(3, 5)).object = id(); + enemy.sprite.centerEmitter().start(Speck.factory(Speck.HEART), + 0.2f, 5); + Sample.INSTANCE.play(Assets.SND_CHARMS); + } + Hero hero = Dungeon.hero; + KindOfArmor armor = hero.belongings.armor; + if (Random.Int(10) == 0) { + if (armor != null && !(armor instanceof WoodenArmor || armor instanceof RubberArmor || armor instanceof NormalArmor) + && !armor.cursed) { + hero.belongings.armor = null; + Dungeon.level.drop(armor, hero.pos).sprite.drop(); + GLog.w(Messages.get(this, "disarm")); + } + } + return damage; + } + + public boolean checkObelisk() { + + int obeliskAlive = 0; + if (Dungeon.level.mobs != null) { + for (Mob mob : Dungeon.level.mobs) { + if (mob instanceof Obelisk && mob.HP > 10) { + obeliskAlive++; + } + } + } + if (obeliskAlive > 0) { + return true; + } else { + return false; + } + } + + @Override + public void damage(int dmg, Object src) { + if (dmg > this.HP && checkObelisk()) { + dmg = Random.Int(this.HP); + //Buff.affect(this,ShieldArmor.class).level(100); + } + super.damage(dmg, src); + } + + @Override + protected boolean act() { + + if (orbAlive < 1) { + spawnObe(); + orbAlive++; + + return true; + } + + if (HP < 50 && waves == 0 && breaks == 0) { + summonHunter(pos); + waves++; + Buff.affect(this,ShieldArmor.class).level(100); + sprite.centerEmitter().start(Speck.factory(Speck.SCREAM), 0.4f, 2); + Sample.INSTANCE.play(Assets.SND_CHALLENGE); + return true; + } + + if (HP < 50 && waves == 1 && breaks == 1) { + summonWarlock(pos); + waves++; + Buff.affect(this,ShieldArmor.class).level(100); + sprite.centerEmitter().start(Speck.factory(Speck.SCREAM), 0.4f, 2); + Sample.INSTANCE.play(Assets.SND_CHALLENGE); + return true; + } + + if (HP < 50 && waves == 2 && breaks == 2) { + summonMonk(pos); + waves++; + Buff.affect(this,ShieldArmor.class).level(100); + sprite.centerEmitter().start(Speck.factory(Speck.SCREAM), 0.4f, 2); + Sample.INSTANCE.play(Assets.SND_CHALLENGE); + return true; + } + + if (HP < 50 && waves == 3 && breaks == 3) { + summonMech(pos); + waves++; + Buff.affect(this,ShieldArmor.class).level(100); + sprite.centerEmitter().start(Speck.factory(Speck.SCREAM), 0.4f, 2); + Sample.INSTANCE.play(Assets.SND_CHALLENGE); + return true; + } + + return super.act(); + } + + private void summonHunter(int pos) { + TheHunter.spawnAround(pos); + } + + private void summonWarlock(int pos) { + TheWarlock.spawnAround(pos); + } + + private void summonMonk(int pos) { + TheMonk.spawnAround(pos); + } + + private void summonMech(int pos) { + TheMech.spawnAround(pos); + } + + @Override + public void die(Object cause) { + + yell(Messages.get(this, "died")); + + GameScene.bossSlain(); + ((CityBossLevel) Dungeon.level).unseal(); + if (!Dungeon.limitedDrops.journal.dropped()) { + Dungeon.level.drop(new DolyaSlate(), pos).sprite.drop(); + Dungeon.limitedDrops.journal.drop(); + } + Dungeon.level.drop(new Sokoban4(), pos).sprite.drop(); + + Dungeon.level.drop(new SkeletonKey(Dungeon.depth), pos).sprite.drop(); + Dungeon.level.drop(new Gold(Random.Int(4900, 10000)), pos).sprite.drop(); + + Badges.validateBossSlain(); + + super.die(cause); + } + + @Override + public void notice() { + super.notice(); + yell(Messages.get(this, "notice")); + } + + private static final HashSet> RESISTANCES = new HashSet>(); + + static { + RESISTANCES.add(ToxicGas.class); + RESISTANCES.add(Amok.class); + RESISTANCES.add(Vertigo.class); + + RESISTANCES.add(WandOfDisintegration.class); + } + + @Override + public HashSet> resistances() { + return RESISTANCES; + } + + private static final HashSet> IMMUNITIES = new HashSet>(); + + static { + IMMUNITIES.add(Paralysis.class); + IMMUNITIES.add(Charm.class); + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } + + public static class TheHunter extends Mob { + + { + spriteClass = MusketeerSprite.class; + + HP = HT = 100; + evadeSkill = 15; + EXP = 0; + baseSpeed = 3f; + viewDistance = 6; + state = WANDERING; + properties.add(Property.ALIEN); + properties.add(Property.BOSS); + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(20, 35); + } + + @Override + public int hitSkill(Char target) { + return 60; + } + + @Override + protected boolean canAttack(Char enemy) { + if (buff(Disarm.class) != null){ + return false; + } else + return new Ballistica( pos, enemy.pos, Ballistica.PROJECTILE).collisionPos == enemy.pos; + } + + @Override + public int attackProc(Char enemy, int damage) { + Buff.affect(this, Disarm.class,5f); + Buff.affect(enemy,ArmorBreak.class,3f).level(30); + 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); + } + + @Override + public int drRoll() { + return 5; + } + + 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 TheHunter spawnAt(int pos) { + + TheHunter d = new TheHunter(); + + d.pos = pos; + d.state = d.HUNTING; + GameScene.add(d, 2f); + + return d; + + } + + private static final HashSet> IMMUNITIES = new HashSet>(); + + static { + IMMUNITIES.add(Charm.class); + IMMUNITIES.add(Amok.class); + IMMUNITIES.add(Paralysis.class); + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } + } + + public static class TheWarlock extends Mob { + { + spriteClass = WarlockSprite.class; + + HP = HT = 150; + evadeSkill = 15; + EXP = 0; + state = WANDERING; + properties.add(Property.ALIEN); + properties.add(Property.BOSS); + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(25, 45); + } + + @Override + public int hitSkill(Char target) { + return 60; + } + + @Override + public int attackProc(Char enemy, int damage) { + Buff.prolong(enemy,Vertigo.class,3f); + Buff.prolong(enemy,AttackDown.class,3f).level(20); + return damage; + } + + @Override + public void damage(int dmg, Object src) { + dmg =(int)(dmg/2); + super.damage(dmg, src); + } + + @Override + public void die(Object cause) { + super.die(cause); + } + + @Override + public int drRoll() { + return 5; + } + + 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 TheWarlock spawnAt(int pos) { + + TheWarlock d = new TheWarlock(); + + d.pos = pos; + d.state = d.HUNTING; + GameScene.add(d, 2f); + + return d; + + } + + private static final HashSet> IMMUNITIES = new HashSet>(); + + static { + IMMUNITIES.add(Charm.class); + IMMUNITIES.add(Amok.class); + IMMUNITIES.add(Paralysis.class); + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } + } + + public static class TheMonk extends Mob { + + { + spriteClass = MonkSprite.class; + + HP = HT = 100; + evadeSkill = 30; + EXP = 0; + baseSpeed = 2f; + viewDistance = 5; + state = WANDERING; + properties.add(Property.ALIEN); + properties.add(Property.BOSS); + } + + @Override + protected float attackDelay() { + return 0.5f; + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(15, 30); + } + + @Override + public int hitSkill(Char target) { + return 60; + } + + @Override + public int attackProc(Char enemy, int damage) { + if (Random.Int(6) == 0) { + Buff.affect(this,GlassShield.class).turns(1); + } + Buff.prolong(enemy,Blindness.class,3f); + 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); + } + + @Override + public int drRoll() { + return 5; + } + + 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 TheMonk spawnAt(int pos) { + + TheMonk d = new TheMonk(); + + d.pos = pos; + d.state = d.HUNTING; + GameScene.add(d, 2f); + + return d; + + } + + private static final HashSet> IMMUNITIES = new HashSet>(); + + static { + IMMUNITIES.add(Charm.class); + IMMUNITIES.add(Amok.class); + IMMUNITIES.add(Paralysis.class); + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } + } + + public static class TheMech extends Mob { + + { + spriteClass = GolemSprite.class; + + HP = HT = 200; + evadeSkill = 15; + EXP = 0; + state = WANDERING; + baseSpeed = 0.5f; + properties.add(Property.ALIEN); + properties.add(Property.MECH); + properties.add(Property.BOSS); + } + private int addshield = 0; + @Override + public int damageRoll() { + return Random.NormalIntRange(45, 70); + } + + @Override + public int hitSkill(Char target) { + return 30; + } + + @Override + protected boolean act() { + + if (addshield < 1) { + Buff.affect(this,ShieldArmor.class).level(100); + addshield++; + return true; + } + return super.act(); + } + + @Override + public int attackProc(Char enemy, int damage) { + Buff.affect(enemy, Burning.class).reignite(enemy); + return damage; + } + + @Override + public void damage(int dmg, Object src) { + super.damage(dmg, src); + } + + @Override + public void die(Object cause) { + super.die(cause); + } + + @Override + public int drRoll() { + return 10; + } + + 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 TheMech spawnAt(int pos) { + + TheMech d = new TheMech(); + + d.pos = pos; + d.state = d.HUNTING; + GameScene.add(d, 2f); + + return d; + + } + + private static final HashSet> IMMUNITIES = new HashSet>(); + + static { + IMMUNITIES.add(Burning.class); + IMMUNITIES.add(Frost.class); + IMMUNITIES.add(Chill.class); + IMMUNITIES.add(ElectriShock.class); + IMMUNITIES.add(ToxicGas.class); + IMMUNITIES.add(DarkGas.class); + IMMUNITIES.add(GrowSeed.class); + IMMUNITIES.add(Charm.class); + IMMUNITIES.add(Amok.class); + IMMUNITIES.add(Paralysis.class); + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } + } + + public static class Obelisk extends Mob { + + { + spriteClass = ObeliskSprite.class; + + HP = HT = 1000; + evadeSkill = 0; + + EXP = 10; + + hostile = false; + state = PASSIVE; + + loot = new StoneOre(); + lootChance = 0.05f; + + properties.add(Property.UNKNOW); + properties.add(Property.BOSS); + } + + @Override + public void beckon(int cell) { + // Do nothing + } + + @Override + public void add(Buff buff) { + } + + @Override + public int damageRoll() { + return 0; + } + + @Override + public int hitSkill(Char target) { + return 0; + } + + @Override + public int drRoll() { + return 0; + } + + @Override + protected boolean act() { + + if (3 - ElderAvatar.breaks > 4 * HP / HT) { + ElderAvatar.breaks++; + for (Mob mob : Dungeon.level.mobs) { + if (mob instanceof ElderAvatar) { + mob.HP = 600; + } + } + return true; + } + return super.act(); + } + + public boolean checkElder() { + + int elderAlive = 0; + if (Dungeon.level.mobs != null) { + for (Mob mob : Dungeon.level.mobs) { + if (mob instanceof ElderAvatar && mob.HP > 20) { + elderAlive++; + } + } + } + if (elderAlive > 0) { + return true; + } else { + return false; + } + } + + @Override + public void damage(int dmg, Object src) { + if (checkElder()) { + yell(Messages.get(this, "impossible")); + } else { + super.damage(dmg, src); + } + } + + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/Eye.java b/java/com/hmdzl/spspd/actors/mobs/Eye.java new file mode 100644 index 00000000..98a95fd1 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/Eye.java @@ -0,0 +1,200 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs; + +import java.util.HashSet; + +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.ResultDescriptions; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Light; +import com.hmdzl.spspd.actors.buffs.Terror; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.particles.PurpleParticle; +import com.hmdzl.spspd.items.food.meatfood.MysteryMeat; +import com.hmdzl.spspd.items.potions.PotionOfHealing; +import com.hmdzl.spspd.items.wands.WandOfDisintegration; +import com.hmdzl.spspd.items.weapon.enchantments.EnchantmentDark; + +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.CharSprite; +import com.hmdzl.spspd.sprites.EyeSprite; + +import com.watabou.noosa.tweeners.AlphaTweener; +import com.watabou.utils.Random; + +public class Eye extends Mob { + + private static final String TXT_DEATHGAZE_KILLED = "%s's deathgaze killed you..."; + protected static final float SPAWN_DELAY = 2f; + + { + spriteClass = EyeSprite.class; + + HP = HT = 200+(adj(0)*Random.NormalIntRange(4, 7)); + evadeSkill = 20+adj(1); + viewDistance = Light.DISTANCE; + + EXP = 15; + maxLvl = 35; + + flying = true; + + loot = new PotionOfHealing(); + lootChance = 0.1f; + + lootOther = new MysteryMeat(); + lootChanceOther = 0.5f; // by default, see die() + + properties.add(Property.DEMONIC); + } + + private Ballistica beam; + + @Override + public int drRoll() { + return Random.NormalIntRange(10, 20); + } + + private int hitCell; + + @Override + protected boolean canAttack(Char enemy) { + + beam = new Ballistica( pos, enemy.pos, Ballistica.STOP_TERRAIN); + + return beam.subPath(1, beam.dist).contains(enemy.pos); + } + + + @Override + public int hitSkill(Char target) { + return 30+adj(0); + } + + @Override + protected float attackDelay() { + return 1.6f; + } + + @Override + protected boolean doAttack(Char enemy) { + + spend(attackDelay()); + + boolean rayVisible = false; + + for (int i : beam.subPath(0, beam.dist)) { + if (Dungeon.visible[i]) { + rayVisible = true; + } + } + + if (rayVisible) { + sprite.attack(beam.collisionPos); + return false; + } else { + attack(enemy); + return true; + } + } + + @Override + public boolean attack(Char enemy) { + + for (int pos : beam.subPath(1, beam.dist)) { + + Char ch = Actor.findChar( pos ); + if (ch == null) { + continue; + } + + if (hit(this, ch, true)) { + ch.damage(Random.NormalIntRange(14, 20+adj(0)), 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(Messages.format(ResultDescriptions.MOB)); + //GLog.n(Messages.get(this, "kill")); + } + } else { + ch.sprite.showStatus(CharSprite.NEUTRAL, ch.defenseVerb()); + } + } + + return true; + } + + + public static void spawnAroundChance(int pos) { + for (int n : Level.NEIGHBOURS4) { + int cell = pos + n; + if (Level.passable[cell] && Actor.findChar(cell) == null && Random.Float()<0.50f) { + spawnAt(cell); + } + } + } + + public static Eye spawnAt(int pos) { + if (Level.passable[pos] && Actor.findChar(pos) == null) { + + Eye e = new Eye(); + e.pos = pos; + e.state = e.HUNTING; + GameScene.add(e, SPAWN_DELAY); + + e.sprite.alpha(0); + e.sprite.parent.add(new AlphaTweener(e.sprite, 1, 0.5f)); + + return e; + + } else { + return null; + } + } + + private static final HashSet> RESISTANCES = new HashSet>(); + static { + RESISTANCES.add(WandOfDisintegration.class); + RESISTANCES.add(EnchantmentDark.class); + } + + @Override + public HashSet> resistances() { + return RESISTANCES; + } + + private static final HashSet> IMMUNITIES = new HashSet>(); + static { + IMMUNITIES.add(Terror.class); + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/FetidRat.java b/java/com/hmdzl/spspd/actors/mobs/FetidRat.java new file mode 100644 index 00000000..d2bd95a3 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/FetidRat.java @@ -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 + */ +package com.hmdzl.spspd.actors.mobs; + +import java.util.HashSet; + +import com.hmdzl.spspd.actors.mobs.npcs.Ghost; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.Blob; +import com.hmdzl.spspd.actors.blobs.StenchGas; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Ooze; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.FetidRatSprite; + +import com.watabou.utils.Random; + + public class FetidRat extends Rat { + + { + //name = "fetidrat"; + spriteClass = FetidRatSprite.class; + + HP = HT = 45; + evadeSkill = 5; + + EXP = 4; + + state = WANDERING; + + properties.add(Property.BEAST); + properties.add(Property.MINIBOSS); + } + + @Override + public int hitSkill(Char target) { + return 12; + } + + @Override + public int drRoll() { + return Random.NormalIntRange(0, 2); + } + + @Override + public int attackProc(Char enemy, int damage) { + if (Random.Int(3) == 0) { + Buff.affect(enemy, Ooze.class); + } + + return damage; + } + + @Override + public int defenseProc(Char enemy, int damage) { + + GameScene.add(Blob.seed(pos, 20, StenchGas.class)); + + return super.defenseProc(enemy, damage); + } + + @Override + public void die(Object cause) { + super.die(cause); + + Ghost.Quest.process(); + } + + private static final HashSet> IMMUNITIES = new HashSet>(); + static { + IMMUNITIES.add(StenchGas.class); + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } + } \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/mobs/Fiend.java b/java/com/hmdzl/spspd/actors/mobs/Fiend.java new file mode 100644 index 00000000..84342950 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/Fiend.java @@ -0,0 +1,167 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs; + +import com.hmdzl.spspd.actors.buffs.Silent; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.ResultDescriptions; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Weakness; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.CharSprite; +import com.hmdzl.spspd.sprites.FiendSprite; + +import com.watabou.utils.Callback; +import com.watabou.utils.Random; + +public class Fiend extends Mob implements Callback { + + private static final float TIME_TO_ZAP = 2f; + + private static final String TXT_SHADOWBOLT_KILLED = "%s's shadow bolt killed you..."; + + private static final float SPAWN_DELAY = 6f; + + { + spriteClass = FiendSprite.class; + baseSpeed = 1.5f; + viewDistance = 4; + HP = HT = 80+(Dungeon.depth*Random.NormalIntRange(2, 5)); + evadeSkill = 2; + + EXP = 20; + + loot = Generator.Category.SCROLL; + lootChance = 0.15f; + + properties.add(Property.DEMONIC); + properties.add(Property.ELEMENT); + + } + + + @Override + public int damageRoll() { + return Random.NormalIntRange(Dungeon.depth/2, Dungeon.depth); + } + + @Override + public int hitSkill(Char target) { + return 50; + } + + @Override + public int drRoll() { + return Random.NormalIntRange(5, 10); + } + + @Override + protected boolean canAttack(Char enemy) { if (buff(Silent.class) != null){ + return Level.adjacent(pos, enemy.pos) && (!isCharmedBy(enemy)); + } else + return new Ballistica( pos, enemy.pos, Ballistica.MAGIC_BOLT).collisionPos == enemy.pos; + } + + @Override + 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) { + ((FiendSprite) 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(5) == 0) { + Buff.prolong(enemy, Weakness.class, Weakness.duration(enemy)); + } + + int dmg = Random.Int(20, 45); + enemy.damage(dmg, this); + + if (!enemy.isAlive() && enemy == Dungeon.hero) { + Dungeon.fail( Messages.format(ResultDescriptions.MOB)); + //GLog.n(Messages.get(this, "kill")); + } + } else { + enemy.sprite.showStatus(CharSprite.NEUTRAL, enemy.defenseVerb()); + } + } + + public void onZapComplete() { + zap(); + next(); + } + + @Override + public void call() { + next(); + } + + 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 void spawnAroundChance(int pos) { + for (int n : Level.NEIGHBOURS4) { + int cell = pos + n; + if (Level.passable[cell] && Actor.findChar(cell) == null && Random.Float() < 0.75f) { + spawnAt(cell); + } + } + } + + public static Fiend spawnAt(int pos) { + + Fiend b = new Fiend(); + + b.pos = pos; + b.state = b.HUNTING; + GameScene.add(b, SPAWN_DELAY); + + return b; + + } + +} diff --git a/java/com/hmdzl/spspd/actors/mobs/FireElemental.java b/java/com/hmdzl/spspd/actors/mobs/FireElemental.java new file mode 100644 index 00000000..a13aa6c0 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/FireElemental.java @@ -0,0 +1,115 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs; + +import java.util.HashSet; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.Fire; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Burning; +import com.hmdzl.spspd.actors.buffs.Chill; +import com.hmdzl.spspd.actors.buffs.Frost; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.wands.WandOfFirebolt; +import com.hmdzl.spspd.items.potions.PotionOfLiquidFlame; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.sprites.FireElementalSprite; +import com.watabou.utils.Random; + +public class FireElemental extends Mob { + + { + spriteClass = FireElementalSprite.class; + + HP = HT = 120+(adj(0)*Random.NormalIntRange(4, 7)); + evadeSkill = 20+adj(0); + + EXP = 15; + maxLvl = 30; + + flying = true; + + loot = new PotionOfLiquidFlame(); + lootChance = 0.1f; + + lootOther = new WandOfFirebolt(); + lootChanceOther = 0.02f; // by default, see die() + + properties.add(Property.ELEMENT); + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(16, 20+adj(1)); + } + + @Override + public int hitSkill(Char target) { + return 25+adj(1); + } + + @Override + public int drRoll() { + return Random.NormalIntRange(0, 5); + } + + @Override + public int attackProc(Char enemy, int damage) { + if (Random.Int(2) == 0) { + Buff.affect(enemy, Burning.class).reignite(enemy); + } + + return damage; + } + + @Override + protected boolean canAttack(Char enemy) { + return Dungeon.level.distance( pos, enemy.pos ) <= 2 ; + } + + @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 || buff instanceof Chill) { + if (Level.water[this.pos]) + damage(Random.NormalIntRange(HT / 2, HT), buff); + else + damage(Random.NormalIntRange(1, HT * 2 / 3), buff); + } else { + super.add(buff); + } + } + + private static final HashSet> IMMUNITIES = new HashSet>(); + static { + IMMUNITIES.add(Burning.class); + IMMUNITIES.add(Fire.class); + IMMUNITIES.add(WandOfFirebolt.class); + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/FireRabbit.java b/java/com/hmdzl/spspd/actors/mobs/FireRabbit.java new file mode 100644 index 00000000..f4591ee5 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/FireRabbit.java @@ -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 + */ +package com.hmdzl.spspd.actors.mobs; + +import java.util.HashSet; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.Fire; +import com.hmdzl.spspd.actors.buffs.ArmorBreak; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Burning; +import com.hmdzl.spspd.actors.buffs.Locked; +import com.hmdzl.spspd.items.wands.WandOfFirebolt; +import com.hmdzl.spspd.items.potions.PotionOfLiquidFlame; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.FireRabbitSprite; +import com.watabou.utils.Random; + +public class FireRabbit extends Mob { + + { + spriteClass = FireRabbitSprite.class; + + HP = HT = 80+(adj(0)*Random.NormalIntRange(3, 5)); + evadeSkill = 8+adj(0); + + EXP = 5; + maxLvl = 20; + + loot = new PotionOfLiquidFlame(); + lootChance = 0.1f; + + properties.add(Property.ORC); + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(6, 8+adj(0)); + } + + @Override + public int hitSkill(Char target) { + return 12; + } + + @Override + public int drRoll() { + return Random.NormalIntRange(5, 10); + } + + @Override + public int attackProc(Char enemy, int damage) { + if (Random.Int(3) == 0) { + Buff.affect(enemy, Burning.class).reignite(enemy); + yell( Messages.get(this, "yell") ); + } + if (Dungeon.level.distance( pos, enemy.pos ) == 3){ + damage = 0; + Buff.affect(enemy, ArmorBreak.class,5f).level(20); + } + return damage; + } + + @Override + protected boolean canAttack(Char enemy) { + return Dungeon.level.distance( pos, enemy.pos ) <= 3 ; + } + + + private static final HashSet> IMMUNITIES = new HashSet>(); + static { + IMMUNITIES.add(Locked.class); + IMMUNITIES.add(Burning.class); + IMMUNITIES.add(Fire.class); + IMMUNITIES.add(WandOfFirebolt.class); + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/FishProtector.java b/java/com/hmdzl/spspd/actors/mobs/FishProtector.java new file mode 100644 index 00000000..17ffb9ae --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/FishProtector.java @@ -0,0 +1,146 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs; + +import java.util.HashSet; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.ResultDescriptions; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Invisibility; +import com.hmdzl.spspd.actors.buffs.Silent; +import com.hmdzl.spspd.effects.particles.SparkParticle; +import com.hmdzl.spspd.items.VioletDewdrop; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.traps.LightningTrap; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.sprites.CharSprite; +import com.hmdzl.spspd.sprites.FishProtectorSprite; + +import com.hmdzl.spspd.messages.Messages; +import com.watabou.noosa.Camera; +import com.watabou.utils.Callback; +import com.watabou.utils.Random; + +public class FishProtector 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..."; + + { + spriteClass = FishProtectorSprite.class; + + EXP = 1; + state = HUNTING; + flying = true; + + HP = HT = 300; + evadeSkill = 25; + + loot = new VioletDewdrop(); + lootChance = 1f; + + properties.add(Property.ELEMENT); + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(12, 20); + } + + @Override + public int hitSkill(Char target) { + return 25; + } + + @Override + public int drRoll() { + return Random.NormalIntRange(0, 15); + } + + + @Override + protected boolean canAttack(Char enemy) { if (buff(Silent.class) != null){ + return Level.adjacent(pos, enemy.pos) && (!isCharmedBy(enemy)); + } else + return new Ballistica( pos, enemy.pos, Ballistica.MAGIC_BOLT).collisionPos == 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) { + ((FishProtectorSprite) sprite).zap(enemy.pos); + } + + spend(TIME_TO_ZAP); + + if (hit(this, enemy, true)) { + int dmg = Random.Int(25, 60); + if (Level.water[enemy.pos] && !enemy.flying) { + dmg *= 1.5f; + } + enemy.damage(dmg, this); + + 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( Messages.format(ResultDescriptions.MOB) ); + //GLog.n(Messages.get(this, "zap_kill")); + } + } + } else { + enemy.sprite + .showStatus(CharSprite.NEUTRAL, enemy.defenseVerb()); + } + + return !visible; + } + } + + @Override + public void call() { + next(); + } + + + private static final HashSet> RESISTANCES = new HashSet>(); + static { + RESISTANCES.add(LightningTrap.Electricity.class); + RESISTANCES.add(Invisibility.class); + } + + @Override + public HashSet> resistances() { + return RESISTANCES; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/FlyingProtector.java b/java/com/hmdzl/spspd/actors/mobs/FlyingProtector.java new file mode 100644 index 00000000..e4b34487 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/FlyingProtector.java @@ -0,0 +1,152 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs; + +import java.util.HashSet; + +import com.hmdzl.spspd.actors.buffs.Silent; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.ResultDescriptions; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.effects.particles.SparkParticle; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.traps.LightningTrap; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.CharSprite; +import com.hmdzl.spspd.sprites.FlyingProtectorSprite; + +import com.watabou.noosa.Camera; +import com.watabou.utils.Callback; +import com.watabou.utils.Random; + +public class FlyingProtector extends Mob implements Callback { + + private static final float TIME_TO_ZAP = 2f; + + private static final float SPAWN_DELAY = 0.2f; + + + private static final String TXT_LIGHTNING_KILLED = "%s's lightning bolt killed you..."; + + { + spriteClass = FlyingProtectorSprite.class; + + EXP = 5; + state = HUNTING; + flying = true; + + HP = HT = 50 + Dungeon.depth * 4; + evadeSkill = 4 + Dungeon.depth * 1; + + properties.add(Property.ELEMENT); + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(20, 30); + } + + @Override + public int hitSkill(Char target) { + return (int) ((9 + Dungeon.depth)); + } + + @Override + public int drRoll() { + return Random.NormalIntRange(0, Dungeon.depth); + } + + @Override + protected boolean canAttack(Char enemy) { if (buff(Silent.class) != null){ + return Level.adjacent(pos, enemy.pos) && (!isCharmedBy(enemy)); + } else + return new Ballistica( pos, enemy.pos, Ballistica.MAGIC_BOLT).collisionPos == 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) { + ((FlyingProtectorSprite) sprite).zap(enemy.pos); + } + + spend(TIME_TO_ZAP); + + if (hit(this, enemy, true)) { + int dmg = Random.Int(25, 40); + if (Level.water[enemy.pos] && !enemy.flying) { + dmg *= 1.5f; + } + enemy.damage(dmg, this); + + 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( Messages.format(ResultDescriptions.MOB) ); + //GLog.n(Messages.get(this, "kill")); + } + } + } else { + enemy.sprite + .showStatus(CharSprite.NEUTRAL, enemy.defenseVerb()); + } + + return !visible; + } + } + + public static FlyingProtector spawnAt(int pos) { + + FlyingProtector b = new FlyingProtector(); + + b.pos = pos; + b.state = b.HUNTING; + GameScene.add(b, SPAWN_DELAY); + return b; + } + + @Override + public void call() { + next(); + } + + private static final HashSet> RESISTANCES = new HashSet>(); + static { + RESISTANCES.add(LightningTrap.Electricity.class); + } + + @Override + public HashSet> resistances() { + return RESISTANCES; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/ForestProtector.java b/java/com/hmdzl/spspd/actors/mobs/ForestProtector.java new file mode 100644 index 00000000..d846e340 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/ForestProtector.java @@ -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 + */ +package com.hmdzl.spspd.actors.mobs; + +import java.util.HashSet; + +import com.hmdzl.spspd.actors.buffs.Silent; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.ResultDescriptions; +import com.hmdzl.spspd.Statistics; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.effects.particles.SparkParticle; +import com.hmdzl.spspd.items.VioletDewdrop; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.traps.LightningTrap; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.sprites.CharSprite; +import com.hmdzl.spspd.sprites.ForestProtectorSprite; + +import com.watabou.noosa.Camera; +import com.watabou.utils.Callback; +import com.watabou.utils.Random; + +public class ForestProtector 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..."; + + { + spriteClass = ForestProtectorSprite.class; + + + EXP = 1; + state = HUNTING; + flying = true; + + HP = HT = 250; + evadeSkill = 10; + + loot = new VioletDewdrop(); + lootChance = 1f; + + properties.add(Property.ELEMENT); + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(5, 10); + } + + @Override + public int hitSkill(Char target) { + return 16; + } + + @Override + public int drRoll() { + return Random.NormalIntRange(0, 5); + } + + @Override + protected boolean canAttack(Char enemy) { if (buff(Silent.class) != null){ + return Level.adjacent(pos, enemy.pos) && (!isCharmedBy(enemy)); + } else + return new Ballistica( pos, enemy.pos, Ballistica.MAGIC_BOLT).collisionPos == 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) { + ((ForestProtectorSprite) sprite).zap(enemy.pos); + } + + spend(TIME_TO_ZAP); + + if (hit(this, enemy, true)) { + int dmg = Random.Int(5+Math.round(Statistics.archersKilled/10), 10+Math.round(Statistics.archersKilled/5)); + if (Level.water[enemy.pos] && !enemy.flying) { + dmg *= 1.5f; + } + enemy.damage(dmg, this); + + 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(Messages.format(ResultDescriptions.MOB)); + //GLog.n(Messages.get(this, "kill")); + } + } + } else { + enemy.sprite + .showStatus(CharSprite.NEUTRAL, enemy.defenseVerb()); + } + + return !visible; + } + } + + @Override + public void call() { + next(); + } + + private static final HashSet> RESISTANCES = new HashSet>(); + static { + RESISTANCES.add(LightningTrap.Electricity.class); + } + + @Override + public HashSet> resistances() { + return RESISTANCES; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/Gnoll.java b/java/com/hmdzl/spspd/actors/mobs/Gnoll.java new file mode 100644 index 00000000..86f90540 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/Gnoll.java @@ -0,0 +1,73 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.buffs.Locked; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.items.Gold; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.sprites.GnollSprite; +import com.watabou.utils.Random; + +public class Gnoll extends Mob { + + { + spriteClass = GnollSprite.class; + + HP = HT = 70+(adj(0)*Random.NormalIntRange(3, 7)); + evadeSkill = 9+adj(1); + + + EXP = 10; + maxLvl = 18; + + loot = Gold.class; + lootChance = 0.5f; + + lootOther = Generator.random(Generator.Category.RANGEWEAPON); + lootChanceOther = 0.5f; // by default, see die() + + properties.add(Property.ORC); + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(10+adj(0), 20+adj(0)); + } + + + @Override + protected boolean canAttack(Char enemy) {if (buff(Locked.class) != null){ + return Level.adjacent(pos, enemy.pos) && (!isCharmedBy(enemy)); + } else + return Dungeon.level.distance( pos, enemy.pos ) <= 2 ; + } + + @Override + public int hitSkill(Char target) { + return 12+adj(0); + } + + @Override + public int drRoll() { + return Random.NormalIntRange(5, 8); + } + +} diff --git a/java/com/hmdzl/spspd/actors/mobs/GnollArcher.java b/java/com/hmdzl/spspd/actors/mobs/GnollArcher.java new file mode 100644 index 00000000..789cf9d6 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/GnollArcher.java @@ -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 + */ +package com.hmdzl.spspd.actors.mobs; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.Statistics; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Locked; +import com.hmdzl.spspd.items.TreasureMap; +import com.hmdzl.spspd.items.challengelists.SewerChallenge; +import com.hmdzl.spspd.items.food.completefood.GoldenNut; +import com.hmdzl.spspd.items.reward.SewerReward; +import com.hmdzl.spspd.items.scrolls.ScrollOfSacrifice; +import com.hmdzl.spspd.items.weapon.missiles.ForestDart; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.sprites.GnollArcherSprite; +import com.hmdzl.spspd.utils.GLog; + +import com.hmdzl.spspd.messages.Messages; +import com.watabou.utils.Random; + +public class GnollArcher extends Mob { + + private static final String TXT_KILLCOUNT = "Gnoll Archer Kill Count: %s"; + { + //name = "gnollarcher"; + spriteClass = GnollArcherSprite.class; + + HP = HT = 25 + Statistics.archersKilled; + evadeSkill = 5; + + EXP = 1; + + baseSpeed = 0.9f; + + state = WANDERING; + + properties.add(Property.ORC); + + } + + @Override + public int hitSkill(Char target) { + return 30; + } + + @Override + protected boolean canAttack(Char enemy) { + Ballistica attack = new Ballistica( pos, enemy.pos, Ballistica.PROJECTILE); + if (buff(Locked.class) != null){ + return Level.adjacent(pos, enemy.pos) && (!isCharmedBy(enemy)); + } else + + return !Level.adjacent(pos, enemy.pos) && attack.collisionPos == enemy.pos; + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(1+Math.round(Statistics.archersKilled/10), 8+Math.round(Statistics.archersKilled/5)); + } + + @Override + public int drRoll() { + return 0; + } + + @Override + protected boolean getCloser(int target) { + if (Level.adjacent(pos, enemy.pos)) { + return getFurther(target); + } else { + return super.getCloser(target); + } + } + + @Override + public void die(Object cause) { + super.die(cause); + if (Dungeon.depth > 25) { + Dungeon.level.drop(new ForestDart(3), pos).sprite.drop(); + } + + Statistics.archersKilled++; + GLog.w(Messages.get(Mob.class, "killcount", Statistics.archersKilled)); + + + if (!Dungeon.limitedDrops.sewerkey.dropped() && Dungeon.depth < 27) { + Dungeon.limitedDrops.sewerkey.drop(); + Dungeon.level.drop(new SewerChallenge(), pos).sprite.drop(); + explodeDew(pos); + } else { + explodeDew(pos); + } + + if (Statistics.archersKilled == 25) { + Dungeon.limitedDrops.treasuremap.drop(); + Dungeon.level.drop(new TreasureMap(), pos).sprite.drop(); + } + + if (Statistics.archersKilled == 50) { + Dungeon.level.drop(new ScrollOfSacrifice(), pos).sprite.drop(); + } + + if (Statistics.archersKilled == 100) { + Dungeon.level.drop(new SewerReward(), pos).sprite.drop(); + } + + if (Statistics.goldThievesKilled > 99 && Statistics.skeletonsKilled > 99 + && Statistics.albinoPiranhasKilled > 99 && Statistics.archersKilled == 100 ) { + Dungeon.level.drop(new GoldenNut(), pos).sprite.drop(); + } + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/mobs/GnollKing.java b/java/com/hmdzl/spspd/actors/mobs/GnollKing.java new file mode 100644 index 00000000..28363e58 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/GnollKing.java @@ -0,0 +1,337 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs; + +import java.util.HashSet; + +import com.hmdzl.spspd.items.quest.GnollClothes; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.items.Gold; +import com.hmdzl.spspd.sprites.GnollKingSprite; +import com.hmdzl.spspd.sprites.GnollKeeperSprite; +import com.hmdzl.spspd.items.AdamantRing; +import com.hmdzl.spspd.actors.buffs.Burning; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.blobs.Blob; +import com.hmdzl.spspd.actors.blobs.CorruptGas; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Cripple; +import com.hmdzl.spspd.actors.buffs.Roots; +import com.hmdzl.spspd.actors.buffs.Weakness; +import com.hmdzl.spspd.actors.buffs.Amok; +import com.hmdzl.spspd.actors.buffs.Bleeding; +import com.hmdzl.spspd.actors.buffs.Charm; +import com.hmdzl.spspd.actors.buffs.Poison; +import com.hmdzl.spspd.actors.buffs.Sleep; +import com.hmdzl.spspd.actors.buffs.Terror; +import com.hmdzl.spspd.actors.buffs.Vertigo; +import com.hmdzl.spspd.actors.buffs.Paralysis; +import com.hmdzl.spspd.actors.blobs.ToxicGas; +import com.hmdzl.spspd.items.scrolls.ScrollOfPsionicBlast; +import com.hmdzl.spspd.items.weapon.enchantments.EnchantmentDark; +import com.hmdzl.spspd.levels.Level; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public class GnollKing extends Mob { + + protected int breaks = 0; + + { + spriteClass = GnollKingSprite.class; + + HP = HT = 1000; + evadeSkill = 0; + + EXP = 30; + + baseSpeed = 0.75f; + + loot = new GnollClothes(); + lootChance = 1f; + + FLEEING = new Fleeing(); + + properties.add(Property.ORC); + properties.add(Property.BOSS); + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(15,25); + } + + @Override + public int hitSkill(Char target) { + return 100; + } + + @Override + public int drRoll() { + return Random.NormalIntRange(0, 5); + } + + @Override + public float speed() { + if (breaks == 1) return 4*super.speed(); + else return super.speed(); + } + + + @Override + public boolean act() { + + if( 3 - breaks > 4 * HP / HT ) { + breaks++; + yell(Messages.get(this,"angry")); + return true; + } + + if (breaks == 1){ + state = FLEEING; + } + + if (breaks == 2){ + state = HUNTING; + } + + if (breaks > 0){ + int newPos = -1; + for (int i = 0; i < 10; i++) { + newPos = Dungeon.level.randomRespawnCellMob(); + if (newPos != -1) { + break; + } + } + if (Dungeon.level.mobs.size()<4){ + GnollKeeper.spawnAroundChance(newPos); + } + } + return super.act(); + } + + @Override + public int attackProc(Char enemy, int damage) { + + if (breaks == 0){ + if (Random.Int(2) == 0) { + if(enemy == Dungeon.hero){ + Buff.prolong(enemy, Cripple.class, 3 ); + } + } + } + + + if (breaks == 2){ + if (Random.Int(2) == 0) { + if(enemy == Dungeon.hero){ + Buff.prolong(enemy, Roots.class, 3 ); + } + } + } + + if (breaks == 3){ + if (Random.Int(2) == 0) { + if(enemy == Dungeon.hero){ + Buff.prolong(enemy, Weakness.class, 3); + } + } + } + + return damage; + } + + @Override + public int defenseProc(Char enemy, int damage) { + + int dmg = Random.IntRange(0, 20); + + if (breaks == 3){ + if (dmg > 0 || (Random.Int(3) == 0 )) { + enemy.damage(dmg, this); + } + } + return super.defenseProc(enemy, damage); + } + + @Override + public void damage(int dmg, Object src) { + + dmg = Random.Int(10,20); + + if (breaks == 2){ + if (dmg > 15){ + GameScene.add(Blob.seed(pos, 30, CorruptGas.class)); + } + } + super.damage(dmg, src); + } + + @Override + protected boolean canAttack(Char enemy) { + + if (breaks == 2){ + return Dungeon.level.distance( pos, enemy.pos ) <= 2 ;} + else return Dungeon.level.distance( pos, enemy.pos ) <= 1; + } + + @Override + public void die(Object cause) { + + super.die(cause); + + GameScene.bossSlain(); + Dungeon.level.drop(new AdamantRing(), pos).sprite.drop(); + Dungeon.level.drop(new Gold(Random.Int(1000, 1500)), pos).sprite.drop(); + + + Dungeon.gnollkingkilled=true; + + yell(Messages.get(this,"die")); + + } + + @Override + public void notice() { + super.notice(); + yell(Messages.get(this,"notice")); + } + + + private static final HashSet> RESISTANCES = new HashSet>(); + private static final HashSet> IMMUNITIES = new HashSet>(); + static { + RESISTANCES.add(ToxicGas.class); + RESISTANCES.add(Poison.class); + RESISTANCES.add(EnchantmentDark.class); + IMMUNITIES.add(EnchantmentDark.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); + IMMUNITIES.add(Vertigo.class); + IMMUNITIES.add(Paralysis.class); + IMMUNITIES.add(Bleeding.class); + IMMUNITIES.add(CorruptGas.class); + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } + + @Override + public HashSet> resistances() { + return RESISTANCES; + } + + private static final String BREAKS = "breaks"; + + @Override + public void storeInBundle( Bundle bundle ) { + super.storeInBundle(bundle); + bundle.put( BREAKS, breaks ); + } + + @Override + public void restoreFromBundle( Bundle bundle ) { + super.restoreFromBundle(bundle); + breaks = bundle.getInt( BREAKS ); + } + public static class GnollKeeper extends Mob { + + private static final float SPAWN_DELAY = 10f; + + { + //name = "Gnoll Keeper"; + spriteClass = GnollKeeperSprite.class; + + HP = HT = 5; + evadeSkill = 10; + + EXP = 0; + + state = WANDERING; + } + + @Override + public int hitSkill(Char target) { + return 36; + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(0, 0); + } + + @Override + public int drRoll() { + return 1; + } + + @Override + public int attackProc(Char enemy, int damage) { + yell(Messages.get(this ,"safe")); + return damage; + } + + @Override + public boolean act() { + + return super.act(); + } + + 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 void spawnAroundChance(int pos) { + for (int n : Level.NEIGHBOURS4) { + int cell = pos + n; + if (Level.passable[cell] && Actor.findChar(cell) == null && Random.Float() < 0.75f) { + spawnAt(cell); + } + } + } + + public static GnollKeeper spawnAt(int pos) { + + GnollKeeper g1 = new GnollKeeper(); + + g1.pos = pos; + g1.state = g1.HUNTING; + GameScene.add(g1, SPAWN_DELAY); + + return g1; + + } + + } + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/mobs/GnollShaman.java b/java/com/hmdzl/spspd/actors/mobs/GnollShaman.java new file mode 100644 index 00000000..ef9e1f90 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/GnollShaman.java @@ -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 + */ +package com.hmdzl.spspd.actors.mobs; + +import java.util.HashSet; + +import com.hmdzl.spspd.actors.buffs.Silent; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.ResultDescriptions; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.effects.particles.SparkParticle; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.items.wands.WandOfLightning; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.traps.LightningTrap; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.sprites.CharSprite; +import com.hmdzl.spspd.sprites.ShamanSprite; + +import com.watabou.noosa.Camera; +import com.watabou.utils.Callback; +import com.watabou.utils.Random; + +public class GnollShaman 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..."; + + { + spriteClass = ShamanSprite.class; + + HP = HT = 80+(adj(0)*Random.NormalIntRange(2, 5)); + evadeSkill = 15+adj(0); + + EXP = 10; + maxLvl = 25; + + loot = Generator.Category.SCROLL; + lootChance = 0.15f; + + lootOther = new WandOfLightning(); + lootChanceOther = 0.02f; + + properties.add(Property.ORC); + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(14, 20+adj(0)); + } + + @Override + public int hitSkill(Char target) { + return 16+adj(0); + } + + @Override + public int drRoll() { + return Random.NormalIntRange(0, 4); + } + + @Override + protected boolean canAttack(Char enemy) { if (buff(Silent.class) != null){ + return Level.adjacent(pos, enemy.pos) && (!isCharmedBy(enemy)); + } else + return new Ballistica( pos, enemy.pos, Ballistica.MAGIC_BOLT).collisionPos == 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+adj(0), 12+adj(3)); + if (Level.water[enemy.pos] && !enemy.flying) { + dmg *= 1.5f; + } + enemy.damage(dmg, this); + + 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( Messages.format(ResultDescriptions.MOB)); + //GLog.n(Messages.get(this, "zap_kill")); + } + } + } else { + enemy.sprite + .showStatus(CharSprite.NEUTRAL, enemy.defenseVerb()); + } + + return !visible; + } + } + + @Override + public void call() { + next(); + } + + private static final HashSet> RESISTANCES = new HashSet>(); + static { + RESISTANCES.add(LightningTrap.Electricity.class); + } + + @Override + public HashSet> resistances() { + return RESISTANCES; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/GnollTrickster.java b/java/com/hmdzl/spspd/actors/mobs/GnollTrickster.java new file mode 100644 index 00000000..2e11f5d4 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/GnollTrickster.java @@ -0,0 +1,127 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs; + +import com.hmdzl.spspd.actors.buffs.Locked; +import com.hmdzl.spspd.actors.mobs.npcs.Ghost; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.Blob; +import com.hmdzl.spspd.actors.blobs.Fire; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Burning; +import com.hmdzl.spspd.actors.buffs.Poison; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.items.weapon.missiles.PoisonDart; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.GnollTricksterSprite; + +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + + public class GnollTrickster extends Gnoll { + { + //name = "gnolltrickster"; + spriteClass = GnollTricksterSprite.class; + + HP = HT = 60; + evadeSkill = 5; + + EXP = 5; + + state = WANDERING; + + loot = Generator.random(PoisonDart.class); + lootChance = 1f; + + properties.add(Property.ORC); + properties.add(Property.MINIBOSS); + } + + private int combo = 0; + + @Override + public int hitSkill(Char target) { + return 16; + } + + @Override + protected boolean canAttack(Char enemy) { + Ballistica attack = new Ballistica( pos, enemy.pos, Ballistica.PROJECTILE); + if (buff(Locked.class) != null){ + return Level.adjacent(pos, enemy.pos) && (!isCharmedBy(enemy)); + } else + return !Level.adjacent( pos, enemy.pos ) && attack.collisionPos == enemy.pos; + } + + @Override + public int attackProc(Char enemy, int damage) { + // The gnoll's attacks get more severe the more the player lets it + // hit them + combo++; + int effect = Random.Int(4) + combo; + + if (effect > 2) { + + if (effect >= 6 && enemy.buff(Burning.class) == null) { + + if (Level.flamable[enemy.pos]) + GameScene.add(Blob.seed(enemy.pos, 4, Fire.class)); + Buff.affect(enemy, Burning.class).reignite(enemy); + + } else + Buff.affect(enemy, Poison.class).set( + (effect - 2) * Poison.durationFactor(enemy)); + + } + return damage; + } + + @Override + protected boolean getCloser(int target) { + combo = 0; // if he's moving, he isn't attacking, reset combo. + if (Level.adjacent(pos, enemy.pos)) { + return getFurther(target); + } else { + return super.getCloser(target); + } + } + + @Override + public void die(Object cause) { + super.die(cause); + + Ghost.Quest.process(); + } + + private static final String COMBO = "combo"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(COMBO, combo); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + combo = bundle.getInt(COMBO); + } + + } \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/mobs/GoldCollector.java b/java/com/hmdzl/spspd/actors/mobs/GoldCollector.java new file mode 100644 index 00000000..0167c275 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/GoldCollector.java @@ -0,0 +1,71 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2014 Oleg Dolya + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.actors.mobs; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Taunt; +import com.hmdzl.spspd.sprites.RatSprite; + +public class GoldCollector extends Mob { + + { + spriteClass = RatSprite.class; + + HP = HT = Dungeon.gold; + evadeSkill = Dungeon.gold; + baseSpeed = 3f; + flying = true; + + state = WANDERING; + + properties.add(Property.BOSS); + } + + @Override + public int damageRoll() { + return Dungeon.gold; + } + + @Override + public int hitSkill(Char target) { + return Dungeon.gold; + } + + @Override + public int attackProc(Char enemy, int damage) { + if (enemy.buff(Taunt.class)== null && enemy == Dungeon.hero) { + Buff.affect(enemy, Taunt.class); + Dungeon.gold=0; + damage = 0; + this.damage(this.HT*2,this); + return damage; + } else return damage; + } + + @Override + public int drRoll() { + return Dungeon.gold; + } + + @Override + public void add( Buff buff ) { + //in other words, can't be directly affected by buffs/debuffs. + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/GoldOrc.java b/java/com/hmdzl/spspd/actors/mobs/GoldOrc.java new file mode 100644 index 00000000..6fc7e545 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/GoldOrc.java @@ -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 + */ +package com.hmdzl.spspd.actors.mobs; + +import java.util.HashSet; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Amok; +import com.hmdzl.spspd.actors.blobs.Blob; +import com.hmdzl.spspd.actors.blobs.CorruptGas; +import com.hmdzl.spspd.actors.buffs.Terror; +import com.hmdzl.spspd.actors.buffs.Vertigo; +import com.hmdzl.spspd.sprites.GoldOrcSprite; +import com.hmdzl.spspd.scenes.GameScene; +import com.watabou.utils.Random; + +public class GoldOrc extends Mob { + + { + spriteClass = GoldOrcSprite.class; + state = SLEEPING; + + HP = HT = 500; + evadeSkill = 35; + + EXP = 25; + + properties.add(Property.ORC); + properties.add(Property.DEMONIC); + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(55, 115); + } + + @Override + public int hitSkill(Char target) { + return 55; + } + + @Override + protected float attackDelay() { + return 1.5f; + } + + @Override + public int drRoll() { + return Random.NormalIntRange(16, 32); + } + + @Override + public void damage(int dmg, Object src) { + if (dmg > HT/8){ + GameScene.add(Blob.seed(pos, 30, CorruptGas.class)); + } + super.damage(dmg, src); + } + + + private static final HashSet> RESISTANCES = new HashSet>(); + static { + } + + @Override + public HashSet> resistances() { + return RESISTANCES; + } + + private static final HashSet> IMMUNITIES = new HashSet>(); + static { + IMMUNITIES.add(Amok.class); + IMMUNITIES.add(Terror.class); + IMMUNITIES.add(CorruptGas.class); + IMMUNITIES.add(Vertigo.class); + + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/GoldThief.java b/java/com/hmdzl/spspd/actors/mobs/GoldThief.java new file mode 100644 index 00000000..bda7c078 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/GoldThief.java @@ -0,0 +1,182 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs; + +import com.hmdzl.spspd.items.challengelists.CityChallenge; +import com.hmdzl.spspd.items.food.completefood.GoldenNut; +import com.hmdzl.spspd.items.reward.CityReward; +import com.hmdzl.spspd.items.scrolls.ScrollOfSacrifice; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.Statistics; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Terror; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.items.AncientCoin; +import com.hmdzl.spspd.items.Gold; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.sprites.CharSprite; +import com.hmdzl.spspd.sprites.GoldThiefSprite; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public class GoldThief extends Mob { + + protected static final String TXT_STOLE = "%s stole %s gold from you!"; + private static final String TXT_KILLCOUNT = "Gold Thief Kill Count: %s"; + + public Item item; + + { + spriteClass = GoldThiefSprite.class; + + HP = HT = 100+Statistics.goldThievesKilled; + evadeSkill = 26; + + EXP = 1; + + FLEEING = new Fleeing(); + + properties.add(Property.ELF); + } + + private int goldtodrop = 0; + + private static final String GOLDTODROP = "goldtodrop"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(GOLDTODROP, goldtodrop); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + goldtodrop = bundle.getInt(GOLDTODROP); + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(20, 30+Statistics.goldThievesKilled/2); + } + + @Override + protected float attackDelay() { + return 0.75f; + } + + @Override + public void die(Object cause) { + + super.die(cause); + Statistics.goldThievesKilled++; + GLog.w(Messages.get(Mob.class,"killcount",Statistics.goldThievesKilled)); + + + if (item != null) { + Dungeon.level.drop(item, pos).sprite.drop(); + } + + if (!Dungeon.limitedDrops.citykey.dropped() && Dungeon.depth<27) { + Dungeon.limitedDrops.citykey.drop(); + Dungeon.level.drop(new CityChallenge(), pos).sprite.drop(); + explodeDew(pos); + } else { + explodeDew(pos); + } + + if(Statistics.goldThievesKilled == 25) { + Dungeon.limitedDrops.ancientcoin.drop(); + Dungeon.level.drop(new AncientCoin(), pos).sprite.drop(); + } + + if(Statistics.goldThievesKilled == 50) { + Dungeon.level.drop(new ScrollOfSacrifice(), pos).sprite.drop(); + } + + if(Statistics.goldThievesKilled == 100) { + Dungeon.level.drop(new CityReward(), pos).sprite.drop(); + } + + if (Statistics.goldThievesKilled == 100 && Statistics.skeletonsKilled>99 + && Statistics.albinoPiranhasKilled>99 && Statistics.archersKilled>99){ + Dungeon.level.drop(new GoldenNut(), pos).sprite.drop(); + } + + } + + @Override + protected Item createLoot() { + return new Gold(Random.NormalIntRange(goldtodrop+50, goldtodrop+100)); + } + + @Override + public int hitSkill(Char target) { + return 40; + } + + @Override + public int drRoll() { + return 13+Math.round((Statistics.goldThievesKilled+1/10)+1); + } + + @Override + public int attackProc(Char enemy, int damage) { + if (item == null && enemy instanceof Hero && steal((Hero) enemy)) { + state = FLEEING; + } + + return damage; + } + + @Override + public int defenseProc(Char enemy, int damage) { + if (state == FLEEING) { + Dungeon.level.drop(new Gold(), pos).sprite.drop(); + } + + return damage; + } + + protected boolean steal(Hero hero) { + + Gold gold = new Gold(Random.Int(100, 300)); + if (gold.quantity() > 0) { + goldtodrop = Math.min((gold.quantity()+100),Dungeon.gold); + Dungeon.gold -= goldtodrop; + GLog.w(Messages.get(GoldThief.class, "stole", gold.quantity())); + return true; + } else { + return false; + } + } + + private class Fleeing extends Mob.Fleeing { + @Override + protected void nowhereToRun() { + if (buff(Terror.class) == null) { + sprite.showStatus(CharSprite.NEGATIVE, Messages.get(Mob.class, "rage")); + state = HUNTING; + } else { + super.nowhereToRun(); + } + } + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/Golem.java b/java/com/hmdzl/spspd/actors/mobs/Golem.java new file mode 100644 index 00000000..c1a6ffae --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/Golem.java @@ -0,0 +1,124 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs; + +import java.util.HashSet; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.items.StoneOre; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.Blob; +import com.hmdzl.spspd.actors.blobs.TarGas; +import com.hmdzl.spspd.actors.buffs.Amok; +import com.hmdzl.spspd.actors.buffs.Tar; +import com.hmdzl.spspd.actors.buffs.Sleep; +import com.hmdzl.spspd.actors.buffs.Terror; +import com.hmdzl.spspd.actors.mobs.npcs.Imp; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.GolemSprite; + +import com.watabou.utils.Random; + +public class Golem extends Mob { + + { + spriteClass = GolemSprite.class; + + HP = HT = 180+(adj(0)*Random.NormalIntRange(4, 7)); + evadeSkill = 18+adj(1); + + EXP = 15; + maxLvl = 30; + + loot = new StoneOre(); + lootChance = 0.5f; + + properties.add(Property.MECH); + } + + @Override + public boolean act() { + //GameScene.add(Blob.seed(pos, 30, TarGas.class)); + return super.act(); + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(20+adj(0), 60+adj(1)); + } + + @Override + public int hitSkill(Char target) { + return 28+adj(1); + } + + @Override + protected float attackDelay() { + return 1.5f; + } + + @Override + public int drRoll() { + return Random.NormalIntRange(10, 15); + } + + @Override + public void damage(int dmg, Object src) { + if (dmg > HT/8){ + GameScene.add(Blob.seed(pos, 30, TarGas.class)); + } + super.damage(dmg, src); + } + + @Override + public void die(Object cause) { + + Imp.Quest.process(this); + if (Dungeon.limitedDrops.nornstones.count<6 + && Random.Int(6)<3 + ){ + Dungeon.level.drop(Generator.random(Generator.Category.NORNSTONE), pos).sprite.drop(); + Dungeon.limitedDrops.nornstones.count++; + } + super.die(cause); + } + + private static final HashSet> RESISTANCES = new HashSet>(); + static { + } + + @Override + public HashSet> resistances() { + return RESISTANCES; + } + + private static final HashSet> IMMUNITIES = new HashSet>(); + static { + IMMUNITIES.add(Amok.class); + IMMUNITIES.add(Terror.class); + IMMUNITIES.add(Sleep.class); + IMMUNITIES.add(TarGas.class); + IMMUNITIES.add(Tar.class); + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/Goo.java b/java/com/hmdzl/spspd/actors/mobs/Goo.java new file mode 100644 index 00000000..0057eea1 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/Goo.java @@ -0,0 +1,573 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs; + +import java.util.ArrayList; +import java.util.HashSet; + +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.blobs.Web; +import com.hmdzl.spspd.actors.buffs.Burning; +import com.hmdzl.spspd.actors.buffs.Poison; +import com.hmdzl.spspd.actors.buffs.Terror; +import com.hmdzl.spspd.effects.Pushing; +import com.hmdzl.spspd.items.StoneOre; +import com.hmdzl.spspd.items.UpgradeBlobViolet; +import com.hmdzl.spspd.items.wands.WandOfFirebolt; +import com.hmdzl.spspd.items.weapon.enchantments.EnchantmentFire; +import com.hmdzl.spspd.levels.Terrain; +import com.hmdzl.spspd.levels.features.Door; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.Badges.Badge; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.Blob; +import com.hmdzl.spspd.actors.blobs.GooWarn; +import com.hmdzl.spspd.actors.blobs.ToxicGas; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Ooze; +import com.hmdzl.spspd.actors.buffs.Roots; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.effects.particles.ElmoParticle; +import com.hmdzl.spspd.items.summon.ActiveMrDestructo; +import com.hmdzl.spspd.items.journalpages.Sokoban1; +import com.hmdzl.spspd.items.keys.SkeletonKey; +import com.hmdzl.spspd.items.weapon.enchantments.EnchantmentDark; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.SewerBossLevel; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.CharSprite; +import com.hmdzl.spspd.sprites.GooSprite; +import com.hmdzl.spspd.sprites.PoisonGooSprite; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.noosa.Camera; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public class Goo extends Mob { + { + HP = HT = 350; + EXP = 20; + evadeSkill = 12; + spriteClass = GooSprite.class; + + loot = new UpgradeBlobViolet(); + lootChance = 0.2f; + + lootOther = new ActiveMrDestructo(); + lootChanceOther = 1f; + + properties.add(Property.ELEMENT); + properties.add(Property.BOSS); + } + + private int pumpedUp = 0; + private int goosAlive = 0; + + @Override + public int damageRoll() { + if (pumpedUp > 0) { + pumpedUp = 0; + for (int i = 0; i < Level.NEIGHBOURS9DIST2.length; i++) { + int j = pos + Level.NEIGHBOURS9DIST2[i]; + if (j >= 0 && j <= 1023 && Level.passable[j]) + CellEmitter.get(j).burst(ElmoParticle.FACTORY, 10); + } + Sample.INSTANCE.play(Assets.SND_BURNING); + return Random.NormalIntRange(5, 30); + } else { + return Random.NormalIntRange(2, 12); + } + } + + @Override + public int hitSkill(Char target) { + return (pumpedUp > 0) ? 30 : 15; + } + + @Override + public int drRoll() { + return Random.NormalIntRange(0, 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 > 0) ? 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 > 0) { + Camera.main.shake(3, 0.2f); + } + + return damage; + } + + @Override + protected boolean doAttack(Char enemy) { + if (pumpedUp == 1) { + ((GooSprite) sprite).pumpUp(); + for (int i = 0; i < Level.NEIGHBOURS9DIST2.length; i++) { + int j = pos + Level.NEIGHBOURS9DIST2[i]; + if (j >= 0 && j <= 1023 && Level.passable[j]) + GameScene.add(Blob.seed(j, 2, GooWarn.class)); + } + pumpedUp++; + + spend(attackDelay()); + + return true; + } else if (pumpedUp >= 2 || Random.Int( (HP*2 <= HT) ? 2 : 5 ) > 0) { + + boolean visible = Dungeon.visible[pos]; + + if (visible) { + if (pumpedUp >= 2) { + ((GooSprite) sprite).pumpAttack(); + } else + sprite.attack(enemy.pos); + } else { + attack(enemy); + } + + spend(attackDelay()); + + return !visible; + + } else { + + pumpedUp++; + + ((GooSprite) sprite).pumpUp(); + + for (int i = 0; i < Level.NEIGHBOURS9.length; i++) { + int j = pos + Level.NEIGHBOURS9[i]; + GameScene.add(Blob.seed(j, 2, GooWarn.class)); + + } + + if (Dungeon.visible[pos]) { + sprite.showStatus(CharSprite.NEGATIVE, "!!!"); + GLog.n(Messages.get(this,"atk")); + } + + spend(attackDelay()); + + return true; + } + } + + @Override + public boolean attack(Char enemy) { + boolean result = super.attack(enemy); + pumpedUp = 0; + return result; + } + + @Override + protected boolean getCloser(int target) { + pumpedUp = 0; + return super.getCloser(target); + } + + @Override + public void die(Object cause) { + + super.die(cause); + + for (Mob mob : Dungeon.level.mobs) { + + if (mob instanceof Goo || mob instanceof PoisonGoo){ + goosAlive++; + } + + } + + if(goosAlive==0){ + + ((SewerBossLevel) Dungeon.level).unseal(); + + GameScene.bossSlain(); + Dungeon.level.drop(new SkeletonKey(Dungeon.depth), pos).sprite.drop(); + Badges.validateBossSlain(); + } + + 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; + case PERFORMER: + badgeToCheck = Badge.MASTERY_PERFORMER; + break; + case SOLDIER: + badgeToCheck = Badge.MASTERY_SOLDIER; + break; + case FOLLOWER: + badgeToCheck = Badge.MASTERY_FOLLOWER; + break; + } + + + Dungeon.level.drop(new Sokoban1(), pos).sprite.drop(); + + + yell("glurp... glurp..."); + } + + protected boolean spawnedMini = false; + + @Override + public void notice() { + super.notice(); + yell("GLURP-GLURP!"); + ((SewerBossLevel) Dungeon.level).seal(); + if (!spawnedMini){ + PoisonGoo.spawnAround(pos); + spawnedMini = true; + } + } + + private final String PUMPEDUP = "pumpedup"; + + @Override + public void storeInBundle(Bundle bundle) { + + super.storeInBundle(bundle); + + bundle.put(PUMPEDUP, pumpedUp); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + + super.restoreFromBundle(bundle); + + pumpedUp = bundle.getInt(PUMPEDUP); + } + + private static final HashSet> IMMUNITIES = new HashSet>(); + private static final HashSet> RESISTANCES = new HashSet>(); + private static final HashSet> WEAKNESS = new HashSet>(); + static { + RESISTANCES.add(ToxicGas.class); + RESISTANCES.add(EnchantmentDark.class); + + + IMMUNITIES.add(Roots.class); + + WEAKNESS.add(Burning.class); + WEAKNESS.add(WandOfFirebolt.class); + WEAKNESS.add(EnchantmentFire.class); + } + + @Override + public HashSet> resistances() { + return RESISTANCES; + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } + + @Override + public HashSet> weakness() { + return WEAKNESS; + } + + public static class PoisonGoo extends Mob { + + protected static final float SPAWN_DELAY = 2f; + + private boolean gooSplit = false; + + private int gooGeneration = 0; + private int goosAlive = 0; + + private static final String GOOGENERATION = "gooGeneration"; + + { + HP = HT = 100; + EXP = 1; + evadeSkill = 12; + spriteClass = PoisonGooSprite.class; + baseSpeed = 1.5f; + + loot = new StoneOre(); + lootChance = 0.25f; + FLEEING = new Fleeing(); + + properties.add(Property.ELEMENT); + properties.add(Property.MINIBOSS); + } + + private static final float SPLIT_DELAY = 1f; + + @Override + protected boolean act() { + boolean result = super.act(); + + if (state == FLEEING && buff(Terror.class) == null && enemy != null + && enemySeen && enemy.buff(Poison.class) == null) { + state = HUNTING; + } + if (Level.water[pos] && HP < HT) { + sprite.emitter().burst( Speck.factory( Speck.HEALING ), 1 ); + HP++; + } else if(Level.water[pos] && HP == HT && HT < 100){ + sprite.emitter().burst( Speck.factory( Speck.HEALING ), 1 ); + HT=HT+5; + HP=HT; + } + return result; + } + + @Override + public int attackProc(Char enemy, int damage) { + if (Random.Int(1) == 0) { + Buff.affect(enemy, Poison.class).set( + Random.Int(7, 10) * Poison.durationFactor(enemy)); + state = FLEEING; + } + + return damage; + } + + @Override + public void move(int step) { + if (state == FLEEING) { + GameScene.add(Blob.seed(pos, Random.Int(7, 10), Web.class)); + } + super.move(step); + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(1, 10); + } + + @Override + public int hitSkill(Char target) { + return 5; + } + + @Override + public int drRoll() { + return 0; + } + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(GOOGENERATION, gooGeneration); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + gooGeneration = bundle.getInt(GOOGENERATION); + } + + @Override + public int defenseProc(Char enemy, int damage) { + gooSplit = false; + for (Mob mob : Dungeon.level.mobs) { + if (mob instanceof Goo) { + gooSplit = true; + } + } + if (HP >= damage + 2 && gooSplit) { + ArrayList candidates = new ArrayList(); + boolean[] passable = Level.passable; + + int[] neighbours = { pos + 1, pos - 1, pos + Level.getWidth(), + pos - Level.getWidth() }; + for (int n : neighbours) { + if (passable[n] && Actor.findChar(n) == null) { + candidates.add(n); + } + } + + if (candidates.size() > 0) { + PoisonGoo clone = split(); + clone.HP = (HP - damage) / 2; + clone.pos = Random.element(candidates); + clone.state = clone.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; + } + + + private PoisonGoo split() { + PoisonGoo clone = new PoisonGoo(); + clone.gooGeneration = gooGeneration + 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 + public void die(Object cause) { + + if (gooGeneration > 0){ + lootChance = 0; + } + + super.die(cause); + + for (Mob mob : Dungeon.level.mobs) { + + if (mob instanceof Goo || mob instanceof PoisonGoo){ + goosAlive++; + } + + } + + if(goosAlive==0){ + ((SewerBossLevel) Dungeon.level).unseal(); + + GameScene.bossSlain(); + Dungeon.level.drop(new SkeletonKey(Dungeon.depth), pos).sprite.drop(); + + //Dungeon.level.drop(new Gold(Random.Int(900, 2000)), pos).sprite.drop(); + + Badges.validateBossSlain(); + } else { + + //Dungeon.level.drop(new Gold(Random.Int(100, 200)), pos).sprite.drop(); + } + + yell("glurp... glurp..."); + } + + @Override + public void notice() { + super.notice(); + yell("GLURP-GLURP!"); + } + + private static final HashSet> RESISTANCES = new HashSet>(); + static { + RESISTANCES.add(ToxicGas.class); + RESISTANCES.add(EnchantmentDark.class); + + } + + @Override + public HashSet> resistances() { + return RESISTANCES; + } + + private static final HashSet> IMMUNITIES = new HashSet>(); + + static { + IMMUNITIES.add(Roots.class); + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } + + private class Fleeing extends Mob.Fleeing { + @Override + protected void nowhereToRun() { + if (buff(Terror.class) == null) { + state = HUNTING; + } else { + super.nowhereToRun(); + } + } + } + + + 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 PoisonGoo spawnAt(int pos) { + + PoisonGoo b = new PoisonGoo(); + + b.pos = pos; + b.state = b.HUNTING; + GameScene.add(b, SPAWN_DELAY); + + return b; + + } + + + } + +} diff --git a/java/com/hmdzl/spspd/actors/mobs/GraveProtector.java b/java/com/hmdzl/spspd/actors/mobs/GraveProtector.java new file mode 100644 index 00000000..44c2e01a --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/GraveProtector.java @@ -0,0 +1,143 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs; + +import java.util.HashSet; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.ResultDescriptions; +import com.hmdzl.spspd.Statistics; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Silent; +import com.hmdzl.spspd.effects.particles.SparkParticle; +import com.hmdzl.spspd.items.VioletDewdrop; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.traps.LightningTrap; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.sprites.CharSprite; +import com.hmdzl.spspd.sprites.GraveProtectorSprite; + +import com.hmdzl.spspd.messages.Messages; +import com.watabou.noosa.Camera; +import com.watabou.utils.Callback; +import com.watabou.utils.Random; + +public class GraveProtector 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..."; + + { + spriteClass = GraveProtectorSprite.class; + + EXP = 1; + state = HUNTING; + flying = true; + + HP = HT = 350; + evadeSkill = 15; + + loot = new VioletDewdrop(); + lootChance = 1f; + + properties.add(Property.ELEMENT); + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(8+Math.round(Statistics.skeletonsKilled/10), 15+Math.round(Statistics.skeletonsKilled/5)); + } + + @Override + public int hitSkill(Char target) { + return 20; + } + + @Override + public int drRoll() { + return Random.NormalIntRange(0, 8); + } + + @Override + protected boolean canAttack(Char enemy) { if (buff(Silent.class) != null){ + return Level.adjacent(pos, enemy.pos) && (!isCharmedBy(enemy)); + } else + return new Ballistica( pos, enemy.pos, Ballistica.MAGIC_BOLT).collisionPos == 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) { + ((GraveProtectorSprite) sprite).zap(enemy.pos); + } + + spend(TIME_TO_ZAP); + + if (hit(this, enemy, true)) { + int dmg = Random.Int(10+Math.round(Statistics.skeletonsKilled/10), 25+Math.round(Statistics.skeletonsKilled/5)); + if (Level.water[enemy.pos] && !enemy.flying) { + dmg *= 1.5f; + } + enemy.damage(dmg, this); + + 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( Messages.format(ResultDescriptions.MOB)); + //GLog.n(Messages.get(this, "kill")); + } + } + } else { + enemy.sprite + .showStatus(CharSprite.NEUTRAL, enemy.defenseVerb()); + } + + return !visible; + } + } + + @Override + public void call() { + next(); + } + + private static final HashSet> RESISTANCES = new HashSet>(); + static { + RESISTANCES.add(LightningTrap.Electricity.class); + } + + @Override + public HashSet> resistances() { + return RESISTANCES; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/GreatCrab.java b/java/com/hmdzl/spspd/actors/mobs/GreatCrab.java new file mode 100644 index 00000000..17951c3c --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/GreatCrab.java @@ -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 + */ +package com.hmdzl.spspd.actors.mobs; + +import com.hmdzl.spspd.actors.mobs.npcs.Ghost; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.items.food.meatfood.MysteryMeat; +import com.hmdzl.spspd.items.wands.Wand; +import com.hmdzl.spspd.levels.traps.LightningTrap; +import com.hmdzl.spspd.sprites.CharSprite; +import com.hmdzl.spspd.sprites.GreatCrabSprite; +import com.hmdzl.spspd.utils.GLog; + +import com.hmdzl.spspd.messages.Messages; + +public class GreatCrab extends Crab { + { + //name = "great crab"; + spriteClass = GreatCrabSprite.class; + + HP = HT = 100; + evadeSkill = 0; // see damage() + baseSpeed = 1f; + + EXP = 6; + + state = WANDERING; + + properties.add(Property.BEAST); + properties.add(Property.MINIBOSS); + } + + private int moving = 0; + + @Override + protected boolean getCloser(int target) { + // this is used so that the crab remains slower, but still detects + // the player at the expected rate. + moving++; + if (moving < 3) { + return super.getCloser(target); + } else { + moving = 0; + return true; + } + + } + + @Override + public void damage(int dmg, Object src) { + // crab blocks all attacks originating from the hero or enemy + // characters or traps if it is alerted. + // All direct damage from these sources is negated, no exceptions. + // blob/debuff effects go through as normal. + if ((enemySeen && state != SLEEPING && paralysed == 0) + && (src instanceof Wand || src instanceof LightningTrap.Electricity || src instanceof Char)){ + GLog.n( Messages.get(this, "noticed") ); + sprite.showStatus( CharSprite.NEUTRAL, Messages.get(this, "blocked") ); + } else { + super.damage(dmg, src); + } + } + + @Override + public void die(Object cause) { + super.die(cause); + + Ghost.Quest.process(); + + Dungeon.level.drop(new MysteryMeat(), pos); + Dungeon.level.drop(new MysteryMeat(), pos).sprite.drop(); + } + + } \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/mobs/GreyRat.java b/java/com/hmdzl/spspd/actors/mobs/GreyRat.java new file mode 100644 index 00000000..444e3e48 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/GreyRat.java @@ -0,0 +1,140 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs; + +import java.util.HashSet; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.StenchGas; +import com.hmdzl.spspd.actors.blobs.ToxicGas; +import com.hmdzl.spspd.actors.buffs.Amok; +import com.hmdzl.spspd.actors.buffs.Burning; +import com.hmdzl.spspd.actors.buffs.Poison; +import com.hmdzl.spspd.actors.buffs.Sleep; +import com.hmdzl.spspd.actors.buffs.Terror; +import com.hmdzl.spspd.actors.buffs.Vertigo; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.items.food.meatfood.Meat; +import com.hmdzl.spspd.items.scrolls.ScrollOfPsionicBlast; +import com.hmdzl.spspd.items.weapon.enchantments.EnchantmentDark; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.GreyRatSprite; +import com.watabou.utils.Random; + +public class GreyRat extends Mob { + + + private static final float SPAWN_DELAY = 2f; + + { + spriteClass = GreyRatSprite.class; + + HP = HT = 80+(adj(0)*Random.NormalIntRange(3, 5)); + evadeSkill = 8+adj(0); + + EXP = 5; + + loot = new Meat(); + lootChance = 0.5f; + + lootOther = Generator.Category.MUSHROOM; + lootChanceOther = 0.25f; + + properties.add(Property.BEAST); + + } + + + + @Override + public int damageRoll() { + return Random.NormalIntRange(1, 7+adj(0)); + } + + @Override + protected float attackDelay() { + return 0.8f; + } + + + @Override + public int hitSkill(Char target) { + return 6 + Dungeon.depth; + } + + @Override + public int drRoll() { + return Random.NormalIntRange(0, 3); + } + + 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 GreyRat spawnAt(int pos) { + + GreyRat b = new GreyRat(); + + b.pos = pos; + b.state = b.HUNTING; + GameScene.add(b, SPAWN_DELAY); + + return b; + + } + + private static final HashSet> RESISTANCES = new HashSet>(); + static { + RESISTANCES.add(ToxicGas.class); + RESISTANCES.add(EnchantmentDark.class); + + } + + @Override + public HashSet> resistances() { + return RESISTANCES; + } + + private static final HashSet> IMMUNITIES = new HashSet>(); + static { + IMMUNITIES.add(Amok.class); + IMMUNITIES.add(Sleep.class); + IMMUNITIES.add(Terror.class); + IMMUNITIES.add(Burning.class); + IMMUNITIES.add(ScrollOfPsionicBlast.class); + IMMUNITIES.add(Vertigo.class); + IMMUNITIES.add(Poison.class); + IMMUNITIES.add(StenchGas.class); + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } + + + +} diff --git a/java/com/hmdzl/spspd/actors/mobs/Guard.java b/java/com/hmdzl/spspd/actors/mobs/Guard.java new file mode 100644 index 00000000..b7d9f28e --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/Guard.java @@ -0,0 +1,232 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs; + +import java.util.HashSet; + +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.buffs.Cripple; +import com.hmdzl.spspd.actors.buffs.Silent; +import com.hmdzl.spspd.effects.Chains; +import com.hmdzl.spspd.effects.Pushing; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.ResultDescriptions; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.weapon.enchantments.EnchantmentDark; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.sprites.GuardSprite; + +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Bundle; +import com.watabou.utils.Callback; +import com.watabou.utils.Random; + + + +public class Guard extends Mob { + + private boolean chainsUsed = false; + + { + spriteClass = GuardSprite.class; + + HP = HT = 75+(adj(0)*Random.NormalIntRange(3, 7)); + evadeSkill = 9+adj(1); + + EXP = 10; + maxLvl = 20; + + loot = Generator.Category.ARMOR; + lootChance = 0.2f; + + properties.add(Property.HUMAN); + //HUNTING = new Hunting(); + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(12+adj(0), 20+adj(3)); + } + + @Override + protected float attackDelay() { + return 1.2f; + } + + @Override + protected boolean act() { + Dungeon.level.updateFieldOfView( this ); + + if (state == HUNTING && + paralysed <= 0 && + enemy != null && + enemy.invisible == 0 && + Level.fieldOfView[enemy.pos] && + Level.distance( pos, enemy.pos ) < 5 && !Level.adjacent( pos, enemy.pos ) && + Random.Int(3) == 0 && (buff(Silent.class) == null) && + + chain(enemy.pos)) { + + return false; + + } else { + return super.act(); + } + } + private boolean chain(int target){ + if (chainsUsed || enemy.properties().contains(Property.IMMOVABLE)) + return false; + + Ballistica chain = new Ballistica(pos, target, Ballistica.PROJECTILE); + + if (chain.collisionPos != enemy.pos || Level.pit[chain.path.get(1)]) + return false; + else { + int newPos = -1; + for (int i : chain.subPath(1, chain.dist)){ + if (!Level.solid[i] && Actor.findChar(i) == null){ + newPos = i; + break; + } + } + + if (newPos == -1){ + return false; + } else { + final int newPosFinal = newPos; + yell( Messages.get(this, "scorpion") ); + sprite.parent.add(new Chains(pos, enemy.pos, new Callback() { + public void call() { + Actor.addDelayed(new Pushing(enemy, enemy.pos, newPosFinal), -1); + enemy.pos = newPosFinal; + Dungeon.level.press(newPosFinal, enemy); + Cripple.prolong(enemy, Cripple.class, 4f); + if (enemy == Dungeon.hero) { + Dungeon.hero.interrupt(); + Dungeon.observe(); + } + next(); + } + })); + } + } + chainsUsed = true; + return true; + } + + + @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, + Random.NormalIntRange(3, 8) - Random.IntRange(0, ch.drRoll() / 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(Messages.format(ResultDescriptions.MOB)); + //GLog.n(Messages.get(this, "kill")); + } + } + + @Override + protected Item createLoot() { + Item loot = Generator.random(Generator.Category.ARMOR); + for (int i = 0; i < 2; i++) { + Item l = Generator.random(Generator.Category.ARMOR); + if (l.level < loot.level) { + loot = l; + } + } + return loot; + } + + @Override + public int hitSkill(Char target) { + return 12+adj(0); + } + + @Override + public int drRoll() { + return Random.NormalIntRange(5, 10); + } + + private final String CHAINSUSED = "chainsused"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(CHAINSUSED, chainsUsed); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + chainsUsed = bundle.getBoolean(CHAINSUSED); + } + + private static final HashSet> IMMUNITIES = new HashSet>(); + static { + IMMUNITIES.add(EnchantmentDark.class); + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } + + /*private class Hunting extends Mob.Hunting{ + @Override + public boolean act( boolean enemyInFOV, boolean justAlerted ) { + enemySeen = enemyInFOV; + + if (!chainsUsed + && enemyInFOV + && !isCharmedBy( enemy ) + && !canAttack( enemy ) + && Dungeon.level.distance( pos, enemy.pos ) < 5 + && Random.Int(3) == 0 + + && chain(enemy.pos)){ + return false; + } else { + return super.act( enemyInFOV, justAlerted ); + } + + } + } */ +} diff --git a/java/com/hmdzl/spspd/actors/mobs/HermitCrab.java b/java/com/hmdzl/spspd/actors/mobs/HermitCrab.java new file mode 100644 index 00000000..72356b6c --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/HermitCrab.java @@ -0,0 +1,169 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs; + +import java.util.HashSet; + +import com.hmdzl.spspd.actors.buffs.Silent; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.ResultDescriptions; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.effects.particles.SparkParticle; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.items.keys.GoldenSkeletonKey; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.traps.LightningTrap; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.sprites.CharSprite; +import com.hmdzl.spspd.sprites.HermitCrabSprite; +import com.hmdzl.spspd.utils.GLog; + +import com.watabou.noosa.Camera; +import com.watabou.utils.Callback; +import com.watabou.utils.Random; + +public class HermitCrab 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..."; + private static final String TXT_SHELL_ABSORB = "Hermit Crab absorbed the attack in its shell."; + private static final String TXT_SHELL_CHARGE = "Lightning Shell charged by %s."; + + { + spriteClass = HermitCrabSprite.class; + + HP = HT = 200; + evadeSkill = 22; + + EXP = 60; + + loot = Generator.Category.BERRY; + lootChance = 0.33f; + + properties.add(Property.BEAST); + properties.add(Property.BOSS); + + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(25, 50); + } + + @Override + public int hitSkill(Char target) { + return 25; + } + + @Override + public int drRoll() { + return Random.NormalIntRange(0, 4); + } + + @Override + public void damage(int dmg, Object src) { + + if (dmg>HT/4 && src != this){ + for (Mob mob : Dungeon.level.mobs) { + if (mob instanceof Shell && mob.isAlive()){ + GLog.n(Messages.get(this, "absorb")); + dmg=1; + } + } + } + super.damage(dmg, src); + } + + + @Override + protected boolean canAttack(Char enemy) { if (buff(Silent.class) != null){ + return Level.adjacent(pos, enemy.pos) && (!isCharmedBy(enemy)); + } else + return new Ballistica( pos, enemy.pos, Ballistica.MAGIC_BOLT).collisionPos == 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) { + ((HermitCrabSprite) sprite).zap(enemy.pos); + } + + spend(TIME_TO_ZAP); + + if (hit(this, enemy, true)) { + int dmg = Random.Int(15, 30); + if (Level.water[enemy.pos] && !enemy.flying) { + dmg *= 1.5f; + } + enemy.damage(dmg, this); + + 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(Messages.format(ResultDescriptions.MOB)); + //GLog.n(Messages.get(this, "kill")); + } + } + } else { + enemy.sprite + .showStatus(CharSprite.NEUTRAL, enemy.defenseVerb()); + } + + return !visible; + } + } + + @Override + public void call() { + next(); + } + + @Override + public void die(Object cause) { + super.die(cause); + if(Random.Int(1)==0){ + Dungeon.level.drop(new GoldenSkeletonKey(0), pos).sprite.drop(); + } + } + + private static final HashSet> RESISTANCES = new HashSet>(); + static { + RESISTANCES.add(LightningTrap.Electricity.class); + } + + @Override + public HashSet> resistances() { + return RESISTANCES; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/Hybrid.java b/java/com/hmdzl/spspd/actors/mobs/Hybrid.java new file mode 100644 index 00000000..1c3dd93a --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/Hybrid.java @@ -0,0 +1,312 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2015 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.actors.mobs; + + +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.Badges.Badge; +import com.hmdzl.spspd.Challenges; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.ConfusionGas; +import com.hmdzl.spspd.actors.blobs.DarkGas; +import com.hmdzl.spspd.actors.blobs.ParalyticGas; +import com.hmdzl.spspd.actors.blobs.ToxicGas; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Poison; +import com.hmdzl.spspd.actors.buffs.ShieldArmor; +import com.hmdzl.spspd.actors.buffs.Tar; +import com.hmdzl.spspd.effects.Pushing; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.items.TomeOfMastery; +import com.hmdzl.spspd.items.bombs.DangerousBomb; +import com.hmdzl.spspd.items.journalpages.Sokoban3; +import com.hmdzl.spspd.items.keys.SkeletonKey; +import com.hmdzl.spspd.items.potions.PotionOfExperience; +import com.hmdzl.spspd.levels.CavesBossLevel; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.Terrain; +import com.hmdzl.spspd.levels.features.Door; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.HybridSprite; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +import java.util.ArrayList; +import java.util.HashSet; + +public class Hybrid extends Mob { + + { + spriteClass = HybridSprite.class; + + HP = HT = 800; + evadeSkill = 10; + baseSpeed = 1.5f; + + EXP = 50; + + loot = Generator.Category.EGGS; + lootChance = 0.2f; + + lootOther = new PotionOfExperience(); + lootChanceOther = 1f; + + FLEEING = new Fleeing(); + + properties.add(Property.BEAST); + properties.add(Property.ALIEN); + properties.add(Property.UNDEAD); + properties.add(Property.MECH); + properties.add(Property.BOSS); + } + + private int breaks=0; + + @Override + public boolean act() { + DangerousBomb bomb = new DangerousBomb(); + if (3 - breaks > 4 * HP / HT) { + breaks++; + bomb.explode(pos); + Buff.affect(this,ShieldArmor.class).level(200); + return true; + } + + return super.act(); + } + + @Override + public void move(int step) { + super.move(step); + + if (Dungeon.level.map[step] == Terrain.INACTIVE_TRAP) { + if (state == FLEEING){ + Buff.affect(this,ShieldArmor.class).level(200); + yell(Messages.get(this, "shield")); + state = HUNTING; + } + + } + + } + + @Override + public int attackProc(Char enemy, int damage) { + if (Random.Int(5) == 0) { + Buff.affect(enemy, Poison.class).set( + Random.Int(7, 9) * Poison.durationFactor(enemy)); + state = FLEEING; + } + + + return damage; + } + + @Override + public int defenseProc(Char enemy, int damage) { + if (Random.Int(3) == 0) { + Buff.affect(enemy, Tar.class); + state = HUNTING; + } + return super.defenseProc(enemy, damage); + } + + + + @Override + public void damage(int dmg, Object src) { + if ( breaks > 2 && dmg > 5){ + ArrayList candidates = new ArrayList(); + boolean[] passable = Level.passable; + + int[] neighbours = { pos + 1, pos - 1, pos + Level.getWidth(), + pos - Level.getWidth() }; + for (int n : neighbours) { + if (passable[n] && Actor.findChar(n) == null) { + candidates.add(n); + } + } + + if (candidates.size() > 0) { + + Mixers clone = new Mixers(); + clone.HT = dmg; + clone.HP = dmg; + clone.pos = Random.element(candidates); + clone.state = clone.HUNTING; + + if (Dungeon.level.map[clone.pos] == Terrain.DOOR) { + Door.enter(clone.pos); + } + + GameScene.add(clone, 1f); + Actor.addDelayed(new Pushing(clone, pos, clone.pos), -1); + } + } + + super.damage(dmg, src); + } + + @Override + public void destroy() { + super.destroy(); + } + + @Override + protected boolean canAttack(Char enemy) { + return Dungeon.level.distance( pos, enemy.pos ) <= 2 ; + } + + @Override + public void die(Object cause) { + super.die(cause); + GameScene.bossSlain(); + ((CavesBossLevel) Dungeon.level).unseal(); + Dungeon.level.drop(new SkeletonKey(Dungeon.depth), pos).sprite.drop(); + Badges.validateBossSlain(); + + 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; + case PERFORMER: + badgeToCheck = Badge.MASTERY_PERFORMER; + break; + case SOLDIER: + badgeToCheck = Badge.MASTERY_SOLDIER; + break; + case FOLLOWER: + badgeToCheck = Badge.MASTERY_FOLLOWER; + break; + } + + Dungeon.level.drop(new TomeOfMastery(), pos).sprite.drop(); + Dungeon.level.drop(new Sokoban3(), pos).sprite.drop(); + yell(Messages.get(this,"die")); + + } + + @Override + public void notice() { + super.notice(); + yell(Messages.get(this, "notice")); + } + + @Override + public int damageRoll() { + return Dungeon.isChallenged(Challenges.TEST_TIME) ? Random.NormalIntRange(0, 1) : Random.NormalIntRange(30, 42); + } + + + + @Override + public int hitSkill(Char target) { + return 50; + } + + @Override + public int drRoll() { + return Random.NormalIntRange(10, 15); + } + + private static final String BREAKS = "breaks"; + + @Override + public void storeInBundle( Bundle bundle ) { + super.storeInBundle(bundle); + bundle.put( BREAKS, breaks ); + } + + @Override + public void restoreFromBundle( Bundle bundle ) { + super.restoreFromBundle(bundle); + breaks = bundle.getInt( BREAKS ); + } + + private static final HashSet> IMMUNITIES = new HashSet<>(); + static { + IMMUNITIES.add(ToxicGas.class ); + IMMUNITIES.add(ParalyticGas.class); + IMMUNITIES.add(DarkGas.class); + IMMUNITIES.add(ConfusionGas.class); + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } + + public static class Mixers extends Mob { + + { + spriteClass = HybridSprite.class; + + HP = HT = 1; + evadeSkill = 0; + baseSpeed = 1f; + properties.add(Property.UNKNOW); + properties.add(Property.BOSS); + } + + private static final float SPAWN_DELAY = 1f; + + @Override + public int damageRoll() { + return Random.NormalIntRange(25, 55 ); + } + + @Override + public int hitSkill(Char target) { + return 100; + } + + @Override + public int drRoll() { + return 0; + } + + public static Mixers spawnAt(int pos) { + + Mixers b = new Mixers(); + + b.pos = pos; + b.state = b.HUNTING; + GameScene.add(b, SPAWN_DELAY); + + return b; + + } + } + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/mobs/King.java b/java/com/hmdzl/spspd/actors/mobs/King.java new file mode 100644 index 00000000..4a4e93e3 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/King.java @@ -0,0 +1,473 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs; + +import java.util.HashSet; + +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.items.DolyaSlate; +import com.hmdzl.spspd.items.Gold; +import com.hmdzl.spspd.items.StoneOre; +import com.hmdzl.spspd.items.artifacts.ChaliceOfBlood; +import com.hmdzl.spspd.items.keys.SkeletonKey; +import com.hmdzl.spspd.items.scrolls.ScrollOfTeleportation; +import com.hmdzl.spspd.items.weapon.missiles.Skull; +import com.hmdzl.spspd.levels.Terrain; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.ToxicGas; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Paralysis; +import com.hmdzl.spspd.actors.buffs.Vertigo; +import com.hmdzl.spspd.effects.Flare; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.effects.particles.ElmoParticle; +import com.hmdzl.spspd.items.journalpages.Sokoban4; +import com.hmdzl.spspd.items.wands.WandOfDisintegration; +import com.hmdzl.spspd.items.weapon.enchantments.EnchantmentDark; +import com.hmdzl.spspd.levels.CityBossLevel; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.DwarfKingTombSprite; +import com.hmdzl.spspd.sprites.KingSprite; +import com.hmdzl.spspd.sprites.UndeadSprite; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.noosa.audio.Sample; +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; + private static final int REGEN = 3; + + + { + spriteClass = KingSprite.class; + + HP = HT = 1500; + EXP = 60; + evadeSkill = 25; + baseSpeed = 0.75f; + + loot = new ChaliceOfBlood().identify(); + lootChance = 0.2f; + + lootOther = new Skull(5); + lootChanceOther = 1f; + + properties.add(Property.DWARF); + properties.add(Property.BOSS); + + Undead.count = 0; + + } + + private boolean nextPedestal = true; + + private int tombAlive = 0; + private static final String TOMBALIVE = "tombAlive"; + private static final String PEDESTAL = "pedestal"; + + public void spawnTomb() { + DwarfKingTomb a = new DwarfKingTomb(); + + a.pos = Terrain.EMPTY_WELL; + do { + a.pos = Random.Int(Dungeon.level.randomRespawnCellMob()); + } while (Dungeon.level.map[a.pos] != Terrain.EMPTY_WELL + || Actor.findChar(a.pos) != null); + GameScene.add(a); + } + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(PEDESTAL, nextPedestal); + bundle.put( TOMBALIVE, tombAlive ); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + nextPedestal = bundle.getBoolean(PEDESTAL); + tombAlive = bundle.getInt( TOMBALIVE ); + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(20, 38); + } + + @Override + public int hitSkill(Char target) { + return 62; + } + + @Override + public int drRoll() { + return Random.NormalIntRange(0, 14); + } + + @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 + protected boolean act() { + + if (tombAlive < 1){ + spawnTomb(); + tombAlive++; + } + + if (HP < HT) { + sprite.emitter().burst( Speck.factory( Speck.HEALING ), 1 ); + HP = HP + REGEN; + } + + return super.act(); + } + + + private void summonLiches (int pos){ + DwarfLich.spawnAround(pos); + } + + @Override + public void die(Object cause) { + + int findTomb=Dungeon.hero.pos; + yell(Messages.get(this, "cannot")); + for (Mob mob : Dungeon.level.mobs) { + if (mob instanceof DwarfKingTomb){findTomb=mob.pos;} + } + + Dungeon.level.drop(new Sokoban4(), pos).sprite.drop(); + + if (!Dungeon.limitedDrops.journal.dropped()){ + Dungeon.level.drop(new DolyaSlate(), pos).sprite.drop(); + Dungeon.limitedDrops.journal.drop(); + } + + summonLiches(findTomb); + GLog.n(Messages.get(this, "liches")); + + super.die(cause); + + } + + 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.getLength(); j++) { + if (PathFinder.distance[j] == dist) { + + Undead undead = new Undead(); + undead.pos = j; + GameScene.add(undead); + + ScrollOfTeleportation.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(Messages.get(this, "arise")); + HP += Random.Int(1, HT - HP); + sprite.emitter().burst(ElmoParticle.FACTORY, 5); + } + + @Override + public void notice() { + super.notice(); + yell(Messages.get(this,"meeting")); + } + + private static final HashSet> RESISTANCES = new HashSet>(); + static { + RESISTANCES.add(ToxicGas.class); + RESISTANCES.add(EnchantmentDark.class); + + RESISTANCES.add(WandOfDisintegration.class); + } + + @Override + public HashSet> resistances() { + return RESISTANCES; + } + + private static final HashSet> IMMUNITIES = new HashSet>(); + static { + IMMUNITIES.add(Paralysis.class); + IMMUNITIES.add(Vertigo.class); + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } + + public static class Undead extends Mob { + + public static int count = 0; + + { + //name = "undead dwarf"; + spriteClass = UndeadSprite.class; + + HP = HT = 100; + evadeSkill = 15; + + EXP = 0; + + state = WANDERING; + + + properties.add(Property.UNDEAD); + properties.add(Property.BOSS); + } + + @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 hitSkill(Char target) { + return 49; + } + + @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 drRoll() { + return 5; + } + + private static final HashSet> IMMUNITIES = new HashSet>(); + static { + IMMUNITIES.add(EnchantmentDark.class); + IMMUNITIES.add(Paralysis.class); + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } + } + + public static class DwarfKingTomb extends Mob { + + { + spriteClass = DwarfKingTombSprite.class; + + HP = HT = 1000; + evadeSkill = 5; + + EXP = 10; + + hostile = false; + state = PASSIVE; + + loot = new StoneOre(); + lootChance = 0.05f; + + properties.add(Property.UNKNOW); + properties.add(Property.BOSS); + } + + @Override + public void beckon(int cell) { + // Do nothing + } + + @Override + public void add(Buff buff) { + } + + + @Override + public int damageRoll() { + return 0; + } + + @Override + public int hitSkill(Char target) { + return 0; + } + + @Override + public int drRoll() { + return 0; + + } + + + public boolean checkKing(){ + + int kingAlive=0; + if(Dungeon.level.mobs!=null){ + for (Mob mob : Dungeon.level.mobs) { + if (mob instanceof King){ + kingAlive++; + } + } + } + if (kingAlive>0){ + return true; + } else { + return false; + } + } + + @Override + public void damage(int dmg, Object src) { + if(checkKing()){ + yell(Messages.get(this , "impossible")); + } else { + super.damage(dmg, src); + } + } + + @SuppressWarnings("unchecked") + @Override + public void die(Object cause) { + + super.die(cause); + + for (Mob mob : (Iterable) Dungeon.level.mobs.clone()) { + if (mob instanceof DwarfLich || mob instanceof King || mob instanceof King.Undead || mob instanceof Wraith) { + mob.die(cause); + } + } + + GameScene.bossSlain(); + ((CityBossLevel) Dungeon.level).unseal(); + + Dungeon.level.drop(new SkeletonKey(Dungeon.depth), pos).sprite.drop(); + Dungeon.level.drop(new Gold(Random.Int(1000, 2000)), pos).sprite.drop(); + + Badges.validateBossSlain(); + + } + + +} +} diff --git a/java/com/hmdzl/spspd/actors/mobs/LevelChecker.java b/java/com/hmdzl/spspd/actors/mobs/LevelChecker.java new file mode 100644 index 00000000..ada79bd6 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/LevelChecker.java @@ -0,0 +1,81 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Taunt; +import com.hmdzl.spspd.sprites.RatSprite; + +public class LevelChecker extends Mob { + + { + spriteClass = RatSprite.class; + + HP = HT = Dungeon.hero.lvl*1000; + evadeSkill = Dungeon.hero.lvl*1000; + baseSpeed = 3f; + flying = true; + + state = WANDERING; + + properties.add(Property.BOSS); + } + + @Override + protected boolean getCloser(int target) { + return super.getCloser(Dungeon.hero.pos); + } + + @Override + public int damageRoll() { + return Dungeon.hero.lvl*1000; + } + + @Override + public int attackProc(Char enemy, int damage) { + if (enemy.buff(Taunt.class)== null && enemy == Dungeon.hero) { + Buff.affect(enemy, Taunt.class); + Dungeon.hero.exp=0; + Dungeon.hero.lvl=1; + + //Dungeon.hero.HT=30; + //Dungeon.hero.hitSkill=10; + //Dungeon.hero.evadeSkill=5; + damage = 0; + this.damage(this.HT*2,this); + return damage; + } else return damage; + } + + @Override + public int hitSkill(Char target) { + return Dungeon.hero.lvl*1000; + } + + @Override + public int drRoll() { + return Dungeon.hero.lvl*1000; + } + + @Override + public void add( Buff buff ) { + //in other words, can't be directly affected by buffs/debuffs. + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/LichDancer.java b/java/com/hmdzl/spspd/actors/mobs/LichDancer.java new file mode 100644 index 00000000..d097adc0 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/LichDancer.java @@ -0,0 +1,381 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs; + +import java.util.ArrayList; +import java.util.HashSet; + +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.items.DolyaSlate; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.items.Gold; +import com.hmdzl.spspd.items.StoneOre; +import com.hmdzl.spspd.items.artifacts.GlassTotem; +import com.hmdzl.spspd.items.bombs.DungeonBomb; +import com.hmdzl.spspd.items.keys.SkeletonKey; +import com.hmdzl.spspd.items.scrolls.ScrollOfTeleportation; +import com.hmdzl.spspd.levels.Terrain; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.ToxicGas; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Paralysis; +import com.hmdzl.spspd.actors.buffs.Vertigo; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.journalpages.Sokoban4; +import com.hmdzl.spspd.items.wands.WandOfDisintegration; +import com.hmdzl.spspd.items.weapon.enchantments.EnchantmentDark; +import com.hmdzl.spspd.levels.CityBossLevel; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.BatteryTombSprite; +import com.hmdzl.spspd.sprites.LichDancerSprite; +import com.hmdzl.spspd.sprites.SeekingBombSprite; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Bundle; +import com.watabou.utils.PathFinder; +import com.watabou.utils.Random; + +public class LichDancer extends Mob { + + private static final int MAX_ARMY_SIZE = 4; + + + { + spriteClass = LichDancerSprite.class; + + HP = HT = 1000; + EXP = 60; + evadeSkill = 25; + baseSpeed = 1f; + + loot = new GlassTotem().identify(); + lootChance = 0.2f; + + lootOther = Generator.Category.MUSICWEAPON; + lootChanceOther= 1f; + + properties.add(Property.UNDEAD); + properties.add(Property.BOSS); + + } + + private int breaks=0; + + public void spawnTomb() { + BatteryTomb a = new BatteryTomb(); + a.pos = Terrain.PEDESTAL; + do { + a.pos = Random.Int(Dungeon.level.randomRespawnCellMob()); + } while (Dungeon.level.map[a.pos] != Terrain.PEDESTAL + || Actor.findChar(a.pos) != null); + GameScene.add(a); + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(20, 38); + } + + @Override + public int hitSkill(Char target) { + return 65; + } + + @Override + public int drRoll() { + return Random.NormalIntRange(0, 20); + } + + @Override + protected boolean act() { + + if( 3 - breaks > 4 * HP / HT ) { + breaks++; + spawnTomb(); + jump(); + return true; + } + + if (Random.Int(5) == 0 && breaks > 0){ + ArrayList spawnPoints = new ArrayList<>(); + + for (int i = 0; i < PathFinder.NEIGHBOURS8.length; i++) { + int p = enemy.pos + PathFinder.NEIGHBOURS8[i]; + if (Actor.findChar( p ) == null && (Dungeon.level.passable[p] || Dungeon.level.avoid[p])) { + spawnPoints.add( p ); + } + } + + if (spawnPoints.size() > 0) { + Mob m = new LinkBomb(); + if (m != null) { + GameScene.add(m); + ScrollOfTeleportation.appear(m, Random.element(spawnPoints)); + } + } + } + + if (HP < HT) { + //sprite.emitter().burst( Speck.factory( Speck.HEALING ), 1 ); + HP = HP + 3; + } + + return super.act(); + } + + private void jump() { + int newPos; + do { + newPos = Random.Int(Level.getLength()); + } while (Dungeon.level.map[newPos] != Terrain.EMPTY_WELL); + 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 int attackProc(Char enemy, int damage) { + if (Random.Int(5) == 0) { + Buff.prolong(enemy, Vertigo.class,3f); + } + return damage; + } + + + + private static final String BREAKS = "breaks"; + + @Override + public void storeInBundle( Bundle bundle ) { + super.storeInBundle(bundle); + bundle.put( BREAKS, breaks ); + } + + @Override + public void restoreFromBundle( Bundle bundle ) { + super.restoreFromBundle(bundle); + breaks = bundle.getInt( BREAKS ); + } + + @Override + public void die(Object cause) { + + Dungeon.level.drop(new Sokoban4(), pos).sprite.drop(); + + if (!Dungeon.limitedDrops.journal.dropped()){ + Dungeon.level.drop(new DolyaSlate(), pos).sprite.drop(); + Dungeon.limitedDrops.journal.drop(); + } + + GameScene.bossSlain(); + ((CityBossLevel) Dungeon.level).unseal(); + + Dungeon.level.drop(new SkeletonKey(Dungeon.depth), pos).sprite.drop(); + Dungeon.level.drop(new Gold(Random.Int(1000, 2000)), pos).sprite.drop(); + + Badges.validateBossSlain(); + //summonLiches(findTomb); + //GLog.n(Messages.get(this, "liches")); + + super.die(cause); + + } + + private int maxArmySize() { + return 2; + } + + public boolean checkBattery() { + + int batteryAlive = 0; + if (Dungeon.level.mobs != null) { + for (Mob mob : Dungeon.level.mobs) { + if (mob instanceof BatteryTomb) { + batteryAlive++; + } + } + } + if (batteryAlive > 0) { + return true; + } else { + return false; + } + } + + @Override + public void damage(int dmg, Object src) { + if (checkBattery()) { + dmg = Random.Int(10); + //Buff.affect(this,ShieldArmor.class).level(100); + } + super.damage(dmg, src); + } + + @Override + public void notice() { + super.notice(); + yell(Messages.get(this,"notice")); + } + + private static final HashSet> RESISTANCES = new HashSet>(); + static { + RESISTANCES.add(ToxicGas.class); + RESISTANCES.add(EnchantmentDark.class); + + RESISTANCES.add(WandOfDisintegration.class); + } + + @Override + public HashSet> resistances() { + return RESISTANCES; + } + + private static final HashSet> IMMUNITIES = new HashSet>(); + static { + IMMUNITIES.add(Paralysis.class); + IMMUNITIES.add(Vertigo.class); + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } + + public static class BatteryTomb extends Mob { + + { + spriteClass = BatteryTombSprite.class; + + HP = HT = 200; + evadeSkill = 0; + + EXP = 10; + + hostile = false; + state = PASSIVE; + + loot = new StoneOre(); + lootChance = 0.05f; + + properties.add(Property.MECH); + properties.add(Property.BOSS); + } + + @Override + public boolean act() { + + if( Random.Int(20) == 0 && Dungeon.level.mobs.size()< 6) { + ManySkeleton.spawnAround(pos); + } + return super.act(); + } + + @Override + public void beckon(int cell) { + // Do nothing + } + + @Override + public void add(Buff buff) { + } + + + @Override + public int damageRoll() { + return 0; + } + + @Override + public int hitSkill(Char target) { + return 0; + } + + @Override + public int drRoll() { + return 0; + + } + + @Override + public void damage(int dmg, Object src) { + if ( dmg > 50 ) dmg = 50; + super.damage(dmg, src); + + } +} + public static class LinkBomb extends Mob { + { + spriteClass = SeekingBombSprite.class; + + HP = HT = 1; + evadeSkill = 0; + baseSpeed = 1f; + EXP = 0; + + state = PASSIVE; + + properties.add(Property.MECH); + properties.add(Property.MINIBOSS); + } + + private int bombtime=3; + private static final String BOMBTIME = "bombtime"; + + public void storeInBundle( Bundle bundle ) { + super.storeInBundle(bundle); + bundle.put( BOMBTIME, bombtime ); + } + + @Override + public void restoreFromBundle( Bundle bundle ) { + super.restoreFromBundle(bundle); + bombtime = bundle.getInt( BOMBTIME ); + } + + @Override + public int drRoll() { + return 0; + } + + @Override + public boolean act() { + yell(""+bombtime+"!"); + if (bombtime < 1){ + DungeonBomb bomb = new DungeonBomb(); + bomb.explode(pos); + yell("KA-BOOM!!!"); + destroy(); + sprite.die(); + } + bombtime --; + return super.act(); + } + + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/LitTower.java b/java/com/hmdzl/spspd/actors/mobs/LitTower.java new file mode 100644 index 00000000..cc7da20f --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/LitTower.java @@ -0,0 +1,198 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs; + +import java.util.HashSet; + +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.ConfusionGas; +import com.hmdzl.spspd.actors.blobs.ToxicGas; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Terror; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.particles.SparkParticle; +import com.hmdzl.spspd.items.RedDewdrop; +import com.hmdzl.spspd.items.weapon.enchantments.EnchantmentDark; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.traps.LightningTrap; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.sprites.OtiluckStoneSprite; + +import com.watabou.noosa.Camera; +import com.watabou.utils.Callback; +import com.watabou.utils.Random; + +public class LitTower 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..."; + + { + spriteClass = OtiluckStoneSprite.class; + + HP = HT = 600; + evadeSkill = 1000; + + EXP = 25; + + hostile = false; + state = PASSIVE; + + loot = new RedDewdrop(); + lootChance = 1f; + + properties.add(Property.MECH); + properties.add(Property.BOSS); + } + + @Override + public void beckon(int cell) { + // Do nothing + } + + @Override + public int damageRoll() { + return 0; + } + + + @Override + public int hitSkill(Char target) { + return 100; + } + + @Override + public int drRoll() { + return 1000; + } + + + @Override + public void damage(int dmg, Object src) { + } + + @Override + protected boolean act() { + if(Level.distance(pos, Dungeon.hero.pos)<5 && Dungeon.hero.isAlive() && checkOtiluke()){ + zapAll(Dungeon.hero.pos); + } + return super.act(); + } + + @Override + public void call() { + next(); + } + + protected boolean checkOtiluke(){ + boolean check = false; + + for (Mob mob : Dungeon.level.mobs) { + if (mob instanceof Otiluke) { + check=true; + } + } + return check; + } + + + protected boolean heroNear (){ + boolean check=false; + for (int i : Level.NEIGHBOURS9DIST2){ + int cell=pos+i; + if (Actor.findChar(cell) != null + && (Actor.findChar(cell) instanceof Hero) + ){ + check=true; + } + } + return check; + } + + + @Override + protected boolean canAttack(Char enemy) { + return new Ballistica( pos, enemy.pos, Ballistica.MAGIC_BOLT).collisionPos == enemy.pos; + } + + @Override + protected boolean doAttack(Char enemy) { + return false; + } + + + public void zapAll(int loc){ + + yell(Messages.get(this,"zap")); + + Char hero=Dungeon.hero; + + int mobDmg=Random.Int(200, 300); + + + boolean visible = Level.fieldOfView[pos] || Level.fieldOfView[loc]; + + + if (visible) { + ((OtiluckStoneSprite) sprite).zap(loc); + } + + + hero.damage(mobDmg, this); + + hero.sprite.centerEmitter().burst(SparkParticle.FACTORY, 3); + hero.sprite.flash(); + + Camera.main.shake(2, 0.3f); + } + + @Override + public void add(Buff buff) { + } + + + private static final HashSet> RESISTANCES = new HashSet>(); + static { + RESISTANCES.add(EnchantmentDark.class); + + RESISTANCES.add(LightningTrap.Electricity.class); + } + + @Override + public HashSet> resistances() { + return RESISTANCES; + } + + private static final HashSet> IMMUNITIES = new HashSet>(); + static { + IMMUNITIES.add(ToxicGas.class); + IMMUNITIES.add(Terror.class); + IMMUNITIES.add(ConfusionGas.class); + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } + + +} diff --git a/java/com/hmdzl/spspd/actors/mobs/LiveMoss.java b/java/com/hmdzl/spspd/actors/mobs/LiveMoss.java new file mode 100644 index 00000000..3b9b29b7 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/LiveMoss.java @@ -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 + */ +package com.hmdzl.spspd.actors.mobs; + +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.GrowSeed; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.sprites.LiveMossSprite; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public class LiveMoss extends Mob { + + private boolean liveseed = false; + + { + spriteClass = LiveMossSprite.class; + + HP = HT = 50+(adj(0)*Random.NormalIntRange(1, 3)); + evadeSkill = 5+adj(1); + + EXP = 5; + maxLvl = 9; + + loot = Generator.random(Generator.Category.MUSHROOM); + lootChance = 0.2f; + + properties.add(Property.PLANT); + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(3, 6+adj(0)); + } + + @Override + public int hitSkill(Char target) { + return 12+adj(0); + } + + @Override + public int drRoll() { + return Random.NormalIntRange(0, 4); + } + + @Override + public int attackProc(Char enemy, int damage) { + if (Random.Int(3) == 0 && !liveseed) { + Buff.affect(enemy, GrowSeed.class).reignite(enemy); + liveseed=true; + } + + return damage; + } + + private final String LIVESEED = "liveseed"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(LIVESEED, liveseed); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + liveseed = bundle.getBoolean(LIVESEED); + } + +} diff --git a/java/com/hmdzl/spspd/actors/mobs/MagicEye.java b/java/com/hmdzl/spspd/actors/mobs/MagicEye.java new file mode 100644 index 00000000..b2e526ff --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/MagicEye.java @@ -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 + */ +package com.hmdzl.spspd.actors.mobs; + +import java.util.HashSet; + +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.ResultDescriptions; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Light; +import com.hmdzl.spspd.actors.buffs.Terror; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.particles.PurpleParticle; +import com.hmdzl.spspd.items.potions.PotionOfMending; +import com.hmdzl.spspd.items.wands.WandOfDisintegration; +import com.hmdzl.spspd.items.weapon.enchantments.EnchantmentDark; + +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.CharSprite; +import com.hmdzl.spspd.sprites.MagicEyeSprite; + +import com.watabou.noosa.tweeners.AlphaTweener; +import com.watabou.utils.Random; + +public class MagicEye extends Mob { + + private static final String TXT_DEATHGAZE_KILLED = "%s's deathgaze killed you..."; + protected static final float SPAWN_DELAY = 2f; + + { + spriteClass = MagicEyeSprite.class; + + HP = HT = 100+(adj(0)*Random.NormalIntRange(4, 7)); + evadeSkill = 40+adj(1); + viewDistance = Light.DISTANCE; + + EXP = 16; + + flying = true; + + loot = new PotionOfMending(); + lootChance = 0.05f; + + properties.add(Property.DEMONIC); + properties.add(Property.ELEMENT); + } + + private Ballistica beam; + + @Override + public int drRoll() { + return Random.NormalIntRange(0, 20); + } + + @Override + protected boolean canAttack(Char enemy) { + + beam = new Ballistica( pos, enemy.pos, Ballistica.STOP_TERRAIN); + + return beam.subPath(1, beam.dist).contains(enemy.pos); + } + + @Override + public int hitSkill(Char target) { + return 30+adj(0); + } + + @Override + protected float attackDelay() { + return 2f; + } + + @Override + protected boolean doAttack(Char enemy) { + + spend(attackDelay()); + + boolean rayVisible = false; + + for (int i : beam.subPath(0, beam.dist)) { + if (Dungeon.visible[i]) { + rayVisible = true; + } + } + + if (rayVisible) { + sprite.attack( beam.collisionPos ); + return false; + } else { + attack( enemy ); + return true; + } + } + + @Override + public boolean attack(Char enemy) { + + for (int pos : beam.subPath(1, beam.dist)) { + + Char ch = Actor.findChar(pos); + if (ch == null) { + continue; + } + + if (hit(this, ch, true)) { + ch.damage(Random.NormalIntRange(50, 100), this); + damage(Random.NormalIntRange(50, 100), 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( Messages.format(ResultDescriptions.MOB)); + //GLog.n(Messages.get(this, "kill")); + } + } else { + ch.sprite.showStatus(CharSprite.NEUTRAL, ch.defenseVerb()); + } + } + + return true; + } + + public static void spawnAroundChance(int pos) { + for (int n : Level.NEIGHBOURS4) { + int cell = pos + n; + if (Level.passable[cell] && Actor.findChar(cell) == null && Random.Float()<0.50f) { + spawnAt(cell); + } + } + } + + public static MagicEye spawnAt(int pos) { + if (Level.passable[pos] && Actor.findChar(pos) == null) { + + MagicEye e = new MagicEye(); + e.pos = pos; + e.state = e.HUNTING; + GameScene.add(e, SPAWN_DELAY); + + e.sprite.alpha(0); + e.sprite.parent.add(new AlphaTweener(e.sprite, 1, 0.5f)); + + return e; + + } else { + return null; + } + } + + private static final HashSet> RESISTANCES = new HashSet>(); + static { + RESISTANCES.add(WandOfDisintegration.class); + RESISTANCES.add(EnchantmentDark.class); + + } + + @Override + public HashSet> resistances() { + return RESISTANCES; + } + + private static final HashSet> IMMUNITIES = new HashSet>(); + static { + IMMUNITIES.add(Terror.class); + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/ManySkeleton.java b/java/com/hmdzl/spspd/actors/mobs/ManySkeleton.java new file mode 100644 index 00000000..a3ebac44 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/ManySkeleton.java @@ -0,0 +1,143 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.effects.Pushing; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.Terrain; +import com.hmdzl.spspd.levels.features.Door; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ManySkeletonSprite; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public class ManySkeleton extends Mob { + + { + spriteClass = ManySkeletonSprite.class; + + HP = HT = 100; + evadeSkill = 5; + + EXP = 10; + maxLvl = 30; + + flying = true; + + properties.add(Property.UNDEAD); + } + + 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(4, 7); + } + + @Override + public int defenseProc(Char enemy, int damage) { + + if (HP >= damage + 2) { + ArrayList candidates = new ArrayList(); + boolean[] passable = Level.passable; + + int[] neighbours = { pos + 1, pos - 1, pos + Level.getWidth(), + pos - Level.getWidth() }; + for (int n : neighbours) { + if (passable[n] && Actor.findChar(n) == null) { + candidates.add(n); + } + } + + if (candidates.size() > 0) { + + SommonSkeleton clone = new SommonSkeleton(); + clone.HP = (HP - damage) / 2; + clone.pos = Random.element(candidates); + clone.state = clone.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 hitSkill(Char target) { + return 30+adj(01); + } + + @Override + public void die(Object cause) { + Skeleton.spawnAround(this.pos); + super.die(cause); + } + + 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 ManySkeleton spawnAt(int pos) { + if (Level.passable[pos] && Actor.findChar(pos) == null) { + + ManySkeleton w = new ManySkeleton(); + w.pos = pos; + w.state = w.HUNTING; + GameScene.add(w, 1f); + return w; + + } else { + return null; + } + } + +} diff --git a/java/com/hmdzl/spspd/actors/mobs/Mimic.java b/java/com/hmdzl/spspd/actors/mobs/Mimic.java new file mode 100644 index 00000000..7fa1ab5e --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/Mimic.java @@ -0,0 +1,169 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 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 + */ +package com.hmdzl.spspd.actors.mobs; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.Pushing; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.scrolls.ScrollOfPsionicBlast; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.MimicSprite; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public class Mimic extends Mob { + + private int level; + + { + spriteClass = MimicSprite.class; + + properties.add(Property.UNKNOW); + } + + public ArrayList items; + + private static final String LEVEL = "level"; + private static final String ITEMS = "items"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(ITEMS, items); + bundle.put(LEVEL, level); + } + + @SuppressWarnings("unchecked") + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + items = new ArrayList( + (Collection) ((Collection) bundle.getCollection(ITEMS))); + adjustStats(bundle.getInt(LEVEL)); + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(HT/20, HT/10); + } + + @Override + public int hitSkill(Char target) { + return 9 + level; + } + + @Override + public int attackProc(Char enemy, int damage) { + return super.attackProc(enemy, damage); + } + + public void adjustStats(int level) { + this.level = level; + + HT = (30 + level) * 4; + EXP = 2 + 2 * (level - 1) / 5; + evadeSkill = hitSkill(null) / 2; + + enemySeen = true; + } + + @Override + public void die(Object cause) { + + super.die(cause); + + if (items != null) { + for (Item item : items) { + Dungeon.level.drop(item, pos).sprite.drop(); + } + } + } + + @Override + public boolean reset() { + state = WANDERING; + return true; + } + + public static Mimic spawnAt(int pos, List items) { + Char ch = Actor.findChar(pos); + if (ch != null) { + ArrayList candidates = new ArrayList(); + for (int n : Level.NEIGHBOURS8) { + int cell = pos + n; + if ((Level.passable[cell] || Level.avoid[cell]) + && Actor.findChar(cell) == null) { + candidates.add(cell); + } + } + if (candidates.size() > 0) { + int newPos = Random.element(candidates); + Actor.addDelayed(new Pushing(ch, ch.pos, newPos), -1); + + ch.pos = newPos; + // FIXME + if (ch instanceof Mob) { + Dungeon.level.mobPress((Mob) ch); + } else { + Dungeon.level.press(newPos, ch); + } + } else { + return null; + } + } + + Mimic m = new Mimic(); + m.items = new ArrayList(items); + m.adjustStats(Dungeon.depth); + m.HP = m.HT; + m.pos = pos; + m.state = m.HUNTING; + GameScene.add(m, 1); + + m.sprite.turnTo(pos, Dungeon.hero.pos); + + if (Dungeon.visible[m.pos]) { + CellEmitter.get(pos).burst(Speck.factory(Speck.STAR), 10); + Sample.INSTANCE.play(Assets.SND_MIMIC); + } + + return m; + } + + private static final HashSet> IMMUNITIES = new HashSet>(); + static { + IMMUNITIES.add(ScrollOfPsionicBlast.class); + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/MineSentinel.java b/java/com/hmdzl/spspd/actors/mobs/MineSentinel.java new file mode 100644 index 00000000..fed65928 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/MineSentinel.java @@ -0,0 +1,264 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs; + +import java.util.ArrayList; +import java.util.HashSet; + +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.ToxicGas; +import com.hmdzl.spspd.actors.buffs.Amok; +import com.hmdzl.spspd.actors.buffs.Burning; +import com.hmdzl.spspd.actors.buffs.Charm; +import com.hmdzl.spspd.actors.buffs.Poison; +import com.hmdzl.spspd.actors.buffs.Sleep; +import com.hmdzl.spspd.actors.buffs.Terror; +import com.hmdzl.spspd.actors.buffs.Vertigo; +import com.hmdzl.spspd.actors.buffs.Paralysis; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.items.scrolls.ScrollOfPsionicBlast; +import com.hmdzl.spspd.items.weapon.Weapon; +import com.hmdzl.spspd.items.weapon.Weapon.Enchantment; +import com.hmdzl.spspd.items.weapon.enchantments.EnchantmentDark; + +import com.hmdzl.spspd.items.weapon.melee.MeleeWeapon; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.sprites.SentinelSprite; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public class MineSentinel extends Mob { + + + { + spriteClass = SentinelSprite.class; + + EXP = 25; + state = PASSIVE; + + properties.add(Property.MECH); + } + private static final int REGENERATION = 100; + + private Weapon weapon; + + public MineSentinel() { + super(); + + do { + weapon = (Weapon) Generator.random(Generator.Category.OLDWEAPON); + } while (!(weapon instanceof MeleeWeapon) || weapon.level < 0); + + weapon.identify(); + weapon.enchant(Enchantment.randomLow()); + weapon.upgrade(10); + + + HP = HT = 400 + Dungeon.depth * 10; + //HP = HT = 5; + evadeSkill = 15; + //evadeSkill = 2; + } + + 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() { + + Hero hero = Dungeon.hero; + ArrayList spawnPoints = new ArrayList(); + + + if(state==HUNTING){ + for (int i = 0; i < Level.NEIGHBOURS8.length; i++) { + int p = pos + Level.NEIGHBOURS8[i]; + Char ch = Actor.findChar(p); + if (ch != null && ch instanceof MineSentinel && Random.Int(10)<2) { + ch.damage(1, this); + if (((Mob)ch).state==PASSIVE){ + ((Mob)ch).state = HUNTING; + } + break; + } + } + + } + + if (!heroNear() && Random.Float() < 0.50f && state==HUNTING){ + for (int i = 0; i < Level.NEIGHBOURS8.length; i++) { + int p = hero.pos + Level.NEIGHBOURS8[i]; + if (Actor.findChar(p) == null + && (Level.passable[p] || Level.avoid[p])) { + spawnPoints.add(p); + } + } + + if (spawnPoints.size() > 0) { + int newPos; + newPos=Random.element(spawnPoints); + 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 { + + if (HP<(HT/4) && Random.Float() < 0.50f && state!=PASSIVE){ + int newPos = -1; + for (int i = 0; i < 20; i++) { + newPos = Dungeon.level.randomRespawnCellMob(); + 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]; + HP += REGENERATION; + } + + } + } + return super.act(); + } + + protected boolean heroNear (){ + boolean check=false; + for (int i : Level.NEIGHBOURS9DIST2){ + int cell=pos+i; + if (Actor.findChar(cell) != null + && (Actor.findChar(cell) instanceof Hero) + ){ + check=true; + } + } + return check; + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(weapon.MIN, weapon.MAX); + } + + @Override + public int hitSkill(Char target) { + return (int) ((30 + Dungeon.depth*2) * weapon.ACU); + } + + @Override + protected float attackDelay() { + return weapon.DLY; + } + + @Override + public int drRoll() { + //return Dungeon.depth*3; + return Random.NormalIntRange(3, 30); + } + + @Override + public void damage(int dmg, Object src) { + + if (state == PASSIVE) { + 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) { + // Do nothing + } + + @Override + public void die(Object cause) { + super.die(cause); + Dungeon.level.drop(weapon, pos).sprite.drop(); + } + + @Override + public boolean reset() { + state = PASSIVE; + return true; + } + + @Override + public String description() { + return Messages.get(this, "desc", weapon.name()); + } + + private static final HashSet> RESISTANCES = new HashSet>(); + private static final HashSet> IMMUNITIES = new HashSet>(); + static { + RESISTANCES.add(ToxicGas.class); + RESISTANCES.add(Poison.class); + RESISTANCES.add(EnchantmentDark.class); + + IMMUNITIES.add(EnchantmentDark.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); + IMMUNITIES.add(Vertigo.class); + IMMUNITIES.add(Paralysis.class); + } + + @Override + public HashSet> resistances() { + return RESISTANCES; + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/Mob.java b/java/com/hmdzl/spspd/actors/mobs/Mob.java new file mode 100644 index 00000000..d04da17a --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/Mob.java @@ -0,0 +1,1059 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs; + +import java.util.ArrayList; +import java.util.HashSet; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.Challenges; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.Statistics; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.AflyBless; +import com.hmdzl.spspd.actors.buffs.Amok; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Corruption; +import com.hmdzl.spspd.actors.buffs.Dewcharge; +import com.hmdzl.spspd.actors.buffs.Disarm; +import com.hmdzl.spspd.actors.buffs.Feed; +import com.hmdzl.spspd.actors.buffs.Hunger; +import com.hmdzl.spspd.actors.buffs.Rhythm; +import com.hmdzl.spspd.actors.buffs.Rhythm2; +import com.hmdzl.spspd.actors.buffs.Sleep; +import com.hmdzl.spspd.actors.buffs.SoulMark; +import com.hmdzl.spspd.actors.buffs.SpAttack; +import com.hmdzl.spspd.actors.buffs.Terror; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.hero.HeroClass; +import com.hmdzl.spspd.actors.hero.HeroSubClass; +import com.hmdzl.spspd.actors.mobs.npcs.NPC; +import com.hmdzl.spspd.effects.Pushing; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.effects.Surprise; +import com.hmdzl.spspd.effects.Wound; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.RedDewdrop; +import com.hmdzl.spspd.items.VioletDewdrop; +import com.hmdzl.spspd.items.YellowDewdrop; +import com.hmdzl.spspd.items.artifacts.TimekeepersHourglass; +import com.hmdzl.spspd.items.misc.LuckyBadge; +import com.hmdzl.spspd.items.misc.Shovel; +import com.hmdzl.spspd.items.rings.RingOfAccuracy; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.Level.Feeling; +import com.hmdzl.spspd.levels.Terrain; +import com.hmdzl.spspd.levels.features.Door; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.CharSprite; +import com.hmdzl.spspd.utils.GLog; + +import com.hmdzl.spspd.messages.Messages; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public abstract class Mob extends Char { + + { + name = Messages.get(this, "name"); + } + + 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 AiState SLEEPING = new Sleeping(); + public AiState HUNTING = new Hunting(); + public AiState WANDERING = new Wandering(); + public AiState FLEEING = new Fleeing(); + public AiState PASSIVE = new Passive(); + public AiState state = SLEEPING; + + public Class spriteClass; + + protected int target = -1; + + protected int evadeSkill = 0; + + //public int EXP = 1; + protected int EXP = 1; + //public int maxLvl = 100; + protected int maxLvl = 100; + protected int dewLvl = 1; + + protected Char enemy; + protected boolean enemySeen; + protected boolean alerted = false; + + protected static final float TIME_TO_WAKE_UP = 1f; + + public boolean hostile = true; + public boolean ally = false; + public boolean originalgen = false; + + private static final String STATE = "state"; + private static final String SEEN = "seen"; + private static final String TARGET = "target"; + private static final String ORIGINAL = "originalgen"; + + public int getExp(){ + return EXP; + } + + @Override + public void storeInBundle(Bundle bundle) { + + super.storeInBundle(bundle); + + if (state == SLEEPING) { + bundle.put(STATE, Sleeping.TAG); + } else if (state == WANDERING) { + bundle.put(STATE, Wandering.TAG); + } else if (state == HUNTING) { + bundle.put(STATE, Hunting.TAG); + } else if (state == FLEEING) { + bundle.put(STATE, Fleeing.TAG); + } else if (state == PASSIVE) { + bundle.put(STATE, Passive.TAG); + } + bundle.put(SEEN, enemySeen); + bundle.put(TARGET, target); + bundle.put(ORIGINAL, originalgen); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + + super.restoreFromBundle(bundle); + + String state = bundle.getString(STATE); + if (state.equals(Sleeping.TAG)) { + this.state = SLEEPING; + } else if (state.equals(Wandering.TAG)) { + this.state = WANDERING; + } else if (state.equals(Hunting.TAG)) { + this.state = HUNTING; + } else if (state.equals(Fleeing.TAG)) { + this.state = FLEEING; + } else if (state.equals(Passive.TAG)) { + this.state = PASSIVE; + } + + enemySeen = bundle.getBoolean(SEEN); + + target = bundle.getInt(TARGET); + + originalgen = bundle.getBoolean(ORIGINAL); + } + + public CharSprite sprite() { + CharSprite sprite = null; + try { + sprite = spriteClass.newInstance(); + } catch (Exception e) { + } + return sprite; + } + + @Override + protected boolean act() { + + super.act(); + + boolean justAlerted = alerted; + alerted = false; + + //sprite.hideAlert(); + if (justAlerted){ + sprite.showAlert(); + } else { + sprite.hideAlert(); + sprite.hideLost(); + } + + + if (paralysed > 0) { + enemySeen = false; + spend(TICK); + return true; + } + + enemy = chooseEnemy(); + + if (!(this instanceof NPC)){ + if (enemy != null) { + ArrayList candidates = new ArrayList(); + for (int n : Level.NEIGHBOURS8) { + int cell = enemy.pos + n; + if ((Level.passable[cell] || Level.avoid[cell])) { + candidates.add(cell); + } + } + if (candidates.size() > 0 && this.pos == enemy.pos) { + int newPos = Random.element(candidates); + Actor.addDelayed(new Pushing(enemy, enemy.pos, newPos), -1); + enemy.pos = newPos; + } + } + } + boolean enemyInFOV = enemy != null && enemy.isAlive() + && Level.fieldOfView[enemy.pos] && enemy.invisible<=0 ; + + return state.act(enemyInFOV, justAlerted); + + } + + protected Char chooseEnemy() { + + Terror terror = buff( Terror.class ); + if (terror != null) { + Char source = (Char)Actor.findById( terror.object ); + if (source != null) { + return source; + } + } + + //find a new enemy if.. + boolean newEnemy = false; + //we have no enemy, or the current one is dead + if ( enemy == null || !enemy.isAlive() || state == WANDERING) + newEnemy = true; + //We are corrupted, and current enemy is either the hero or another corrupted character. + else if (buff(Corruption.class) != null && (enemy == Dungeon.hero || enemy.buff(Corruption.class) != null)) + newEnemy = true; + //We are amoked and current enemy is the hero + else if (buff( Amok.class ) != null && enemy == Dungeon.hero) + newEnemy = true; + + if ( newEnemy ) { + + HashSet enemies = new HashSet<>(); + + //if the mob is corrupted... + if ( buff(Corruption.class) != null) { + + //look for enemy mobs to attack, which are also not corrupted + for (Mob mob : Dungeon.level.mobs) + if (mob != this && Level.fieldOfView[mob.pos] && mob.hostile && mob.buff(Corruption.class) == null) + enemies.add(mob); + if (enemies.size() > 0) return Random.element(enemies); + + //otherwise go for nothing + return this; + + //if the mob is amoked... + } else if ( buff(Amok.class) != null) { + + //try to find an enemy mob to attack first. + for (Mob mob : Dungeon.level.mobs) + if (mob != this && Level.fieldOfView[mob.pos] && mob.hostile) + enemies.add(mob); + if (enemies.size() > 0) return Random.element(enemies); + + //try to find ally mobs to attack second. + for (Mob mob : Dungeon.level.mobs) + if (mob != this && Level.fieldOfView[mob.pos] && mob.ally) + enemies.add(mob); + if (enemies.size() > 0) return Random.element(enemies); + + //if there is nothing, go for the hero + else return Dungeon.hero; + + } else { + + //try to find ally mobs to attack. + for (Mob mob : Dungeon.level.mobs) + if (mob != this && Level.fieldOfView[mob.pos] && mob.ally) + enemies.add(mob); + + //and add the hero to the list of targets. + enemies.add(Dungeon.hero); + + //go after the closest enemy, preferring the hero if two are equidistant + // Char closest = null; + //for (Char curr : enemies){ + //if (closest == null + // || Dungeon.level.distance(pos, curr.pos) < Dungeon.level.distance(pos, closest.pos) + // || Dungeon.level.distance(pos, curr.pos) == Dungeon.level.distance(pos, closest.pos) && curr == Dungeon.hero){ + //closest = curr; + //} + //} + //return closest; + return Random.element(enemies); + + } + + } else + return enemy; + + // resets target if: the target is dead, the target has been lost + // (wandering) + // or if the mob is amoked and targeting the hero (will try to target + // something else) + /*if (enemy != null && !enemy.isAlive() || state == WANDERING + || (buff(Amok.class) != null && enemy == Dungeon.hero) + || (buff(Corruption.class) != null && enemy == Dungeon.hero)) + enemy = null; + // if there is no current target, find a new one. + if (enemy == null) { + HashSet enemies = new HashSet(); + // if the mob is amoked... + if (buff(Amok.class) != null) { + // try to find an enemy mob to attack first. + for (Mob mob : Dungeon.level.mobs) + if (mob != this && Level.fieldOfView[mob.pos] + && mob.hostile) + enemies.add(mob); + if (enemies.size() > 0) + return Random.element(enemies); + // try to find ally mobs to attack second. + for (Mob mob : Dungeon.level.mobs) + if (mob != this && Level.fieldOfView[mob.pos] && mob.ally) + enemies.add(mob); + if (enemies.size() > 0) + return Random.element(enemies); + + // if there is nothing, go for the hero. + return Dungeon.hero; + + // if the mob is Corruption... + } else if (buff(Corruption.class) != null) { + // try to find an enemy mob to attack first. + for (Mob mob : Dungeon.level.mobs) + if (mob != this && Level.fieldOfView[mob.pos] + && mob.hostile) + enemies.add(mob); + if (enemies.size() > 0) + return Random.element(enemies); + + // try to find ally mobs to attack second. + for (Mob mob : Dungeon.level.mobs) + if (mob != this && Level.fieldOfView[mob.pos] && !mob.ally) + enemies.add(mob); + if (enemies.size() > 0) + return Random.element(enemies); + + // if there is nothing, go for the itself. + return null; + // if the mob is not amoked... + } else { + // try to find ally mobs to attack. + for (Mob mob : Dungeon.level.mobs) + if (mob != this && Level.fieldOfView[mob.pos] && mob.ally) + enemies.add(mob); + // and add the hero to the list of targets. + enemies.add(Dungeon.hero); + // target one at random. + return Random.element(enemies); + + } + + } else + return enemy; + */ + + } + + protected boolean moveSprite(int from, int to) { + + if (sprite.isVisible() + && (Dungeon.visible[from] || Dungeon.visible[to])) { + sprite.move(from, to); + return true; + } 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, Messages.get(this, "rage")); + } + state = HUNTING; + } else if (buff instanceof Terror) { + state = FLEEING; + } else if (buff instanceof Sleep) { + state = SLEEPING; + this.sprite().showSleep(); + postpone(Sleep.SWS); + } + } + + @Override + public void remove(Buff buff) { + super.remove(buff); + if (buff instanceof Terror) { + sprite.showStatus(CharSprite.NEGATIVE,Messages.get(this, "rage")); + state = HUNTING; + } + } + + protected boolean canAttack(Char enemy) { + return Level.adjacent(pos, enemy.pos) && (!isCharmedBy(enemy) && (buff(Disarm.class) == null)); + } + + 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 updateSpriteState() { + super.updateSpriteState(); + if (Dungeon.hero.buff(TimekeepersHourglass.timeFreeze.class) != null) + sprite.add(CharSprite.State.PARALYSED); + } + + @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 evadeSkill(Char enemy) { + if (enemySeen && (paralysed == 0)) { + int evadeSkill = this.evadeSkill; + int penalty = 0; + for (Buff buff : enemy.buffs(RingOfAccuracy.Accuracy.class)) { + penalty += ((RingOfAccuracy.Accuracy) buff).level; + } + if (penalty != 0 && enemy == Dungeon.hero) + evadeSkill *= Math.pow(0.75, penalty); + return evadeSkill; + } else { + return 0; + } + } + + @Override + public int drRoll() { + return 0; + } + + @Override + public int defenseProc(Char enemy, int damage) { + if (!enemySeen && enemy == Dungeon.hero) { + if (((Hero)enemy).subClass == HeroSubClass.ASSASSIN) { + damage *= 1.5f; + Wound.hit(this); + } else { + Surprise.hit(this); + } + } + + SpAttack spatk = enemy.buff(SpAttack.class); + + if (HP == HT && spatk != null) { + damage *= 3f; + } + + if (HP < HT/4 && spatk != null) { + damage *= 1.5f; + } + + if (buff(SoulMark.class) != null) { + int restoration = Math.max(damage, HP); + Dungeon.hero.buff(Hunger.class).satisfy(restoration*0.5f); + Dungeon.hero.HP = (int)Math.ceil(Math.min(Dungeon.hero.HT, Dungeon.hero.HP+(restoration*0.25f))); + Dungeon.hero.sprite.emitter().burst( Speck.factory(Speck.HEALING), 1 ); + } + + return damage; + } + + public void aggro(Char ch) { + enemy = ch; + if (state != PASSIVE){ + state = HUNTING; + } + } + + public int adj(int type){ + + int adjustment; + + if (type == 0){ + adjustment = Dungeon.depth; + } else if (type == 1){ + adjustment = (int) Dungeon.depth/2; + } else if (type == 2){ + adjustment = (int) Dungeon.depth/4; + } else if (type == 3){ + adjustment = (int) Dungeon.depth*2; + } else adjustment = 1; + + return adjustment; + } + + @Override + public void damage(int dmg, Object src) { + + Terror.recover(this); + + if (state == SLEEPING) { + state = WANDERING; + } + + if (state != HUNTING) { + alerted = true; + } + //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.level.feeling == Feeling.DARK) { + Statistics.nightHunt++; + } else { + Statistics.nightHunt = 0; + } + Badges.validateNightHunter(); + + } + + if(Dungeon.hero.heroClass == HeroClass.PERFORMER){ + Buff.affect(Dungeon.hero,Rhythm.class,10); + + Shovel shovel = Dungeon.hero.belongings.getItem(Shovel.class); + if (shovel!=null && shovel.charge 0) { + Dungeon.hero.sprite.showStatus(CharSprite.POSITIVE, Messages.get(this, "exp", EXP)); + Dungeon.hero.earnExp(EXP); + } else if (EXP > 0) { + EXP = 1; + Dungeon.hero.sprite.showStatus(CharSprite.POSITIVE, Messages.get(this, "exp", EXP)); + Dungeon.hero.earnExp(EXP); + } + } + } + + public boolean checkOriginalGenMobs (){ + for (Mob mob : Dungeon.level.mobs.toArray(new Mob[0])) { + if (mob.originalgen){return true;} + } + return false; + } + + @Override + public void die(Object cause) { + + super.die(cause); + + int generation=0; + + if(this instanceof Swarm){ + Swarm swarm = (Swarm) this; + generation=swarm.generation; + } + + if(this instanceof Virus){ + Virus virus = (Virus) this; + generation=virus.generation; + } + + if(this instanceof SandMob.MiniSand){ + SandMob.MiniSand mnsand = (SandMob.MiniSand) this; + generation=mnsand.generation; + } + + if (Dungeon.hero.buff(Dewcharge.class) != null && generation==0) { + explodeDewHigh(pos); + } + + if (!Dungeon.level.cleared && originalgen && !checkOriginalGenMobs() && Dungeon.depth>2 + && Dungeon.depth<25 && !Dungeon.bossLevel(Dungeon.depth) && (Dungeon.dewDraw || Dungeon.dewWater)){ + Dungeon.level.cleared=true; + GameScene.levelCleared(); + if(Dungeon.depth>0){Statistics.prevfloormoves=Math.max(Dungeon.pars[Dungeon.depth]-Dungeon.level.currentmoves,0); + if (Statistics.prevfloormoves>1){ + GLog.h(Messages.get(this, "clear1"), Statistics.prevfloormoves); + } else if (Statistics.prevfloormoves==1){ + GLog.h(Messages.get(this, "clear2")); + } else if (Statistics.prevfloormoves==0){ + GLog.h(Messages.get(this, "clear3")); + } + } + } + + float lootChance = this.lootChance; + float lootChanceOther = this.lootChanceOther; + int bonus = 0; + for (Buff buff : Dungeon.hero.buffs(LuckyBadge.GreatLucky.class)) { + bonus += ((LuckyBadge.GreatLucky) buff).level; + } + if (Dungeon.hero.heroClass == HeroClass.SOLDIER) + bonus += 5; + if (Dungeon.hero.buff(AflyBless.class)!=null) { + bonus += 5; + } + + lootChance += 0.02*bonus; + lootChanceOther += 0.02*bonus; + + if (Random.Float() < lootChance && Dungeon.hero.lvl <= maxLvl + 800) { + Item loot = createLoot(); + if (loot != null) + Dungeon.level.drop(loot, pos).sprite.drop(); + + } else if (Random.Float() < lootChanceOther + && Dungeon.hero.lvl <= maxLvl + 800) { + Item lootOther = createLootOther(); + if (lootOther != null) + Dungeon.level.drop(lootOther, pos).sprite.drop(); + } + + if (Dungeon.hero.isAlive() && !Dungeon.visible[pos]) { + GLog.i(Messages.get(this, "died")); + } + + if (Dungeon.isChallenged(Challenges.NIGHTMARE_VIRUS) && !(this instanceof Virus)) { + ArrayList candidates = new ArrayList(); + boolean[] passable = Level.passable; + int[] neighbours = { pos + 1, pos - 1, pos + Level.getWidth(), + pos - Level.getWidth() }; + for (int n : neighbours) { + if (passable[n] && Actor.findChar(n) == null) { + candidates.add(n); + } + } + + if (candidates.size() > 0) { + + Virus virus = new Virus(); + virus.pos = Random.element(candidates); + virus.state = virus.HUNTING; + + if (Dungeon.level.map[virus.pos] == Terrain.DOOR) { + Door.enter(virus.pos); + } + + GameScene.add(virus, 1f); + Actor.addDelayed(new Pushing(virus, pos, virus.pos), -1); + } + + } + + } + + protected Object loot = null; + protected Object lootOther = null; + protected float lootChance = 0; + protected float lootChanceOther = 0; + + @SuppressWarnings("unchecked") + protected Item createLoot() { + Item item; + if (loot instanceof Generator.Category) { + + item = Generator.random((Generator.Category) loot); + + } else if (loot instanceof Class) { + + item = Generator.random((Class) loot); + + } else { + + item = (Item) loot; + + } + return item; + } + + @SuppressWarnings("unchecked") + protected Item createLootOther() { + Item item; + if (lootOther instanceof Generator.Category) { + + item = Generator.random((Generator.Category) lootOther); + + } else if (lootOther instanceof Class) { + + item = Generator.random((Class) lootOther); + + } else { + + item = (Item) lootOther; + + } + return item; + } + + public void explodeDew(int cell) { + + if (Dungeon.dewDraw || Dungeon.dewWater){ + Sample.INSTANCE.play(Assets.SND_BLAST, 2); + + if (Dungeon.isChallenged(Challenges.DEW_REJECTION)) { + for (int n : Level.NEIGHBOURS4) { + int c = cell + n; + if (c >= 0 && c < Level.getLength() && Level.passable[c]) { + + if (Random.Int(20) == 1) { + Dungeon.level.drop(new VioletDewdrop(), c).sprite.drop(); + } else if (Random.Int(8) == 1) { + Dungeon.level.drop(new RedDewdrop(), c).sprite.drop(); + } + } + } + } else { + for (int n : Level.NEIGHBOURS9) { + int c = cell + n; + if (c >= 0 && c < Level.getLength() && Level.passable[c]) { + + if (Random.Int(20) == 1) { + Dungeon.level.drop(new VioletDewdrop(), c).sprite.drop(); + } else if (Random.Int(8) == 1) { + Dungeon.level.drop(new RedDewdrop(), c).sprite.drop(); + } + } + } + } + } + } + + public void explodeDewHigh(int cell) { + + if (Dungeon.dewDraw || Dungeon.dewWater){ + Sample.INSTANCE.play(Assets.SND_BLAST, 2); + + if (Dungeon.isChallenged(Challenges.DEW_REJECTION)) { + for (int n : Level.NEIGHBOURS4) { + int c = cell + n; + if (c >= 0 && c < Level.getLength() && Level.passable[c]) { + + if (Random.Int(80) == 1) { + Dungeon.level.drop(new VioletDewdrop(), c).sprite.drop(); + } else if (Random.Int(10) == 1) { + Dungeon.level.drop(new RedDewdrop(), c).sprite.drop(); + } else if (Random.Int(2) == 0) { + Dungeon.level.drop(new YellowDewdrop(), c).sprite.drop(); + } + } + } + }else{ + for (int n : Level.NEIGHBOURS9) { + int c = cell + n; + if (c >= 0 && c < Level.getLength() && Level.passable[c]) { + + if (Random.Int(80)==1){Dungeon.level.drop(new VioletDewdrop(), c).sprite.drop();} + else if (Random.Int(10)==1){Dungeon.level.drop(new RedDewdrop(), c).sprite.drop();} + else if (Random.Int(2)==0){Dungeon.level.drop(new YellowDewdrop(), c).sprite.drop();} + } + } + } + } + } + + public boolean reset() { + return false; + } + + public void beckon(int cell) { + + notice(); + + if (state != HUNTING) { + state = WANDERING; + } + target = cell; + } + + public String description() { + return Messages.get(this, "desc"); + } + + public void notice() { + sprite.showAlert(); + } + + public void yell(String str) { + GLog.n("%s: \"%s\" ", name, str); + } + + // returns true when a mob sees the hero, and is currently targeting them. + public boolean focusingHero() { + return enemySeen && (target == Dungeon.hero.pos); + } + + public interface AiState { + public boolean act(boolean enemyInFOV, boolean justAlerted); + + public String status(); + } + + private class Sleeping implements AiState { + + public static final String TAG = "SLEEPING"; + + @Override + public boolean act(boolean enemyInFOV, boolean justAlerted) { + if (enemyInFOV + && Random.Int(distance(enemy) + enemy.stealth() + + (enemy.flying ? 2 : 0)) == 0) { + + enemySeen = true; + + notice(); + state = HUNTING; + target = enemy.pos; + + spend(TIME_TO_WAKE_UP); + + } else { + + enemySeen = false; + + spend(TICK); + + } + return true; + } + + @Override + public String status() { + return Messages.get(this, "status", name); + } + } + + private class Wandering implements AiState { + + public static final String TAG = "WANDERING"; + + @Override + public boolean act(boolean enemyInFOV, boolean justAlerted) { + if (enemyInFOV + && (justAlerted || Random.Int(distance(enemy) / 2 + + enemy.stealth()) == 0)) { + + enemySeen = true; + + notice(); + alerted = true; + state = HUNTING; + target = enemy.pos; + + } else { + + enemySeen = false; + + int oldPos = pos; + if (target != -1 && getCloser(target)) { + spend(1 / speed()); + return moveSprite(oldPos, pos); + } else { + target = Dungeon.level.randomDestination(); + spend(TICK); + } + + } + return true; + } + + @Override + public String status() { + return Messages.get(this, "status", name); + } + } + + private class Hunting implements AiState { + + public static final String TAG = "HUNTING"; + + @Override + public boolean act(boolean enemyInFOV, boolean justAlerted) { + enemySeen = enemyInFOV; + if (enemyInFOV && !isCharmedBy( enemy ) && canAttack(enemy)) { + + return doAttack(enemy); + + } else { + + if (enemyInFOV) { + target = enemy.pos; + } else if (enemy == null) { + state = WANDERING; + target = Dungeon.level.randomDestination(); + return true; + } + + int oldPos = pos; + if (target != -1 && getCloser(target)) { + + spend(1 / speed()); + return moveSprite(oldPos, pos); + + } else { + + spend(TICK); + if (!enemyInFOV) { + sprite.showLost(); + state = WANDERING; + target = Dungeon.level.randomDestination(); + } + return true; + } + } + } + + @Override + public String status() { + return Messages.get(this, "status", name); + } + } + + protected class Fleeing implements AiState { + + public static final String TAG = "FLEEING"; + + @Override + public boolean act(boolean enemyInFOV, boolean justAlerted) { + enemySeen = enemyInFOV; + if (enemyInFOV) { + target = enemy.pos; + } + + int oldPos = pos; + if (target != -1 && getFurther(target)) { + + spend(1 / speed()); + return moveSprite(oldPos, pos); + + } else { + + spend(TICK); + nowhereToRun(); + + return true; + } + } + + protected void nowhereToRun() { + } + + @Override + public String status() { + return Messages.get(this, "status", name); + } + } + + private class Passive implements AiState { + + public static final String TAG = "PASSIVE"; + + @Override + public boolean act(boolean enemyInFOV, boolean justAlerted) { + enemySeen = false; + spend(TICK); + return true; + } + + @Override + public String status() { + return Messages.get(this, "status", name); + } + } + + +} diff --git a/java/com/hmdzl/spspd/actors/mobs/Monk.java b/java/com/hmdzl/spspd/actors/mobs/Monk.java new file mode 100644 index 00000000..3522e6ab --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/Monk.java @@ -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 + */ +package com.hmdzl.spspd.actors.mobs; + +import java.util.HashSet; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Amok; +import com.hmdzl.spspd.actors.buffs.Terror; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.mobs.npcs.Imp; +import com.hmdzl.spspd.items.KindOfWeapon; +import com.hmdzl.spspd.items.food.staplefood.NormalRation; +import com.hmdzl.spspd.items.food.staplefood.OverpricedRation; +import com.hmdzl.spspd.items.weapon.melee.FightGloves; +import com.hmdzl.spspd.items.weapon.melee.Knuckles; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.MonkSprite; +import com.hmdzl.spspd.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!"; + + { + spriteClass = MonkSprite.class; + + HP = HT = 160+(adj(0)*Random.NormalIntRange(3, 5)); + evadeSkill = 30+adj(1); + + EXP = 14; + maxLvl = 30; + + loot = new NormalRation(); + lootChance = 0.1f; + + lootOther = new OverpricedRation(); + lootChanceOther = 0.4f; // by default, see die() + + properties.add(Property.DWARF); + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(22, 36+adj(0)); + } + + @Override + public int hitSkill(Char target) { + return 30+adj(01); + } + + @Override + protected float attackDelay() { + return 0.5f; + } + + @Override + public int drRoll() { + return Random.NormalIntRange(2, 12); + } + + @Override + public void die(Object cause) { + Imp.Quest.process(this); + + super.die(cause); + } + + @Override + public int attackProc(Char enemy, int damage) { + + if (Random.Int(12) == 0 && enemy == Dungeon.hero) { + + Hero hero = Dungeon.hero; + KindOfWeapon weapon = hero.belongings.weapon; + + if (weapon != null && !(weapon instanceof Knuckles || weapon instanceof FightGloves) + && !weapon.cursed) { + hero.belongings.weapon = null; + Dungeon.level.drop(weapon, hero.pos).sprite.drop(); + GLog.w(Messages.get(this, "disarm")); + weapon.updateQuickslot(); + } + } + + return damage; + } + + private static final HashSet> IMMUNITIES = new HashSet>(); + static { + IMMUNITIES.add(Amok.class); + IMMUNITIES.add(Terror.class); + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/MonsterBox.java b/java/com/hmdzl/spspd/actors/mobs/MonsterBox.java new file mode 100644 index 00000000..0fa90d9f --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/MonsterBox.java @@ -0,0 +1,182 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 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 + */ +package com.hmdzl.spspd.actors.mobs; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.Pushing; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.scrolls.ScrollOfPsionicBlast; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.MonsterBoxSprite; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public class MonsterBox extends Mob { + + private int level; + + { + name = "monster box"; + spriteClass = MonsterBoxSprite.class; + + properties.add(Property.UNKNOW); + } + + public ArrayList items; + + private static final String LEVEL = "level"; + private static final String ITEMS = "items"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(ITEMS, items); + bundle.put(LEVEL, level); + } + + @SuppressWarnings("unchecked") + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + items = new ArrayList( + (Collection) ((Collection) bundle.getCollection(ITEMS))); + adjustStats(bundle.getInt(LEVEL)); + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(HT / 10, HT / 4); + } + + @Override + public int hitSkill(Char target) { + return 9 + level; + } + + + public void adjustStats(int level) { + this.level = level; + + HT = (3 + level) * 4; + EXP = 2 + 2 * (level - 1) / 5; + evadeSkill = hitSkill(null) / 2; + + enemySeen = true; + } + + //@Override + //protected boolean act() { + // Char ch = Actor.findChar(pos); + // if (Random.Int(5)==0){ + // SummoningTrap.trigger(pos, ch); + // } + // return rooted; + //} + + @Override + public void die(Object cause) { + + super.die(cause); + + if (items != null) { + for (Item item : items) { + Dungeon.level.drop(item, pos).sprite.drop(); + } + } + } + + @Override + public boolean reset() { + state = WANDERING; + return true; + } + + @Override + public String description() { + return "Mimics are magical creatures which can take any shape they wish. In dungeons they almost always " + + "choose a shape of a treasure chest, because they know how to beckon an adventurer."; + } + + public static MonsterBox spawnAt(int pos, List items) { + Char ch = Actor.findChar(pos); + if (ch != null) { + ArrayList candidates = new ArrayList(); + for (int n : Level.NEIGHBOURS8) { + int cell = pos + n; + if ((Level.passable[cell] || Level.avoid[cell]) + && Actor.findChar(cell) == null) { + candidates.add(cell); + } + } + if (candidates.size() > 0) { + int newPos = Random.element(candidates); + Actor.addDelayed(new Pushing(ch, ch.pos, newPos), -1); + + ch.pos = newPos; + // FIXME + if (ch instanceof Mob) { + Dungeon.level.mobPress((Mob) ch); + } else { + Dungeon.level.press(newPos, ch); + } + } else { + return null; + } + } + + MonsterBox m = new MonsterBox(); + m.items = new ArrayList(items); + m.adjustStats(Dungeon.depth); + m.HP = m.HT; + m.pos = pos; + m.state = m.HUNTING; + GameScene.add(m, 1); + + m.sprite.turnTo(pos, Dungeon.hero.pos); + //Buff.affect(m, Roots.class, 1000); + + if (Dungeon.visible[m.pos]) { + CellEmitter.get(pos).burst(Speck.factory(Speck.STAR), 10); + Sample.INSTANCE.play(Assets.SND_MIMIC); + } + + return m; + } + + private static final HashSet> IMMUNITIES = new HashSet>(); + static { + IMMUNITIES.add(ScrollOfPsionicBlast.class); + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/MossySkeleton.java b/java/com/hmdzl/spspd/actors/mobs/MossySkeleton.java new file mode 100644 index 00000000..793e1b66 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/MossySkeleton.java @@ -0,0 +1,136 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs; + +import java.util.HashSet; + +import com.hmdzl.spspd.items.challengelists.PrisonChallenge; +import com.hmdzl.spspd.items.food.completefood.GoldenNut; +import com.hmdzl.spspd.items.reward.PrisonReward; +import com.hmdzl.spspd.items.scrolls.ScrollOfSacrifice; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.Statistics; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.items.Bone; +import com.hmdzl.spspd.items.RedDewdrop; +import com.hmdzl.spspd.items.YellowDewdrop; +import com.hmdzl.spspd.items.weapon.enchantments.EnchantmentDark; +import com.hmdzl.spspd.sprites.MossySkeletonSprite; +import com.hmdzl.spspd.utils.GLog; + +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Random; + +public class MossySkeleton extends Mob { + + private static final String TXT_KILLCOUNT = "Mossy Skeleton Kill Count: %s"; + + { + spriteClass = MossySkeletonSprite.class; + + HP = HT = 90+(10*Random.NormalIntRange(7, 10)); + evadeSkill = 20; + + EXP = 1; + + baseSpeed = 0.5f+(Math.min(1f, Statistics.skeletonsKilled/50)); + + loot = new YellowDewdrop(); + lootChance = 0.5f; // by default, see die() + + lootOther= new RedDewdrop(); + lootChanceOther = 0.1f; // by default, see die() + + properties.add(Property.UNDEAD); + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(20+Math.round(Statistics.skeletonsKilled/10), 45+Math.round(Statistics.skeletonsKilled/5)); + + } + + @Override + protected float attackDelay() { + return 2f-(Math.min(1.5f, Statistics.skeletonsKilled/50)); + } + + @Override + public void die(Object cause) { + + super.die(cause); + + Statistics.skeletonsKilled++; + GLog.w(Messages.get(Mob.class,"killcount", Statistics.skeletonsKilled)); + + if (!Dungeon.limitedDrops.prisonkey.dropped() && Dungeon.depth<27) { + Dungeon.limitedDrops.prisonkey.drop(); + Dungeon.level.drop(new PrisonChallenge(), pos).sprite.drop(); + explodeDew(pos); + } else { + explodeDew(pos); + } + + if(Statistics.skeletonsKilled == 25) { + Dungeon.limitedDrops.bone.drop(); + Dungeon.level.drop(new Bone(), pos).sprite.drop(); + } + + if(Statistics.skeletonsKilled == 50) { + Dungeon.level.drop(new ScrollOfSacrifice(), pos).sprite.drop(); + } + + if(Statistics.skeletonsKilled == 100) { + Dungeon.level.drop(new PrisonReward(), pos).sprite.drop(); + } + + if (Statistics.goldThievesKilled>99 && Statistics.skeletonsKilled == 100 + && Statistics.albinoPiranhasKilled>99 && Statistics.archersKilled>99){ + Dungeon.level.drop(new GoldenNut(), pos).sprite.drop(); + } + + if (Dungeon.visible[pos]) { + Sample.INSTANCE.play(Assets.SND_BONES); + } + } + + + + + @Override + public int hitSkill(Char target) { + return 28; + } + + @Override + public int drRoll() { + return 10+Statistics.skeletonsKilled/5; + } + + private static final HashSet> IMMUNITIES = new HashSet>(); + static { + IMMUNITIES.add(EnchantmentDark.class); + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/Musketeer.java b/java/com/hmdzl/spspd/actors/mobs/Musketeer.java new file mode 100644 index 00000000..88187d4c --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/Musketeer.java @@ -0,0 +1,148 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs; + +import java.util.HashSet; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Amok; +import com.hmdzl.spspd.actors.buffs.ArmorBreak; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Terror; +import com.hmdzl.spspd.effects.particles.EnergyParticle; +import com.hmdzl.spspd.items.StoneOre; +import com.hmdzl.spspd.items.bombs.DungeonBomb; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.sprites.MusketeerSprite; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public class Musketeer extends Mob { + + + private boolean charged = false; + + private static final String CHARGED = "charged"; + + { + spriteClass = MusketeerSprite.class; + + HP = HT = 160+(adj(0)*Random.NormalIntRange(3, 5)); + evadeSkill = 30+adj(1); + + EXP = 12; + maxLvl = 30; + + loot = new StoneOre(); + lootChance = 0.2f; + + lootOther = new DungeonBomb(); + lootChanceOther = 0.1f; // by default, see die() + + properties.add(Property.DWARF); + } + + @Override + public boolean act() { + + if( !enemySeen ) + charged = false; + + return super.act(); + + } + + @Override + protected boolean doAttack( Char enemy ) { + //Ballistica dis = new Ballistica(pos, enemy.pos, Ballistica.PROJECTILE); + int dist = Level.distance(pos, enemy.pos); + if (dist == 1){ + return super.doAttack( enemy ); + } else if( enemySeen && state != SLEEPING && paralysed == 0 && !charged ) { + + charged = true; + + if( Dungeon.visible[ pos ] ) { + sprite.centerEmitter().burst(EnergyParticle.FACTORY, 15); + } + + spend( attackDelay() ); + + return true; + + } else { + + charged = false; + + return super.doAttack( enemy ); + } + } + + @Override + protected boolean canAttack( Char enemy ) { + return new Ballistica( pos, enemy.pos, Ballistica.MAGIC_BOLT).collisionPos == enemy.pos; + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(35, 60+adj(0)); + } + + @Override + public int hitSkill(Char target) { + return 35+adj(01); + } + + @Override + public int drRoll() { + return Random.NormalIntRange(5, 10); + } + + @Override + public int attackProc(Char enemy, int damage) { + int dist = Level.distance(pos, enemy.pos); + if (dist > 1 && Random.Int(4)< 1 ){ + Buff.affect(enemy, ArmorBreak.class,5f).level(25); + } + return damage; + } + private static final HashSet> IMMUNITIES = new HashSet>(); + static { + IMMUNITIES.add(Amok.class); + IMMUNITIES.add(Terror.class); + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } + + @Override + public void storeInBundle( Bundle bundle ) { + super.storeInBundle(bundle); + bundle.put( CHARGED, charged ); + } + + @Override + public void restoreFromBundle( Bundle bundle ) { + super.restoreFromBundle(bundle); + charged = bundle.getBoolean( CHARGED ); + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/NormalCell.java b/java/com/hmdzl/spspd/actors/mobs/NormalCell.java new file mode 100644 index 00000000..b320a682 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/NormalCell.java @@ -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 + */ +package com.hmdzl.spspd.actors.mobs; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.sprites.CellmobSprite; +import com.watabou.utils.Random; + +public class NormalCell extends Mob { + + { + spriteClass = CellmobSprite.class; + + HP = HT = 1; + evadeSkill = 0; + baseSpeed = 0.5f; + + properties.add(Property.BOSS); + properties.add(Property.MINIBOSS); + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(Dungeon.hero.HT/20, Dungeon.hero.HT/10); + } + + @Override + public int hitSkill(Char target) { + return 99; + } + +} diff --git a/java/com/hmdzl/spspd/actors/mobs/OrbOfZotMob.java b/java/com/hmdzl/spspd/actors/mobs/OrbOfZotMob.java new file mode 100644 index 00000000..21ee4cbb --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/OrbOfZotMob.java @@ -0,0 +1,220 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs; + +import java.util.HashSet; + +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.ResultDescriptions; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.ToxicGas; +import com.hmdzl.spspd.actors.buffs.Terror; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.particles.PurpleParticle; +import com.hmdzl.spspd.items.OrbOfZot; +import com.hmdzl.spspd.items.weapon.enchantments.EnchantmentDark; + +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.CharSprite; +import com.hmdzl.spspd.sprites.OrbOfZotSprite; + +import com.watabou.utils.Random; + +public class OrbOfZotMob extends Mob { + + private static final String TXT_DEATHGAZE_KILLED = "%s's deathray killed you..."; + + { + spriteClass = OrbOfZotSprite.class; + hostile = false; + state = HUNTING; + HP = HT= 500; + evadeSkill = 35; + + properties.add(Property.MECH); + } + + private Ballistica beam; + + private static final float SPAWN_DELAY = 1f; + + + @Override + public int drRoll() { + return 0; + } + + + @Override + protected boolean act() { + + for (int n : Level.NEIGHBOURS8DIST2) { + int c = pos + n; + if (c0){ + Char ch = Actor.findChar(c); + } + } + //Level.fieldOfView[Dungeon.hero.pos] && + + boolean result = super.act(); + return result; + } + + @Override + public void move(int step) { + } + + @Override + protected Char chooseEnemy() { + + if (enemy == null || !enemy.isAlive()) { + HashSet enemies = new HashSet(); + for (Mob mob : Dungeon.level.mobs) { + if (mob.hostile && Level.fieldOfView[mob.pos]) { + enemies.add(mob); + } + } + + enemy = enemies.size() > 0 ? Random.element(enemies) : null; + } + + return enemy; + } + + + + public static OrbOfZotMob spawnAt(int pos) { + + OrbOfZotMob b = new OrbOfZotMob(); + + b.pos = pos; + b.state = b.HUNTING; + GameScene.add(b, SPAWN_DELAY); + + return b; + + } + + private int hitCell; + + @Override + protected boolean canAttack(Char enemy) { + + beam = new Ballistica( pos, enemy.pos, Ballistica.STOP_TERRAIN); + + return beam.subPath(1, beam.dist).contains(enemy.pos); + } + + @Override + public int hitSkill(Char target) { + return 70+(Dungeon.depth); + } + + @Override + protected boolean doAttack(Char enemy) { + + spend(attackDelay()); + + boolean rayVisible = false; + + for (int i : beam.subPath(0, beam.dist)) { + if (Dungeon.visible[i]) { + rayVisible = true; + } + } + + if (rayVisible) { + sprite.attack( beam.collisionPos ); + return false; + } else { + attack(enemy); + return true; + } + } + + @Override + public boolean attack(Char enemy) { + + for (int pos : beam.subPath(1, beam.dist)) { + + Char ch = Actor.findChar( pos ); + if (ch == null) { + continue; + } + + if (hit(this, ch, true)) { + ch.damage(Random.NormalIntRange(100, 200), this); + damage(Random.NormalIntRange(10, 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(Messages.format(ResultDescriptions.MOB)); + //GLog.n(Messages.get(this, "kill")); + } + } else { + ch.sprite.showStatus(CharSprite.NEUTRAL, ch.defenseVerb()); + } + } + + return true; + } + + @Override + public void beckon(int cell) { + } + + @Override + public void die(Object cause) { + + yell(Messages.get(this, "die")); + Dungeon.level.drop(new OrbOfZot(), pos); + super.die(cause); + } + + private static final HashSet> RESISTANCES = new HashSet>(); + static { + RESISTANCES.add(EnchantmentDark.class); + + } + + @Override + public HashSet> resistances() { + return RESISTANCES; + } + + private static final HashSet> IMMUNITIES = new HashSet>(); + static { + IMMUNITIES.add(Terror.class); + IMMUNITIES.add(ToxicGas.class); + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/Orc.java b/java/com/hmdzl/spspd/actors/mobs/Orc.java new file mode 100644 index 00000000..b91a2ec6 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/Orc.java @@ -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 + */ +package com.hmdzl.spspd.actors.mobs; + +import java.util.HashSet; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.Blob; +import com.hmdzl.spspd.actors.blobs.CorruptGas; +import com.hmdzl.spspd.actors.buffs.Amok; +import com.hmdzl.spspd.actors.buffs.Terror; +import com.hmdzl.spspd.actors.buffs.Vertigo; +import com.hmdzl.spspd.sprites.OrcSprite; +import com.hmdzl.spspd.scenes.GameScene; +import com.watabou.utils.Random; + +public class Orc extends Mob { + + { + spriteClass = OrcSprite.class; + state = SLEEPING; + + HP = HT = 200+(Dungeon.depth*10); + evadeSkill = 18+(Math.round((Dungeon.depth)/2)); + + EXP = 22; + maxLvl = 40; + + properties.add(Property.ORC); + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(50, 90); + } + + @Override + public int hitSkill(Char target) { + return 35; + } + + @Override + protected float attackDelay() { + return 1.5f; + } + + @Override + public int drRoll() { + return Random.NormalIntRange(16, 32); + } + + @Override + public void damage(int dmg, Object src) { + if (dmg > HT/8){ + GameScene.add(Blob.seed(pos, 30, CorruptGas.class)); + } + super.damage(dmg, src); + } + + private static final HashSet> RESISTANCES = new HashSet>(); + static { + } + + @Override + public HashSet> resistances() { + return RESISTANCES; + } + + private static final HashSet> IMMUNITIES = new HashSet>(); + static { + IMMUNITIES.add(Amok.class); + IMMUNITIES.add(Terror.class); + IMMUNITIES.add(CorruptGas.class); + IMMUNITIES.add(Vertigo.class); + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/Otiluke.java b/java/com/hmdzl/spspd/actors/mobs/Otiluke.java new file mode 100644 index 00000000..aa4bcb51 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/Otiluke.java @@ -0,0 +1,208 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs; + +import java.util.HashSet; + +import com.hmdzl.spspd.actors.buffs.Silent; +import com.hmdzl.spspd.items.misc.SkillOfMig; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.ResultDescriptions; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.ToxicGas; +import com.hmdzl.spspd.actors.buffs.Amok; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Burning; +import com.hmdzl.spspd.actors.buffs.Charm; +import com.hmdzl.spspd.actors.buffs.Poison; +import com.hmdzl.spspd.actors.buffs.Sleep; +import com.hmdzl.spspd.actors.buffs.Terror; +import com.hmdzl.spspd.actors.buffs.Vertigo; +import com.hmdzl.spspd.actors.buffs.Weakness; +import com.hmdzl.spspd.actors.buffs.Paralysis; +import com.hmdzl.spspd.items.scrolls.ScrollOfPsionicBlast; +import com.hmdzl.spspd.items.weapon.enchantments.EnchantmentDark; + +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.sprites.CharSprite; +import com.hmdzl.spspd.sprites.OtilukeSprite; + +import com.watabou.utils.Callback; +import com.watabou.utils.Random; + +public class Otiluke 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..."; + + { + spriteClass = OtilukeSprite.class; + + HP = HT = 10000; + evadeSkill = 40; + + state=PASSIVE; + + EXP = 101; + + loot = new SkillOfMig(); + lootChance = 1f; + + properties.add(Property.ELEMENT); + properties.add(Property.BOSS); + + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(150, 150+adj(0)); + } + + @Override + public int hitSkill(Char target) { + return 150+adj(0); + } + + @Override + public int drRoll() { + return Random.NormalIntRange(20, 40); + } + + @Override + public void damage(int dmg, Object src) { + + if (state == PASSIVE) { + state = HUNTING; + } + + if(state==HUNTING){ + + for (Mob mob : Dungeon.level.mobs) { + if (mob != null && mob instanceof MineSentinel && Random.Int(20)<2) { + if (mob.state==PASSIVE){ + mob.damage(1, this); + mob.state = HUNTING; + } + break; + } + } + } + + super.damage(dmg, src); + } + + + + + @Override + protected boolean canAttack(Char enemy) { if (buff(Silent.class) != null){ + return Level.adjacent(pos, enemy.pos) && (!isCharmedBy(enemy)); + } else + return new Ballistica( pos, enemy.pos, Ballistica.MAGIC_BOLT).collisionPos == enemy.pos; + } + + @Override + 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) { + ((OtilukeSprite) 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(100, 160+adj(0)); + enemy.damage(dmg, this); + + if (!enemy.isAlive() && enemy == Dungeon.hero) { + Dungeon.fail(Messages.format(ResultDescriptions.MOB)); + //GLog.n(Messages.get(this, "kill")); + } + } else { + enemy.sprite.showStatus(CharSprite.NEUTRAL, enemy.defenseVerb()); + } + } + + public void onZapComplete() { + zap(); + next(); + } + + @Override + public void call() { + next(); + } + + + @Override + public void die(Object cause) { + super.die(cause); + Dungeon.level.locked=false; + + } + + private static final HashSet> RESISTANCES = new HashSet>(); + private static final HashSet> IMMUNITIES = new HashSet>(); + static { + RESISTANCES.add(ToxicGas.class); + RESISTANCES.add(Poison.class); + RESISTANCES.add(EnchantmentDark.class); + + IMMUNITIES.add(EnchantmentDark.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); + IMMUNITIES.add(Vertigo.class); + IMMUNITIES.add(Paralysis.class); + } + + @Override + public HashSet> resistances() { + return RESISTANCES; + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + }} diff --git a/java/com/hmdzl/spspd/actors/mobs/PatrolUAV.java b/java/com/hmdzl/spspd/actors/mobs/PatrolUAV.java new file mode 100644 index 00000000..fe240e6f --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/PatrolUAV.java @@ -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 + */ +package com.hmdzl.spspd.actors.mobs; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.Blob; +import com.hmdzl.spspd.actors.blobs.ElectriShock; +import com.hmdzl.spspd.actors.buffs.Amok; +import com.hmdzl.spspd.actors.buffs.Burning; +import com.hmdzl.spspd.actors.buffs.Sleep; +import com.hmdzl.spspd.actors.buffs.Terror; +import com.hmdzl.spspd.actors.buffs.Vertigo; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.particles.EnergyParticle; +import com.hmdzl.spspd.items.StoneOre; +import com.hmdzl.spspd.items.wands.WandOfLightning; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.PatrolUAVSprite; +import com.watabou.utils.Random; + +import java.util.HashSet; + +public class PatrolUAV extends Mob { + + + { + spriteClass = PatrolUAVSprite.class; + + HP = HT = 50+(Dungeon.depth*Random.NormalIntRange(1, 3)); + evadeSkill = adj(1); + + EXP = 5; + maxLvl = 10; + + state = WANDERING; + + flying = true; + + loot = new StoneOre(); + lootChance = 0.4f; + + properties.add(Property.MECH); + } + + + + @Override + public int damageRoll() { + return Random.NormalIntRange(4, 7); + } + + @Override + public int hitSkill(Char target) { + return 5; + } + + @Override + public int drRoll() { + return Random.NormalIntRange(5, 10); + } + + @Override + public void die(Object cause) { + + super.die(cause); + for (int i : Level.NEIGHBOURS9) { + if (Level.insideMap(pos+i) && !Level.solid[pos+i]) { + GameScene.add(Blob.seed(pos + i, 3, ElectriShock.class)); + CellEmitter.get(pos + i).burst(EnergyParticle.FACTORY, 5); + } + } + + } + + + private static final HashSet> IMMUNITIES = new HashSet>(); + static { + IMMUNITIES.add(Amok.class); + IMMUNITIES.add(Sleep.class); + IMMUNITIES.add(Terror.class); + IMMUNITIES.add(Burning.class); + IMMUNITIES.add(Vertigo.class); + IMMUNITIES.add(ElectriShock.class); + IMMUNITIES.add(WandOfLightning.class); + } + @Override + public HashSet> immunities() { + return IMMUNITIES; + } + +} diff --git a/java/com/hmdzl/spspd/actors/mobs/Piranha.java b/java/com/hmdzl/spspd/actors/mobs/Piranha.java new file mode 100644 index 00000000..4926d86f --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/Piranha.java @@ -0,0 +1,164 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs; + +import java.util.HashSet; + +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.Statistics; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.ToxicGas; +import com.hmdzl.spspd.actors.buffs.Burning; +import com.hmdzl.spspd.actors.buffs.Corruption; +import com.hmdzl.spspd.actors.buffs.Frost; +import com.hmdzl.spspd.actors.buffs.Paralysis; +import com.hmdzl.spspd.actors.buffs.Roots; +import com.hmdzl.spspd.items.challengelists.CaveChallenge; +import com.hmdzl.spspd.items.food.meatfood.Meat; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.sprites.PiranhaSprite; +import com.watabou.utils.Random; + +public class Piranha extends Mob { + + { + spriteClass = PiranhaSprite.class; + + baseSpeed = 1.5f; + + EXP = 5; + + loot = new Meat(); + lootChance = 1f; + + properties.add(Property.BEAST); + } + + public Piranha() { + super(); + + HP = HT = 40 + Dungeon.depth * 5; + evadeSkill = 10 + Dungeon.depth * 2; + } + + @Override + protected boolean act() { + if (!Level.water[pos]) { + die(null); + return true; + } else { + // this causes pirahna to move away when a door is closed on them. + Dungeon.level.updateFieldOfView(this); + enemy = chooseEnemy(); + if (state == this.HUNTING + && !(enemy.isAlive() && Level.fieldOfView[enemy.pos] && enemy.invisible <= 0)) { + state = this.WANDERING; + int oldPos = pos; + int i = 0; + do { + i++; + target = Dungeon.level.randomDestination(); + if (i == 100) + return true; + } while (!getCloser(target)); + moveSprite(oldPos, pos); + return true; + } + + return super.act(); + } + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(Dungeon.depth, 4 + Dungeon.depth * 2); + } + + @Override + public int hitSkill(Char target) { + return 20 + Dungeon.depth * 2; + } + + @Override + public int drRoll() { + return Random.NormalIntRange(0, Dungeon.depth); + } + + @Override + public void die(Object cause) { + super.die(cause); + + if (!Dungeon.limitedDrops.caveskey.dropped() && Statistics.deepestFloor > 10) { + Dungeon.limitedDrops.caveskey.drop(); + Dungeon.level.drop(new CaveChallenge(), pos).sprite.drop(); + } + + 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; + } + } + + private static final HashSet> IMMUNITIES = new HashSet>(); + static { + IMMUNITIES.add(Burning.class); + IMMUNITIES.add(Paralysis.class); + IMMUNITIES.add(ToxicGas.class); + IMMUNITIES.add(Roots.class); + IMMUNITIES.add(Frost.class); + IMMUNITIES.add(Corruption.class); + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/PlagueDoctor.java b/java/com/hmdzl/spspd/actors/mobs/PlagueDoctor.java new file mode 100644 index 00000000..2b91eda9 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/PlagueDoctor.java @@ -0,0 +1,455 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2015 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.actors.mobs; + + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.Badges.Badge; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.Blob; +import com.hmdzl.spspd.actors.blobs.ConfusionGas; +import com.hmdzl.spspd.actors.blobs.DarkGas; +import com.hmdzl.spspd.actors.blobs.ParalyticGas; +import com.hmdzl.spspd.actors.blobs.ToxicGas; +import com.hmdzl.spspd.actors.buffs.AttackDown; +import com.hmdzl.spspd.actors.buffs.AttackUp; +import com.hmdzl.spspd.actors.buffs.Bleeding; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Burning; +import com.hmdzl.spspd.actors.buffs.DefenceUp; +import com.hmdzl.spspd.actors.buffs.Poison; +import com.hmdzl.spspd.actors.buffs.Speed; +import com.hmdzl.spspd.actors.buffs.Vertigo; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.items.StoneOre; +import com.hmdzl.spspd.items.artifacts.AlchemistsToolkit; +import com.hmdzl.spspd.items.journalpages.Sokoban1; +import com.hmdzl.spspd.items.keys.SkeletonKey; +import com.hmdzl.spspd.items.wands.WandOfLight; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.SewerBossLevel; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.PlagueDoctorSprite; +import com.hmdzl.spspd.sprites.ShadowRatSprite; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +import java.util.HashSet; + +import static com.hmdzl.spspd.Dungeon.hero; + +public class PlagueDoctor extends Mob { + + { + spriteClass = PlagueDoctorSprite.class; + + HP = HT = 500; + evadeSkill = 5; + baseSpeed = 0.75f; + + EXP = 30; + + loot = new AlchemistsToolkit(); + lootChance = 0.2f; + + lootOther = Generator.Category.POTION; + lootChanceOther = 1f; + + FLEEING = new Fleeing(); + + properties.add(Property.HUMAN); + properties.add(Property.BOSS); + } + + private int breaks=0; + + @Override + public void notice() { + super.notice(); + yell(Messages.get(this, "notice")); + ((SewerBossLevel) Dungeon.level).seal(); + if (!spawnedshadow) { + Buff.affect(hero, ShadowRatSummon.class); + spawnedshadow = true; + } + //state = PASSIVE; + } + + + @Override + public boolean act() { + + if (3 - breaks > 4 * HP / HT) { + breaks++; + if (breaks > 1){ + GLog.i(Messages.get(this, "crazy")); + yell(Messages.get(this, "yell2")); + } + return true; + } + + if (breaks == 1){ + state = FLEEING; + GameScene.add(Blob.seed(pos, 20, ToxicGas.class)); + } + + if (breaks == 2){ + state = HUNTING; + } + + return super.act(); + } + + @Override + public int attackProc(Char enemy, int damage) { + + if (breaks == 0){ + if (Random.Int(2) == 0) { + switch (Random.Int (4)) { + case 0: + enemy.HP += (int)((enemy.HT)/10); + enemy.sprite.emitter().start(Speck.factory(Speck.HEALING), 0.4f,1); + break; + case 1: + Buff.affect(enemy, AttackUp.class, 5f).level(20); + break; + case 2: + Buff.affect(enemy, DefenceUp.class, 5f).level(20); + break; + case 3: + Buff.affect(enemy, Speed.class, 5f); + break; + default: + break; + } + } + damage = 0 ; + if (Random.Int(3) == 0) { + yell(Messages.get(this, "yell")); + } + } + + + if (breaks == 2){ + if (Random.Int(2) == 0) { + Buff.affect(enemy, Bleeding.class).set(5); + } + } + + if (breaks == 3){ + Buff.affect(this,AttackUp.class,5f).level(50); + Buff.affect(this,DefenceUp.class,5f).level(25); + } + + return damage; + } + + @Override + public int defenseProc(Char enemy, int damage) { + if (breaks == 1 && Random.Int(2) == 0){ + switch (Random.Int (4)) { + case 0: + GameScene.add(Blob.seed(pos, 25, ToxicGas.class)); + break; + case 1: + GameScene.add(Blob.seed(pos, 25, ConfusionGas.class)); + break; + case 2: + GameScene.add(Blob.seed(pos, 25, ParalyticGas.class)); + break; + case 3: + GameScene.add(Blob.seed(pos, 25, DarkGas.class)); + break; + default: + break; + } + } + return super.defenseProc(enemy, damage); + } + + @Override + public void damage(int dmg, Object src) { + super.damage(dmg, src); + } + + @Override + public void destroy() { + super.destroy(); + for (Mob mob : Dungeon.level.mobs.toArray(new Mob[Dungeon.level.mobs.size()])) { + if (mob instanceof ShadowRat) { + mob.die(null); + } + } + } + + @Override + protected boolean canAttack(Char enemy) { + return super.canAttack(enemy); + } + + @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(); + + Buff.detach(hero, ShadowRatSummon.class); + + Badges.Badge badgeToCheck = null; + switch (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; + case PERFORMER: + badgeToCheck = Badge.MASTERY_PERFORMER; + break; + case SOLDIER: + badgeToCheck = Badge.MASTERY_SOLDIER; + break; + case FOLLOWER: + badgeToCheck = Badge.MASTERY_FOLLOWER; + break; + } + Dungeon.level.drop(new Sokoban1(), pos).sprite.drop(); + } + + @Override + public int damageRoll() { + int min = 6; + int max = 19; + return Random.NormalIntRange(min, max); + + } + + @Override + public int hitSkill(Char target) { + return 30; + } + + @Override + public int drRoll() { + return Random.NormalIntRange(0, 5); + } + + private static final HashSet> IMMUNITIES = new HashSet<>(); + static { + IMMUNITIES.add(ToxicGas.class ); + IMMUNITIES.add(ParalyticGas.class); + IMMUNITIES.add(DarkGas.class); + IMMUNITIES.add(ConfusionGas.class); + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } + + private static final String BREAKS = "breaks"; + + @Override + public void storeInBundle( Bundle bundle ) { + super.storeInBundle(bundle); + bundle.put( BREAKS, breaks ); + } + + @Override + public void restoreFromBundle( Bundle bundle ) { + super.restoreFromBundle(bundle); + breaks = bundle.getInt( BREAKS ); + } + + protected boolean spawnedshadow = false; + + public static class ShadowRatSummon extends Buff { + + int spawnPower = 0; + + @Override + public boolean act() { + spawnPower++; + int srat = 1; //we include the wraith we're trying to spawn + for (Mob mob : Dungeon.level.mobs) { + if (mob instanceof ShadowRat) { + srat++; + } + } + + int powerNeeded = Math.min(10, srat); + + if (powerNeeded <= spawnPower) { + spawnPower -= powerNeeded; + int pos = 0; + do { + pos = Random.Int(Dungeon.level.randomRespawnCellMob()); + } while (!Dungeon.level.passable[pos] || Actor.findChar(pos) != null); + ShadowRat.spawnAt(pos); + Sample.INSTANCE.play(Assets.SND_BURNING); + } + + spend(TICK); + return true; + } + + public void dispel() { + detach(); + for (Mob mob : Dungeon.level.mobs.toArray(new Mob[0])) { + if (mob instanceof ShadowRat) { + mob.die(null); + } + } + } + + private static String SPAWNPOWER = "spawnpower"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(SPAWNPOWER, spawnPower); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + spawnPower = bundle.getInt(SPAWNPOWER); + } + } + + public static class ShadowRat extends Mob { + + + private static final float SPAWN_DELAY = 2f; + + { + spriteClass = ShadowRatSprite.class; + + HP = HT = 60; + evadeSkill = 3; + EXP = 1; + + loot = new StoneOre(); + lootChance = 0.2f; + + properties.add(Property.ELEMENT); + properties.add(Property.MINIBOSS); + } + + + @Override + public void damage(int dmg, Object src) { + if (src instanceof WandOfLight) { + destroy(); + sprite.die(); + } else { + + super.damage(dmg, src); + } + } + + @Override + public int attackProc( Char enemy, int damage) { + damage = super.attackProc(enemy, damage); + if (Random.Int(3) < 1) { + Buff.prolong(enemy, AttackDown.class, 10f).level(25); + } else + if (Random.Int(3) < 1) { + Buff.prolong(enemy, Vertigo.class, 5f); + } + return super.attackProc(enemy, damage); + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(6, 9); + } + + @Override + public int hitSkill(Char target) { + return 25; + } + + @Override + public int drRoll() { + return 0; + } + + private static final HashSet> IMMUNITIES = new HashSet<>(); + static { + IMMUNITIES.add( ToxicGas.class ); + IMMUNITIES.add(Poison.class); + IMMUNITIES.add(Burning.class); + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } + + public static void spawnAround(int pos) { + for (int n : Level.NEIGHBOURS8) { + int cell = pos + n; + if (Level.passable[cell] && Actor.findChar(cell) == null) { + spawnAt(cell); + } + } + } + + public static void spawnAroundChance(int pos) { + for (int n : Level.NEIGHBOURS4) { + int cell = pos + n; + if (Level.passable[cell] && Actor.findChar(cell) == null && Random.Float() < 0.75f) { + spawnAt(cell); + } + } + } + + public static ShadowRat spawnAt(int pos) { + + ShadowRat b = new ShadowRat(); + + b.pos = pos; + b.state = b.HUNTING; + GameScene.add(b, SPAWN_DELAY); + + return b; + + } + } + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/mobs/PrisonWander.java b/java/com/hmdzl/spspd/actors/mobs/PrisonWander.java new file mode 100644 index 00000000..f2f07996 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/PrisonWander.java @@ -0,0 +1,392 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs; + +import java.util.HashSet; + +import com.hmdzl.spspd.actors.buffs.Blindness; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Burning; +import com.hmdzl.spspd.actors.buffs.Chill; +import com.hmdzl.spspd.actors.buffs.Cripple; +import com.hmdzl.spspd.actors.buffs.GlassShield; +import com.hmdzl.spspd.actors.buffs.Vertigo; +import com.hmdzl.spspd.actors.buffs.Weakness; +import com.hmdzl.spspd.effects.Chains; +import com.hmdzl.spspd.effects.Pushing; +import com.hmdzl.spspd.items.ArmorKit; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.items.TenguKey; +import com.hmdzl.spspd.items.artifacts.EtherealChains; +import com.hmdzl.spspd.items.bombs.DungeonBomb; +import com.hmdzl.spspd.items.wands.WandOfFlow; +import com.hmdzl.spspd.items.wands.WandOfLight; +import com.hmdzl.spspd.items.weapon.enchantments.EnchantmentLight; +import com.hmdzl.spspd.levels.PrisonBossLevel; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.ToxicGas; +import com.hmdzl.spspd.actors.buffs.Poison; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.journalpages.Sokoban2; +import com.hmdzl.spspd.items.keys.SkeletonKey; +import com.hmdzl.spspd.items.weapon.enchantments.EnchantmentDark; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.plants.Blindweed; +import com.hmdzl.spspd.plants.Firebloom; +import com.hmdzl.spspd.plants.Icecap; +import com.hmdzl.spspd.plants.Plant; +import com.hmdzl.spspd.plants.Sorrowmoss; +import com.hmdzl.spspd.plants.Stormvine; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.PrisonWanderSprite; +import com.hmdzl.spspd.sprites.SeekingBombSprite; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Bundle; +import com.watabou.utils.Callback; +import com.watabou.utils.Random; + +import static com.hmdzl.spspd.Dungeon.hero; + +public class PrisonWander extends Mob { + + private boolean chainsUsed = false; + + { + spriteClass = PrisonWanderSprite.class; + + HP = HT = 800; + EXP = 40; + evadeSkill = 20; + viewDistance = 7; + + properties.add(Property.HUMAN); + properties.add(Property.BOSS); + + loot = new EtherealChains(); + lootChance = 0.2f; + + lootOther = new DungeonBomb(); + lootChanceOther = 1f; + + } + + private int breaks=0; + + @Override + public int damageRoll() { + return Random.NormalIntRange(12, 21); + } + + public void spawnBomb() { + int newPos2; + do { + newPos2 = Random.Int(Level.getLength()); + } while (!Level.fieldOfView[newPos2] || !Level.passable[newPos2] + || Level.adjacent(newPos2, hero.pos) + || Actor.findChar(newPos2) != null); + SeekBombP bomb1 = new SeekBombP(); + bomb1.pos = newPos2; + GameScene.add(bomb1); + } + + @Override + protected float attackDelay() { + return 0.75f; + } + + @Override + protected boolean act() { + if( 7 - breaks > 8 * HP / HT && HP > 0) { + breaks++; + + if (breaks < 4) { + Buff.affect(this, GlassShield.class).turns(1); + spawnBomb(); + chainsUsed = false; + } + return true; + } + Dungeon.level.updateFieldOfView( this ); + if (!chainsUsed && state == HUNTING && + paralysed <= 0 && + enemy != null && + enemy.invisible == 0 && + Level.fieldOfView[enemy.pos] && + Level.distance( pos, enemy.pos ) < 5 && !Level.adjacent( pos, enemy.pos ) && + Random.Int(3) == 0 && + chain(enemy.pos) && HP > 0) { + return false; + } else if(Random.Int(10)<1 && breaks < 4 ){ + Plant.Seed seed = (Plant.Seed) Generator.random(Generator.Category.SEED2); + Dungeon.level.plant(seed, this.pos); + return true; + } else { + return super.act(); + } + } + + private boolean chain(int target){ + //if (chainsUsed || enemy.properties().contains(Property.IMMOVABLE)) + //return false; + Ballistica chain = new Ballistica(pos, target, Ballistica.PROJECTILE); + + if (chain.collisionPos != enemy.pos || Level.pit[chain.path.get(1)]) + return false; + else { + int newPos = -1; + for (int i : chain.subPath(1, chain.dist)){ + if (!Level.solid[i] && Actor.findChar(i) == null){ + newPos = i; + break; + } + } + + if (newPos == -1){ + return false; + } else { + final int newPosFinal = newPos; + yell( Messages.get(this, "scorpion") ); + sprite.parent.add(new Chains(pos, enemy.pos, new Callback() { + public void call() { + Actor.addDelayed(new Pushing(enemy, enemy.pos, newPosFinal), -1); + enemy.pos = newPosFinal; + Dungeon.level.press(newPosFinal, enemy); + Cripple.prolong(enemy, Cripple.class, 4f); + Vertigo.prolong(enemy, Vertigo.class, 8f); + if (enemy == hero) { + hero.interrupt(); + Dungeon.observe(); + } + next(); + } + })); + } + } + chainsUsed = true; + return true; + } + + @Override + public int hitSkill(Char target) { + return 35; + } + + @Override + public int drRoll() { + return Random.NormalIntRange(7, 12); + } + + + + @Override + public int attackProc(Char enemy, int damage) { + if (Random.Int(10)<2){ + int oppositeDefender = enemy.pos + (enemy.pos - pos); + Ballistica trajectory = new Ballistica(enemy.pos, oppositeDefender, Ballistica.MAGIC_BOLT); + WandOfFlow.throwChar(enemy, trajectory, 1); + } else if ((Random.Int(10)<2)) { + int newPos; + do { + newPos = Random.Int(Level.getLength()); + } while (!Level.fieldOfView[newPos] || !Level.passable[newPos] + || Level.adjacent(newPos, hero.pos) + || Actor.findChar(newPos) != null); + + Buff.affect(hero, Weakness.class,5f); + hero.sprite.move(pos, newPos); + hero.move(newPos); + + if (Dungeon.visible[newPos]) { + CellEmitter.get(newPos).burst(Speck.factory(Speck.WOOL), 6); + Sample.INSTANCE.play(Assets.SND_PUFF); + } + + spend(1f); + } + + return damage; + } + + @Override + public void notice() { + super.notice(); + yell(Messages.get(this, "notice")); + + } + + @Override + public void die(Object cause) { + + yell(Messages.get(this,"die")); + + GameScene.bossSlain(); + + Badges.validateBossSlain(); + + ((PrisonBossLevel) Dungeon.level).unseal(); + + Dungeon.level.drop(new ArmorKit(), pos).sprite.drop(); + + Dungeon.level.drop(new Sokoban2(), pos).sprite.drop(); + Dungeon.level.drop(new SkeletonKey(Dungeon.depth), pos).sprite.drop(); + Dungeon.level.drop(new TenguKey(), pos).sprite.drop(); + + super.die(cause); + } + + private final String CHAINSUSED = "chainsused"; + private static final String BREAKS = "breaks"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(CHAINSUSED, chainsUsed); + bundle.put( BREAKS, breaks ); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + chainsUsed = bundle.getBoolean(CHAINSUSED); + breaks = bundle.getInt( BREAKS ); + } + + private static final HashSet> RESISTANCES = new HashSet>(); + private static final HashSet> WEAKNESS = new HashSet>(); + private static final HashSet> IMMUNITIES = new HashSet<>(); + static { + WEAKNESS.add(WandOfLight.class); + WEAKNESS.add(EnchantmentLight.class); + + IMMUNITIES.add(Burning.class); + RESISTANCES.add(ToxicGas.class); + IMMUNITIES.add(Poison.class); + IMMUNITIES.add(Chill.class); + IMMUNITIES.add(Blindness.class); + IMMUNITIES.add(Vertigo.class); + RESISTANCES.add(EnchantmentDark.class); + + + IMMUNITIES.add(Icecap.class); + IMMUNITIES.add(Firebloom.class); + IMMUNITIES.add(Blindweed.class); + IMMUNITIES.add(Stormvine.class); + IMMUNITIES.add(Sorrowmoss.class); + } + + @Override + public HashSet> resistances() { + return RESISTANCES; + } + + @Override + public HashSet> weakness() { + return WEAKNESS; + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } + + public static class SeekBombP extends Mob { + + private static final int BOMB_DELAY = 8; + private int timeToBomb = BOMB_DELAY; + { + spriteClass = SeekingBombSprite.class; + + HP = HT = 1; + evadeSkill = 0; + baseSpeed = 1f; + timeToBomb = BOMB_DELAY; + EXP = 0; + + state = HUNTING; + + properties.add(Property.MECH); + properties.add(Property.MINIBOSS); + } + + @Override + public int attackProc(Char enemy, int damage) { + int dmg = super.attackProc(enemy, damage); + + DungeonBomb bomb = new DungeonBomb(); + bomb.explode(pos); + yell("KA-BOOM!!!"); + + destroy(); + sprite.die(); + + return dmg; + } + + @Override + public void die(Object cause) { + DungeonBomb bomb = new DungeonBomb(); + bomb.explode(pos); + super.die(cause); + + } + + @Override + public int hitSkill(Char target) { + return 10; + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(0, 1); + } + + @Override + public int drRoll() { + return 0; + } + + @Override + public boolean act() { + yell(""+timeToBomb+"!"); + if (timeToBomb == 0){ + DungeonBomb bomb = new DungeonBomb(); + bomb.explode(pos); + yell("KA-BOOM!!!"); + destroy(); + sprite.die(); + } + + return super.act(); + } + + @Override + public void move(int step) { + super.move(step); + timeToBomb --; + } + + } + +} diff --git a/java/com/hmdzl/spspd/actors/mobs/Rat.java b/java/com/hmdzl/spspd/actors/mobs/Rat.java new file mode 100644 index 00000000..cedd36eb --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/Rat.java @@ -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 + */ +package com.hmdzl.spspd.actors.mobs; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.items.food.meatfood.Meat; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.RatSprite; +import com.watabou.utils.Random; + +public class Rat extends Mob { + + + private static final float SPAWN_DELAY = 2f; + + { + spriteClass = RatSprite.class; + + HP = HT = 40+(Dungeon.depth*Random.NormalIntRange(1, 3)); + evadeSkill = 3+(Math.round((Dungeon.depth)/2)); + + EXP = 1; + maxLvl = 4; + + loot = new Meat(); + lootChance = 0.5f; + + properties.add(Property.BEAST); + } + + + + @Override + public int damageRoll() { + return Random.NormalIntRange(1, 5+Dungeon.depth); + } + + @Override + public int hitSkill(Char target) { + return 5+Dungeon.depth; + } + + @Override + public int drRoll() { + return 1; + } + + 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 Rat spawnAt(int pos) { + + Rat b = new Rat(); + + b.pos = pos; + b.state = b.HUNTING; + GameScene.add(b, SPAWN_DELAY); + + return b; + + } + + + +} diff --git a/java/com/hmdzl/spspd/actors/mobs/RatBoss.java b/java/com/hmdzl/spspd/actors/mobs/RatBoss.java new file mode 100644 index 00000000..53fe6bc6 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/RatBoss.java @@ -0,0 +1,73 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs; + + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.items.scrolls.ScrollOfRegrowth; +import com.hmdzl.spspd.sprites.RatBossSprite; +import com.watabou.utils.Random; + +public class RatBoss extends Mob { + + { + spriteClass = RatBossSprite.class; + + HP = HT = 50+(Dungeon.depth*Random.NormalIntRange(2, 5)); + evadeSkill = 5+(Dungeon.depth/4); + + EXP = 10; + + loot = Generator.Category.BERRY; + lootChance = 0.5f; + + lootOther = new ScrollOfRegrowth(); + lootChanceOther = 0.1f; + + properties.add(Property.BEAST); + properties.add(Property.BOSS); + } + + private boolean spawnedRats = false; + + @Override + public int damageRoll() { + return Random.NormalIntRange(2+Dungeon.depth/2, 8+(Dungeon.depth)); + } + + @Override + public int hitSkill(Char target) { + return 11+Dungeon.depth; + } + + @Override + public int drRoll() { + return Dungeon.depth/2; + } + + @Override + public void notice() { + super.notice(); + if (!spawnedRats){ + Rat.spawnAround(pos); + spawnedRats = true; + } + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/RedWraith.java b/java/com/hmdzl/spspd/actors/mobs/RedWraith.java new file mode 100644 index 00000000..de15a97f --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/RedWraith.java @@ -0,0 +1,199 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs; + +import java.util.HashSet; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.ToxicGas; +import com.hmdzl.spspd.actors.buffs.Amok; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Burning; +import com.hmdzl.spspd.actors.buffs.Charm; +import com.hmdzl.spspd.actors.buffs.Frost; +import com.hmdzl.spspd.actors.buffs.Paralysis; +import com.hmdzl.spspd.actors.buffs.Roots; +import com.hmdzl.spspd.actors.buffs.Sleep; +import com.hmdzl.spspd.actors.buffs.Terror; +import com.hmdzl.spspd.actors.buffs.Vertigo; +import com.hmdzl.spspd.effects.particles.ShadowParticle; +import com.hmdzl.spspd.items.RedDewdrop; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.items.scrolls.ScrollOfPsionicBlast; +import com.hmdzl.spspd.items.weapon.enchantments.EnchantmentDark; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.RedWraithSprite; +import com.watabou.noosa.tweeners.AlphaTweener; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public class RedWraith extends Mob { + + protected static final float SPAWN_DELAY = 2f; + + protected int level; + + { + spriteClass = RedWraithSprite.class; + + HP = HT = 10 + Dungeon.depth; + EXP = 1 ; + + flying = true; + + loot = new RedDewdrop(); + lootChance = 0.5f; + + lootOther = Generator.Category.RING; + lootChanceOther = 0.1f; + + properties.add(Property.UNDEAD); + + } + + protected 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 hitSkill(Char target) { + return 10 + level; + } + + public void adjustStats(int level) { + this.level = level; + evadeSkill = hitSkill(null) * 5; + enemySeen = true; + } + + @Override + public int attackProc(Char enemy, int damage) { + if (Random.Int(4) == 0) { + Buff.affect(enemy, Vertigo.class, Vertigo.duration(enemy)); + Buff.affect(enemy, Terror.class, Terror.DURATION).object = enemy.id(); + } + + return damage; + } + + @Override + protected boolean canAttack(Char enemy) { + return Dungeon.level.distance( pos, enemy.pos ) <= 2 ; + } + + @Override + public void die(Object cause) { + + /*if (!Dungeon.limitedDrops.ringofhaste.dropped() && Random.Float()<0.1f) { + Dungeon.limitedDrops.ringofhaste.drop(); + Dungeon.level.drop(new RingOfHaste(), pos).sprite.drop(); + explodeDew(pos); + } else { + explodeDew(pos); + }*/ + + super.die(cause); + + } + + //public void damage(int dmg, Object src) { + // if (enemySeen + // && (src instanceof Wand || src instanceof LightningTrap.Electricity || src instanceof Char)) { + // GLog.n("The attack passes through the wraith."); + // sprite.showStatus(CharSprite.NEUTRAL, "missed"); + // } else { + // super.damage(dmg, src); + // } + //} + + @Override + public boolean reset() { + state = WANDERING; + return true; + } + + 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 RedWraith spawnAt(int pos) { + if (Level.passable[pos] && Actor.findChar(pos) == null) { + + RedWraith w = new RedWraith(); + w.adjustStats(Dungeon.depth); + w.pos = pos; + w.state = w.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; + } + } + + protected static final HashSet> IMMUNITIES = new HashSet>(); + static { + IMMUNITIES.add(EnchantmentDark.class); + IMMUNITIES.add(Terror.class); + IMMUNITIES.add(Amok.class); + IMMUNITIES.add(Charm.class); + IMMUNITIES.add(Sleep.class); + IMMUNITIES.add(ToxicGas.class); + IMMUNITIES.add(ScrollOfPsionicBlast.class); + IMMUNITIES.add(Vertigo.class); + IMMUNITIES.add(Burning.class); + IMMUNITIES.add(Paralysis.class); + IMMUNITIES.add(Roots.class); + IMMUNITIES.add(Frost.class); + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/SandMob.java b/java/com/hmdzl/spspd/actors/mobs/SandMob.java new file mode 100644 index 00000000..826d7be8 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/SandMob.java @@ -0,0 +1,171 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs; + +import java.util.HashSet; + +import com.hmdzl.spspd.actors.buffs.Dry; +import com.hmdzl.spspd.actors.buffs.Paralysis; +import com.hmdzl.spspd.actors.buffs.Slow; +import com.hmdzl.spspd.items.food.WaterItem; +import com.hmdzl.spspd.items.weapon.enchantments.EnchantmentEarth; +import com.hmdzl.spspd.items.weapon.enchantments.EnchantmentEarth2; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.SandmobSprite; +import com.watabou.utils.Random; + +public class SandMob extends Mob { + + { + spriteClass = SandmobSprite.class; + + HP = HT = 90+(adj(0)*Random.NormalIntRange(2, 5)); + evadeSkill = 5+adj(0); + baseSpeed = 0.5f; + + EXP = 10; + maxLvl = 25; + + loot = new WaterItem(); + //loot = new PotionOfMending(); potential nerf + lootChance = 0.5f; // by default, see die() + + properties.add(Property.ELEMENT); + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(17, 25+adj(0)); + } + + @Override + public int hitSkill(Char target) { + return 10+adj(0); + } + + @Override + public int drRoll() { + return Random.NormalIntRange(0, 10); + } + + + @Override + public int attackProc(Char enemy, int damage) { + if (Random.Int(5) == 0) { + Buff.prolong(enemy, Dry.class, 10f); + } + + if (Random.Int(5) == 0) { + Buff.prolong(enemy, Slow.class, 10f); + } + + return damage; + } + + @Override + public void die(Object cause) { + MiniSand.spawnAround(this.pos); + super.die(cause); + } + + public static class MiniSand extends Mob { + + protected static final float SPAWN_DELAY = 1f; + { + spriteClass = SandmobSprite.class; + + HP = HT = 45+(adj(0)*Random.NormalIntRange(2, 5)); + evadeSkill = 25; + + + EXP = 0; + + state = WANDERING; + } + + int generation = 0; + + @Override + public int damageRoll() { + return Random.NormalIntRange(15, 20+adj(0)); + } + + @Override + public int hitSkill(Char target) { + return 30+adj(0); + } + + @Override + public int drRoll() { + return 0; + } + + @Override + public int attackProc(Char enemy, int damage) { + if (Random.Int(5) == 0) { + Buff.prolong(enemy, Dry.class, 10f); + } + + if (Random.Int(5) == 0) { + Buff.prolong(enemy, Slow.class, 10f); + } + + return damage; + } + + 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 MiniSand spawnAt(int pos) { + if (Level.passable[pos] && Actor.findChar(pos) == null) { + + MiniSand w = new MiniSand(); + w.pos = pos; + w.state = w.HUNTING; + GameScene.add(w, SPAWN_DELAY); + return w; + + } else { + return null; + } + } + + private static final HashSet> IMMUNITIES = new HashSet>(); + static { + IMMUNITIES.add(EnchantmentEarth.class); + IMMUNITIES.add(EnchantmentEarth2.class); + IMMUNITIES.add(Paralysis.class); + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } + } + +} diff --git a/java/com/hmdzl/spspd/actors/mobs/Scorpio.java b/java/com/hmdzl/spspd/actors/mobs/Scorpio.java new file mode 100644 index 00000000..358474dd --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/Scorpio.java @@ -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 + */ +package com.hmdzl.spspd.actors.mobs; + +import java.util.HashSet; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Cripple; +import com.hmdzl.spspd.actors.buffs.Light; +import com.hmdzl.spspd.actors.buffs.Locked; +import com.hmdzl.spspd.actors.buffs.Poison; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.food.meatfood.MysteryMeat; +import com.hmdzl.spspd.items.potions.PotionOfHealing; + +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.sprites.ScorpioSprite; +import com.watabou.utils.Random; + +public class Scorpio extends Mob { + + { + spriteClass = ScorpioSprite.class; + + HP = HT = 180+(adj(0)*Random.NormalIntRange(1, 3)); + evadeSkill = 24+adj(1); + viewDistance = Light.DISTANCE; + + EXP = 17; + maxLvl = 35; + + loot = new PotionOfHealing(); + lootChance = 0.2f; + + lootOther = new MysteryMeat(); + lootChanceOther = 0.30f; // by default, see die() + + properties.add(Property.BEAST); + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(20, 52+adj(0)); + } + + @Override + public int hitSkill(Char target) { + return 36+adj(1); + } + + @Override + public int drRoll() { + return Random.NormalIntRange(10, 20); + } + + @Override + protected boolean canAttack(Char enemy) { + if (buff(Locked.class) != null){ + return Level.adjacent(pos, enemy.pos) && (!isCharmedBy(enemy)); + } else + return Dungeon.level.distance( pos, enemy.pos ) <= 2 ; + } + + + @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 == HUNTING) { + return enemySeen && getFurther(target); + } else { + return super.getCloser(target); + } + } + + @Override + protected Item createLoot() { + // 5/count+5 total chance of getting healing, failing the 2nd roll drops + // mystery meat instead. + if (Random.Int(5 ) <= 24) { + return (Item) loot; + } else { + return new MysteryMeat(); + } + } + + private static final HashSet> RESISTANCES = new HashSet>(); + static { + + RESISTANCES.add(Poison.class); + } + + @Override + public HashSet> resistances() { + return RESISTANCES; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/Senior.java b/java/com/hmdzl/spspd/actors/mobs/Senior.java new file mode 100644 index 00000000..a969faed --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/Senior.java @@ -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 + */ +package com.hmdzl.spspd.actors.mobs; + +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Paralysis; +import com.hmdzl.spspd.sprites.SeniorSprite; +import com.watabou.utils.Random; + +public class Senior extends Monk { + + { + spriteClass = SeniorSprite.class; + + properties.add(Property.DWARF); + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(32, 56+adj(0)); + } + + @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 int defenseProc(Char enemy, int damage) { + + int dmg = Random.IntRange(0, damage/3); + if (dmg > 0) { + enemy.damage(dmg, this); + } + + return super.defenseProc(enemy, damage); + } + + + + @Override + public void die(Object cause) { + super.die(cause); + + Badges.validateRare(this); + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/Sentinel.java b/java/com/hmdzl/spspd/actors/mobs/Sentinel.java new file mode 100644 index 00000000..65c87fa6 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/Sentinel.java @@ -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 + */ +package com.hmdzl.spspd.actors.mobs; + +import java.util.HashSet; + +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Levitation; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.Journal; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.ToxicGas; +import com.hmdzl.spspd.actors.buffs.Poison; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.items.weapon.Weapon; +import com.hmdzl.spspd.items.weapon.Weapon.Enchantment; +import com.hmdzl.spspd.items.weapon.enchantments.EnchantmentDark; + +import com.hmdzl.spspd.items.weapon.melee.MeleeWeapon; +import com.hmdzl.spspd.sprites.SentinelSprite; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public class Sentinel extends Mob { + + { + spriteClass = SentinelSprite.class; + + EXP = 18; + state = PASSIVE; + + properties.add(Property.MECH); + } + + private Weapon weapon; + + public Sentinel() { + super(); + + do { + weapon = (Weapon) Generator.random(Generator.Category.OLDWEAPON); + } while (!(weapon instanceof MeleeWeapon) || weapon.level < 0); + + weapon.identify(); + weapon.enchant(Enchantment.random()); + weapon.upgrade(); + weapon.upgrade(); + weapon.upgrade(); + + HP = HT = 15 + Dungeon.depth * 8; + evadeSkill = 4 + Dungeon.depth * 2; + } + + 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 hitSkill(Char target) { + return (int) ((9 + Dungeon.depth) * weapon.ACU); + } + + @Override + protected float attackDelay() { + return weapon.DLY; + } + + @Override + public int drRoll() { + return Random.NormalIntRange(0, Dungeon.depth); + } + + @Override + public void damage(int dmg, Object src) { + + if (state == PASSIVE) { + state = HUNTING; + } + + super.damage(dmg, src); + + Buff.prolong(this,Levitation.class,10f); + } + + @Override + public int attackProc(Char enemy, int damage) { + weapon.proc(this, enemy, damage); + return damage; + } + + @Override + public void beckon(int cell) { + // Do nothing + } + + @Override + public void die(Object cause) { + Dungeon.level.drop(weapon, pos).sprite.drop(); + explodeDew(pos); + /*if (!Dungeon.limitedDrops.hallskey.dropped() && Dungeon.depth==24) { + Dungeon.limitedDrops.hallskey.drop(); + Dungeon.level.drop(new HallsKey(), pos).sprite.drop(); + + } */ + super.die(cause); + } + + @Override + public void destroy() { + Journal.remove(Journal.Feature.STATUE); + super.destroy(); + } + + + @Override + public boolean reset() { + state = PASSIVE; + return true; + } + + @Override + public String description() { + return Messages.get(this, "desc", weapon.name()); + } + + private static final HashSet> RESISTANCES = new HashSet>(); + private static final HashSet> IMMUNITIES = new HashSet>(); + static { + RESISTANCES.add(ToxicGas.class); + RESISTANCES.add(Poison.class); + RESISTANCES.add(EnchantmentDark.class); + + } + + @Override + public HashSet> resistances() { + return RESISTANCES; + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/SewerHeart.java b/java/com/hmdzl/spspd/actors/mobs/SewerHeart.java new file mode 100644 index 00000000..16c616b4 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/SewerHeart.java @@ -0,0 +1,531 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2015 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.actors.mobs; + + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.Badges.Badge; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.ResultDescriptions; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.Blob; +import com.hmdzl.spspd.actors.blobs.ToxicGas; +import com.hmdzl.spspd.actors.buffs.Bleeding; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Burning; +import com.hmdzl.spspd.actors.buffs.Cripple; +import com.hmdzl.spspd.actors.buffs.GrowSeed; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.effects.particles.PurpleParticle; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.items.journalpages.Sokoban1; +import com.hmdzl.spspd.items.keys.SkeletonKey; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.SewerBossLevel; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.plants.Rotberry; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.CharSprite; +import com.hmdzl.spspd.sprites.SewerHeartSprite; +import com.hmdzl.spspd.sprites.SewerLasherSprite; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +import java.util.HashSet; + +import static com.hmdzl.spspd.Dungeon.hero; + +public class SewerHeart extends Mob { + + { + spriteClass = SewerHeartSprite.class; + + HP = HT = 500; + evadeSkill = 0; + + EXP = 30; + + loot = new Rotberry.Seed(); + lootChance = 0.2f; + + lootOther = Generator.Category.SEED; + lootChanceOther = 1f; + + properties.add(Property.PLANT); + properties.add(Property.BOSS); + } + + private Ballistica beam; + private int beamTarget = -1; + private int breaks=0; + private int beamCooldown=0; + public boolean beamCharged; + + @Override + public void notice() { + super.notice(); + //yell("GLURP-GLURP!"); + ((SewerBossLevel) Dungeon.level).seal(); + if (!spawnedLasher){ + Buff.affect(hero, LasherSpawner.class);; + spawnedLasher = true; + } + state = PASSIVE; + } + + + @Override + public boolean act() { + + if( 5 - breaks > 6 * HP / HT ) { + breaks++; + return true; + } + + if (breaks ==3 && state == PASSIVE){ + state = HUNTING; + } + + if (beamCharged && state != HUNTING){ + beamCharged = false; + } + if (beam == null && beamTarget != -1) { + beam = new Ballistica(pos, beamTarget, Ballistica.STOP_TERRAIN); + sprite.turnTo(pos, beamTarget); + } + if (beamCooldown > 0) + beamCooldown--; + return super.act(); + } + + @Override + public void damage(int dmg, Object src) { + if( (5 - breaks) > 6 * HP / HT ) { + int newPos = -1; + for (int i = 0; i < 20; i++) { + newPos = Dungeon.level.randomRespawnCellMob(); + 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]; + GLog.n(Messages.get(this, "blink")); + } + if (Dungeon.level.mobs.size()< hero.lvl*2){ + SewerLasher.spawnAroundChance(newPos); + } + } + + super.damage(dmg, src); + + } + + @Override + public int defenseProc(Char enemy, int damage) { + GameScene.add(Blob.seed(pos, 20, ToxicGas.class)); + + return super.defenseProc(enemy, damage); + } + + @Override + protected boolean getCloser(int target) { + return false; + } + + @Override + public void destroy() { + super.destroy(); + for (Mob mob : Dungeon.level.mobs.toArray(new Mob[Dungeon.level.mobs.size()])){ + if (mob instanceof SewerLasher){ + mob.die(null); + } + } + } + + @Override + protected boolean canAttack(Char enemy) { + if (beamCooldown == 0) { + Ballistica aim = new Ballistica(pos, enemy.pos, Ballistica.STOP_TERRAIN); + + if (enemy.invisible == 0 && !isCharmedBy(enemy) && Level.fieldOfView[enemy.pos] && aim.subPath(1, aim.dist).contains(enemy.pos)){ + beam = aim; + beamTarget = aim.collisionPos; + return true; + } else + //if the beam is charged, it has to attack, will aim at previous location of target. + return beamCharged; + } else + return super.canAttack(enemy); + } + + @Override + protected boolean doAttack(Char enemy) { + if (beamCooldown > 0) { + return super.doAttack(enemy); + } else if (!beamCharged){ + ((SewerHeartSprite)sprite).charge( enemy.pos ); + spend( attackDelay()*2f ); + beamCharged = true; + return true; + } else { + + spend( attackDelay() ); + + beam = new Ballistica(pos, beamTarget, Ballistica.STOP_TERRAIN); + if (Level.fieldOfView[pos] || Level.fieldOfView[beam.collisionPos] ) { + sprite.zap( beam.collisionPos ); + return false; + } else { + deathGaze(); + return true; + } + }} + + public void deathGaze(){ + if (!beamCharged || beamCooldown > 0 || beam == null) + return; + + beamCharged = false; + beamCooldown = Random.IntRange(3, 6); + + boolean terrainAffected = false; + + for (int pos : beam.subPath(1, beam.dist)) { + + if (Dungeon.level.flamable[pos]) { + + Dungeon.level.destroy( pos ); + GameScene.updateMap( pos ); + terrainAffected = true; + + } + + Char ch = Actor.findChar( pos ); + if (ch == null) { + continue; + } + + if (hit( this, ch, true )) { + ch.damage( Random.NormalIntRange( 20, 35 ), this ); + + if (Level.fieldOfView[pos]) { + ch.sprite.flash(); + CellEmitter.center( pos ).burst( PurpleParticle.BURST, Random.IntRange( 1, 2 ) ); + } + + if (!ch.isAlive() && ch == Dungeon.hero) { + Dungeon.fail( Messages.format(ResultDescriptions.BURNING)); + } + } else { + ch.sprite.showStatus( CharSprite.NEUTRAL, ch.defenseVerb() ); + } + } + + if (terrainAffected) { + Dungeon.observe(); + } + + beam = null; + beamTarget = -1; + } + + @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(); + + Buff.detach(hero, LasherSpawner.class); + + Badges.Badge badgeToCheck = null; + switch (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; + case PERFORMER: + badgeToCheck = Badge.MASTERY_PERFORMER; + break; + case SOLDIER: + badgeToCheck = Badge.MASTERY_SOLDIER; + break; + case FOLLOWER: + badgeToCheck = Badge.MASTERY_FOLLOWER; + break; + } + Dungeon.level.drop(new Sokoban1(), pos).sprite.drop(); + } + + @Override + public int damageRoll() { + int min = (HP*2 <= HT) ? 5 : 2; + int max = (HP*2 <= HT) ? 16 : 8; + return Random.NormalIntRange( min, max ); + + } + + @Override + public int hitSkill( Char target ) { + return 30; + } + + @Override + public int drRoll() { + return Random.NormalIntRange(0, 2); + } + + protected boolean spawnedLasher = false; + + + private static final String BEAM_TARGET = "beamTarget"; + private static final String BEAM_COOLDOWN = "beamCooldown"; + private static final String BEAM_CHARGED = "beamCharged"; + private static final String BREAKS = "breaks"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put( BEAM_TARGET, beamTarget); + bundle.put( BEAM_COOLDOWN, beamCooldown ); + bundle.put( BEAM_CHARGED, beamCharged ); + bundle.put( BREAKS, breaks ); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + if (bundle.contains(BEAM_TARGET)) + beamTarget = bundle.getInt(BEAM_TARGET); + beamCooldown = bundle.getInt(BEAM_COOLDOWN); + beamCharged = bundle.getBoolean(BEAM_CHARGED); + breaks = bundle.getInt( BREAKS ); + } + + private static final HashSet> IMMUNITIES = new HashSet<>(); + static { + IMMUNITIES.add( ToxicGas.class ); + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } + + public static class LasherSpawner extends Buff { + + int spawnPower = 0; + + @Override + public boolean act() { + spawnPower++; + int lasher = 1; //we include the wraith we're trying to spawn + for (Mob mob : Dungeon.level.mobs){ + if (mob instanceof SewerLasher){ + lasher++; + } + } + + int powerNeeded = Math.min(25, lasher); + + if (powerNeeded <= spawnPower){ + spawnPower -= powerNeeded; + int pos = 0; + do{ + pos = Random.Int(Dungeon.level.randomRespawnCellMob()); + } while (!Dungeon.level.passable[pos] || Actor.findChar( pos ) != null); + SewerLasher.spawnAt(pos); + Sample.INSTANCE.play(Assets.SND_BURNING); + } + + spend(TICK); + return true; + } + + public void dispel(){ + detach(); + for (Mob mob : Dungeon.level.mobs.toArray(new Mob[0])){ + if (mob instanceof SewerLasher){ + mob.die(null); + } + } + } + + private static String SPAWNPOWER = "spawnpower"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put( SPAWNPOWER, spawnPower ); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + spawnPower = bundle.getInt( SPAWNPOWER ); + } + } + public static class SewerLasher extends Mob { + + protected static final float SPAWN_DELAY = 2f; + + { + spriteClass = SewerLasherSprite.class; + + HP = HT = 60; + evadeSkill = 0; + + EXP = 1; + + loot = Generator.Category.SEED; + lootChance = 0.2f; + + state = HUNTING; + + properties.add(Property.PLANT); + properties.add(Property.MINIBOSS); + //properties.add(Property.IMMOVABLE); + } + + @Override + protected boolean act() { + if (enemy == null || !Level.adjacent(pos, enemy.pos)) { + HP = Math.min(HT, HP + 3); + } + return super.act(); + } + + @Override + public void damage(int dmg, Object src) { + if (src instanceof Burning) { + destroy(); + sprite.die(); + } else { + + super.damage(dmg, src); + } + } + + @Override + public int attackProc( Char enemy, int damage) { + damage = super.attackProc(enemy, damage); + if (Random.Int(5) < 1) { + Buff.affect(enemy, Cripple.class, 2f); + } else + if (Random.Int(4) < 1) { + Buff.affect(enemy, GrowSeed.class).reignite(enemy); + } else + if (Random.Int(3) < 1) { + Buff.affect(enemy, Bleeding.class).set(damage);} + + return super.attackProc(enemy, damage); + + } + @Override + protected boolean getCloser(int target) { + return true; + } + + @Override + protected boolean getFurther(int target) { + return true; + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(4, 12); + } + + @Override + public int hitSkill( Char target ) { + return 15; + } + + @Override + public int drRoll() { + return Random.NormalIntRange(2, 8); + } + + private static final HashSet> IMMUNITIES = new HashSet<>(); + static { + IMMUNITIES.add( ToxicGas.class ); + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } + + public static void spawnAround(int pos) { + for (int n : Level.NEIGHBOURS8) { + int cell = pos + n; + if (Level.passable[cell] && Actor.findChar(cell) == null) { + spawnAt(cell); + } + } + } + + public static void spawnAroundChance(int pos) { + for (int n : Level.NEIGHBOURS4) { + int cell = pos + n; + if (Level.passable[cell] && Actor.findChar(cell) == null && Random.Float() < 0.75f) { + spawnAt(cell); + } + } + } + + public static SewerLasher spawnAt(int pos) { + + SewerLasher b = new SewerLasher(); + + b.pos = pos; + b.state = b.HUNTING; + GameScene.add(b, SPAWN_DELAY); + + return b; + + } + + + } + +} diff --git a/java/com/hmdzl/spspd/actors/mobs/ShadowYog.java b/java/com/hmdzl/spspd/actors/mobs/ShadowYog.java new file mode 100644 index 00000000..246d709c --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/ShadowYog.java @@ -0,0 +1,220 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs; + +import java.util.HashSet; + +import com.hmdzl.spspd.levels.traps.SummoningTrap; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.Statistics; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.ToxicGas; +import com.hmdzl.spspd.actors.buffs.Amok; +import com.hmdzl.spspd.actors.buffs.Burning; +import com.hmdzl.spspd.actors.buffs.Charm; +import com.hmdzl.spspd.actors.buffs.Sleep; +import com.hmdzl.spspd.actors.buffs.Terror; +import com.hmdzl.spspd.actors.buffs.Vertigo; +import com.hmdzl.spspd.actors.buffs.Paralysis; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.OrbOfZot; +import com.hmdzl.spspd.items.scrolls.ScrollOfPsionicBlast; +import com.hmdzl.spspd.items.weapon.enchantments.EnchantmentDark; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.Terrain; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ShadowYogSprite; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public class ShadowYog extends Mob { + + { + spriteClass = ShadowYogSprite.class; + + HP = HT = 50*Dungeon.hero.lvl; + + baseSpeed = 2f; + evadeSkill = 32; + + EXP = 100; + + state = PASSIVE; + + properties.add(Property.UNKNOW); + properties.add(Property.BOSS); + } + + private int yogsAlive = 0; + private int breaks=0; + private static final String BREAKS = "breaks"; + + @Override + public void storeInBundle( Bundle bundle ) { + super.storeInBundle(bundle); + bundle.put( BREAKS, breaks ); + } + + @Override + public void restoreFromBundle( Bundle bundle ) { + super.restoreFromBundle(bundle); + breaks = bundle.getInt( BREAKS ); + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(43, 83); + } + + @Override + public int hitSkill(Char target) { + return 50; + } + + public ShadowYog() { + super(); + } + + @Override + public int drRoll() { + return 25; + } + + @Override + public boolean act() { + + if (5 - breaks > 6 * HP / HT) { + breaks++; + int newPos = -1; + for (int i = 0; i < 20; i++) { + newPos = Dungeon.level.randomRespawnCellMob(); + 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]; + GLog.n(Messages.get(this, "blink")); + } + return true; + } + return super.act(); + } + + @Override + public void damage(int dmg, Object src) { + + //for (Mob mob : Dungeon.level.mobs) { + // mob.beckon(pos); + // } + + for (int i = 0; i < 4; i++) { + int trapPos; + do { + trapPos = Random.Int(Level.getLength()); + } while (!Level.fieldOfView[trapPos] || !Level.passable[trapPos]); + + if (Dungeon.level.map[trapPos] == Terrain.INACTIVE_TRAP) { + Dungeon.level.setTrap( new SummoningTrap().reveal(), trapPos ); + Level.set(trapPos,Terrain.TRAP); + GameScene.updateMap(trapPos); + } + } + if (Dungeon.level.mobs.size()) Dungeon.level.mobs.clone()) { + if (mob instanceof Rat || mob instanceof GoldOrc || mob instanceof Fiend || mob instanceof Eye) { + mob.die(cause); + } + } + + yell(Messages.get(this,"die")); + } + } + + @Override + public void notice() { + super.notice(); + yell(Messages.get(this,"illusion")); + } + + private static final HashSet> IMMUNITIES = new HashSet>(); + static { + + IMMUNITIES.add(EnchantmentDark.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); + IMMUNITIES.add(Paralysis.class); + IMMUNITIES.add(Vertigo.class); + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } + + } diff --git a/java/com/hmdzl/spspd/actors/mobs/Shell.java b/java/com/hmdzl/spspd/actors/mobs/Shell.java new file mode 100644 index 00000000..884dd964 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/Shell.java @@ -0,0 +1,329 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs; + +import java.util.HashSet; + +import com.hmdzl.spspd.actors.buffs.Silent; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.ResultDescriptions; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.ToxicGas; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Terror; +import com.hmdzl.spspd.effects.particles.SparkParticle; +import com.hmdzl.spspd.items.RedDewdrop; +import com.hmdzl.spspd.items.weapon.enchantments.EnchantmentDark; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.traps.LightningTrap; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.sprites.CharSprite; +import com.hmdzl.spspd.sprites.ShellSprite; +import com.hmdzl.spspd.utils.GLog; + +import com.watabou.noosa.Camera; +import com.watabou.utils.Bundle; +import com.watabou.utils.Callback; +import com.watabou.utils.Random; + +public class Shell extends Mob implements Callback { + + private static final float TIME_TO_ZAP = 2f; + + { + spriteClass = ShellSprite.class; + + HP = HT = 500; + evadeSkill = 0; + + EXP = 50; + + hostile = false; + state = PASSIVE; + + loot = new RedDewdrop(); + lootChance = 1f; + + properties.add(Property.MECH); + properties.add(Property.BOSS); + } + + private int shellCharge=0; + + private static final String SHELLCHARGE = "shellCharge"; + + @Override + public void storeInBundle( Bundle bundle ) { + super.storeInBundle(bundle); + bundle.put( SHELLCHARGE, shellCharge ); + } + + @Override + public void restoreFromBundle( Bundle bundle ) { + super.restoreFromBundle(bundle); + shellCharge = bundle.getInt( SHELLCHARGE ); + } + + + @Override + public void beckon(int cell) { + // Do nothing + } + + @Override + public int damageRoll() { + return 0; + } + + @Override + public void damage(int dmg, Object src) { + if(shellCharge>0){zapAround(1);} + super.damage(dmg, src); + } + + @Override + public int hitSkill(Char target) { + return 100; + } + + @Override + public int drRoll() { + return 0; + } + + @Override + protected boolean act() { + + if(Random.Int(shellCharge)>20 && Dungeon.hero.isAlive()){ + zapAll(1); + } + return super.act(); + } + + @Override + public void call() { + next(); + } + + + @Override + protected boolean canAttack(Char enemy) { if (buff(Silent.class) != null){ + return Level.adjacent(pos, enemy.pos) && (!isCharmedBy(enemy)); + } else + return new Ballistica( pos, enemy.pos, Ballistica.MAGIC_BOLT).collisionPos == 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) { + ((ShellSprite) sprite).zap(enemy.pos); + } + zapAll(10); + spend(TIME_TO_ZAP); + + if (hit(this, enemy, true)) { + int dmg = Random.Int(Math.round(shellCharge/4), Math.round(shellCharge/2)); + shellCharge-=dmg; + + if (Level.water[enemy.pos] && !enemy.flying) { + dmg *= 1.5f; + } + enemy.damage(dmg, this); + + 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(Messages.format(ResultDescriptions.MOB)); + //GLog.n(Messages.get(this, "kill")); + } + } + } else { + enemy.sprite + .showStatus(CharSprite.NEUTRAL, enemy.defenseVerb()); + } + + return !visible; + } + } + + + public void zapAll(int dmg){ + + GLog.n(Messages.get(this, "zap")); + + int heroDmg=0; + int mobDmg=Random.Int(1, 2+Math.round(dmg/4)); + + for (Mob mob : Dungeon.level.mobs) { + + + if (Level.distance(pos, mob.pos) > 1 && mob.isAlive()){ + boolean visible = Level.fieldOfView[pos] + || Level.fieldOfView[mob.pos]; + + + if (visible) { + ((ShellSprite) sprite).zap(mob.pos); + } + + mob.damage(mobDmg, this); + + mob.sprite.centerEmitter().burst(SparkParticle.FACTORY, 3); + mob.sprite.flash(); + + } + } + + + if (Dungeon.hero.isAlive()){ + + Char hero=Dungeon.hero; + + if (Level.distance(pos, hero.pos) > 1){ + + boolean visibleHero = Level.fieldOfView[pos] + || Level.fieldOfView[hero.pos]; + if (visibleHero && Random.Int(4) > 2 ) { + ((ShellSprite) sprite).zap(hero.pos); + } + + heroDmg = Random.Int(Math.round(shellCharge/4), Math.round(shellCharge/2)); + shellCharge-=heroDmg; + + hero.damage(heroDmg, this); + + hero.sprite.centerEmitter().burst(SparkParticle.FACTORY, 3); + hero.sprite.flash(); + + } + } + + + } + +public void zapAround(int dmg){ + + GLog.n(Messages.get(this, "zap")); + + int heroDmg=0; + int mobDmg=Random.Int(1, 2+Math.round(dmg/4)); + + for (int n : Level.NEIGHBOURS8) { + int c = pos + n; + + Char ch = Actor.findChar(c); + if (ch != null && ch != Dungeon.hero && ch.isAlive()) { + + boolean visible = Level.fieldOfView[pos] + || Level.fieldOfView[ch.pos]; + + if (visible) { + ((ShellSprite) sprite).zap(ch.pos); + } + + if (Level.water[ch.pos] && !ch.flying) { + mobDmg *= 1.5f; + } + ch.damage(mobDmg, this); + + ch.sprite.centerEmitter().burst(SparkParticle.FACTORY, 3); + ch.sprite.flash(); + + + } else if (ch != null && ch == Dungeon.hero && ch.isAlive()){ + + heroDmg = Random.Int(shellCharge/2, shellCharge); + + if(dmg> RESISTANCES = new HashSet>(); + static { + RESISTANCES.add(EnchantmentDark.class); + + RESISTANCES.add(LightningTrap.Electricity.class); + } + + @Override + public HashSet> resistances() { + return RESISTANCES; + } + + private static final HashSet> IMMUNITIES = new HashSet>(); + static { + IMMUNITIES.add(ToxicGas.class); + IMMUNITIES.add(Terror.class); + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } + + +} diff --git a/java/com/hmdzl/spspd/actors/mobs/Shielded.java b/java/com/hmdzl/spspd/actors/mobs/Shielded.java new file mode 100644 index 00000000..e61f3f3a --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/Shielded.java @@ -0,0 +1,57 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs; + +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.sprites.ShieldedSprite; +import com.watabou.utils.Random; + +public class Shielded extends Brute { + + { + spriteClass = ShieldedSprite.class; + + evadeSkill = 20+adj(0); + + properties.add(Property.ORC); + } + + @Override + public int drRoll() { + return Random.NormalIntRange(10, 30); + } + + @Override + public int defenseProc(Char enemy, int damage) { + + int dmg = Random.IntRange(0, damage/4); + if (dmg > 0) { + enemy.damage(dmg, this); + } + + return super.defenseProc(enemy, damage); + } + + + @Override + public void die(Object cause) { + super.die(cause); + Badges.validateRare(this); + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/Skeleton.java b/java/com/hmdzl/spspd/actors/mobs/Skeleton.java new file mode 100644 index 00000000..06dbbbe9 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/Skeleton.java @@ -0,0 +1,166 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs; + +import java.util.HashSet; + +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Silent; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.ResultDescriptions; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.weapon.enchantments.EnchantmentDark; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.SkeletonSprite; + +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public class Skeleton extends Mob { + + protected static final float SPAWN_DELAY = 2f; + protected static final String LEVEL = "level"; + + protected int level; + { + spriteClass = SkeletonSprite.class; + + HP = HT = 80+(adj(0)*Random.NormalIntRange(2, 5)); + evadeSkill = 15+adj(0); + baseSpeed = 0.8f; + + + EXP = 5; + maxLvl = 25; + + loot = Generator.Category.WEAPON; + lootChance = 0.15f; + + properties.add(Property.UNDEAD); + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(15, 22+adj(0)); + } + + + @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, + Random.NormalIntRange(3, 8) - Random.IntRange(0, ch.drRoll() / 2)); + ch.damage(damage, this); + Buff.affect(ch,Silent.class,10f); + if (ch == Dungeon.hero && !ch.isAlive()) { + heroKilled = true; + } + } + } + + if (Dungeon.visible[pos]) { + Sample.INSTANCE.play(Assets.SND_BONES); + } + + if (heroKilled) { + Dungeon.fail( Messages.format(ResultDescriptions.MOB)); + //GLog.n(Messages.get(this, "kill")); + } + } + + @Override + protected Item createLoot() { + 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; + } + } + return loot; + } + + @Override + public int hitSkill(Char target) { + return 16+adj(0); + } + + @Override + public int drRoll() { + return Random.NormalIntRange(2, 5); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + level = bundle.getInt(LEVEL); + adjustStats(level); + } + + public void adjustStats(int level) { + this.level = level; + evadeSkill = hitSkill(null) * 5; + enemySeen = true; + } + + private static final HashSet> IMMUNITIES = new HashSet>(); + static { + IMMUNITIES.add(EnchantmentDark.class); + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } + + 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 Skeleton spawnAt(int pos) { + if (Level.passable[pos] && Actor.findChar(pos) == null) { + + Skeleton w = new Skeleton(); + w.pos = pos; + w.state = w.HUNTING; + GameScene.add(w, SPAWN_DELAY); + return w; + + } else { + return null; + } + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/SkeletonHand1.java b/java/com/hmdzl/spspd/actors/mobs/SkeletonHand1.java new file mode 100644 index 00000000..7333bb5f --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/SkeletonHand1.java @@ -0,0 +1,107 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs; + +import java.util.HashSet; + +import com.hmdzl.spspd.actors.blobs.Fire; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Burning; +import com.hmdzl.spspd.actors.buffs.Terror; +import com.hmdzl.spspd.items.potions.PotionOfLiquidFlame; +import com.hmdzl.spspd.items.wands.WandOfFirebolt; +import com.hmdzl.spspd.sprites.SkeletonHand1Sprite; +import com.watabou.utils.Random; + +public class SkeletonHand1 extends Mob { + + { + spriteClass = SkeletonHand1Sprite.class; + + HP = HT = 1000; + evadeSkill = 30; + + EXP = 10; + maxLvl = 20; + + flying = true; + + loot = new PotionOfLiquidFlame(); + lootChance = 0.1f; + + properties.add(Property.UNDEAD); + properties.add(Property.BOSS); + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(10, 30); + } + + @Override + public int hitSkill(Char target) { + return 25; + } + + @Override + public int drRoll() { + return Random.NormalIntRange(0, 15); + } + + @Override + protected boolean act() { + boolean result = super.act(); + + if (state == FLEEING && buff(Terror.class) == null && enemy != null + && enemySeen && enemy.buff(Burning.class) == null) { + state = HUNTING; + } + return result; + } + + @Override + public int attackProc(Char enemy, int damage) { + if (Random.Int(2) == 0) { + if(enemy == Dungeon.hero){ + Buff.affect(enemy, Burning.class).reignite(enemy); + state = FLEEING; + } + } + + return damage; + } + + @Override + protected boolean canAttack(Char enemy) { + return Dungeon.level.distance( pos, enemy.pos ) <= 2; + } + + private static final HashSet> IMMUNITIES = new HashSet>(); + static { + IMMUNITIES.add(Burning.class); + IMMUNITIES.add(Fire.class); + IMMUNITIES.add(WandOfFirebolt.class); + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/SkeletonHand2.java b/java/com/hmdzl/spspd/actors/mobs/SkeletonHand2.java new file mode 100644 index 00000000..4c29e52b --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/SkeletonHand2.java @@ -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 + */ +package com.hmdzl.spspd.actors.mobs; + +import java.util.HashSet; + +import com.hmdzl.spspd.actors.blobs.Fire; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Burning; +import com.hmdzl.spspd.actors.buffs.Roots; +import com.hmdzl.spspd.actors.buffs.Terror; +import com.hmdzl.spspd.items.potions.PotionOfLiquidFlame; +import com.hmdzl.spspd.items.wands.WandOfFirebolt; + +import com.hmdzl.spspd.sprites.SkeletonHand2Sprite; +import com.watabou.utils.Random; + +public class SkeletonHand2 extends Mob { + + { + spriteClass = SkeletonHand2Sprite.class; + + HP = HT = 1000; + evadeSkill = 30; + + EXP = 10; + maxLvl = 20; + + flying = true; + + loot = new PotionOfLiquidFlame(); + lootChance = 0.1f; + + properties.add(Property.UNDEAD); + properties.add(Property.BOSS); + + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(10, 30); + } + + @Override + public int hitSkill(Char target) { + return 25; + } + + @Override + public int drRoll() { + return Random.NormalIntRange(0, 15); + } + + @Override + protected boolean act() { + boolean result = super.act(); + + if (state == FLEEING && buff(Terror.class) == null && enemy != null + && enemySeen && enemy.buff(Roots.class) == null) { + state = HUNTING; + } + return result; + } + + @Override + public int attackProc(Char enemy, int damage) { + if (Random.Int(2) == 0) { + if(enemy == Dungeon.hero){ + Buff.prolong(enemy, Roots.class, 20); + state = FLEEING; + } + } + + return damage; + } + + @Override + protected boolean canAttack(Char enemy) { + return Dungeon.level.distance( pos, enemy.pos ) <= 2; + } + + private static final HashSet> IMMUNITIES = new HashSet>(); + static { + IMMUNITIES.add(Burning.class); + IMMUNITIES.add(Fire.class); + IMMUNITIES.add(WandOfFirebolt.class); + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/SkeletonKing.java b/java/com/hmdzl/spspd/actors/mobs/SkeletonKing.java new file mode 100644 index 00000000..cc6d760e --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/SkeletonKing.java @@ -0,0 +1,134 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs; + +import java.util.HashSet; + +import com.hmdzl.spspd.actors.blobs.Fire; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Burning; +import com.hmdzl.spspd.actors.buffs.Terror; +import com.hmdzl.spspd.actors.buffs.Weakness; +import com.hmdzl.spspd.items.AdamantWeapon; +import com.hmdzl.spspd.items.Gold; +import com.hmdzl.spspd.items.potions.PotionOfLiquidFlame; +import com.hmdzl.spspd.items.wands.WandOfFirebolt; + +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.SkeletonKingSprite; +import com.watabou.utils.Random; + +public class SkeletonKing extends Mob { + + { + spriteClass = SkeletonKingSprite.class; + + HP = HT = 2000; + evadeSkill = 30; + + EXP = 50; + + flying = true; + + loot = new PotionOfLiquidFlame(); + lootChance = 0.1f; + + properties.add(Property.UNDEAD); + properties.add(Property.BOSS); + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(20, 40); + } + + @Override + public int hitSkill(Char target) { + return 25; + } + + @Override + public int drRoll() { + return Random.NormalIntRange(10, 25); + } + + @Override + protected boolean act() { + boolean result = super.act(); + + if (state == FLEEING && buff(Terror.class) == null && enemy != null + && enemySeen && enemy.buff(Weakness.class) == null) { + state = HUNTING; + } + return result; + } + + @Override + public int attackProc(Char enemy, int damage) { + if (Random.Int(2) == 0) { + if(enemy == Dungeon.hero){ + Buff.prolong(enemy, Weakness.class, Weakness.duration(enemy)); + state = FLEEING; + } + } + + return damage; + } + + @Override + protected boolean canAttack(Char enemy) { + return Dungeon.level.distance( pos, enemy.pos ) <= 3; + } + + @Override + public void die(Object cause) { + super.die(cause); + + GameScene.bossSlain(); + Dungeon.level.drop(new Gold(Random.Int(1900, 4000)), pos).sprite.drop(); + Dungeon.level.drop(new AdamantWeapon(), pos).sprite.drop(); + Dungeon.skeletonkingkilled=true; + + + + yell(Messages.get(this,"die")); + + } + + + @Override + public void notice() { + super.notice(); + yell(Messages.get(this, "notice", Dungeon.hero.givenName())); + } + + private static final HashSet> IMMUNITIES = new HashSet>(); + static { + IMMUNITIES.add(Burning.class); + IMMUNITIES.add(Fire.class); + IMMUNITIES.add(WandOfFirebolt.class); + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/SokobanSentinel.java b/java/com/hmdzl/spspd/actors/mobs/SokobanSentinel.java new file mode 100644 index 00000000..639ec1d4 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/SokobanSentinel.java @@ -0,0 +1,203 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs; + +import java.util.HashSet; + +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.ToxicGas; +import com.hmdzl.spspd.actors.buffs.Poison; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.items.weapon.Weapon; +import com.hmdzl.spspd.items.weapon.Weapon.Enchantment; +import com.hmdzl.spspd.items.weapon.enchantments.EnchantmentDark; + +import com.hmdzl.spspd.items.weapon.melee.MeleeWeapon; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.sprites.SentinelSprite; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public class SokobanSentinel extends Mob { + + { + spriteClass = SentinelSprite.class; + + baseSpeed = 0.5f; + + EXP = 18; + state = PASSIVE; + + properties.add(Property.MECH); + } + + private Weapon weapon; + + public SokobanSentinel() { + super(); + + do { + weapon = (Weapon) Generator.random(Generator.Category.OLDWEAPON); + } while (!(weapon instanceof MeleeWeapon) || weapon.level < 3); + + weapon.identify(); + weapon.enchant(Enchantment.random()); + weapon.upgrade(); + weapon.upgrade(); + weapon.upgrade(); + weapon.upgrade(); + weapon.upgrade(); + + + HP = HT = 500; + evadeSkill = 40; + } + + 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 + public int damageRoll() { + return Random.NormalIntRange(weapon.MIN, weapon.MAX); + } + + @Override + public int hitSkill(Char target) { + return 40; + } + + @Override + protected float attackDelay() { + return weapon.DLY; + } + + @Override + public int drRoll() { + return Random.NormalIntRange(0, Dungeon.depth); + } + + @Override + public void damage(int dmg, Object src) { + + if (state == PASSIVE) { + state = HUNTING; + } + + super.damage(dmg, src); + } + + @Override + protected boolean getCloser(int target) { + + if (rooted) { + return false; + } + + int step = Dungeon.findPath(this, pos, target, Level.passable, + Level.fieldOfView); + if (step != -1 && !Level.avoid[step]) { + move(step); + return true; + } else { + return false; + } + } + + @Override + protected boolean act() { + + + // this causes pirahna to move away when a door is closed on them. + Dungeon.level.updateFieldOfView(this); + enemy = chooseEnemy(); + if (state == this.HUNTING + && !(enemy.isAlive() && Level.fieldOfView[enemy.pos] && enemy.invisible <= 0)) { + state = this.WANDERING; + int oldPos = pos; + int i = 0; + do { + i++; + target = Dungeon.level.randomDestination(); + if (i == 100) + return true; + } while (!getCloser(target)); + moveSprite(oldPos, pos); + return true; + } else if (state == this.PASSIVE + && !(enemy.isAlive() && Level.fieldOfView[enemy.pos] && enemy.invisible <= 0)){ + state = this.HUNTING; + } + + return super.act(); + + } + @Override + public int attackProc(Char enemy, int damage) { + weapon.proc(this, enemy, damage); + return damage; + } + + @Override + public void beckon(int cell) { + // Do nothing + } + + @Override + public void die(Object cause) { + //Dungeon.level.drop(weapon, pos).sprite.drop(); + super.die(cause); + } + + @Override + public String description() { + return Messages.get(this, "desc", weapon.name()); + } + + private static final HashSet> RESISTANCES = new HashSet>(); + private static final HashSet> IMMUNITIES = new HashSet>(); + static { + RESISTANCES.add(ToxicGas.class); + RESISTANCES.add(Poison.class); + RESISTANCES.add(EnchantmentDark.class); + + } + + @Override + public HashSet> resistances() { + return RESISTANCES; + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/SommonSkeleton.java b/java/com/hmdzl/spspd/actors/mobs/SommonSkeleton.java new file mode 100644 index 00000000..243801d7 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/SommonSkeleton.java @@ -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 + */ +package com.hmdzl.spspd.actors.mobs; + +import java.util.HashSet; + +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.effects.particles.ShadowParticle; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.items.weapon.enchantments.EnchantmentDark; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.SkeletonSprite; + +import com.watabou.noosa.tweeners.AlphaTweener; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public class SommonSkeleton extends Mob { + + protected static final float SPAWN_DELAY = 2f; + protected static final String LEVEL = "level"; + + protected int level; + { + spriteClass = SkeletonSprite.class; + + HP = HT = 80+(adj(0)*Random.NormalIntRange(2, 5)); + evadeSkill = 15+adj(0); + baseSpeed = 0.8f; + + properties.add(Property.UNDEAD); + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(15, 22+adj(0)); + } + + + @Override + public void die(Object cause) { + super.die(cause); + } + + @Override + public int hitSkill(Char target) { + return 16+adj(0); + } + + @Override + public int drRoll() { + return Random.NormalIntRange(0, 4); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + level = bundle.getInt(LEVEL); + adjustStats(level); + } + + public void adjustStats(int level) { + this.level = level; + evadeSkill = hitSkill(null) * 5; + enemySeen = true; + } + + 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 SommonSkeleton spawnAt(int pos) { + if (Level.passable[pos] && Actor.findChar(pos) == null) { + + SommonSkeleton w = new SommonSkeleton(); + w.adjustStats(Dungeon.depth); + w.pos = pos; + w.state = w.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> IMMUNITIES = new HashSet>(); + static { + IMMUNITIES.add(EnchantmentDark.class); + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/SpiderBot.java b/java/com/hmdzl/spspd/actors/mobs/SpiderBot.java new file mode 100644 index 00000000..6d40f30f --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/SpiderBot.java @@ -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 + */ +package com.hmdzl.spspd.actors.mobs; + +import java.util.HashSet; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.Blob; +import com.hmdzl.spspd.actors.blobs.ShockWeb; +import com.hmdzl.spspd.actors.buffs.Bleeding; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Roots; +import com.hmdzl.spspd.actors.buffs.Tar; +import com.hmdzl.spspd.actors.buffs.Terror; +import com.hmdzl.spspd.items.StoneOre; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.SpiderBotSprite; +import com.watabou.utils.Random; + +public class SpiderBot extends Mob { + + { + spriteClass = SpiderBotSprite.class; + + HP = HT = 150+(adj(0)*Random.NormalIntRange(4, 7)); + evadeSkill = 25+adj(1); + + EXP = 12; + maxLvl = 30; + + loot = new StoneOre(); + lootChance = 0.3f; + + FLEEING = new Fleeing(); + + properties.add(Property.MECH); + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(15+adj(0), 40+adj(1)); + } + + @Override + public int hitSkill(Char target) { + return 30+adj(0); + } + + @Override + public int drRoll() { + return Random.NormalIntRange(0, 20); + } + + @Override + protected boolean act() { + boolean result = super.act(); + + if (state == FLEEING && buff(Terror.class) == null && enemy != null + && enemySeen && enemy.buff(Tar.class) == null) { + state = HUNTING; + } + return result; + } + + @Override + public int attackProc(Char enemy, int damage) { + if (Random.Int(3) == 0) { + Buff.affect(enemy, Tar.class); + state = FLEEING; + } + return damage; + } + + @Override + public void move(int step) { + if (state == FLEEING) { + GameScene.add(Blob.seed(pos, Random.Int(5, 7), ShockWeb.class)); + } + super.move(step); + } + + private static final HashSet> RESISTANCES = new HashSet>(); + + static { + RESISTANCES.add(Bleeding.class); + } + + @Override + public HashSet> resistances() { + return RESISTANCES; + } + + private static final HashSet> IMMUNITIES = new HashSet>(); + + static { + IMMUNITIES.add(Roots.class); + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } + + private class Fleeing extends Mob.Fleeing { + @Override + protected void nowhereToRun() { + if (buff(Terror.class) == null) { + state = HUNTING; + } else { + super.nowhereToRun(); + } + } + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/mobs/SpiderQueen.java b/java/com/hmdzl/spspd/actors/mobs/SpiderQueen.java new file mode 100644 index 00000000..4d0b6e9d --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/SpiderQueen.java @@ -0,0 +1,665 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs; + +import java.util.ArrayList; +import java.util.HashSet; + +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.Badges.Badge; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.Blob; +import com.hmdzl.spspd.actors.blobs.ConfusionGas; +import com.hmdzl.spspd.actors.blobs.DarkGas; +import com.hmdzl.spspd.actors.blobs.SlowWeb; +import com.hmdzl.spspd.actors.blobs.ToxicGas; +import com.hmdzl.spspd.actors.buffs.Amok; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.DefenceUp; +import com.hmdzl.spspd.actors.buffs.Poison; +import com.hmdzl.spspd.actors.buffs.Roots; +import com.hmdzl.spspd.actors.buffs.Sleep; +import com.hmdzl.spspd.actors.buffs.Slow; +import com.hmdzl.spspd.actors.buffs.Terror; +import com.hmdzl.spspd.actors.buffs.Vertigo; +import com.hmdzl.spspd.effects.Pushing; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.effects.particles.ElmoParticle; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.items.TomeOfMastery; +import com.hmdzl.spspd.items.artifacts.RobotDMT; +import com.hmdzl.spspd.items.food.meatfood.MysteryMeat; +import com.hmdzl.spspd.items.scrolls.ScrollOfTeleportation; +import com.hmdzl.spspd.levels.CavesBossLevel; +import com.hmdzl.spspd.levels.features.Door; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.items.journalpages.Sokoban3; +import com.hmdzl.spspd.items.keys.SkeletonKey; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.Terrain; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.SpiderEggSprite; +import com.hmdzl.spspd.sprites.SpiderGoldSprite; +import com.hmdzl.spspd.sprites.SpiderJumpSprite; +import com.hmdzl.spspd.sprites.SpiderMindSprite; +import com.hmdzl.spspd.sprites.SpiderNormalSprite; +import com.hmdzl.spspd.sprites.SpiderQueenSprite; +import com.hmdzl.spspd.utils.GLog; + +import com.watabou.utils.Random; + +public class SpiderQueen extends Mob { + + { + spriteClass = SpiderQueenSprite.class; + + HP = HT = 1000; + EXP = 50; + evadeSkill = 35; + baseSpeed = 0.8f; + + loot = new RobotDMT().identify(); + lootChance = 0.2f; + + lootOther = Generator.Category.ARMOR; + lootChance = 1f; + + properties.add(Property.BEAST); + properties.add(Property.BOSS); + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(21, 36); + } + + @Override + public int hitSkill(Char target) { + return 40; + } + + @Override + public int drRoll() { + return Random.NormalIntRange(5, 20); + } + + @Override + public boolean act() { + boolean result = super.act(); + + if (state == FLEEING && buff(Terror.class) == null && enemy != null + && enemySeen && enemy.buff(Poison.class) == null) { + 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(7, 9) * Poison.durationFactor(enemy)); + state = FLEEING; + } + + return damage; + } + + @Override + public void move(int step) { + super.move(step); + + if (Dungeon.level.map[step] == Terrain.INACTIVE_TRAP ) { + sprite.emitter().burst(ElmoParticle.FACTORY, 5); + + ArrayList candidates = new ArrayList(); + boolean[] passable = Level.passable; + int[] neighbours = { pos + 1, pos - 1, pos + Level.getWidth(), + pos - Level.getWidth() }; + for (int n : neighbours) { + if (passable[n] && Actor.findChar(n) == null) { + candidates.add(n); + } + } + if (candidates.size() > 0) { + + SpiderEgg segg = new SpiderEgg(); + segg.HP = 25; + segg.pos = Random.element(candidates); + segg.state = segg.PASSIVE; + + if (Dungeon.level.map[segg.pos] == Terrain.DOOR) { + Door.enter(segg.pos); + } + + GameScene.add(segg, 1f); + Actor.addDelayed(new Pushing(segg, pos, segg.pos), -1); + damage(1,this); + } + + if (Dungeon.visible[step] && Dungeon.hero.isAlive()) { + GLog.n(Messages.get(this,"egg")); + } + } + + } + + @Override + public void die(Object cause) { + + GameScene.bossSlain(); + ((CavesBossLevel) Dungeon.level).unseal(); + Dungeon.level.drop(new SkeletonKey(Dungeon.depth), pos).sprite.drop(); + Badges.validateBossSlain(); + + 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; + case PERFORMER: + badgeToCheck = Badge.MASTERY_PERFORMER; + break; + case SOLDIER: + badgeToCheck = Badge.MASTERY_SOLDIER; + break; + case FOLLOWER: + badgeToCheck = Badge.MASTERY_FOLLOWER; + break; + } + + Dungeon.level.drop(new TomeOfMastery(), pos).sprite.drop(); + + Dungeon.level.drop(new Sokoban3(), pos).sprite.drop(); + yell(Messages.get(this,"die")); + super.die(cause); + } + + @Override + public void notice() { + super.notice(); + yell(Messages.get(this, "notice")); + } + + private static final HashSet> RESISTANCES = new HashSet>(); + + static { + RESISTANCES.add(Poison.class); + } + + @Override + public HashSet> resistances() { + return RESISTANCES; + } + + private static final HashSet> IMMUNITIES = new HashSet>(); + + static { + IMMUNITIES.add(Slow.class); + IMMUNITIES.add(Roots.class); + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } + + private class Fleeing extends Mob.Fleeing { + @Override + protected void nowhereToRun() { + if (buff(Terror.class) == null) { + state = HUNTING; + } else { + super.nowhereToRun(); + } + } + } + + public static class SpiderEgg extends Mob { + + { + spriteClass = SpiderEggSprite.class; + + HP = HT = 25; + evadeSkill = 0; + + EXP = 0; + + state = PASSIVE; + properties.add(Property.UNKNOW); + properties.add(Property.BOSS); + } + + private int life_p=0; + + @Override + public void beckon(int cell) { + // Do nothing + } + + @Override + public void die(Object cause) { + super.die(cause); + if (life_p > 20){ + SpiderGold.spawnAt(pos); + } else if(life_p > 10) { + SpiderJumper.spawnAt(pos); + } else if(life_p > 5 ){ + SpiderMind.spawnAt(pos); + } else SpiderWorker.spawnAt(pos); + } + + @Override + public int hitSkill(Char target) { + return 0; + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(0, 1); + } + + @Override + public int drRoll() { + return 0; + } + + @Override + public boolean act() { + for (int i = 0; i < Level.NEIGHBOURS9DIST2.length; i++) { + GameScene.add(Blob.seed(pos + Level.NEIGHBOURS9DIST2[i], 2, + SlowWeb.class)); + } + life_p ++; + damage(1,this); + return super.act(); + } + + private static final HashSet> IMMUNITIES = new HashSet>(); + static { + IMMUNITIES.add(Amok.class); + IMMUNITIES.add(Sleep.class); + IMMUNITIES.add(Terror.class); + IMMUNITIES.add(Poison.class); + IMMUNITIES.add(Vertigo.class); + IMMUNITIES.add(ToxicGas.class); + IMMUNITIES.add(Slow.class); + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } + } + + public static class SpiderWorker extends Mob { + + { + spriteClass = SpiderNormalSprite.class; + + HP = HT = 150; + evadeSkill = 10; + + EXP = 9; + maxLvl = 16; + + loot = new MysteryMeat(); + lootChance = 0.15f; + + properties.add(Property.BEAST); + } + + private static final float SPAWN_DELAY = 1f; + + @Override + public int damageRoll() { + return Random.NormalIntRange(12, 26+adj(0)); + } + + @Override + public int hitSkill(Char target) { + return 20+adj(0); + } + + @Override + public int drRoll() { + return Random.NormalIntRange(6, 10); + } + + + private static final HashSet> RESISTANCES = new HashSet>(); + + static { + RESISTANCES.add(Poison.class); + } + + @Override + public HashSet> resistances() { + return RESISTANCES; + } + + private static final HashSet> IMMUNITIES = new HashSet>(); + + static { + IMMUNITIES.add(Roots.class); + IMMUNITIES.add(SlowWeb.class); + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } + + public static SpiderWorker spawnAt(int pos) { + + SpiderWorker b = new SpiderWorker(); + + b.pos = pos; + b.state = b.HUNTING; + GameScene.add(b, SPAWN_DELAY); + + return b; + + } + } + + public static class SpiderMind extends SpiderWorker { + + { + spriteClass = SpiderMindSprite.class; + + HP = HT = 100; + evadeSkill = 20; + + properties.add(Property.BEAST); + } + + private static final float SPAWN_DELAY = 1f; + + @Override + public int damageRoll() { + return Random.NormalIntRange(5, 10+adj(0)); + } + + @Override + public int hitSkill(Char target) { + return 20+adj(0); + } + + @Override + public int drRoll() { + return 0; + } + + @Override + public int attackProc(Char enemy, int damage) { + int reg = Random.Int(damage); + if (reg > 0) { + HP += reg; + sprite.emitter().burst(Speck.factory(Speck.HEALING), 1); + } + return damage; + } + + + @Override + public boolean act() { + GameScene.add(Blob.seed(pos, 15, DarkGas.class)); + return super.act(); + } + + private static final HashSet> RESISTANCES = new HashSet>(); + + static { + RESISTANCES.add(Poison.class); + } + + @Override + public HashSet> resistances() { + return RESISTANCES; + } + + private static final HashSet> IMMUNITIES = new HashSet>(); + + static { + IMMUNITIES.add(Roots.class); + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } + + public static SpiderMind spawnAt(int pos) { + + SpiderMind b = new SpiderMind(); + + b.pos = pos; + b.state = b.HUNTING; + GameScene.add(b, SPAWN_DELAY); + + return b; + + } + } + public static class SpiderJumper extends SpiderWorker{ + + private static final int BLINK_DELAY = 3; + + private int delay = 0; + + { + spriteClass = SpiderJumpSprite.class; + + HP = HT = 150; + evadeSkill = 10; + + properties.add(Property.BEAST); + } + + private static final float SPAWN_DELAY = 1f; + + @Override + public int damageRoll() { + return Random.NormalIntRange(12, 26+adj(0)); + } + + @Override + public int hitSkill(Char target) { + return 20+adj(0); + } + + @Override + public int drRoll() { + return Random.NormalIntRange(6, 10); + } + + @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) { + + Ballistica route = new Ballistica( pos, target, Ballistica.PROJECTILE); + int cell = route.collisionPos; + + //can't occupy the same cell as another char, so move back one. + if (Actor.findChar( cell ) != null && cell != this.pos) + cell = route.path.get(route.dist-1); + + if (Level.avoid[ cell ]){ + ArrayList candidates = new ArrayList<>(); + for (int n : Level.NEIGHBOURS8) { + cell = route.collisionPos + n; + if (Level.passable[cell] && Actor.findChar( cell ) == null) { + candidates.add( cell ); + } + } + if (candidates.size() > 0) + cell = Random.element(candidates); + else { + delay = BLINK_DELAY; + return; + } + } + + ScrollOfTeleportation.appear( this, cell ); + + delay = BLINK_DELAY; + } + + private static final HashSet> RESISTANCES = new HashSet>(); + + static { + RESISTANCES.add(Poison.class); + } + + @Override + public HashSet> resistances() { + return RESISTANCES; + } + + private static final HashSet> IMMUNITIES = new HashSet>(); + + static { + IMMUNITIES.add(Roots.class); + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } + + public static SpiderJumper spawnAt(int pos) { + + SpiderJumper b = new SpiderJumper(); + + b.pos = pos; + b.state = b.HUNTING; + GameScene.add(b, SPAWN_DELAY); + + return b; + + } + } + public static class SpiderGold extends SpiderWorker { + + { + spriteClass = SpiderGoldSprite.class; + + HP = HT = 300; + evadeSkill = 5; + baseSpeed = 0.75f; + + properties.add(Property.BEAST); + } + + private static final float SPAWN_DELAY = 1f; + + @Override + public int damageRoll() { + return Random.NormalIntRange(20, 30+adj(0)); + } + + @Override + public int hitSkill(Char target) { + return 40+adj(0); + } + + @Override + public int drRoll() { + return Random.NormalIntRange(0, 10); + } + + @Override + public boolean act() { + GameScene.add(Blob.seed(pos, 15, ConfusionGas.class)); + return super.act(); + } + + @Override + public int defenseProc(Char enemy, int damage) { + + Buff.affect(this,DefenceUp.class,3f).level(20); + + return super.defenseProc(enemy, damage); + } + + private static final HashSet> RESISTANCES = new HashSet>(); + + static { + RESISTANCES.add(Poison.class); + } + + @Override + public HashSet> resistances() { + return RESISTANCES; + } + + private static final HashSet> IMMUNITIES = new HashSet>(); + + static { + IMMUNITIES.add(ConfusionGas.class); + IMMUNITIES.add(Roots.class); + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } + + public static SpiderGold spawnAt(int pos) { + + SpiderGold b = new SpiderGold(); + + b.pos = pos; + b.state = b.HUNTING; + GameScene.add(b, SPAWN_DELAY); + + return b; + + } + } + + +} diff --git a/java/com/hmdzl/spspd/actors/mobs/Spinner.java b/java/com/hmdzl/spspd/actors/mobs/Spinner.java new file mode 100644 index 00000000..ca24ff1f --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/Spinner.java @@ -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 + */ +package com.hmdzl.spspd.actors.mobs; + +import java.util.HashSet; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.Blob; +import com.hmdzl.spspd.actors.blobs.Web; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Poison; +import com.hmdzl.spspd.actors.buffs.Roots; +import com.hmdzl.spspd.actors.buffs.Terror; +import com.hmdzl.spspd.items.food.meatfood.MysteryMeat; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.SpinnerSprite; +import com.watabou.utils.Random; + +public class Spinner extends Mob { + + { + spriteClass = SpinnerSprite.class; + + HP = HT = 120+(adj(0)*Random.NormalIntRange(5, 7)); + evadeSkill = 14+adj(1); + + EXP = 9; + maxLvl = 25; + + loot = new MysteryMeat(); + lootChance = 0.15f; + + FLEEING = new Fleeing(); + + properties.add(Property.BEAST); + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(12, 26+adj(0)); + } + + @Override + public int hitSkill(Char target) { + return 20+adj(0); + } + + @Override + public int drRoll() { + return Random.NormalIntRange(6, 10); + } + + @Override + protected boolean act() { + boolean result = super.act(); + + if (state == FLEEING && buff(Terror.class) == null && enemy != null + && enemySeen && enemy.buff(Poison.class) == null) { + 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(7, 9) * Poison.durationFactor(enemy)); + state = FLEEING; + } + + return damage; + } + + @Override + public void move(int step) { + if (state == FLEEING) { + GameScene.add(Blob.seed(pos, Random.Int(5, 7), Web.class)); + } + super.move(step); + } + + private static final HashSet> RESISTANCES = new HashSet>(); + + static { + RESISTANCES.add(Poison.class); + } + + @Override + public HashSet> resistances() { + return RESISTANCES; + } + + private static final HashSet> IMMUNITIES = new HashSet>(); + + static { + IMMUNITIES.add(Roots.class); + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } + + private class Fleeing extends Mob.Fleeing { + @Override + protected void nowhereToRun() { + if (buff(Terror.class) == null) { + state = HUNTING; + } else { + super.nowhereToRun(); + } + } + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/Statue.java b/java/com/hmdzl/spspd/actors/mobs/Statue.java new file mode 100644 index 00000000..bfc04d31 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/Statue.java @@ -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 + */ +package com.hmdzl.spspd.actors.mobs; + +import java.util.HashSet; + +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.Journal; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.ToxicGas; +import com.hmdzl.spspd.actors.buffs.Poison; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.items.weapon.Weapon; +import com.hmdzl.spspd.items.weapon.Weapon.Enchantment; +import com.hmdzl.spspd.items.weapon.enchantments.EnchantmentDark; + +import com.hmdzl.spspd.items.weapon.melee.MeleeWeapon; +import com.hmdzl.spspd.sprites.StatueSprite; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public class Statue extends Mob { + + { + spriteClass = StatueSprite.class; + + EXP = 50 + Dungeon.depth * 2; + state = PASSIVE; + + properties.add(Property.ELEMENT); + } + + private Weapon weapon; + + public Statue() { + super(); + + do { + weapon = (Weapon) Generator.random(Generator.Category.OLDWEAPON); + } while (!(weapon instanceof MeleeWeapon) || weapon.level < 0); + + weapon.identify(); + weapon.enchant(Enchantment.random()); + + HP = HT = 15 + Dungeon.depth * 5; + evadeSkill = 4 + Dungeon.depth * 2; + } + + 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 hitSkill(Char target) { + return (int) ((9 + Dungeon.depth) * weapon.ACU); + } + + @Override + protected float attackDelay() { + return weapon.DLY; + } + + @Override + public int drRoll() { + return Random.NormalIntRange(0, Dungeon.depth); + } + + @Override + protected boolean canAttack(Char enemy) { + return Dungeon.level.distance( pos, enemy.pos ) <= weapon.RCH; + } + + @Override + public void damage(int dmg, Object src) { + + if (state == PASSIVE) { + 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) { + // Do nothing + } + + @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 = PASSIVE; + return true; + } + + @Override + public String description() { + return Messages.get(this, "desc", weapon.name()); + } + + private static final HashSet> RESISTANCES = new HashSet>(); + private static final HashSet> IMMUNITIES = new HashSet>(); + static { + RESISTANCES.add(ToxicGas.class); + RESISTANCES.add(Poison.class); + RESISTANCES.add(EnchantmentDark.class); + + } + + @Override + public HashSet> resistances() { + return RESISTANCES; + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/Succubus.java b/java/com/hmdzl/spspd/actors/mobs/Succubus.java new file mode 100644 index 00000000..b6203d27 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/Succubus.java @@ -0,0 +1,169 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs; + +import java.util.ArrayList; +import java.util.HashSet; + +import com.hmdzl.spspd.actors.buffs.Silent; +import com.hmdzl.spspd.items.scrolls.ScrollOfTeleportation; +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Charm; +import com.hmdzl.spspd.actors.buffs.Light; +import com.hmdzl.spspd.actors.buffs.Sleep; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.food.meatfood.MysteryMeat; +import com.hmdzl.spspd.items.scrolls.ScrollOfLullaby; + +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.sprites.SuccubusSprite; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Random; + +public class Succubus extends Mob { + + private static final int BLINK_DELAY = 5; + + private int delay = 0; + + { + spriteClass = SuccubusSprite.class; + + HP = HT = 110+(adj(0)*Random.NormalIntRange(5, 7)); + evadeSkill = 25+adj(1); + viewDistance = Light.DISTANCE; + + EXP = 12; + maxLvl = 35; + + loot = new ScrollOfLullaby(); + lootChance = 0.05f; + + lootOther = new MysteryMeat(); + lootChanceOther = 0.1f; // by default, see die() + + properties.add(Property.DEMONIC); + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(15, 25+adj(0)); + } + + @Override + public int attackProc(Char enemy, int damage) { + + if (Random.Int(3) == 0) { + Buff.affect(enemy, Charm.class, Charm.durationFactor(enemy) + * Random.IntRange(3, 7)).object = id(); + enemy.sprite.centerEmitter().start(Speck.factory(Speck.HEART), + 0.2f, 5); + Sample.INSTANCE.play(Assets.SND_CHARMS); + } + + int reg = Math.min(damage, HT - HP); + + if (reg > 0) { + HP += reg; + sprite.emitter().burst(Speck.factory(Speck.HEALING), 1); + } + + return damage; + } + + @Override + protected boolean getCloser(int target) { + if (Level.fieldOfView[target] && Level.distance(pos, target) > 2 + && delay <= 0 &&(buff(Silent.class) == null) ) { + + blink(target); + spend(-1 / speed()); + return true; + + } else { + + delay--; + return super.getCloser(target); + + } + } + + private void blink(int target) { + + Ballistica route = new Ballistica( pos, target, Ballistica.PROJECTILE); + int cell = route.collisionPos; + + //can't occupy the same cell as another char, so move back one. + if (Actor.findChar( cell ) != null && cell != this.pos) + cell = route.path.get(route.dist-1); + + if (Level.avoid[ cell ]){ + ArrayList candidates = new ArrayList<>(); + for (int n : Level.NEIGHBOURS8) { + cell = route.collisionPos + n; + if (Level.passable[cell] && Actor.findChar( cell ) == null) { + candidates.add( cell ); + } + } + if (candidates.size() > 0) + cell = Random.element(candidates); + else { + delay = BLINK_DELAY; + return; + } + } + + ScrollOfTeleportation.appear( this, cell ); + + delay = BLINK_DELAY; + } + + @Override + public int hitSkill(Char target) { + return 40+adj(1); + } + + @Override + public int drRoll() { + return Random.NormalIntRange(5, 10); + } + + private static final HashSet> RESISTANCES = new HashSet>(); + static { + + } + + @Override + public HashSet> resistances() { + return RESISTANCES; + } + + private static final HashSet> IMMUNITIES = new HashSet>(); + static { + IMMUNITIES.add(Sleep.class); + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/Sufferer.java b/java/com/hmdzl/spspd/actors/mobs/Sufferer.java new file mode 100644 index 00000000..2aca7caa --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/Sufferer.java @@ -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 + */ +package com.hmdzl.spspd.actors.mobs; + +import java.util.HashSet; + +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.GlassShield; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Amok; +import com.hmdzl.spspd.actors.buffs.Sleep; +import com.hmdzl.spspd.actors.buffs.Terror; + +import com.hmdzl.spspd.sprites.SuffererSprite; +import com.watabou.utils.Random; + +public class Sufferer extends Mob { + + { + spriteClass = SuffererSprite.class; + + HP = HT = 180+(adj(0)*Random.NormalIntRange(4, 7)); + evadeSkill = 16+adj(1); + + EXP = 16; + maxLvl = 35; + + loot = Generator.Category.SCROLL; + lootChance = 0.35f; + + properties.add(Property.DEMONIC); + properties.add(Property.HUMAN); + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(12+adj(0), 40+adj(1)); + } + + @Override + public int hitSkill(Char target) { + return 34+adj(1); + } + + + @Override + public int drRoll() { + return Random.NormalIntRange(0, 10); + } + + @Override + public int defenseProc(Char enemy, int damage) { + + int dmg = damage; + if (dmg > 50 && buff(GlassShield.class) == null) { + Buff.affect(this,GlassShield.class).turns(4); + } + + return super.defenseProc(enemy, damage); + } + + private static final HashSet> RESISTANCES = new HashSet>(); + + @Override + public HashSet> resistances() { + return RESISTANCES; + } + + private static final HashSet> IMMUNITIES = new HashSet>(); + static { + IMMUNITIES.add(Amok.class); + IMMUNITIES.add(Terror.class); + IMMUNITIES.add(Sleep.class); + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/Swarm.java b/java/com/hmdzl/spspd/actors/mobs/Swarm.java new file mode 100644 index 00000000..d3adb0d3 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/Swarm.java @@ -0,0 +1,146 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Burning; +import com.hmdzl.spspd.actors.buffs.Poison; +import com.hmdzl.spspd.effects.Pushing; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.potions.PotionOfMending; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.Terrain; +import com.hmdzl.spspd.levels.features.Door; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.SwarmSprite; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public class Swarm extends Mob { + + { + spriteClass = SwarmSprite.class; + + HP = HT = 60; + evadeSkill = 5; + + maxLvl = 10; + + flying = true; + + loot = new PotionOfMending(); + //loot = new PotionOfMending(); potential nerf + lootChance = 0.1f; // by default, see die() + + properties.add(Property.BEAST); + } + + 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(4, 7); + } + + @Override + public int defenseProc(Char enemy, int damage) { + + if (HP >= damage + 2) { + ArrayList candidates = new ArrayList(); + boolean[] passable = Level.passable; + + int[] neighbours = { pos + 1, pos - 1, pos + Level.getWidth(), + pos - Level.getWidth() }; + 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 = clone.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 hitSkill(Char target) { + return 10; + } + + 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 + public void die(Object cause) { + // sets drop chance + lootChance = 0.5f / (5 / (generation + 1)); + super.die(cause); + } + + @Override + protected Item createLoot() { + return super.createLoot(); + } + +} diff --git a/java/com/hmdzl/spspd/actors/mobs/Tank.java b/java/com/hmdzl/spspd/actors/mobs/Tank.java new file mode 100644 index 00000000..4a848601 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/Tank.java @@ -0,0 +1,266 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs; + +import java.util.ArrayList; +import java.util.HashSet; + +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Vertigo; +import com.hmdzl.spspd.items.ArmorKit; +import com.hmdzl.spspd.items.TenguKey; +import com.hmdzl.spspd.items.artifacts.DriedRose; +import com.hmdzl.spspd.items.potions.PotionOfToxicGas; +import com.hmdzl.spspd.items.wands.WandOfFlow; +import com.hmdzl.spspd.items.wands.WandOfLight; +import com.hmdzl.spspd.items.weapon.enchantments.EnchantmentLight; +import com.hmdzl.spspd.levels.PrisonBossLevel; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.ToxicGas; +import com.hmdzl.spspd.actors.buffs.Poison; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.journalpages.Sokoban2; +import com.hmdzl.spspd.items.keys.SkeletonKey; +import com.hmdzl.spspd.items.weapon.enchantments.EnchantmentDark; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.Terrain; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.TankSprite; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.noosa.Camera; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Random; + +public class Tank extends Mob { + + private static final int JUMP_DELAY = 20; + + { + spriteClass = TankSprite.class; + + HP = HT = 1000; + EXP = 40; + evadeSkill = 5; + viewDistance = 4; + + properties.add(Property.UNDEAD); + properties.add(Property.BOSS); + + loot = new DriedRose().identify(); + lootChance = 0.2f; + + lootOther = new PotionOfToxicGas(); + lootChanceOther = 1f; // by default, see die() + + } + + private int timeToJump = JUMP_DELAY; + private boolean rock = true; + + @Override + public int damageRoll() { + return Random.NormalIntRange(40, 65); + } + + @Override + public int hitSkill(Char target) { + return 60; + } + + @Override + public int drRoll() { + return 0; + } + + @Override + protected float attackDelay() { + return 3f; + } + + @Override + public void die(Object cause) { + yell(Messages.get(this,"die")); + + GameScene.bossSlain(); + + Badges.validateBossSlain(); + + ((PrisonBossLevel) Dungeon.level).unseal(); + + + Dungeon.level.drop(new ArmorKit(), pos).sprite.drop(); + + Dungeon.level.drop(new Sokoban2(), pos).sprite.drop(); + Dungeon.level.drop(new SkeletonKey(Dungeon.depth), pos).sprite.drop(); + Dungeon.level.drop(new TenguKey(), pos).sprite.drop(); + + super.die(cause); + } + + @Override + public boolean act() { + Dungeon.level.updateFieldOfView( this ); + timeToJump--; + if (timeToJump == 0 ) { + jump(); + rock=false; + } + if (!rock&& timeToJump > 5 && timeToJump < 15 && state == HUNTING && + paralysed <= 0 && + enemy != null && + enemy.invisible == 0 && + Level.fieldOfView[enemy.pos] && + Level.distance( pos, enemy.pos ) < 5 && !Level.adjacent( pos, enemy.pos ) && + Random.Int(3) == 0 && HP > 0 ) { + rockattack(); + } + + return super.act(); + } + + @Override + public void move(int step) { + super.move(step); + + int[] cells = { step - 1, step + 1, step - Level.getWidth(), + step + Level.getWidth(), step - 1 - Level.getWidth(), + step - 1 + Level.getWidth(), step + 1 - Level.getWidth(), + step + 1 + Level.getWidth() }; + 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); + } + + Char ch = Actor.findChar(cell); + if (ch != null && ch != this) { + Buff.prolong(ch, Vertigo.class, 2f); + } + } + + @Override + public int attackProc(Char enemy, int damage) { + int oppositeDefender = enemy.pos + (enemy.pos - pos); + Ballistica trajectory = new Ballistica(enemy.pos, oppositeDefender, Ballistica.MAGIC_BOLT); + WandOfFlow.throwChar(enemy, trajectory, 1); + Buff.affect(enemy, Vertigo.class,3f); + return damage; + } + + private void jump() { + timeToJump = JUMP_DELAY; + int heropos = Dungeon.hero.pos; + ArrayList candidates = new ArrayList(); + boolean[] passable = Level.passable; + int[] heroneighbours = {heropos - 1, heropos + 1, heropos - Level.getWidth(), + heropos + Level.getWidth(), heropos - 1 - Level.getWidth(), + heropos - 1 + Level.getWidth(), heropos + 1 - Level.getWidth(), + heropos + 1 + Level.getWidth()}; + for (int n : heroneighbours) { + if (passable[n] && Actor.findChar(n) == null) { + candidates.add(n); + } + + if (candidates.size() > 0) { + int newPos; + newPos = Random.element(candidates); + sprite.move(pos, newPos); + move(newPos); + + + for (int n2 : Level.NEIGHBOURS8) { + int blockpos = newPos + n2; + if (blockpos > 0 && Dungeon.level.map[blockpos] == Terrain.WALL) { + Level.set(blockpos, Terrain.EMBERS); + GameScene.updateMap(blockpos); + } + } + + } + } + spend(2f); + } + + private void rockattack() { + rock = true; + int heropos = Dungeon.hero.pos; + ArrayList candidates = new ArrayList(); + boolean[] passable = Level.passable; + + int[] heroneighbours2 = { heropos + 1, heropos - 1, heropos + Level.getWidth(), + heropos - Level.getWidth() }; + for (int n : heroneighbours2) { + if (passable[n] && Actor.findChar(n) == null) { + candidates.add(n); + } + } + if (candidates.size() > 0) { + int rockpos; + rockpos = Random.element(candidates); + + Level.set(rockpos, Terrain.WALL); + GameScene.updateMap(rockpos); + + for (int n : Level.NEIGHBOURS8) { + Char ch = Actor.findChar(n+rockpos); + if (ch != null && ch.isAlive()) { + ch.damage(15,this); + } + } + } + + GLog.n(Messages.get(Tank.class,"rock")); + } + + @Override + public void notice() { + super.notice(); + yell(Messages.get(this, "notice")); + } + + private static final HashSet> RESISTANCES = new HashSet>(); + private static final HashSet> WEAKNESS = new HashSet>(); + static { + WEAKNESS.add(WandOfLight.class); + WEAKNESS.add(EnchantmentLight.class); + + RESISTANCES.add(ToxicGas.class); + RESISTANCES.add(Poison.class); + RESISTANCES.add(EnchantmentDark.class); + + } + + @Override + public HashSet> resistances() { + return RESISTANCES; + } + + @Override + public HashSet> weakness() { + return WEAKNESS; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/Tengu.java b/java/com/hmdzl/spspd/actors/mobs/Tengu.java new file mode 100644 index 00000000..f1ca08ea --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/Tengu.java @@ -0,0 +1,223 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs; + +import java.util.HashSet; + +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Burning; +import com.hmdzl.spspd.actors.buffs.Locked; +import com.hmdzl.spspd.actors.buffs.Silent; +import com.hmdzl.spspd.items.ArmorKit; +import com.hmdzl.spspd.items.TenguKey; +import com.hmdzl.spspd.items.artifacts.MasterThievesArmband; +import com.hmdzl.spspd.items.wands.WandOfLight; +import com.hmdzl.spspd.items.weapon.enchantments.EnchantmentLight; +import com.hmdzl.spspd.items.weapon.missiles.HugeShuriken; +import com.hmdzl.spspd.levels.PrisonBossLevel; +import com.hmdzl.spspd.levels.traps.PoisonTrap; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.ToxicGas; +import com.hmdzl.spspd.actors.buffs.Poison; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.journalpages.Sokoban2; +import com.hmdzl.spspd.items.keys.SkeletonKey; +import com.hmdzl.spspd.items.scrolls.ScrollOfMagicMapping; +import com.hmdzl.spspd.items.weapon.enchantments.EnchantmentDark; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.Terrain; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.TenguSprite; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Random; + +public class Tengu extends Mob { + + private static final int JUMP_DELAY = 5; + + { + spriteClass = TenguSprite.class; + + HP = HT = 600; + EXP = 40; + evadeSkill = 30; + viewDistance = 5; + + properties.add(Property.HUMAN); + properties.add(Property.BOSS); + + loot = new MasterThievesArmband().identify(); + lootChance = 0.2f; + + lootOther = new HugeShuriken(20); + lootChanceOther = 1f; // by default, see die() + + } + + private int timeToJump = JUMP_DELAY; + + + @Override + public int damageRoll() { + return Random.NormalIntRange(23, 35); + } + + @Override + public int hitSkill(Char target) { + return 40; + } + + @Override + public int drRoll() { + return Random.NormalIntRange(0, 5); + } + + @Override + public void die(Object cause) { + yell(Messages.get(this,"die")); + GameScene.bossSlain(); + Badges.validateBossSlain(); + ((PrisonBossLevel) Dungeon.level).unseal(); + Dungeon.level.drop(new ArmorKit(), pos).sprite.drop(); + Dungeon.level.drop(new Sokoban2(), pos).sprite.drop(); + Dungeon.level.drop(new SkeletonKey(Dungeon.depth), pos).sprite.drop(); + Dungeon.level.drop(new TenguKey(), pos).sprite.drop(); + super.die(cause); + } + + @Override + protected boolean getCloser(int target) { + if (Level.fieldOfView[target]) { + jump(); + return true; + } else { + return super.getCloser(target); + } + } + + @Override + protected boolean canAttack(Char enemy) { + if (buff(Locked.class) != null){ + return Level.adjacent(pos, enemy.pos) && (!isCharmedBy(enemy)); + } else + return new Ballistica( pos, enemy.pos, Ballistica.PROJECTILE).collisionPos == 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); + } + } + + @Override + public int attackProc(Char enemy, int damage) { + + if (Level.distance(pos, enemy.pos) == 1 ) { + Buff.affect(enemy,Silent.class,.5f); + timeToJump--; + } + + if (Level.distance(pos, enemy.pos) > 1 && Random.Int(10) > 7){ + Buff.affect(enemy, Locked.class,5f); + timeToJump++; + } + + if (Level.distance(pos, enemy.pos) > 1 && Random.Int(10) > 9){ + Buff.affect(enemy, Burning.class).reignite(enemy); + timeToJump++; + } + + return damage; + } + + private void jump() { + timeToJump = JUMP_DELAY; + + for (int i = 0; i < 3; i++) { + int trapPos; + do { + trapPos = Random.Int(Level.getLength()); + } while (!Level.fieldOfView[trapPos] || !Level.passable[trapPos]); + + if (Dungeon.level.map[trapPos] == Terrain.INACTIVE_TRAP) { + Dungeon.level.setTrap( new PoisonTrap().reveal(), trapPos ); + Level.set(trapPos, Terrain.TRAP); + GameScene.updateMap(trapPos); + ScrollOfMagicMapping.discover(trapPos); + } + } + + int newPos; + do { + newPos = Random.Int(Level.getLength()); + } 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(Messages.get(this, "notice", Dungeon.hero.givenName())); + } + + private static final HashSet> RESISTANCES = new HashSet>(); + private static final HashSet> WEAKNESS = new HashSet>(); + static { + WEAKNESS.add(WandOfLight.class); + WEAKNESS.add(EnchantmentLight.class); + + RESISTANCES.add(Burning.class); + RESISTANCES.add(ToxicGas.class); + RESISTANCES.add(Poison.class); + RESISTANCES.add(EnchantmentDark.class); + + } + + @Override + public HashSet> resistances() { + return RESISTANCES; + } + + @Override + public HashSet> weakness() { + return WEAKNESS; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/TenguDen.java b/java/com/hmdzl/spspd/actors/mobs/TenguDen.java new file mode 100644 index 00000000..363141bd --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/TenguDen.java @@ -0,0 +1,209 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs; + +import java.util.HashSet; + +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Burning; +import com.hmdzl.spspd.actors.buffs.Locked; +import com.hmdzl.spspd.actors.buffs.Paralysis; +import com.hmdzl.spspd.actors.buffs.Slow; +import com.hmdzl.spspd.effects.particles.FlameParticle; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.ToxicGas; +import com.hmdzl.spspd.actors.buffs.Poison; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.AdamantRing; +import com.hmdzl.spspd.items.Gold; +import com.hmdzl.spspd.items.weapon.enchantments.EnchantmentDark; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.TenguSprite; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Random; + +public class TenguDen extends Mob { + + private static final int JUMP_DELAY = 5; + protected static final float SPAWN_DELAY = 2f; + + { + spriteClass = TenguSprite.class; + baseSpeed = 2f; + + HP = HT = 2000; + EXP = 20; + evadeSkill = 30; + + properties.add(Property.HUMAN); + properties.add(Property.BOSS); + } + + private int timeToJump = JUMP_DELAY; + + + @Override + public int damageRoll() { + return Random.NormalIntRange(15, 25); + } + + @Override + public int hitSkill(Char target) { + return 28; + } + + @Override + public int drRoll() { + return Random.NormalIntRange(10, 20); + } + + + + + @Override + public void die(Object cause) { + + super.die(cause); + + GameScene.bossSlain(); + Dungeon.tengudenkilled=true; + yell(Messages.get(this,"die")); + + Dungeon.level.drop(new AdamantRing(), pos).sprite.drop(); + Dungeon.level.drop(new Gold(Random.Int(1900, 4000)), pos).sprite.drop(); + + } + + @Override + protected boolean getCloser(int target) { + if (Level.fieldOfView[target]) { + jump(); + return true; + } else { + return super.getCloser(target); + } + } + + @Override + protected boolean canAttack(Char enemy) { + if (buff(Locked.class) != null){ + return Level.adjacent(pos, enemy.pos) && (!isCharmedBy(enemy)); + } else + return new Ballistica( pos, enemy.pos, Ballistica.PROJECTILE).collisionPos == enemy.pos; + } + + @Override + protected boolean doAttack(Char enemy) { + timeToJump--; + if (timeToJump <= 0 ) { + jump(); + return true; + } else { + return super.doAttack(enemy); + } + } + + @Override + public int attackProc(Char enemy, int damage) { + if(Random.Int(15)==0){ + Buff.affect(enemy, Burning.class).reignite(enemy); + enemy.sprite.emitter().burst(FlameParticle.FACTORY, 5); + } + if(Random.Int(20)==0){ + Buff.affect(enemy, Slow.class, Slow.duration(enemy) / 2); + } + + if(Random.Int(30)==0){ + Buff.prolong(enemy, Paralysis.class, 2f); + } + + return damage; + } + + + private void jump() { + timeToJump = JUMP_DELAY; + + int newPos; + do { + newPos = Random.Int(Level.getLength()); + } while (!Level.passable[newPos] + || Level.adjacent(newPos, Dungeon.hero.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()); + + if (Dungeon.level.mobs.size()<7){ + Assassin.spawnAt(pos); + } + + + } + + public static TenguDen spawnAt(int pos) { + if (Level.passable[pos] && Actor.findChar(pos) == null) { + + TenguDen w = new TenguDen(); + w.pos = pos; + w.state = w.HUNTING; + GameScene.add(w, SPAWN_DELAY); + + //w.sprite.alpha(0); + //w.sprite.parent.add(new AlphaTweener(w.sprite, 1, 0.5f)); + + return w; + + } else { + return null; + } + } + + @Override + public void notice() { + super.notice(); + yell(Messages.get(this,"notice")); + } + + private static final HashSet> RESISTANCES = new HashSet>(); + static { + RESISTANCES.add(ToxicGas.class); + RESISTANCES.add(Poison.class); + RESISTANCES.add(EnchantmentDark.class); + + } + + @Override + public HashSet> resistances() { + return RESISTANCES; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/TestMob.java b/java/com/hmdzl/spspd/actors/mobs/TestMob.java new file mode 100644 index 00000000..70ba4402 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/TestMob.java @@ -0,0 +1,146 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs; + +import com.hmdzl.spspd.actors.buffs.Amok; +import com.hmdzl.spspd.actors.buffs.Burning; +import com.hmdzl.spspd.actors.buffs.Charm; +import com.hmdzl.spspd.actors.buffs.Sleep; +import com.hmdzl.spspd.actors.buffs.Terror; +import com.hmdzl.spspd.actors.buffs.Vertigo; +import com.hmdzl.spspd.items.bags.HeartOfScarecrow; +import com.hmdzl.spspd.items.wands.WandOfFirebolt; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.sprites.ScarecrowSprite; +import com.watabou.utils.Bundle; + +import java.util.HashSet; + +public class TestMob extends Mob { + + + private boolean skill = false; + + { + spriteClass = ScarecrowSprite.class; + + HP = HT = 100000; + evadeSkill = 0; + + state = PASSIVE; + + properties.add(Property.PLANT); + } + + + @Override + public boolean act() { + //if( HP < HT && skill == false ) { + //Buff.affect(this,AttackUp.class,5f).level(20); + //Buff.affect(this,DefenceUp.class,5f).level(80); + // skill = true; + // } + return super.act(); + } + + @Override + public void damage(int dmg, Object src) { + + super.damage(dmg, src); + //if (dmg >5) Buff.affect(this,ShieldArmor.class).level(20); + //Buff.prolong(this,Levitation.class,10f); + } + + @Override + public int damageRoll() { + return 1; + } + + @Override + public int hitSkill(Char target) { + return 100; + } + + @Override + public int drRoll() { + return 0; + } + + + @Override + public void beckon(int cell) { + // Do nothing + } + + @Override + public void die(Object cause) { + super.die(cause); + if (!Dungeon.limitedDrops.heartScarecrow.dropped()) { + Dungeon.limitedDrops.heartScarecrow.drop(); + Dungeon.level.drop(new HeartOfScarecrow(), pos).sprite.drop(); + explodeDew(pos); + } + + } + + private static final HashSet> RESISTANCES = new HashSet>(); + private static final HashSet> WEAKNESS = new HashSet>(); + private static final HashSet> IMMUNITIES = new HashSet>(); + static { + WEAKNESS.add(Burning.class); + WEAKNESS.add(WandOfFirebolt.class); + //WEAKNESS.add(TestWeapon.class); + IMMUNITIES.add(Terror.class); + IMMUNITIES.add(Amok.class); + IMMUNITIES.add(Charm.class); + IMMUNITIES.add(Sleep.class); + IMMUNITIES.add(Vertigo.class); + } + + @Override + public HashSet> resistances() { + return RESISTANCES; + } + + @Override + public HashSet> weakness() { + return WEAKNESS; + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } + + + private final String SKILL = "skill"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(SKILL, skill); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + skill = bundle.getBoolean(SKILL); + } + +} diff --git a/java/com/hmdzl/spspd/actors/mobs/TestMob2.java b/java/com/hmdzl/spspd/actors/mobs/TestMob2.java new file mode 100644 index 00000000..e787e6b5 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/TestMob2.java @@ -0,0 +1,151 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs; + +import com.hmdzl.spspd.actors.blobs.ElectriShock; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Locked; +import com.hmdzl.spspd.actors.buffs.Shocked; +import com.hmdzl.spspd.actors.buffs.StoneIce; +import com.hmdzl.spspd.items.bags.HeartOfScarecrow; +import com.hmdzl.spspd.items.wands.WandOfLightning; +import com.hmdzl.spspd.items.weapon.enchantments.EnchantmentShock; +import com.hmdzl.spspd.items.weapon.enchantments.EnchantmentShock2; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.sprites.ScarecrowSprite; +import com.watabou.utils.Bundle; + +import java.util.HashSet; + +public class TestMob2 extends Mob { + + + private boolean skill = false; + + { + spriteClass = ScarecrowSprite.class; + + HP = HT = 100000; + evadeSkill = 0; + + state = PASSIVE; + + properties.add(Property.MECH); + } + + + @Override + public boolean act() { + //if( HP < HT && skill == false ) { + //Buff.affect(this,AttackUp.class,5f).level(20); + //Buff.affect(this,DefenceUp.class,5f).level(80); + // skill = true; + // } + return super.act(); + } + + @Override + public void damage(int dmg, Object src) { + + if (state == PASSIVE) { + state = HUNTING; + } + super.damage(dmg, src); + //Buff.prolong(this,Levitation.class,10f); + //Buff.prolong(this,ArmorBreak.class,10f).level(50); + } + + @Override + public int attackProc(Char enemy, int damage) { + Buff.affect(enemy,StoneIce.class).level(10); + return damage; + } + + @Override + public int damageRoll() { + return 5; + } + + @Override + public int hitSkill(Char target) { + return 100; + } + + @Override + public int drRoll() { + return 0; + } + + @Override + protected boolean canAttack(Char enemy) { + if (buff(Locked.class) != null){ + return Level.adjacent(pos, enemy.pos) && (!isCharmedBy(enemy)); + } else + return new Ballistica( pos, enemy.pos, Ballistica.PROJECTILE).collisionPos == enemy.pos; + } + + @Override + public void die(Object cause) { + super.die(cause); + + if (!Dungeon.limitedDrops.heartScarecrow.dropped()) { + Dungeon.limitedDrops.heartScarecrow.drop(); + Dungeon.level.drop(new HeartOfScarecrow(), pos).sprite.drop(); + explodeDew(pos); + } + + } + + private static final HashSet> RESISTANCES = new HashSet>(); + private static final HashSet> WEAKNESS = new HashSet>(); + static { + WEAKNESS.add(ElectriShock.class); + WEAKNESS.add(WandOfLightning.class); + WEAKNESS.add(EnchantmentShock.class); + WEAKNESS.add(EnchantmentShock2.class); + } + + @Override + public HashSet> resistances() { + return RESISTANCES; + } + + @Override + public HashSet> weakness() { + return WEAKNESS; + } + + + private final String SKILL = "skill"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(SKILL, skill); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + skill = bundle.getBoolean(SKILL); + } + +} diff --git a/java/com/hmdzl/spspd/actors/mobs/Thief.java b/java/com/hmdzl/spspd/actors/mobs/Thief.java new file mode 100644 index 00000000..acfcc681 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/Thief.java @@ -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 + */ +package com.hmdzl.spspd.actors.mobs; + +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Locked; +import com.hmdzl.spspd.items.food.vegetable.NutVegetable; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Terror; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.items.Gold; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.sprites.CharSprite; +import com.hmdzl.spspd.sprites.ThiefSprite; +import com.watabou.utils.Random; + +public class Thief extends Mob { + + public Item item; + + { + spriteClass = ThiefSprite.class; + + HP = HT = 80+(adj(0)*Random.NormalIntRange(3, 5)); + evadeSkill = 8+adj(0); + + EXP = 5; + maxLvl = 20; + + loot = new NutVegetable(); + lootChance = 0.1f; + + lootOther = Generator.Category.BERRY; + lootChanceOther = 0.05f; // by default, see die() + + FLEEING = new Fleeing(); + + properties.add(Property.ELF); + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(1, 7+adj(0)); + } + + @Override + protected float attackDelay() { + return 0.5f; + } + + @Override + protected boolean act() { + boolean result = super.act(); + + if (state == FLEEING && buff(Terror.class) == null && enemy != null + && enemySeen && enemy.buff(Locked.class) == null) { + state = HUNTING; + } + return result; + } + + @Override + public void die(Object cause) { + super.die(cause); + } + + @Override + protected Item createLoot() { + return super.createLoot(); + } + + @Override + public int hitSkill(Char target) { + return 12; + } + + @Override + public int drRoll() { + return Random.NormalIntRange(0, 3); + } + + @Override + public int attackProc(Char enemy, int damage) { + if (Random.Int(5) == 0) { + Buff.affect(enemy, Locked.class,20f); + state = FLEEING; + } + + return damage; + } + + @Override + public int defenseProc(Char enemy, int damage) { + if (state == FLEEING) { + Dungeon.level.drop(new Gold(), pos).sprite.drop(); + } + + return damage; + } + + private class Fleeing extends Mob.Fleeing { + @Override + protected void nowhereToRun() { + if (buff(Terror.class) == null) { + sprite.showStatus(CharSprite.NEGATIVE, Messages.get(Mob.class, "rage")); + state = HUNTING; + } else { + super.nowhereToRun(); + } + } + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/ThiefImp.java b/java/com/hmdzl/spspd/actors/mobs/ThiefImp.java new file mode 100644 index 00000000..118bd91e --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/ThiefImp.java @@ -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 + */ +package com.hmdzl.spspd.actors.mobs; + +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Terror; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.items.Gold; +import com.hmdzl.spspd.items.summon.Honeypot; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.sprites.CharSprite; +import com.hmdzl.spspd.sprites.ThiefImpSprite; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public class ThiefImp 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."; + protected static final String TXT_RATCHECK1 = "Spork is avail"; + protected static final String TXT_RATCHECK2 = "Spork is not avail"; + + public Item item; + + { + spriteClass = ThiefImpSprite.class; + + HP = HT = 200+(adj(0)*Random.NormalIntRange(4, 7)); + evadeSkill = 20+adj(1); + + EXP = 13; + maxLvl = 35; + + flying = true; + + loot = Generator.Category.BERRY; + lootChance = 0.05f; + + FLEEING = new Fleeing(); + + properties.add(Property.DEMONIC); + } + + 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(15, 25+adj(0)); + } + + + @Override + public void die(Object cause) { + + super.die(cause); + + if (item != null) { + Dungeon.level.drop(item, pos).sprite.drop(); + } + } + + @Override + protected Item createLoot() { + return new Gold(Random.NormalIntRange(100, 250)); + } + + @Override + public int hitSkill(Char target) { + return 30+adj(0); + } + + @Override + public int drRoll() { + return Random.NormalIntRange(10, 20); + } + + @Override + public int attackProc(Char enemy, int damage) { + if (item == null && enemy instanceof Hero && steal((Hero) enemy)) { + state = FLEEING; + } + + return damage; + } + + @Override + public int defenseProc(Char enemy, int damage) { + if (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 && !item.unique && item.level < 1 ) { + + Dungeon.quickslot.clearItem( item ); + item.updateQuickslot(); + GLog.w(Messages.get(ThiefImp.class, "stole", item.name())); + + if (item instanceof Honeypot) { + this.item = ((Honeypot) item).shatter(this, this.pos); + item.detach(hero.belongings.backpack); + } else { + this.item = item.detach( hero.belongings.backpack ); + if (item instanceof Honeypot.ShatteredPot) + ((Honeypot.ShatteredPot) item).setHolder(this); + } + + return true; + } else { + return false; + } + } + + @Override + public String description() { + String desc = super.description(); + + if (item != null) { + desc += Messages.get(this, "carries", item.name() ); + } + + return desc; + } + + private class Fleeing extends Mob.Fleeing { + @Override + protected void nowhereToRun() { + if (buff(Terror.class) == null) { + sprite.showStatus(CharSprite.NEGATIVE, Messages.get(Mob.class, "rage")); + state = HUNTING; + } else { + super.nowhereToRun(); + } + } + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/ThiefKing.java b/java/com/hmdzl/spspd/actors/mobs/ThiefKing.java new file mode 100644 index 00000000..466fe694 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/ThiefKing.java @@ -0,0 +1,116 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs; + +import java.util.HashSet; + +import com.hmdzl.spspd.actors.buffs.Locked; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.items.AdamantRing; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.items.Gold; +import com.hmdzl.spspd.levels.traps.LightningTrap; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ThiefKingSprite; +import com.watabou.utils.Callback; +import com.watabou.utils.Random; + +public class ThiefKing extends Mob implements Callback { + + + { + spriteClass = ThiefKingSprite.class; + + HP = HT = 2000; + evadeSkill = 28; + + EXP = 60; + flying = true; + + loot = Generator.Category.SCROLL; + lootChance = 1f; + + properties.add(Property.ELF); + properties.add(Property.BOSS); + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(20, 70); + } + + @Override + public int hitSkill(Char target) { + return 25; + } + + @Override + public int drRoll() { + return Random.NormalIntRange(6, 14); + } + + @Override + protected boolean canAttack(Char enemy) { + if (buff(Locked.class) != null){ + return Level.adjacent(pos, enemy.pos) && (!isCharmedBy(enemy)); + } else + return new Ballistica( pos, enemy.pos, Ballistica.PROJECTILE).collisionPos == enemy.pos; + } + + @Override + public void die(Object cause) { + + super.die(cause); + + GameScene.bossSlain(); + Dungeon.level.drop(new AdamantRing(), pos).sprite.drop(); + Dungeon.level.drop(new Gold(Random.Int(1900, 4000)), pos).sprite.drop(); + + + Dungeon.banditkingkilled=true; + + yell(Messages.get(this,"die")); + + } + + + @Override + public void call() { + next(); + } + + @Override + public void notice() { + super.notice(); + yell(Messages.get(this,"notice",Dungeon.hero.givenName())); + } + + private static final HashSet> RESISTANCES = new HashSet>(); + static { + RESISTANCES.add(LightningTrap.Electricity.class); + } + + @Override + public HashSet> resistances() { + return RESISTANCES; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/TrollWarrior.java b/java/com/hmdzl/spspd/actors/mobs/TrollWarrior.java new file mode 100644 index 00000000..a2a2f202 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/TrollWarrior.java @@ -0,0 +1,111 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs; + +import java.util.HashSet; + +import com.hmdzl.spspd.actors.buffs.AttackUp; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.DefenceUp; +import com.hmdzl.spspd.items.weapon.enchantments.EnchantmentDark; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.items.StoneOre; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.ToxicGas; +import com.hmdzl.spspd.actors.buffs.Poison; +import com.hmdzl.spspd.sprites.TrollWarriorSprite; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public class TrollWarrior extends Mob { + + private boolean endless = false; + + { + spriteClass = TrollWarriorSprite.class; + baseSpeed = 1.2f; + + HP = HT = 80+(5*Random.NormalIntRange(2, 5)); + EXP = 10; + maxLvl = 20; + evadeSkill = 15; + + loot = new StoneOre(); + lootChance = 0.2f; + + properties.add(Property.TROLL); + + } + + @Override + public boolean act() { + if( HP < HT && endless == false ) { + Buff.affect(this,AttackUp.class,8f).level(20); + Buff.affect(this,DefenceUp.class,8f).level(80); + endless = true; + yell(Messages.get(this,"angry"));} + return super.act(); + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(15, 30); + } + + @Override + public int hitSkill(Char target) { + return 30; + } + + @Override + public int drRoll() { + return Random.NormalIntRange(5, 7); + } + @Override + protected float attackDelay() { + return 1.2f; + } + + private static final HashSet> RESISTANCES = new HashSet>(); + static { + RESISTANCES.add(ToxicGas.class); + RESISTANCES.add(Poison.class); + RESISTANCES.add(EnchantmentDark.class); + + } + + @Override + public HashSet> resistances() { + return RESISTANCES; + } + + private final String ENDLESS = "endless"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(ENDLESS, endless); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + endless = bundle.getBoolean(ENDLESS); + } + +} diff --git a/java/com/hmdzl/spspd/actors/mobs/UAmulet.java b/java/com/hmdzl/spspd/actors/mobs/UAmulet.java new file mode 100644 index 00000000..8f92953f --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/UAmulet.java @@ -0,0 +1,233 @@ +/* + * 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 + */ + +package com.hmdzl.spspd.actors.mobs; + +import java.util.HashSet; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.Blob; +import com.hmdzl.spspd.actors.blobs.ToxicGas; +import com.hmdzl.spspd.actors.buffs.Amok; +import com.hmdzl.spspd.actors.buffs.Burning; +import com.hmdzl.spspd.actors.buffs.Charm; +import com.hmdzl.spspd.actors.buffs.Poison; +import com.hmdzl.spspd.actors.buffs.Sleep; +import com.hmdzl.spspd.actors.buffs.Terror; +import com.hmdzl.spspd.actors.buffs.Vertigo; +import com.hmdzl.spspd.items.scrolls.ScrollOfPsionicBlast; +import com.hmdzl.spspd.items.weapon.enchantments.EnchantmentDark; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ErrorSprite; + +import com.hmdzl.spspd.sprites.MirrorSprite; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; +import com.hmdzl.spspd.actors.blobs.CorruptGas; +import com.hmdzl.spspd.actors.buffs.Bleeding; +import com.hmdzl.spspd.actors.buffs.Paralysis; +import com.hmdzl.spspd.items.Playericon; + +public class UAmulet extends Mob { + + protected static final float SPAWN_DELAY = 2f; + + { + spriteClass = ErrorSprite.class; + baseSpeed = 0.75f; + + HP = HT = 1000; + EXP = 20; + evadeSkill = 5; + + loot = new Playericon(); + lootChance = 1f; + + properties.add(Property.UNKNOW); + properties.add(Property.BOSS); + } + + private int breaks=0; + + @Override + public int damageRoll() { + return Random.NormalIntRange(Dungeon.hero.lvl/2, Dungeon.hero.lvl); + } + + @Override + public int hitSkill(Char target) { + return 100; + } + + @Override + public int drRoll() { + return Random.NormalIntRange(0, 2); + } + + @Override + public float speed() { + if (breaks == 3) return 2*super.speed(); + else return super.speed(); + } + + @Override + public boolean act() { + + if( 3 - breaks > 4 * HP / HT ) { + breaks++; + //DarkMirror.spawnAround(pos); + return true; + } + return super.act(); + } + + private static final String BREAKS = "breaks"; + + @Override + public void storeInBundle( Bundle bundle ) { + super.storeInBundle(bundle); + bundle.put( BREAKS, breaks ); + } + + @Override + public void restoreFromBundle( Bundle bundle ) { + super.restoreFromBundle(bundle); + breaks = bundle.getInt( BREAKS ); + } + + @Override + public void damage(int dmg, Object src) { + + dmg = Random.Int(10,20); + if (dmg > 15){ + GameScene.add(Blob.seed(pos, 30, CorruptGas.class)); + } + super.damage(dmg, src); + } + + @Override + public void die(Object cause) { + + GameScene.bossSlain(); + super.die(cause); + //UYog.spawnAt(pos); + } + + public static UAmulet spawnAt(int pos) { + if (Level.passable[pos] && Actor.findChar(pos) == null) { + + UAmulet w = new UAmulet(); + w.pos = pos; + w.state = w.HUNTING; + GameScene.add(w, SPAWN_DELAY); + + return w; + + } else { + return null; + } + } + + private static final HashSet> RESISTANCES = new HashSet>(); + private static final HashSet> IMMUNITIES = new HashSet>(); + static { + RESISTANCES.add(ToxicGas.class); + RESISTANCES.add(Poison.class); + RESISTANCES.add(EnchantmentDark.class); + IMMUNITIES.add(EnchantmentDark.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); + IMMUNITIES.add(Vertigo.class); + IMMUNITIES.add(Paralysis.class); + IMMUNITIES.add(Bleeding.class); + IMMUNITIES.add(CorruptGas.class); + + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } + + @Override + public HashSet> resistances() { + return RESISTANCES; + } + + + public static class DarkMirror extends Mob { + + { + //name = "mirror image"; + spriteClass = MirrorSprite.class; + + HP = HT = Dungeon.hero.HT/5; + state = HUNTING; + + properties.add(Property.UNKNOW); + } + + public int tier; + + @Override + public int hitSkill(Char target) { + return 100; + } + + @Override + public int damageRoll() { + return (int)(Dungeon.hero.HT/10); + } + + @Override + public int attackProc(Char enemy, int damage) { + int dmg = super.attackProc(enemy, damage); + return dmg; + } + + 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 DarkMirror spawnAt(int pos) { + + DarkMirror d = new DarkMirror(); + + d.pos = pos; + d.state = d.HUNTING; + GameScene.add(d, 2f); + + return d; + + } + + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/mobs/UDM300.java b/java/com/hmdzl/spspd/actors/mobs/UDM300.java new file mode 100644 index 00000000..2255a67e --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/UDM300.java @@ -0,0 +1,343 @@ +/* + * 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 + */ + +package com.hmdzl.spspd.actors.mobs; + +import java.util.HashSet; + +import com.hmdzl.spspd.items.bombs.DungeonBomb; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.Blob; +import com.hmdzl.spspd.actors.blobs.ToxicGas; +import com.hmdzl.spspd.actors.blobs.ShockWeb; +import com.hmdzl.spspd.actors.blobs.FrostGas; +import com.hmdzl.spspd.actors.blobs.TarGas; +import com.hmdzl.spspd.actors.blobs.DarkGas; +import com.hmdzl.spspd.actors.buffs.Amok; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Burning; +import com.hmdzl.spspd.actors.buffs.Charm; +import com.hmdzl.spspd.actors.buffs.Poison; +import com.hmdzl.spspd.actors.buffs.Sleep; +import com.hmdzl.spspd.actors.buffs.Terror; +import com.hmdzl.spspd.actors.buffs.Vertigo; +import com.hmdzl.spspd.items.scrolls.ScrollOfPsionicBlast; +import com.hmdzl.spspd.items.weapon.enchantments.EnchantmentDark; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.UDM300Sprite; +import com.watabou.utils.Random; +import com.hmdzl.spspd.actors.blobs.CorruptGas; +import com.hmdzl.spspd.actors.buffs.Bleeding; +import com.hmdzl.spspd.actors.buffs.Tar; +import com.hmdzl.spspd.actors.buffs.Paralysis; +import com.hmdzl.spspd.sprites.SeekingBombSprite; + +public class UDM300 extends Mob { + + protected static final float SPAWN_DELAY = 2f; + + { + spriteClass = UDM300Sprite.class; + baseSpeed = 0.75f; + + HP = HT = 1000; + EXP = 20; + evadeSkill = 5; + + FLEEING = new Fleeing(); + + properties.add(Property.MECH); + properties.add(Property.BOSS); + } + + private int breaks=0; + private static int CountBomb = 0; + + @Override + public int damageRoll() { + return Random.NormalIntRange(Dungeon.hero.lvl/2, Dungeon.hero.lvl); + } + + @Override + public int hitSkill(Char target) { + return 100; + } + + @Override + public int drRoll() { + return Random.NormalIntRange(0, 2); + } + + @Override + public float speed() { + if (breaks == 3) return 2*super.speed(); + else return super.speed(); + } + + public void spawnBomb() { + SeekBomb bomb1 = new SeekBomb(); + SeekBomb bomb2 = new SeekBomb(); + SeekBomb bomb3 = new SeekBomb(); + SeekBomb bomb4 = new SeekBomb(); + + bomb1.pos = Dungeon.level.randomRespawnCellMob(); + bomb2.pos = Dungeon.level.randomRespawnCellMob(); + bomb3.pos = Dungeon.level.randomRespawnCellMob(); + bomb4.pos = Dungeon.level.randomRespawnCellMob(); + + GameScene.add(bomb1); + GameScene.add(bomb2); + GameScene.add(bomb3); + GameScene.add(bomb4); + } + + @Override + public boolean act() { + + if( 3 - breaks > 4 * HP / HT ) { + + breaks++; + spawnBomb(); + return true; + } + + if (breaks == 1){ + GameScene.add(Blob.seed(pos, 30, FrostGas.class)); + } + + if (breaks == 2){ + GameScene.add(Blob.seed(pos, 60, TarGas.class)); + } + + if (breaks == 3){ + GameScene.add(Blob.seed(pos, 100, DarkGas.class)); + } + + if (state == FLEEING && buff(Terror.class) == null && enemy != null + && enemySeen && (enemy.buff(Poison.class) == null && enemy.buff(Burning.class) == null && enemy.buff(Tar.class) == null)) { + state = HUNTING; + } + + return super.act(); + + } + + @Override + public int attackProc(Char enemy, int damage) { + if (breaks == 0 ){ + if (Random.Int(2) == 0) { + Buff.affect(enemy, Poison.class).set(Random.Int(7, 9) * Poison.durationFactor(enemy)); + state = FLEEING; + } + } + if (breaks == 1 ){ + if (Random.Int(2) == 0) { + Buff.affect(enemy, Tar.class); + state = FLEEING; + } + } + if (breaks == 2 ){ + if (Random.Int(2) == 0) { + Buff.affect(enemy, Burning.class).reignite(enemy); + state = FLEEING; + } + } + + + return damage; + } + + @Override + public void move(int step) { + if (state == FLEEING) { + GameScene.add(Blob.seed(pos, Random.Int(5, 7), ShockWeb.class)); + } + super.move(step); + } + + @Override + public void damage(int dmg, Object src) { + + dmg = Random.Int(10,20); + if (dmg > 15){ + GameScene.add(Blob.seed(pos, 30, CorruptGas.class)); + } + super.damage(dmg, src); + } + + @Override + public int defenseProc(Char enemy, int damage) { + + int dmg = Random.IntRange(0, damage/3); + + if (dmg > 0 || (Random.Int(3) == 0 )) { + enemy.damage(dmg, this); + } + + return super.defenseProc(enemy, damage); + } + + @Override + public void die(Object cause) { + + GameScene.bossSlain(); + super.die(cause); + UKing.spawnAt(pos); + } + + public static UDM300 spawnAt(int pos) { + if (Level.passable[pos] && Actor.findChar(pos) == null) { + + UDM300 w = new UDM300(); + w.pos = pos; + w.state = w.HUNTING; + GameScene.add(w, SPAWN_DELAY); + + return w; + + } else { + return null; + } + } + + private class Fleeing extends Mob.Fleeing { + @Override + protected void nowhereToRun() { + if (buff(Terror.class) == null) { + state = HUNTING; + } else { + super.nowhereToRun(); + } + } + } + + private static final HashSet> RESISTANCES = new HashSet>(); + private static final HashSet> IMMUNITIES = new HashSet>(); + static { + RESISTANCES.add(ToxicGas.class); + RESISTANCES.add(Poison.class); + RESISTANCES.add(EnchantmentDark.class); + IMMUNITIES.add(EnchantmentDark.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); + IMMUNITIES.add(Vertigo.class); + IMMUNITIES.add(Paralysis.class); + IMMUNITIES.add(Bleeding.class); + IMMUNITIES.add(CorruptGas.class); + IMMUNITIES.add(FrostGas.class); + IMMUNITIES.add(TarGas.class); + IMMUNITIES.add(Tar.class); + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } + + @Override + public HashSet> resistances() { + return RESISTANCES; + } + + public static class SeekBomb extends Mob { + + private static final int BOMB_DELAY = 10; + private int timeToBomb = BOMB_DELAY; + { + spriteClass = SeekingBombSprite.class; + + HP = HT = 1; + evadeSkill = 0; + baseSpeed = 1f; + timeToBomb = BOMB_DELAY; + EXP = 0; + + state = HUNTING; + + properties.add(Property.MECH); + properties.add(Property.MINIBOSS); + } + + @Override + public int attackProc(Char enemy, int damage) { + int dmg = super.attackProc(enemy, damage); + + DungeonBomb bomb = new DungeonBomb(); + bomb.explode(pos); + yell("KA-BOOM!!!"); + + destroy(); + sprite.die(); + + return dmg; + } + + @Override + public void die(Object cause) { + DungeonBomb bomb = new DungeonBomb(); + bomb.explode(pos); + super.die(cause); + + } + + @Override + public int hitSkill(Char target) { + return 10; + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(0, 1); + } + + @Override + public int drRoll() { + return 0; + } + + @Override + public boolean act() { + yell(""+timeToBomb+"!"); + if (timeToBomb == 0){ + DungeonBomb bomb = new DungeonBomb(); + bomb.explode(pos); + yell("KA-BOOM!!!"); + destroy(); + sprite.die(); + } + + return super.act(); + } + + @Override + public void move(int step) { + super.move(step); + timeToBomb --; + } + + } + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/mobs/UGoo.java b/java/com/hmdzl/spspd/actors/mobs/UGoo.java new file mode 100644 index 00000000..28189582 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/UGoo.java @@ -0,0 +1,622 @@ +/* + * 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 + */ + +package com.hmdzl.spspd.actors.mobs; + +import java.util.HashSet; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.ResultDescriptions; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.Blob; +import com.hmdzl.spspd.actors.blobs.ElectriShock; +import com.hmdzl.spspd.actors.blobs.Fire; +import com.hmdzl.spspd.actors.blobs.FrostGas; +import com.hmdzl.spspd.actors.blobs.ToxicGas; +import com.hmdzl.spspd.actors.buffs.Amok; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Burning; +import com.hmdzl.spspd.actors.buffs.Charm; +import com.hmdzl.spspd.actors.buffs.Ooze; +import com.hmdzl.spspd.actors.buffs.Poison; +import com.hmdzl.spspd.actors.buffs.Roots; +import com.hmdzl.spspd.actors.buffs.Silent; +import com.hmdzl.spspd.actors.buffs.Sleep; +import com.hmdzl.spspd.actors.buffs.Terror; +import com.hmdzl.spspd.actors.buffs.Vertigo; +import com.hmdzl.spspd.items.scrolls.ScrollOfPsionicBlast; +import com.hmdzl.spspd.items.weapon.enchantments.EnchantmentDark; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.CharSprite; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.UGooSprite; + +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; +import com.hmdzl.spspd.actors.blobs.CorruptGas; +import com.hmdzl.spspd.actors.buffs.Bleeding; +import com.hmdzl.spspd.actors.buffs.Paralysis; +import com.hmdzl.spspd.items.weapon.melee.special.Handcannon; + + +public class UGoo extends Mob { + + protected static final float SPAWN_DELAY = 2f; + private static final String TXT_UNKNOW = "??? I know nothing about it ???"; + + { + spriteClass = UGooSprite.class; + baseSpeed = 0.25f; + + HP = HT = 1000; + EXP = 20; + evadeSkill = 5; + + loot = new Handcannon(); + lootChance = 0.5f; + + properties.add(Property.ELEMENT); + properties.add(Property.UNKNOW); + properties.add(Property.BOSS); + } + + private int breaks=0; + private static int GoosCount = 0; + + public void spawnGoos() { + EarthGoo goo1 = new EarthGoo(); + FireGoo goo2 = new FireGoo(); + ShockGoo goo3 = new ShockGoo(); + IceGoo goo4 = new IceGoo(); + + + goo1.pos = Dungeon.level.randomRespawnCellMob(); + goo2.pos = Dungeon.level.randomRespawnCellMob(); + goo3.pos = Dungeon.level.randomRespawnCellMob(); + goo4.pos = Dungeon.level.randomRespawnCellMob(); + + GameScene.add(goo1); + GameScene.add(goo2); + GameScene.add(goo3); + GameScene.add(goo4); + } + + + @Override + public int damageRoll() { + return Random.NormalIntRange(Dungeon.hero.lvl/2, Dungeon.hero.lvl); + } + + @Override + public int hitSkill(Char target) { + return 100; + } + + @Override + public int drRoll() { + return Random.NormalIntRange(0, 2); + } + + @Override + public float speed() { + if (breaks == 3) return 6*super.speed(); + else return super.speed(); + } + + private static final String BREAKS = "breaks"; + + @Override + public void storeInBundle( Bundle bundle ) { + super.storeInBundle(bundle); + bundle.put( BREAKS, breaks ); + } + + @Override + public void restoreFromBundle( Bundle bundle ) { + super.restoreFromBundle(bundle); + breaks = bundle.getInt( BREAKS ); + } + + @Override + public boolean act() { + + if( 3 - breaks > 4 * HP / HT ) { + + if (GoosCount==0){ + spawnGoos(); + } + breaks++; + + return true; + } + + if (breaks == 1){ + + } + + if (breaks == 2){ + + } + + if (breaks > 0){ + + } + return super.act(); + } + + @Override + public void damage(int dmg, Object src) { + + if (GoosCount > 0){ + dmg = Random.Int(0,1); + } else dmg = Random.Int(10,20); + if (dmg > 15){ + GameScene.add(Blob.seed(pos, 30, CorruptGas.class)); + } + super.damage(dmg, src); + } + + @Override + public void die(Object cause) { + for (Mob mob : (Iterable) Dungeon.level.mobs.clone()) { + if (mob instanceof FireGoo || mob instanceof EarthGoo || mob instanceof Eye || mob instanceof ShockGoo || mob instanceof IceGoo) { + mob.die(cause); + } + } + + GameScene.bossSlain(); + super.die(cause); + UTengu.spawnAt(pos); + } + + public static UGoo spawnAt(int pos) { + if (Level.passable[pos] && Actor.findChar(pos) == null) { + + UGoo w = new UGoo(); + w.pos = pos; + w.state = w.HUNTING; + GameScene.add(w, SPAWN_DELAY); + GoosCount = 0; + + return w; + + } else { + return null; + } + } + + private static final HashSet> RESISTANCES = new HashSet>(); + private static final HashSet> IMMUNITIES = new HashSet>(); + static { + RESISTANCES.add(ToxicGas.class); + RESISTANCES.add(Poison.class); + RESISTANCES.add(EnchantmentDark.class); + IMMUNITIES.add(EnchantmentDark.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); + IMMUNITIES.add(Vertigo.class); + IMMUNITIES.add(Paralysis.class); + IMMUNITIES.add(Bleeding.class); + IMMUNITIES.add(CorruptGas.class); + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } + + @Override + public HashSet> resistances() { + return RESISTANCES; + } + + public static class EarthGoo extends Mob { + + { + spriteClass =UGooSprite.EarthSpawnSprite.class; + + HP = HT = 10; + evadeSkill = 5; + baseSpeed = 0.75f; + + EXP = 0; + + state = WANDERING; + + properties.add(Property.ELEMENT); + properties.add(Property.UNKNOW); + properties.add(Property.MINIBOSS); + } + + public EarthGoo() { + super(); + GoosCount++; + } + + @Override + public void die(Object cause) { + super.die(cause); + GoosCount--; + } + + @Override + public int hitSkill(Char target) { + return 10; + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(0, 1); + } + + @Override + public int drRoll() { + return 0; + } + + @Override + public int attackProc(Char enemy, int damage) { + if (Random.Int(5) == 0) { + Buff.affect(enemy, Ooze.class); + enemy.sprite.burst(0xFF000000, 5); + } + if (Random.Int(5) == 0) { + Buff.prolong(enemy, Roots.class,2f); + enemy.sprite.burst(0xFF000000, 5); + } + + return damage; + } + + private static final HashSet> RESISTANCES = new HashSet>(); + static { + RESISTANCES.add(ToxicGas.class); + RESISTANCES.add(EnchantmentDark.class); + + } + + @Override + public HashSet> resistances() { + return RESISTANCES; + } + + private static final HashSet> IMMUNITIES = new HashSet>(); + static { + IMMUNITIES.add(Amok.class); + IMMUNITIES.add(Sleep.class); + IMMUNITIES.add(Terror.class); + IMMUNITIES.add(Poison.class); + IMMUNITIES.add(Vertigo.class); + IMMUNITIES.add(ToxicGas.class); + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } + } + + public static class FireGoo extends Mob { + + { + spriteClass = UGooSprite.FireSpawnSprite.class; + + HP = HT = 10; + evadeSkill = 5; + baseSpeed = 0.75f; + + EXP = 0; + + state = WANDERING; + + properties.add(Property.ELEMENT); + properties.add(Property.UNKNOW); + properties.add(Property.MINIBOSS); + } + + public FireGoo() { + super(); + GoosCount++; + } + + @Override + public void die(Object cause) { + super.die(cause); + GoosCount--; + } + + @Override + public int hitSkill(Char target) { + return 10; + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(0, 1); + } + + @Override + public int drRoll() { + return 2; + } + + @Override + protected boolean canAttack(Char enemy) { if (buff(Silent.class) != null){ + return Level.adjacent(pos, enemy.pos) && (!isCharmedBy(enemy)); + } else + return new Ballistica( pos, enemy.pos, Ballistica.MAGIC_BOLT).collisionPos == 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(Messages.format(ResultDescriptions.MOB)); + //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(); + } + + private static final HashSet> RESISTANCES = new HashSet>(); + static { + RESISTANCES.add(ToxicGas.class); + RESISTANCES.add(EnchantmentDark.class); + + } + + @Override + public HashSet> resistances() { + return RESISTANCES; + } + + private static final HashSet> IMMUNITIES = new HashSet>(); + static { + IMMUNITIES.add(Amok.class); + IMMUNITIES.add(Sleep.class); + IMMUNITIES.add(Terror.class); + IMMUNITIES.add(Burning.class); + IMMUNITIES.add(ScrollOfPsionicBlast.class); + IMMUNITIES.add(Vertigo.class); + IMMUNITIES.add(ToxicGas.class); + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } + } + + public static class IceGoo extends Mob { + + { + spriteClass = UGooSprite.IceSpawnSprite.class; + + HP = HT = 10; + evadeSkill = 5; + baseSpeed = 0.75f; + + EXP = 0; + + state = FLEEING; + + properties.add(Property.ELEMENT); + properties.add(Property.UNKNOW); + properties.add(Property.MINIBOSS); + } + + public IceGoo() { + super(); + GoosCount++; + } + + @Override + public void die(Object cause) { + super.die(cause); + GoosCount--; + } + + @Override + public int hitSkill(Char target) { + return 10; + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(0, 1); + } + + @Override + public int drRoll() { + return 2; + } + + @Override + public int attackProc(Char enemy, int damage) { + return damage; + } + + @Override + public boolean act() { + + for (int i = 0; i < Level.NEIGHBOURS9.length; i++) { + GameScene.add(Blob.seed(pos + Level.NEIGHBOURS9[i], 2, + FrostGas.class)); + } + + return super.act(); + } + + private static final HashSet> RESISTANCES = new HashSet>(); + static { + RESISTANCES.add(ToxicGas.class); + RESISTANCES.add(EnchantmentDark.class); + + } + + @Override + public HashSet> resistances() { + return RESISTANCES; + } + + private static final HashSet> IMMUNITIES = new HashSet>(); + static { + IMMUNITIES.add(Amok.class); + IMMUNITIES.add(Sleep.class); + IMMUNITIES.add(Terror.class); + IMMUNITIES.add(Poison.class); + IMMUNITIES.add(Vertigo.class); + IMMUNITIES.add(ToxicGas.class); + IMMUNITIES.add(FrostGas.class); + + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } + } + + + public static class ShockGoo extends Mob { + private static final float TIME_TO_ZAP = 2f; + { + spriteClass = UGooSprite.ShockSpawnSprite.class; + + HP = HT = 10; + evadeSkill = 5; + baseSpeed = 0.75f; + + EXP = 0; + + state = WANDERING; + + properties.add(Property.ELEMENT); + properties.add(Property.UNKNOW); + properties.add(Property.MINIBOSS); + } + + public ShockGoo() { + super(); + GoosCount++; + } + + @Override + public void die(Object cause) { + super.die(cause); + GoosCount--; + } + + @Override + public int hitSkill(Char target) { + return 10; + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(0, 1); + } + + @Override + public int drRoll() { + return 2; + } + + @Override + protected boolean canAttack(Char enemy) { if (buff(Silent.class) != null){ + return Level.adjacent(pos, enemy.pos) && (!isCharmedBy(enemy)); + } else + return new Ballistica( pos, enemy.pos, Ballistica.MAGIC_BOLT).collisionPos == enemy.pos; + } + + @Override + public void damage(int dmg, Object src) { + GameScene.add(Blob.seed(pos, 5, ElectriShock.class)); + super.damage(dmg, src); + } + + + + private static final HashSet> RESISTANCES = new HashSet>(); + static { + RESISTANCES.add(ToxicGas.class); + RESISTANCES.add(EnchantmentDark.class); + + } + + @Override + public HashSet> resistances() { + return RESISTANCES; + } + + private static final HashSet> IMMUNITIES = new HashSet>(); + static { + IMMUNITIES.add(Amok.class); + IMMUNITIES.add(Sleep.class); + IMMUNITIES.add(Terror.class); + IMMUNITIES.add(Burning.class); + IMMUNITIES.add(ScrollOfPsionicBlast.class); + IMMUNITIES.add(Vertigo.class); + IMMUNITIES.add(ElectriShock.class); + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/mobs/UIcecorps.java b/java/com/hmdzl/spspd/actors/mobs/UIcecorps.java new file mode 100644 index 00000000..f38e9fc8 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/UIcecorps.java @@ -0,0 +1,265 @@ +/* + * 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 + */ + +package com.hmdzl.spspd.actors.mobs; + +import java.util.HashSet; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.Blob; +import com.hmdzl.spspd.actors.blobs.ToxicGas; +import com.hmdzl.spspd.actors.buffs.Amok; +import com.hmdzl.spspd.actors.buffs.BoxStar; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Burning; +import com.hmdzl.spspd.actors.buffs.Charm; +import com.hmdzl.spspd.actors.buffs.Chill; +import com.hmdzl.spspd.actors.buffs.Frost; +import com.hmdzl.spspd.actors.buffs.Poison; +import com.hmdzl.spspd.actors.buffs.Sleep; +import com.hmdzl.spspd.actors.buffs.StoneIce; +import com.hmdzl.spspd.actors.buffs.Terror; +import com.hmdzl.spspd.actors.buffs.Vertigo; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.eggs.EasterEgg; +import com.hmdzl.spspd.items.scrolls.ScrollOfMagicMapping; +import com.hmdzl.spspd.items.scrolls.ScrollOfPsionicBlast; +import com.hmdzl.spspd.items.weapon.enchantments.EnchantmentDark; +import com.hmdzl.spspd.items.weapon.melee.special.Handcannon; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.traps.SpearTrap; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ErrorSprite; +import com.hmdzl.spspd.sprites.IceRabbitSprite; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; +import com.hmdzl.spspd.actors.blobs.CorruptGas; +import com.hmdzl.spspd.actors.buffs.Bleeding; +import com.hmdzl.spspd.actors.buffs.Slow; +import com.hmdzl.spspd.actors.buffs.Paralysis; +import com.watabou.noosa.Camera; +import com.watabou.noosa.audio.Sample; +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.levels.Terrain; + + +public class UIcecorps extends Mob { + + protected static final float SPAWN_DELAY = 2f; + + { + spriteClass = IceRabbitSprite.class; + baseSpeed = 0.75f; + + HP = HT = 1500; + EXP = 20; + evadeSkill = 5; + + loot = new EasterEgg(); + lootChance = 1f; + + properties.add(Property.ORC); + properties.add(Property.BOSS); + } + + private int breaks = 0; + private int timeToIce = 0; + + + public void spawnfires() { + FireRabbit fr1 = new FireRabbit(); + + fr1.pos = Dungeon.level.randomRespawnCellMob(); + + GameScene.add(fr1); + + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(Dungeon.hero.lvl/2, Dungeon.hero.lvl); + } + + @Override + public int hitSkill(Char target) { + return 100; + } + + @Override + public int drRoll() { + return Random.NormalIntRange(0, 2); + } + + @Override + protected boolean canAttack(Char enemy) { + return Dungeon.level.distance( pos, enemy.pos ) <= 2 ; + } + + + @Override + public int attackProc(Char enemy, int damage) { + if (Random.Int(2) == 0) { + Buff.affect(enemy, StoneIce.class).level(3); + } + + return damage; + } + + private static final String BREAKS = "breaks"; + + @Override + public void storeInBundle( Bundle bundle ) { + super.storeInBundle(bundle); + bundle.put( BREAKS, breaks ); + } + + @Override + public void restoreFromBundle( Bundle bundle ) { + super.restoreFromBundle(bundle); + breaks = bundle.getInt( BREAKS ); + } + + @Override + public boolean act() { + + if( HP < 100 ) { + if (breaks == 0) { + breaks++; + HP = HT; + + return false; + } + } + + + timeToIce++; + if (timeToIce > 20){ + spawnfires(); + timeToIce=0; + } + + return super.act(); + } + + @Override + public void damage(int dmg, Object src) { + if (buff(BoxStar.class) != null && !(src instanceof StoneIce) ) + dmg = 0; + if (src instanceof StoneIce) + dmg = 10; + if (dmg > 40) + dmg = Random.Int(10, 40); + if(HP-dmg<100 && breaks ==0){ + Buff.affect(this,BoxStar.class,10f); + Buff.affect(this,StoneIce.class).level(100); + } + + super.damage(dmg, src); + } + + @Override + public void move(int step) { + super.move(step); + if ( timeToIce > 0 ){ + int[] cells = { step - 1, step + 1, step - Level.getWidth(), + step + Level.getWidth(), step - 1 - Level.getWidth(), + step - 1 + Level.getWidth(), step + 1 - Level.getWidth(), + step + 1 + Level.getWidth() }; + 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]) { + Dungeon.level.setTrap( new SpearTrap().reveal(), cell ); + Level.set(cell, Terrain.TRAP); + GameScene.updateMap(cell); + ScrollOfMagicMapping.discover(cell); + } else if (Dungeon.level.map[cell] == Terrain.EMPTY) { + Level.set(cell, Terrain.WATER); + GameScene.updateMap(cell); + } + } + Char ch = Actor.findChar(cell); + if (ch != null && ch != this) { + Buff.prolong(ch, Slow.class, 5); + } + } + } + + @Override + public void die(Object cause) { + + GameScene.bossSlain(); + super.die(cause); + UYog.spawnAt(pos); + } + + public static UIcecorps spawnAt(int pos) { + if (Level.passable[pos] && Actor.findChar(pos) == null) { + + UIcecorps w = new UIcecorps(); + w.pos = pos; + w.state = w.HUNTING; + GameScene.add(w, SPAWN_DELAY); + + return w; + + } else { + return null; + } + } + + private static final HashSet> RESISTANCES = new HashSet>(); + private static final HashSet> IMMUNITIES = new HashSet>(); + static { + RESISTANCES.add(ToxicGas.class); + RESISTANCES.add(Poison.class); + RESISTANCES.add(EnchantmentDark.class); + IMMUNITIES.add(EnchantmentDark.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(Chill.class); + IMMUNITIES.add(Frost.class); + IMMUNITIES.add(ScrollOfPsionicBlast.class); + IMMUNITIES.add(Vertigo.class); + IMMUNITIES.add(Paralysis.class); + IMMUNITIES.add(Bleeding.class); + IMMUNITIES.add(CorruptGas.class); + + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } + + @Override + public HashSet> resistances() { + return RESISTANCES; + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/mobs/UKing.java b/java/com/hmdzl/spspd/actors/mobs/UKing.java new file mode 100644 index 00000000..3b20e7cf --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/UKing.java @@ -0,0 +1,230 @@ +/* + * 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 + */ + +package com.hmdzl.spspd.actors.mobs; + +import java.util.HashSet; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.ToxicGas; +import com.hmdzl.spspd.actors.buffs.Amok; +import com.hmdzl.spspd.actors.buffs.AttackUp; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Burning; +import com.hmdzl.spspd.actors.buffs.Charm; +import com.hmdzl.spspd.actors.buffs.Poison; +import com.hmdzl.spspd.actors.buffs.Roots; +import com.hmdzl.spspd.actors.buffs.Sleep; +import com.hmdzl.spspd.actors.buffs.Terror; +import com.hmdzl.spspd.actors.buffs.Vertigo; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.misc.FourClover; +import com.hmdzl.spspd.items.scrolls.ScrollOfPsionicBlast; +import com.hmdzl.spspd.items.weapon.enchantments.EnchantmentDark; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.Terrain; +import com.hmdzl.spspd.scenes.GameScene; + +import com.hmdzl.spspd.sprites.PlantKingSprite; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; +import com.hmdzl.spspd.actors.blobs.CorruptGas; +import com.hmdzl.spspd.actors.buffs.Bleeding; +import com.hmdzl.spspd.actors.buffs.Paralysis; + +public class UKing extends Mob { + + protected static final float SPAWN_DELAY = 2f; + + { + spriteClass = PlantKingSprite.class; + baseSpeed = 1f; + + HP = HT = 2000; + EXP = 20; + evadeSkill = 5; + flying = true; + + loot = new FourClover(); + lootChance = 1f; + + properties.add(Property.PLANT); + properties.add(Property.BOSS); + } + + private int breaks=0; + + @Override + public int damageRoll() { + return Random.NormalIntRange(Dungeon.hero.lvl/2, Dungeon.hero.lvl); + } + + @Override + public int hitSkill(Char target) { + return 100; + } + + @Override + public int drRoll() { + return Random.NormalIntRange(0, 2); + } + + @Override + public boolean act() { + + if (Level.flamable[pos] && HP < HT) { + sprite.emitter().burst( Speck.factory( Speck.HEALING ), 1 ); + HP++; + } + + if( 3 - breaks > 4 * HP / HT ) { + breaks++; + for (int i = 0; i < Level.NEIGHBOURS9.length; i++) { + if (i == Terrain.EMPTY || i == Terrain.EMBERS + || i == Terrain.EMPTY_DECO || i == Terrain.GRASS) { + + Level.set(i, Terrain.HIGH_GRASS); + + } + } + return true; + } + + return super.act(); + } + + @Override + public void move(int step) { + super.move(step); + + int[] cells = { step - 1, step + 1, step - Level.getWidth(), + step + Level.getWidth(), step - 1 - Level.getWidth(), + step - 1 + Level.getWidth(), step + 1 - Level.getWidth(), + step + 1 + Level.getWidth() }; + int cell = cells[Random.Int(cells.length)]; + + if (cell == Terrain.EMPTY || cell == Terrain.EMBERS + || cell == Terrain.EMPTY_DECO) { + + Level.set(cell, Terrain.GRASS); + + } + } + + @Override + public float speed() { + if (breaks == 3) return 2*super.speed(); + else return super.speed(); + } + + @Override + protected boolean canAttack(Char enemy) { + if (breaks >2){ + return Dungeon.level.distance( pos, enemy.pos ) <= 3;} + else return Dungeon.level.distance( pos, enemy.pos ) <= 1; + } + + @Override + public int attackProc(Char enemy, int damage) { + if (breaks >2){ + if(Random.Int(5)>2){ + Buff.prolong(enemy, Roots.class,2f); + } else Buff.affect(enemy, Poison.class).set(5); + } + return damage; + } + + private static final String BREAKS = "breaks"; + + @Override + public void storeInBundle( Bundle bundle ) { + super.storeInBundle(bundle); + bundle.put( BREAKS, breaks ); + } + + @Override + public void restoreFromBundle( Bundle bundle ) { + super.restoreFromBundle(bundle); + breaks = bundle.getInt( BREAKS ); + } + + @Override + public void damage(int dmg, Object src) { + + dmg = (int)(dmg*0.4); + Buff.affect(this, AttackUp.class,3f).level((int)(15*dmg/85)); + super.damage(dmg, src); + } + + @Override + public void die(Object cause) { + + GameScene.bossSlain(); + super.die(cause); + UIcecorps.spawnAt(pos); + } + + public static UKing spawnAt(int pos) { + if (Level.passable[pos] && Actor.findChar(pos) == null) { + + UKing w = new UKing(); + w.pos = pos; + w.state = w.HUNTING; + GameScene.add(w, SPAWN_DELAY); + + return w; + + } else { + return null; + } + } + + private static final HashSet> RESISTANCES = new HashSet>(); + private static final HashSet> IMMUNITIES = new HashSet>(); + static { + RESISTANCES.add(ToxicGas.class); + RESISTANCES.add(Poison.class); + RESISTANCES.add(EnchantmentDark.class); + IMMUNITIES.add(EnchantmentDark.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); + IMMUNITIES.add(Vertigo.class); + IMMUNITIES.add(Paralysis.class); + IMMUNITIES.add(Bleeding.class); + IMMUNITIES.add(CorruptGas.class); + + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } + + @Override + public HashSet> resistances() { + return RESISTANCES; + } + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/mobs/UTengu.java b/java/com/hmdzl/spspd/actors/mobs/UTengu.java new file mode 100644 index 00000000..2b9399e7 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/UTengu.java @@ -0,0 +1,282 @@ +/* + * 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 + */ + +package com.hmdzl.spspd.actors.mobs; + +import com.hmdzl.spspd.items.wands.WandOfFlow; + +import java.util.HashSet; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.Blob; +import com.hmdzl.spspd.actors.blobs.ToxicGas; +import com.hmdzl.spspd.actors.buffs.Amok; +import com.hmdzl.spspd.actors.buffs.Burning; +import com.hmdzl.spspd.actors.buffs.Charm; +import com.hmdzl.spspd.actors.buffs.Poison; +import com.hmdzl.spspd.actors.buffs.Sleep; +import com.hmdzl.spspd.actors.buffs.Terror; +import com.hmdzl.spspd.actors.buffs.Vertigo; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.scrolls.ScrollOfPsionicBlast; +import com.hmdzl.spspd.items.weapon.enchantments.EnchantmentDark; +import com.hmdzl.spspd.items.weapon.melee.block.TenguSword; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.UTenguSprite; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; +import com.hmdzl.spspd.actors.blobs.CorruptGas; +import com.hmdzl.spspd.actors.buffs.Bleeding; +import com.hmdzl.spspd.actors.buffs.Paralysis; +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.watabou.noosa.audio.Sample; + + + +public class UTengu extends Mob { + + private int timeToJump = JUMP_DELAY; + private static final int JUMP_DELAY = 10; + protected static final float SPAWN_DELAY = 2f; + private static final String TXT_UNKNOW = "??? I know nothing about it ???"; + private static final int maxDistance = 3; + + { + spriteClass = UTenguSprite.class; + baseSpeed = 1f; + + HP = HT = 1000; + EXP = 20; + evadeSkill = 5; + + loot = new TenguSword(); + lootChance = 0.5f; + + properties.add(Property.HUMAN); + properties.add(Property.BOSS); + } + + private int breaks=0; + + @Override + public int damageRoll() { + return Random.NormalIntRange(Dungeon.hero.lvl/2, Dungeon.hero.lvl); + } + + @Override + public int hitSkill(Char target) { + return 100; + } + + @Override + public int drRoll() { + return Random.NormalIntRange(0, 2); + } + + @Override + public float speed() { + if (breaks == 3) return 2*super.speed(); + else return super.speed(); + } + + @Override + public boolean act() { + + if( 3 - breaks > 4 * HP / HT ) { + breaks++; + return true; + } + + if (breaks == 1){ + + } + + if (breaks == 2){ + + } + + if (breaks > 0){ + + } + return super.act(); + } + + private static final String BREAKS = "breaks"; + + @Override + public void storeInBundle( Bundle bundle ) { + super.storeInBundle(bundle); + bundle.put( BREAKS, breaks ); + } + + @Override + public void restoreFromBundle( Bundle bundle ) { + super.restoreFromBundle(bundle); + breaks = bundle.getInt( BREAKS ); + + } + + @Override + public void damage(int dmg, Object src) { + + dmg = Random.Int(10,20); + if (dmg > 15){ + GameScene.add(Blob.seed(pos, 30, CorruptGas.class)); + } + super.damage(dmg, src); + } + @Override + public int defenseProc(Char enemy, int damage) { + + int dmg = Random.IntRange(0, 20); + + if (breaks == 2){ + if (dmg > 0 || (Random.Int(3) == 0 )) { + enemy.damage(dmg, this); + } + } + return super.defenseProc(enemy, damage); + } + + @Override + protected boolean canAttack(Char enemy) { + if (breaks <2){ + return Dungeon.level.distance( pos, enemy.pos ) <= 4;} + else return Dungeon.level.distance( pos, enemy.pos ) <= 1; + } + + @Override + protected boolean doAttack(Char enemy) { + timeToJump--; + if (timeToJump <= 0 && Level.adjacent(pos, enemy.pos)) { + jump(); + return true; + } else { + return super.doAttack(enemy); + } + } + + @Override + public int attackProc(Char enemy, int damage) { + Char ch; + + if (Random.Int( 5 ) >= 3 && Dungeon.level.distance( pos, enemy.pos )<= 1){ + int oppositeTengu = enemy.pos + (enemy.pos - pos); + Ballistica trajectory = new Ballistica(enemy.pos, oppositeTengu, Ballistica.MAGIC_BOLT); + WandOfFlow.throwChar(enemy, trajectory, 1); + } + /*for (int i = 1; i < maxDistance; i++) { + + int c = Ballistica.trace[i]; + + if ((ch = Actor.findChar(c)) != null && ch instanceof Hero) { + int next = Ballistica.trace[i + 1]; + if ((Dungeon.level.passable[next] || Dungeon.level.avoid[next]) + && Actor.findChar(next) == null) { + ch.move(next); + Actor.addDelayed(new Pushing(ch, ch.pos, next), -1); + Dungeon.observe(); + } else { + return damage *2 ; + } + } + }*/ + return damage; + } + + @Override + public void die(Object cause) { + + GameScene.bossSlain(); + super.die(cause); + UDM300.spawnAt(pos); + } + + public static UTengu spawnAt(int pos) { + if (Level.passable[pos] && Actor.findChar(pos) == null) { + + UTengu w = new UTengu(); + w.pos = pos; + w.state = w.HUNTING; + GameScene.add(w, SPAWN_DELAY); + + return w; + + } else { + return null; + } + } + + private void jump() { + timeToJump = JUMP_DELAY; + + int newPos; + do { + newPos = Random.Int(Level.getLength()); + } 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()); + + } + + private static final HashSet> RESISTANCES = new HashSet>(); + private static final HashSet> IMMUNITIES = new HashSet>(); + static { + RESISTANCES.add(ToxicGas.class); + RESISTANCES.add(Poison.class); + RESISTANCES.add(EnchantmentDark.class); + IMMUNITIES.add(EnchantmentDark.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); + IMMUNITIES.add(Vertigo.class); + IMMUNITIES.add(Paralysis.class); + IMMUNITIES.add(Bleeding.class); + IMMUNITIES.add(CorruptGas.class); + + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } + + @Override + public HashSet> resistances() { + return RESISTANCES; + } + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/mobs/UYog.java b/java/com/hmdzl/spspd/actors/mobs/UYog.java new file mode 100644 index 00000000..ce7d149c --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/UYog.java @@ -0,0 +1,192 @@ +/* + * 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 + */ + +package com.hmdzl.spspd.actors.mobs; + +import java.util.HashSet; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.Blob; +import com.hmdzl.spspd.actors.blobs.ToxicGas; +import com.hmdzl.spspd.actors.buffs.Amok; +import com.hmdzl.spspd.actors.buffs.Burning; +import com.hmdzl.spspd.actors.buffs.Charm; +import com.hmdzl.spspd.actors.buffs.Poison; +import com.hmdzl.spspd.actors.buffs.Sleep; +import com.hmdzl.spspd.actors.buffs.Terror; +import com.hmdzl.spspd.actors.buffs.Vertigo; +import com.hmdzl.spspd.items.PowerHand; +import com.hmdzl.spspd.items.scrolls.ScrollOfPsionicBlast; +import com.hmdzl.spspd.items.weapon.enchantments.EnchantmentDark; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ErrorSprite; + +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; +import com.hmdzl.spspd.actors.blobs.CorruptGas; +import com.hmdzl.spspd.actors.buffs.Bleeding; +import com.hmdzl.spspd.actors.buffs.Paralysis; + +public class UYog extends Mob { + + protected static final float SPAWN_DELAY = 2f; + private static final String TXT_UNKNOW = "??? I know nothing about it ???"; + { + spriteClass = ErrorSprite.class; + baseSpeed = 0.75f; + + HP = HT = 1000; + EXP = 20; + evadeSkill = 5; + + loot = new PowerHand(); + lootChance = 1f; + + properties.add(Property.UNKNOW); + properties.add(Property.BOSS); + } + + private int breaks=0; + + @Override + public int damageRoll() { + return Random.NormalIntRange(Dungeon.hero.lvl/2, Dungeon.hero.lvl); + } + + @Override + public int hitSkill(Char target) { + return 100; + } + + @Override + public int drRoll() { + return Random.NormalIntRange(0, 2); + } + + @Override + public float speed() { + if (breaks == 3) return 2*super.speed(); + else return super.speed(); + } + + @Override + public boolean act() { + + if( 3 - breaks > 4 * HP / HT ) { + + breaks++; + + return true; + } + + if (breaks == 1){ + + } + + if (breaks == 2){ + + } + + if (breaks > 0){ + + } + return super.act(); + } + + private static final String BREAKS = "breaks"; + + @Override + public void storeInBundle( Bundle bundle ) { + super.storeInBundle(bundle); + bundle.put( BREAKS, breaks ); + } + + @Override + public void restoreFromBundle( Bundle bundle ) { + super.restoreFromBundle(bundle); + breaks = bundle.getInt( BREAKS ); + } + + @Override + public void damage(int dmg, Object src) { + + dmg = Random.Int(10,20); + if (dmg > 15){ + GameScene.add(Blob.seed(pos, 30, CorruptGas.class)); + } + super.damage(dmg, src); + } + + @Override + public void die(Object cause) { + + GameScene.bossSlain(); + super.die(cause); + UAmulet.spawnAt(pos); + } + + public static UYog spawnAt(int pos) { + if (Level.passable[pos] && Actor.findChar(pos) == null) { + + UYog w = new UYog(); + w.pos = pos; + w.state = w.HUNTING; + GameScene.add(w, SPAWN_DELAY); + + return w; + + } else { + return null; + } + } + + private static final HashSet> RESISTANCES = new HashSet>(); + private static final HashSet> IMMUNITIES = new HashSet>(); + static { + RESISTANCES.add(ToxicGas.class); + RESISTANCES.add(Poison.class); + RESISTANCES.add(EnchantmentDark.class); + IMMUNITIES.add(EnchantmentDark.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); + IMMUNITIES.add(Vertigo.class); + IMMUNITIES.add(Paralysis.class); + IMMUNITIES.add(Bleeding.class); + IMMUNITIES.add(CorruptGas.class); + + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } + + @Override + public HashSet> resistances() { + return RESISTANCES; + } + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/mobs/VaultProtector.java b/java/com/hmdzl/spspd/actors/mobs/VaultProtector.java new file mode 100644 index 00000000..99a7b194 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/VaultProtector.java @@ -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 + */ +package com.hmdzl.spspd.actors.mobs; + +import java.util.HashSet; + +import com.hmdzl.spspd.actors.buffs.Silent; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.ResultDescriptions; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.effects.particles.SparkParticle; +import com.hmdzl.spspd.items.VioletDewdrop; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.traps.LightningTrap; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.sprites.CharSprite; +import com.hmdzl.spspd.sprites.VaultProtectorSprite; + +import com.watabou.noosa.Camera; +import com.watabou.utils.Callback; +import com.watabou.utils.Random; + +public class VaultProtector 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..."; + + { + spriteClass = VaultProtectorSprite.class; + + EXP = 1; + state = HUNTING; + flying = true; + + HP = HT = 400; + evadeSkill = 10; + + loot = new VioletDewdrop(); + lootChance = 1f; + + properties.add(Property.ELEMENT); + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(20, 40); + } + + @Override + public int hitSkill(Char target) { + return 35; + } + + @Override + public int drRoll() { + return Random.NormalIntRange(10, 20); + } + + @Override + protected boolean canAttack(Char enemy) { if (buff(Silent.class) != null){ + return Level.adjacent(pos, enemy.pos) && (!isCharmedBy(enemy)); + } else + return new Ballistica( pos, enemy.pos, Ballistica.MAGIC_BOLT).collisionPos == 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) { + ((VaultProtectorSprite) sprite).zap(enemy.pos); + } + + spend(TIME_TO_ZAP); + + if (hit(this, enemy, true)) { + int dmg = Random.Int(30, 70); + if (Level.water[enemy.pos] && !enemy.flying) { + dmg *= 1.5f; + } + enemy.damage(dmg, this); + + 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( Messages.format(ResultDescriptions.MOB)); + //GLog.n(Messages.get(this, "kill")); + } + } + } else { + enemy.sprite + .showStatus(CharSprite.NEUTRAL, enemy.defenseVerb()); + } + + return !visible; + } + } + + @Override + public void call() { + next(); + } + + private static final HashSet> RESISTANCES = new HashSet>(); + static { + RESISTANCES.add(LightningTrap.Electricity.class); + } + + @Override + public HashSet> resistances() { + return RESISTANCES; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/Virus.java b/java/com/hmdzl/spspd/actors/mobs/Virus.java new file mode 100644 index 00000000..72be6f4d --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/Virus.java @@ -0,0 +1,111 @@ +/* + * 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 + */ + +package com.hmdzl.spspd.actors.mobs; + +import java.util.HashSet; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.Blob; +import com.hmdzl.spspd.actors.blobs.ToxicGas; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Burning; +import com.hmdzl.spspd.items.scrolls.ScrollOfPsionicBlast; +import com.hmdzl.spspd.items.weapon.enchantments.EnchantmentDark; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ErrorSprite; + +import com.watabou.utils.Random; +import com.hmdzl.spspd.actors.blobs.CorruptGas; + + +public class Virus extends Mob { + protected static final float SPAWN_DELAY = 1f; + { + spriteClass = ErrorSprite.class; + HP = HT = (int)Dungeon.hero.HT/5; + EXP = 0; + evadeSkill = Dungeon.hero.evadeSkill; + + properties.add(Property.UNKNOW); + properties.add(Property.BOSS); + } + + int generation = 0; + + @Override + public int damageRoll() { + return Random.NormalIntRange(Dungeon.hero.lvl/2, Dungeon.hero.lvl); + } + + @Override + public int hitSkill(Char target) { + return Dungeon.hero.hitSkill; + } + + @Override + protected boolean act() { + damage(1, this); + return super.act(); + } + + @Override + public int drRoll() { + return 0; + } + + @Override + public float speed() { + return 1f; + } + + @Override + public void damage(int dmg, Object src) { + + if (dmg > HT/2){ + GameScene.add(Blob.seed(pos, 50, CorruptGas.class)); + } + super.damage(dmg, src); + } + + @Override + public void die(Object cause) { + super.die(cause); + } + + @Override + public void add( Buff buff ) { + //in other words, can't be directly affected by buffs/debuffs. + } + + private static final HashSet> IMMUNITIES = new HashSet>(); + static { + + IMMUNITIES.add(EnchantmentDark.class); + IMMUNITIES.add(Burning.class); + IMMUNITIES.add(ToxicGas.class); + IMMUNITIES.add(ScrollOfPsionicBlast.class); + IMMUNITIES.add(CorruptGas.class); + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/mobs/Warlock.java b/java/com/hmdzl/spspd/actors/mobs/Warlock.java new file mode 100644 index 00000000..c1eecb1f --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/Warlock.java @@ -0,0 +1,152 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs; + +import java.util.HashSet; + +import com.hmdzl.spspd.actors.buffs.Silent; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.ResultDescriptions; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Weakness; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.weapon.enchantments.EnchantmentDark; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.sprites.CharSprite; +import com.hmdzl.spspd.sprites.WarlockSprite; + +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..."; + + { + spriteClass = WarlockSprite.class; + + HP = HT = 120+(adj(0)*Random.NormalIntRange(5, 7)); + evadeSkill = 18+adj(0); + + EXP = 11; + maxLvl = 30; + + loot = Generator.Category.POTION; + lootChance = 0.83f; + + lootOther = Generator.Category.WAND; + lootChanceOther = 0.02f; // by default, see die() + + properties.add(Property.DWARF); + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(12, 25+adj(0)); + } + + @Override + public int hitSkill(Char target) { + return 25+adj(0); + } + + @Override + public int drRoll() { + return Random.NormalIntRange(4, 8); + } + + @Override + protected boolean canAttack(Char enemy) { if (buff(Silent.class) != null){ + return Level.adjacent(pos, enemy.pos) && (!isCharmedBy(enemy)); + } else + return new Ballistica( pos, enemy.pos, Ballistica.MAGIC_BOLT).collisionPos == enemy.pos; + } + + @Override + 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(16, 24+adj(0)); + enemy.damage(dmg, this); + + if (!enemy.isAlive() && enemy == Dungeon.hero) { + Dungeon.fail(Messages.format(ResultDescriptions.MOB)); + //GLog.n(Messages.get(this, "kill")); + } + } else { + enemy.sprite.showStatus(CharSprite.NEUTRAL, enemy.defenseVerb()); + } + } + + public void onZapComplete() { + zap(); + next(); + } + + @Override + public void call() { + next(); + } + + @Override + public Item createLoot() { + Item loot = super.createLoot(); + return loot; + } + + private static final HashSet> RESISTANCES = new HashSet>(); + static { + RESISTANCES.add(EnchantmentDark.class); + } + + @Override + public HashSet> resistances() { + return RESISTANCES; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/Wraith.java b/java/com/hmdzl/spspd/actors/mobs/Wraith.java new file mode 100644 index 00000000..a0184f63 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/Wraith.java @@ -0,0 +1,190 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs; + +import java.util.HashSet; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.ToxicGas; +import com.hmdzl.spspd.actors.buffs.Amok; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Burning; +import com.hmdzl.spspd.actors.buffs.Charm; +import com.hmdzl.spspd.actors.buffs.Frost; +import com.hmdzl.spspd.actors.buffs.Paralysis; +import com.hmdzl.spspd.actors.buffs.Roots; +import com.hmdzl.spspd.actors.buffs.Sleep; +import com.hmdzl.spspd.actors.buffs.Terror; +import com.hmdzl.spspd.actors.buffs.Vertigo; +import com.hmdzl.spspd.effects.particles.ShadowParticle; +import com.hmdzl.spspd.items.scrolls.ScrollOfMagicalInfusion; +import com.hmdzl.spspd.items.scrolls.ScrollOfPsionicBlast; +import com.hmdzl.spspd.items.scrolls.ScrollOfUpgrade; +import com.hmdzl.spspd.items.weapon.enchantments.EnchantmentDark; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.WraithSprite; +import com.watabou.noosa.tweeners.AlphaTweener; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public class Wraith extends Mob { + + protected static final float SPAWN_DELAY = 2f; + + protected int level; + + { + spriteClass = WraithSprite.class; + + HP = HT = 1+Dungeon.depth; + EXP = 1; + + flying = true; + + loot = new ScrollOfMagicalInfusion(); + lootChance = 0.06f; + + lootOther = new ScrollOfUpgrade(); + lootChanceOther = 0.09f; + + properties.add(Property.UNDEAD); + } + + protected static final String LEVEL = "level"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(LEVEL, level); + } + + @Override + protected boolean canAttack(Char enemy) { + return Dungeon.level.distance( pos, enemy.pos ) <= 4 ; + } + + + @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 hitSkill(Char target) { + return 10 + level; + } + + public void adjustStats(int level) { + this.level = level; + evadeSkill = hitSkill(null) * 5; + enemySeen = true; + } + + @Override + public int attackProc(Char enemy, int damage) { + if (Random.Int(10) == 0) { + Buff.affect(enemy, Vertigo.class, Vertigo.duration(enemy)); + Buff.affect(enemy, Terror.class, Terror.DURATION).object = enemy.id(); + } + + return damage; + } + + //public void damage(int dmg, Object src) { + // if (enemySeen + // && (src instanceof Wand || src instanceof LightningTrap.Electricity || src instanceof Char)) { + // GLog.n("The attack passes through the wraith."); + // sprite.showStatus(CharSprite.NEUTRAL, "missed"); + // } else { + // super.damage(dmg, src); + // } + //} + + @Override + public boolean reset() { + state = WANDERING; + return true; + } + + @Override + public void notice() { + super.notice(); + if (Dungeon.getMonth()==9) {yell("BOO!");} + } + + 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 = w.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; + } + } + + protected static final HashSet> IMMUNITIES = new HashSet>(); + static { + IMMUNITIES.add(EnchantmentDark.class); + IMMUNITIES.add(Terror.class); + IMMUNITIES.add(Amok.class); + IMMUNITIES.add(Charm.class); + IMMUNITIES.add(Sleep.class); + IMMUNITIES.add(ToxicGas.class); + IMMUNITIES.add(ScrollOfPsionicBlast.class); + IMMUNITIES.add(Vertigo.class); + IMMUNITIES.add(Burning.class); + IMMUNITIES.add(Paralysis.class); + IMMUNITIES.add(Roots.class); + IMMUNITIES.add(Frost.class); + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/YearBeast.java b/java/com/hmdzl/spspd/actors/mobs/YearBeast.java new file mode 100644 index 00000000..9c61b976 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/YearBeast.java @@ -0,0 +1,251 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs; + +import java.util.HashSet; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.Blob; +import com.hmdzl.spspd.actors.blobs.Fire; +import com.hmdzl.spspd.actors.blobs.ToxicGas; +import com.hmdzl.spspd.actors.buffs.AttackUp; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Burning; +import com.hmdzl.spspd.actors.buffs.Charm; +import com.hmdzl.spspd.actors.buffs.DefenceUp; +import com.hmdzl.spspd.actors.buffs.Frost; +import com.hmdzl.spspd.actors.buffs.GlassShield; +import com.hmdzl.spspd.actors.buffs.Poison; +import com.hmdzl.spspd.actors.buffs.Sleep; +import com.hmdzl.spspd.actors.buffs.Terror; +import com.hmdzl.spspd.actors.buffs.Vertigo; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.particles.ElmoParticle; +import com.hmdzl.spspd.items.KindOfArmor; +import com.hmdzl.spspd.items.KindOfWeapon; +import com.hmdzl.spspd.items.armor.normalarmor.NormalArmor; +import com.hmdzl.spspd.items.armor.normalarmor.RubberArmor; +import com.hmdzl.spspd.items.armor.normalarmor.WoodenArmor; +import com.hmdzl.spspd.items.journalpages.Vault; +import com.hmdzl.spspd.items.scrolls.ScrollOfPsionicBlast; +import com.hmdzl.spspd.items.wands.WandOfFlow; +import com.hmdzl.spspd.items.weapon.melee.FightGloves; +import com.hmdzl.spspd.items.weapon.melee.Knuckles; +import com.hmdzl.spspd.items.weapon.melee.special.FireCracker; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.BeastYearSprite; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public class YearBeast extends Mob { + protected static final float SPAWN_DELAY = 1f; + { + //name = "YearBeast"; + spriteClass = BeastYearSprite.class; + baseSpeed = 1f; + + HP = HT = 1000; + EXP = 0; + evadeSkill = 30; + viewDistance = 6; + baseSpeed=1.5f; + flying = true; + } + + private int times=0; + + private static final String TIMES = "times"; + + @Override + public void storeInBundle( Bundle bundle ) { + super.storeInBundle(bundle); + bundle.put( TIMES, times ); + } + + @Override + public void restoreFromBundle( Bundle bundle ) { + super.restoreFromBundle(bundle); + times = bundle.getInt( TIMES ); + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(40, 60); + } + + @Override + public int hitSkill(Char target) { + return 40; + } + + + @Override + public boolean act() { + times++; + for (Char ch : Dungeon.level.mobs) { + Buff.affect(ch,Burning.class).reignite(ch); + } + for (int i = 0; i < Level.NEIGHBOURS9.length; i++) { + GameScene.add(Blob.seed(pos + Level.NEIGHBOURS9[i], 2, + Fire.class)); + } + return super.act(); + } + @Override + protected boolean canAttack(Char enemy) { + return Dungeon.level.distance( pos, enemy.pos ) <= 2 ; + } + @Override + public int attackProc(Char enemy, int damage) { + + if (Random.Int(2) == 0) { + Buff.affect(enemy, Burning.class).reignite(enemy); + } else { + Buff.affect(enemy, Frost.class); + } + + if (Random.Int(5) == 0) { + Buff.affect(enemy, Charm.class,4f); + } + + if (Random.Int(5) == 0) { + int oppositeDefender = enemy.pos + (enemy.pos - pos); + Ballistica trajectory = new Ballistica(enemy.pos, oppositeDefender, Ballistica.MAGIC_BOLT); + WandOfFlow.throwChar(enemy, trajectory, 1); + Buff.affect(enemy, Vertigo.class,3f); + } + + if (enemy == Dungeon.hero) { + Hero hero = Dungeon.hero; + KindOfWeapon weapon = hero.belongings.weapon; + KindOfArmor armor = hero.belongings.armor; + if (Random.Int(10)==0){ + if (Random.Int(2)==0) { + if (weapon != null && !(weapon instanceof Knuckles || weapon instanceof FightGloves) + && !weapon.cursed) { + hero.belongings.weapon = null; + Dungeon.level.drop(weapon, hero.pos).sprite.drop(); + GLog.w(Messages.get(this, "disarm")); + } + } else { + if (armor != null && !(armor instanceof WoodenArmor || armor instanceof RubberArmor || armor instanceof NormalArmor) + && !armor.cursed) { + hero.belongings.armor = null; + Dungeon.level.drop(armor, hero.pos).sprite.drop(); + GLog.w(Messages.get(this, "disarm")); + } + } + } + } + + return damage; + } + + @Override + public int defenseProc(Char enemy, int damage) { + + int dmg = damage; + if (dmg > 200 && buff(GlassShield.class) == null) { + Buff.affect(this,GlassShield.class).turns(3); + } + Buff.prolong(this,DefenceUp.class,3f).level(20); + Buff.prolong(this,AttackUp.class,3f).level(20); + return super.defenseProc(enemy, damage); + } + + @Override + public void damage(int dmg, Object src) { + if ( src instanceof FireCracker) { + times=0; + } + + super.damage(dmg, src); + } + + + @Override + public void die(Object cause) { + + //super.die(cause); + + if (times>= (Dungeon.getMonth()<3 ? 1000 : 5)){ + yell(Messages.get(this, "escape")); + } else { + yell(Messages.get(this, "die")); + Dungeon.level.drop(new Vault(), pos).sprite.drop(); + } + times=0; + destroy(); + sprite.killAndErase(); + CellEmitter.get(pos).burst(ElmoParticle.FACTORY, 6); + + } + + public static YearBeast spawnAt(int pos) { + if (Level.passable[pos] && Actor.findChar(pos) == null) { + + YearBeast w = new YearBeast(); + w.pos = pos; + w.state = w.HUNTING; + GameScene.add(w, SPAWN_DELAY); + return w; + } else { + return null; + } + } + + @Override + public void notice() { + super.notice(); + yell(Messages.get(this, "notice")); + } + + + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } + + @Override + public HashSet> resistances() { + return RESISTANCES; + } + + private static final HashSet> IMMUNITIES = new HashSet>(); + private static final HashSet> RESISTANCES = new HashSet>(); + static { + RESISTANCES.add(ToxicGas.class); + RESISTANCES.add(Poison.class); + RESISTANCES.add(ScrollOfPsionicBlast.class); + IMMUNITIES.add(Charm.class); + IMMUNITIES.add(Sleep.class); + IMMUNITIES.add(Terror.class); + IMMUNITIES.add(Fire.class); + IMMUNITIES.add(Vertigo.class); + IMMUNITIES.add(Burning.class); + } + +} diff --git a/java/com/hmdzl/spspd/actors/mobs/YearBeast2.java b/java/com/hmdzl/spspd/actors/mobs/YearBeast2.java new file mode 100644 index 00000000..8b42ce59 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/YearBeast2.java @@ -0,0 +1,222 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs; + +import java.util.HashSet; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.Fire; +import com.hmdzl.spspd.actors.blobs.ToxicGas; +import com.hmdzl.spspd.actors.buffs.AttackUp; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Burning; +import com.hmdzl.spspd.actors.buffs.Charm; +import com.hmdzl.spspd.actors.buffs.DefenceUp; +import com.hmdzl.spspd.actors.buffs.Frost; +import com.hmdzl.spspd.actors.buffs.GlassShield; +import com.hmdzl.spspd.actors.buffs.Poison; +import com.hmdzl.spspd.actors.buffs.Sleep; +import com.hmdzl.spspd.actors.buffs.Terror; +import com.hmdzl.spspd.actors.buffs.Vertigo; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.items.KindOfArmor; +import com.hmdzl.spspd.items.KindOfWeapon; +import com.hmdzl.spspd.items.armor.normalarmor.NormalArmor; +import com.hmdzl.spspd.items.armor.normalarmor.RubberArmor; +import com.hmdzl.spspd.items.armor.normalarmor.WoodenArmor; +import com.hmdzl.spspd.items.eggs.YearPetEgg; +import com.hmdzl.spspd.items.scrolls.ScrollOfPsionicBlast; +import com.hmdzl.spspd.items.wands.Wand; +import com.hmdzl.spspd.items.wands.WandOfFlow; +import com.hmdzl.spspd.items.weapon.melee.FightGloves; +import com.hmdzl.spspd.items.weapon.melee.Knuckles; +import com.hmdzl.spspd.items.weapon.melee.special.FireCracker; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.BeastYearSprite; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public class YearBeast2 extends Mob { + protected static final float SPAWN_DELAY = 1f; + { + //name = "YearBeast"; + spriteClass = BeastYearSprite.class; + baseSpeed = 1f; + + HP = HT = 1000; + EXP = 0; + evadeSkill = 30; + viewDistance = 6; + baseSpeed=1.5f; + flying = true; + } + + private int times=0; + + private static final String TIMES = "times"; + + @Override + public void storeInBundle( Bundle bundle ) { + super.storeInBundle(bundle); + bundle.put( TIMES, times ); + } + + @Override + public void restoreFromBundle( Bundle bundle ) { + super.restoreFromBundle(bundle); + times = bundle.getInt( TIMES ); + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(40, 60); + } + + @Override + public int hitSkill(Char target) { + return 40; + } + + + @Override + public boolean act() { + times++; + return super.act(); + } + @Override + protected boolean canAttack(Char enemy) { + return Dungeon.level.distance( pos, enemy.pos ) <= 2 ; + } + @Override + public int attackProc(Char enemy, int damage) { + + if (Random.Int(2) == 0) { + Buff.affect(enemy, Burning.class).reignite(enemy); + } else { + Buff.affect(enemy, Frost.class); + } + + if (Random.Int(5) == 0) { + Buff.affect(enemy, Charm.class,4f); + } + + if (Random.Int(5) == 0) { + int oppositeDefender = enemy.pos + (enemy.pos - pos); + Ballistica trajectory = new Ballistica(enemy.pos, oppositeDefender, Ballistica.MAGIC_BOLT); + WandOfFlow.throwChar(enemy, trajectory, 1); + Buff.affect(enemy, Vertigo.class,3f); + } + + if (enemy == Dungeon.hero) { + Hero hero = Dungeon.hero; + KindOfWeapon weapon = hero.belongings.weapon; + KindOfArmor armor = hero.belongings.armor; + if (Random.Int(10)==0){ + if (Random.Int(2)==0) { + if (weapon != null && !(weapon instanceof Knuckles || weapon instanceof FightGloves) + && !weapon.cursed) { + hero.belongings.weapon = null; + Dungeon.level.drop(weapon, hero.pos).sprite.drop(); + GLog.w(Messages.get(this, "disarm")); + } + } else { + if (armor != null && !(armor instanceof WoodenArmor || armor instanceof RubberArmor || armor instanceof NormalArmor) + && !armor.cursed) { + hero.belongings.armor = null; + Dungeon.level.drop(armor, hero.pos).sprite.drop(); + GLog.w(Messages.get(this, "disarm")); + } + } + } + } + + return damage; + } + + @Override + public int defenseProc(Char enemy, int damage) { + + int dmg = damage; + if (dmg > 200 && buff(GlassShield.class) == null) { + Buff.affect(this,GlassShield.class).turns(3); + } + Buff.prolong(this,DefenceUp.class,2f).level(times); + Buff.prolong(this,AttackUp.class,4f).level(times); + return super.defenseProc(enemy, damage); + } + + @Override + public void damage(int dmg, Object src) { + + if(src instanceof Wand) { + dmg = (int)(dmg/3); + } + + if ( src instanceof FireCracker) { + times=0; + } + + if (times > 50) + times-=3; + + super.damage(dmg, src); + } + + + @Override + public void die(Object cause) { + super.die(cause); + Dungeon.level.drop(new YearPetEgg(), pos).sprite.drop(); + } + + @Override + public void notice() { + super.notice(); + yell(Messages.get(this, "notice")); + } + + + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } + + @Override + public HashSet> resistances() { + return RESISTANCES; + } + + private static final HashSet> IMMUNITIES = new HashSet>(); + private static final HashSet> RESISTANCES = new HashSet>(); + static { + RESISTANCES.add(ToxicGas.class); + RESISTANCES.add(Poison.class); + RESISTANCES.add(ScrollOfPsionicBlast.class); + IMMUNITIES.add(Charm.class); + IMMUNITIES.add(Sleep.class); + IMMUNITIES.add(Terror.class); + IMMUNITIES.add(Fire.class); + IMMUNITIES.add(Vertigo.class); + IMMUNITIES.add(Burning.class); + } + +} diff --git a/java/com/hmdzl/spspd/actors/mobs/Yog.java b/java/com/hmdzl/spspd/actors/mobs/Yog.java new file mode 100644 index 00000000..b54529b8 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/Yog.java @@ -0,0 +1,745 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs; + +import java.util.ArrayList; +import java.util.HashSet; + +import com.hmdzl.spspd.actors.buffs.Silent; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.items.DolyaSlate; +import com.hmdzl.spspd.items.Elevator; +import com.hmdzl.spspd.levels.HallsBossLevel; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.ResultDescriptions; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.Blob; +import com.hmdzl.spspd.actors.blobs.Fire; +import com.hmdzl.spspd.actors.blobs.ToxicGas; +import com.hmdzl.spspd.actors.buffs.Amok; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Burning; +import com.hmdzl.spspd.actors.buffs.Charm; +import com.hmdzl.spspd.actors.buffs.Ooze; +import com.hmdzl.spspd.actors.buffs.Poison; +import com.hmdzl.spspd.actors.buffs.Roots; +import com.hmdzl.spspd.actors.buffs.Sleep; +import com.hmdzl.spspd.actors.buffs.Terror; +import com.hmdzl.spspd.actors.buffs.Vertigo; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.Pushing; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.effects.particles.ShadowParticle; +import com.hmdzl.spspd.items.keys.SkeletonKey; +import com.hmdzl.spspd.items.scrolls.ScrollOfPsionicBlast; +import com.hmdzl.spspd.items.weapon.enchantments.EnchantmentDark; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.BurningFistSprite; +import com.hmdzl.spspd.sprites.CharSprite; +import com.hmdzl.spspd.sprites.InfectingFistSprite; +import com.hmdzl.spspd.sprites.LarvaSprite; +import com.hmdzl.spspd.sprites.PinningFistSprite; +import com.hmdzl.spspd.sprites.RottingFistSprite; +import com.hmdzl.spspd.sprites.YogSprite; +import com.hmdzl.spspd.utils.GLog; + +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public class Yog extends Mob { + + { + spriteClass = YogSprite.class; + + HP = HT = 2000; + + EXP = 50; + + state = PASSIVE; + + properties.add(Property.UNKNOW); + properties.add(Property.BOSS); + } + + private static final int REGENERATION = 50; + private int breaks=0; + + public boolean checkYear() { + + int yearAlive = 0; + if (Dungeon.level.mobs != null) { + for (Mob mob : Dungeon.level.mobs) { + if (mob instanceof YearBeast) { + yearAlive++; + } + } + } + if (yearAlive++ > 0) { + return true; + } else { + return false; + } + } + + @Override + public boolean act() { + + if( 4 - breaks > 5 * HP / HT ) { + breaks++; + int newPos = -1; + for (int i = 0; i < 20; i++) { + newPos = Dungeon.level.randomRespawnCellMob(); + 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]; + GLog.n(Messages.get(this, "blink")); + } + + if (breaks == 4 && !checkYear()){ + int newPos2; + do { + newPos2 = Random.Int(Level.getLength()); + } while (!Level.passable[newPos2] + || Level.adjacent(newPos2, Dungeon.hero.pos) + || Actor.findChar(newPos2) != null); + YearBeast.spawnAt(newPos2); + } + return true; + } + + return super.act(); + } + + private static final String BREAKS = "breaks"; + + @Override + public void storeInBundle( Bundle bundle ) { + super.storeInBundle(bundle); + bundle.put( BREAKS, breaks ); + } + + @Override + public void restoreFromBundle( Bundle bundle ) { + super.restoreFromBundle(bundle); + breaks = bundle.getInt( BREAKS ); + + } + private static int fistsCount = 0; + + public Yog() { + super(); + } + + public void spawnFists() { + RottingFist fist1 = new RottingFist(); + BurningFist fist2 = new BurningFist(); + PinningFist fist3 = new PinningFist(); + InfectingFist fist4 = new InfectingFist(); + + + fist1.pos = Dungeon.level.randomRespawnCellMob(); + fist2.pos = Dungeon.level.randomRespawnCellMob(); + fist3.pos = Dungeon.level.randomRespawnCellMob(); + fist4.pos = Dungeon.level.randomRespawnCellMob(); + + GameScene.add(fist1); + GameScene.add(fist2); + GameScene.add(fist3); + GameScene.add(fist4); + } + + @Override + public int drRoll() { + + int checkFists = 0; + + for (Mob mob : Dungeon.level.mobs) { + if (mob instanceof BurningFist || mob instanceof RottingFist || mob instanceof PinningFist || mob instanceof InfectingFist) { + checkFists++; + } + } + + return 0+(30*checkFists); + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(54, 96); + } + + @Override + public void damage(int dmg, Object src) { + if (dmg > HP && (src instanceof Hero)) { + dmg = 1; + } + super.damage(dmg, src); + } + + @Override + public int defenseProc(Char enemy, int damage) { + + ArrayList spawnPoints = new ArrayList(); + + 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); + } + + for (Mob mob : Dungeon.level.mobs) { + if (mob instanceof BurningFist || mob instanceof RottingFist || mob instanceof InfectingFist || mob instanceof PinningFist + || mob instanceof Larva) { + mob.aggro(enemy); + } + } + if (fistsCount<1){ + spawnFists(); + sprite.emitter().burst(ShadowParticle.UP, 2); + this.damage(REGENERATION,this); + } + return super.defenseProc(enemy, damage); + } + + @Override + public void beckon(int cell) { + } + + @SuppressWarnings("unchecked") + @Override + public void die(Object cause) { + + ((HallsBossLevel) Dungeon.level).unseal(); + + for (Mob mob : (Iterable) Dungeon.level.mobs.clone()) { + if (mob instanceof BurningFist || mob instanceof RottingFist || mob instanceof Eye || mob instanceof PinningFist || mob instanceof InfectingFist) { + mob.die(cause); + } + } + + if (!Dungeon.limitedDrops.journal.dropped()){ + Dungeon.level.drop(new DolyaSlate(), pos).sprite.drop(); + Dungeon.limitedDrops.journal.drop(); + } + Dungeon.level.drop(new Elevator(), pos).sprite.drop(); + //Dungeon.level.drop(new Vault(), pos).sprite.drop(); + GameScene.bossSlain(); + Dungeon.level.drop(new SkeletonKey(Dungeon.depth), pos).sprite.drop(); + //Dungeon.level.drop(new Gold(Random.Int(6000, 8000)), pos).sprite.drop(); + super.die(cause); + + yell(Messages.get(this, "die")); + } + + @Override + public void notice() { + super.notice(); + yell(Messages.get(this, "notice")); + } + + + private static final HashSet> IMMUNITIES = new HashSet>(); + static { + + IMMUNITIES.add(EnchantmentDark.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); + IMMUNITIES.add(Vertigo.class); + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } + + public static class RottingFist extends Mob { + + private static final int REGENERATION = 50; + + { + //name = "rotting fist"; + spriteClass = RottingFistSprite.class; + + HP = HT = 1500; + evadeSkill = 25; + + EXP = 0; + + state = WANDERING; + properties.add(Property.ELEMENT); + properties.add(Property.BOSS); + } + + public RottingFist() { + super(); + fistsCount++; + } + + @Override + public void die(Object cause) { + super.die(cause); + fistsCount--; + } + + @Override + public int hitSkill(Char target) { + return 36; + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(44, 86); + } + + @Override + public int drRoll() { + return 35; + } + + @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(); + } + + private static final HashSet> RESISTANCES = new HashSet>(); + static { + RESISTANCES.add(ToxicGas.class); + RESISTANCES.add(EnchantmentDark.class); + + } + + @Override + public HashSet> resistances() { + return RESISTANCES; + } + + private static final HashSet> IMMUNITIES = new HashSet>(); + static { + IMMUNITIES.add(Amok.class); + IMMUNITIES.add(Sleep.class); + IMMUNITIES.add(Terror.class); + IMMUNITIES.add(Poison.class); + IMMUNITIES.add(Vertigo.class); + IMMUNITIES.add(ToxicGas.class); + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } + } + + public static class BurningFist extends Mob { + + { + spriteClass = BurningFistSprite.class; + + HP = HT = 1000; + evadeSkill = 25; + + EXP = 0; + + state = WANDERING; + properties.add(Property.ELEMENT); + properties.add(Property.BOSS); + } + + public BurningFist() { + super(); + fistsCount++; + } + + @Override + public void die(Object cause) { + super.die(cause); + fistsCount--; + } + + @Override + public int hitSkill(Char target) { + return 36; + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(40, 52); + } + + @Override + public int drRoll() { + return 25; + } + + @Override + protected boolean canAttack(Char enemy) { if (buff(Silent.class) != null){ + return Level.adjacent(pos, enemy.pos) && (!isCharmedBy(enemy)); + } else + return new Ballistica( pos, enemy.pos, Ballistica.MAGIC_BOLT).collisionPos == 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(Messages.format(ResultDescriptions.MOB)); + //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(); + } + + private static final HashSet> RESISTANCES = new HashSet>(); + static { + RESISTANCES.add(EnchantmentDark.class); + + } + + @Override + public HashSet> resistances() { + return RESISTANCES; + } + + private static final HashSet> IMMUNITIES = new HashSet>(); + static { + IMMUNITIES.add(Amok.class); + IMMUNITIES.add(Sleep.class); + IMMUNITIES.add(Terror.class); + IMMUNITIES.add(Burning.class); + IMMUNITIES.add(ScrollOfPsionicBlast.class); + IMMUNITIES.add(Vertigo.class); + IMMUNITIES.add(ToxicGas.class); + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } + } + + public static class InfectingFist extends Mob { + + { + spriteClass = InfectingFistSprite.class; + + HP = HT = 1500; + evadeSkill = 25; + + EXP = 0; + + state = WANDERING; + properties.add(Property.ELEMENT); + properties.add(Property.BOSS); + } + + public InfectingFist() { + super(); + fistsCount++; + } + + @Override + public void die(Object cause) { + super.die(cause); + fistsCount--; + } + + @Override + public int hitSkill(Char target) { + return 36; + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(44, 86); + } + + @Override + public int drRoll() { + return 35; + } + + @Override + public int attackProc(Char enemy, int damage) { + if (Random.Int(2) == 0) { + Buff.affect(enemy, Poison.class).set(Random.Int(7, 9) * Poison.durationFactor(enemy)); + state = FLEEING; + } + + return damage; + } + + @Override + public boolean act() { + + GameScene.add(Blob.seed(pos, 30, ToxicGas.class)); + + return super.act(); + } + + private static final HashSet> RESISTANCES = new HashSet>(); + static { + RESISTANCES.add(ToxicGas.class); + RESISTANCES.add(EnchantmentDark.class); + + } + + @Override + public HashSet> resistances() { + return RESISTANCES; + } + + private static final HashSet> IMMUNITIES = new HashSet>(); + static { + IMMUNITIES.add(Amok.class); + IMMUNITIES.add(Sleep.class); + IMMUNITIES.add(Terror.class); + IMMUNITIES.add(Poison.class); + IMMUNITIES.add(Vertigo.class); + IMMUNITIES.add(ToxicGas.class); + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } + } + + + public static class PinningFist extends Mob { + + { + spriteClass = PinningFistSprite.class; + + HP = HT = 1000; + evadeSkill = 25; + + EXP = 0; + + state = WANDERING; + properties.add(Property.ELEMENT); + properties.add(Property.BOSS); + } + + public PinningFist() { + super(); + fistsCount++; + } + + @Override + public void die(Object cause) { + super.die(cause); + fistsCount--; + } + + @Override + public int hitSkill(Char target) { + return 36; + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(30, 42); + } + + @Override + public int drRoll() { + return 25; + } + + @Override + protected boolean canAttack(Char enemy) { if (buff(Silent.class) != null){ + return Level.adjacent(pos, enemy.pos) && (!isCharmedBy(enemy)); + } else + return new Ballistica( pos, enemy.pos, Ballistica.MAGIC_BOLT).collisionPos == enemy.pos; + } + + @Override + protected boolean getCloser(int target) { + if (state == HUNTING) { + return enemySeen && getFurther(target); + } else { + return super.getCloser(target); + } + } + + @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); + + if(Random.Int(10)==0){ + Buff.prolong(enemy, Roots.class, 20); + } + + enemy.sprite.bloodBurstA(sprite.center(), dmg); + enemy.sprite.flash(); + + if (!enemy.isAlive() && enemy == Dungeon.hero) { + Dungeon.fail(Messages.format(ResultDescriptions.MOB)); + GLog.n(TXT_KILL, name); + } + return true; + + } else { + + enemy.sprite.showStatus(CharSprite.NEUTRAL, + enemy.defenseVerb()); + return false; + } + } else { + return super.attack(enemy); + } + } + + + private static final HashSet> RESISTANCES = new HashSet>(); + static { + RESISTANCES.add(ToxicGas.class); + RESISTANCES.add(EnchantmentDark.class); + + } + + @Override + public HashSet> resistances() { + return RESISTANCES; + } + + private static final HashSet> IMMUNITIES = new HashSet>(); + static { + IMMUNITIES.add(Amok.class); + IMMUNITIES.add(Sleep.class); + IMMUNITIES.add(Terror.class); + IMMUNITIES.add(Burning.class); + IMMUNITIES.add(ScrollOfPsionicBlast.class); + IMMUNITIES.add(Vertigo.class); + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } + } + + public static class Larva extends Mob { + + { + spriteClass = LarvaSprite.class; + + HP = HT = 25; + evadeSkill = 20; + + EXP = 0; + + state = HUNTING; + properties.add(Property.UNKNOW); + } + + @Override + public int hitSkill(Char target) { + return 30; + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(15, 20); + } + + @Override + public int drRoll() { + return 8; + } + + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/Zombie.java b/java/com/hmdzl/spspd/actors/mobs/Zombie.java new file mode 100644 index 00000000..b3f2d2c5 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/Zombie.java @@ -0,0 +1,101 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.ToxicGas; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Burning; +import com.hmdzl.spspd.actors.buffs.Poison; +import com.hmdzl.spspd.items.potions.PotionOfToxicGas; +import com.hmdzl.spspd.items.wands.WandOfFirebolt; +import com.hmdzl.spspd.sprites.ZombieSprite; +import com.watabou.utils.Random; + +import java.util.HashSet; + +public class Zombie extends Mob { + + + { + spriteClass = ZombieSprite.class; + + HP = HT = 70+(adj(0)*Random.NormalIntRange(3, 7)); + evadeSkill = 9+adj(1); + baseSpeed = 2f; + + + EXP = 7; + maxLvl = 18; + + state = WANDERING; + + loot = PotionOfToxicGas.class; + lootChance = 0.1f; + + properties.add(Property.UNDEAD); + } + + @Override + protected float attackDelay() { + return 2f; + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(10+adj(0), 20+adj(0)); + } + + @Override + public int hitSkill(Char target) { + return 15 +adj(0); + } + + @Override + public int drRoll() { + return Random.NormalIntRange(3, 8); + } + + @Override + public int attackProc(Char enemy, int damage) { + if (Random.Int(5) == 0) { + Buff.affect(enemy, Poison.class).set( + Random.Int(7, 9) * Poison.durationFactor(enemy)); + } + + return damage; + } + + private static final HashSet> RESISTANCES = new HashSet>(); + private static final HashSet> WEAKNESS = new HashSet>(); + static { + WEAKNESS.add(Burning.class); + WEAKNESS.add(WandOfFirebolt.class); + RESISTANCES.add(ToxicGas.class); + } + + @Override + public HashSet> resistances() { + return RESISTANCES; + } + + @Override + public HashSet> weakness() { + return WEAKNESS; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/Zot.java b/java/com/hmdzl/spspd/actors/mobs/Zot.java new file mode 100644 index 00000000..eb48b8b1 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/Zot.java @@ -0,0 +1,318 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs; + +import java.util.ArrayList; +import java.util.HashSet; + +import com.hmdzl.spspd.actors.buffs.Silent; +import com.hmdzl.spspd.items.SoulCollect; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.ToxicGas; +import com.hmdzl.spspd.actors.buffs.Amok; +import com.hmdzl.spspd.actors.buffs.Burning; +import com.hmdzl.spspd.actors.buffs.Charm; +import com.hmdzl.spspd.actors.buffs.Poison; +import com.hmdzl.spspd.actors.buffs.Sleep; +import com.hmdzl.spspd.actors.buffs.Terror; +import com.hmdzl.spspd.actors.buffs.Vertigo; +import com.hmdzl.spspd.actors.buffs.Paralysis; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.Pushing; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.misc.AutoPotion.AutoHealPotion; +import com.hmdzl.spspd.items.scrolls.ScrollOfPsionicBlast; +import com.hmdzl.spspd.items.weapon.enchantments.EnchantmentDark; + +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ZotSprite; + +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Random; + +public class Zot extends Mob { + + private static final int JUMP_DELAY = 10; + + { + spriteClass = ZotSprite.class; + baseSpeed = 0.5f; + + HP = HT = 25000; + //HP = HT = 25; + EXP = 20; + evadeSkill = 40; + //evadeSkill = 0; + + loot = new SoulCollect(); + lootChance = 1f; + + properties.add(Property.UNKNOW); + properties.add(Property.BOSS); + } + + private int timeToJump = JUMP_DELAY; + + + @Override + public int damageRoll() { + return Random.NormalIntRange(75, 125); + //return Random.NormalIntRange(1, 2); + } + + @Override + public int hitSkill(Char target) { + return 200; + } + + @Override + public int drRoll() { + return Random.NormalIntRange(25, 45); + //return 0; + } + + @Override + protected boolean act() { + + if (paralysed > 0) { + yell(Messages.get(this,"pain")); + + if(!checkEyes()){ + ArrayList spawnPoints = new ArrayList(); + + for (int i = 0; /*i < Level.NEIGHBOURS4.length*/ i < 2; i++) { + int p = Dungeon.hero.pos + Level.NEIGHBOURS4[i]; + if (Actor.findChar(p) == null + && (Level.passable[p] || Level.avoid[p])) { + spawnPoints.add(p); + } + } + + if (spawnPoints.size() > 0 && Random.Int(10) == 0) { + MagicEye eye = new MagicEye(); + eye.pos = Random.element(spawnPoints); + + GameScene.add(eye); + Actor.addDelayed(new Pushing(eye, pos, eye.pos), -1); + } + } + + if (HP < HT) { + sprite.emitter().burst( Speck.factory( Speck.HEALING ), 1 ); + HP = HP + 5; + } + } + + + boolean result = super.act(); + + int regen = Dungeon.hero.buff(AutoHealPotion.class) != null ? 1 : Random.Int(2,5); + + + if (HP < HT) { + sprite.emitter().burst( Speck.factory( Speck.HEALING ), 1 ); + HP = HP + regen; + } + return result; + } + + @SuppressWarnings("unchecked") + @Override + public void die(Object cause) { + + yell(Messages.get(this,"die")); + + super.die(cause); + + GameScene.bossSlain(); + //Dungeon.level.locked=false; + Dungeon.zotkilled=true; + + for (Mob mob : Dungeon.level.mobs.toArray(new Mob[Dungeon.level.mobs.size()])) { + if (mob instanceof ZotPhase || mob instanceof MagicEye) { + mob.die(null); + } + } + } + + @Override + protected boolean getCloser(int target) { + if (Level.fieldOfView[target]) { + jump(); + return true; + } else { + return super.getCloser(target); + } + } + + @Override + protected boolean canAttack(Char enemy) { + if (buff(Silent.class) != null){ + return Level.adjacent(pos, enemy.pos) && (!isCharmedBy(enemy)); + } else + return new Ballistica( pos, enemy.pos, Ballistica.MAGIC_BOLT).collisionPos == 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; + + if (!checkPhases()){ + ArrayList spawnPoints = new ArrayList(); + + 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) { + ZotPhase zot = new ZotPhase(); + zot.pos = Random.element(spawnPoints); + + GameScene.add(zot); + Actor.addDelayed(new Pushing(zot, pos, zot.pos), -1); + } + } + + int newPos; + do { + newPos = Random.Int(Level.getLength()); + } 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()); + } + + private boolean checkPhases(){ + boolean check = false; + int phases = 0; + for (Mob mob : Dungeon.level.mobs) { + if (mob != null && mob instanceof ZotPhase) { + phases++; + if (phases>6){ + check=true; + } + } + } + return check; + + } + + private boolean checkEyes(){ + boolean check = false; + int phases = 0; + for (Mob mob : Dungeon.level.mobs) { + if (mob != null && mob instanceof MagicEye) { + phases++; + if (phases>10){ + check=true; + } + } + } + return check; + } + + @Override + public void damage(int dmg, Object src) { + + if(!checkPhases()){ + ArrayList spawnPoints = new ArrayList(); + + for (int i = 0; i < Level.NEIGHBOURS8.length; i++) { + int p = Dungeon.hero.pos + Level.NEIGHBOURS8[i]; + if (Actor.findChar(p) == null + && (Level.passable[p] || Level.avoid[p])) { + spawnPoints.add(p); + } + } + + if (spawnPoints.size() > 0) { + MagicEye eye = new MagicEye(); + eye.pos = Random.element(spawnPoints); + + GameScene.add(eye); + Actor.addDelayed(new Pushing(eye, pos, eye.pos), -1); + } + } + + super.damage(dmg, src); + } + + @Override + public void notice() { + super.notice(); + yell(Messages.get(this,"notice")); + } + + private static final HashSet> RESISTANCES = new HashSet>(); + private static final HashSet> IMMUNITIES = new HashSet>(); + static { + RESISTANCES.add(ToxicGas.class); + RESISTANCES.add(Poison.class); + RESISTANCES.add(EnchantmentDark.class); + + IMMUNITIES.add(EnchantmentDark.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); + IMMUNITIES.add(Vertigo.class); + IMMUNITIES.add(Paralysis.class); + } + + @Override + public HashSet> resistances() { + return RESISTANCES; + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/ZotPhase.java b/java/com/hmdzl/spspd/actors/mobs/ZotPhase.java new file mode 100644 index 00000000..7d2a331f --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/ZotPhase.java @@ -0,0 +1,91 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs; + +import java.util.HashSet; + +import com.hmdzl.spspd.actors.buffs.Silent; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.traps.LightningTrap; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.sprites.ZotPhaseSprite; + +import com.watabou.utils.Random; + +public class ZotPhase extends Mob{ + + private static final float TIME_TO_ZAP = 2f; + + private static final String TXT_LIGHTNING_KILLED = "%s's lightning bolt killed you..."; + + { + spriteClass = ZotPhaseSprite.class; + + HP = HT = 200; + evadeSkill = 40; + baseSpeed = 1f; + + EXP = 30; + + loot = Generator.Category.SCROLL; + lootChance = 0.33f; + + properties.add(Property.UNKNOW); + + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(115, 160+adj(1)); + } + + @Override + public int hitSkill(Char target) { + return 100+adj(0); + } + + @Override + protected float attackDelay() { + return 2f; + } + + + @Override + public int drRoll() { + return 0; + } + + @Override + protected boolean canAttack(Char enemy) { if (buff(Silent.class) != null){ + return Level.adjacent(pos, enemy.pos) && (!isCharmedBy(enemy)); + } else + return new Ballistica( pos, enemy.pos, Ballistica.MAGIC_BOLT).collisionPos == enemy.pos; + } + + private static final HashSet> RESISTANCES = new HashSet>(); + static { + RESISTANCES.add(LightningTrap.Electricity.class); + } + + @Override + public HashSet> resistances() { + return RESISTANCES; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/npcs/AFly.java b/java/com/hmdzl/spspd/actors/mobs/npcs/AFly.java new file mode 100644 index 00000000..bf84a524 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/npcs/AFly.java @@ -0,0 +1,87 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs.npcs; + + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.AFlySprite; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.windows.WndAflyInfo; +import com.watabou.utils.Random; + +public class AFly extends NPC { + + { + //name = "AFly"; + spriteClass = AFlySprite.class; + //state = WANDERING; + properties.add(Property.ELF); + properties.add(Property.DEMONIC); + } + + /*@Override + protected boolean act() { + throwItem(); + return super.act(); + } */ + + @Override + public int evadeSkill(Char enemy) { + return 1000; + } + + + @Override + protected Char chooseEnemy() { + return null; + } + + @Override + public void damage(int dmg, Object src) { + } + + @Override + public void add(Buff buff) { + } + + @Override + public boolean reset() { + return true; + } + + + + @Override + public boolean interact() { + + sprite.turnTo(pos, Dungeon.hero.pos); + switch (Random.Int (2)) { + case 0: + yell(Messages.get(this, "yell1")); + break; + case 1: + GameScene.show(new WndAflyInfo()); + break; + } + return true; + } + +} diff --git a/java/com/hmdzl/spspd/actors/mobs/npcs/ARealMan.java b/java/com/hmdzl/spspd/actors/mobs/npcs/ARealMan.java new file mode 100644 index 00000000..aef45251 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/npcs/ARealMan.java @@ -0,0 +1,59 @@ +package com.hmdzl.spspd.actors.mobs.npcs; + + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ARealManSprite; +import com.hmdzl.spspd.windows.WndMix; + +public class ARealMan extends NPC { + + { + //name = Messages.get(this,"name"); + spriteClass = ARealManSprite.class; + properties.add(Property.BEAST); + } + + @Override + protected boolean act() { + throwItem(); + return super.act(); + } + + @Override + public int evadeSkill(Char enemy) { + return 1000; + } + + + @Override + protected Char chooseEnemy() { + return null; + } + + @Override + public void damage(int dmg, Object src) { + } + + @Override + public void add(Buff buff) { + } + + @Override + public boolean reset() { + return true; + } + + + + @Override + public boolean interact() { + + sprite.turnTo(pos, Dungeon.hero.pos); + GameScene.show(new WndMix()); + return true; + } + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/mobs/npcs/AliveFish.java b/java/com/hmdzl/spspd/actors/mobs/npcs/AliveFish.java new file mode 100644 index 00000000..61efcf8d --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/npcs/AliveFish.java @@ -0,0 +1,82 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2014 Oleg Dolya + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.actors.mobs.npcs; + + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.sprites.PiranhaSprite; +import com.hmdzl.spspd.messages.Messages; +import com.watabou.utils.Random; + +public class AliveFish extends NPC { + + { + //name = Messages.get(this,"name"); + spriteClass = PiranhaSprite.class; + properties.add(Property.BEAST); + } + + @Override + protected boolean act() { + throwItem(); + return super.act(); + } + + @Override + public int evadeSkill(Char enemy) { + return 1000; + } + + + @Override + protected Char chooseEnemy() { + return null; + } + + @Override + public void damage(int dmg, Object src) { + } + + @Override + public void add(Buff buff) { + } + + @Override + public boolean reset() { + return true; + } + + + + @Override + public boolean interact() { + + sprite.turnTo(pos, Dungeon.hero.pos); + switch (Random.Int (2)) { + case 0: + yell(Messages.get(this, "yell1")); + break; + case 1: + yell(Messages.get(this, "yell2")); + break; + } + return true; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/npcs/Apostle.java b/java/com/hmdzl/spspd/actors/mobs/npcs/Apostle.java new file mode 100644 index 00000000..d87e2307 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/npcs/Apostle.java @@ -0,0 +1,92 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs.npcs; + + +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ApostleSprite; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.windows.WndDream; +import com.watabou.utils.Random; + +public class Apostle extends NPC { + + { + //name = "apostle"; + spriteClass = ApostleSprite.class; + //state = WANDERING; + properties.add(Property.MECH); + properties.add(Property.ELEMENT); + } + + /*@Override + protected boolean act() { + throwItem(); + return super.act(); + } */ + + @Override + public int evadeSkill(Char enemy) { + return 1000; + } + + + @Override + protected Char chooseEnemy() { + return null; + } + + @Override + public void damage(int dmg, Object src) { + } + + @Override + public void add(Buff buff) { + } + + @Override + public boolean reset() { + return true; + } + + + + @Override + public boolean interact() { + + sprite.turnTo(pos, Dungeon.hero.pos); + switch (Random.Int (2)) { + case 0: + yell(Messages.get(this, "yell1")); + break; + case 1: + yell(Messages.get(this, "yell2")); + break; + case 2: + if (Badges.checkOtilukeRescued()) + yell(Messages.get(this, "yell3")); + break; + } + return true; + } + +} diff --git a/java/com/hmdzl/spspd/actors/mobs/npcs/Bilboldev.java b/java/com/hmdzl/spspd/actors/mobs/npcs/Bilboldev.java new file mode 100644 index 00000000..16de0116 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/npcs/Bilboldev.java @@ -0,0 +1,85 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs.npcs; + + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.sprites.BilboldevSprite; +import com.hmdzl.spspd.messages.Messages; +import com.watabou.utils.Random; + +public class Bilboldev extends NPC { + + { + //name = "Bilboldev"; + spriteClass = BilboldevSprite.class; + properties.add(Property.MECH); + } + + @Override + protected boolean act() { + throwItem(); + return super.act(); + } + + @Override + public int evadeSkill(Char enemy) { + return 1000; + } + + + @Override + protected Char chooseEnemy() { + return null; + } + + @Override + public void damage(int dmg, Object src) { + } + + @Override + public void add(Buff buff) { + } + + @Override + public boolean reset() { + return true; + } + + + + @Override + public boolean interact() { + + sprite.turnTo(pos, Dungeon.hero.pos); + switch (Random.Int (3)) { + case 0: + yell(Messages.get(this, "yell1")); + break; + case 1: + yell(Messages.get(this, "yell2")); + break; + case 2: + yell(Messages.get(this, "yell3")); + break; + } + return true; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/npcs/Blacksmith.java b/java/com/hmdzl/spspd/actors/mobs/npcs/Blacksmith.java new file mode 100644 index 00000000..2b52d69d --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/npcs/Blacksmith.java @@ -0,0 +1,397 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs.npcs; + +import java.util.Collection; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.Journal; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.items.ChaosPack; +import com.hmdzl.spspd.items.CurseBlood; +import com.hmdzl.spspd.items.EmptyBody; +import com.hmdzl.spspd.items.EquipableItem; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.TriForce; +import com.hmdzl.spspd.items.TriforceOfCourage; +import com.hmdzl.spspd.items.TriforceOfPower; +import com.hmdzl.spspd.items.TriforceOfWisdom; +import com.hmdzl.spspd.items.quest.DarkGold; +import com.hmdzl.spspd.items.quest.Pickaxe; +import com.hmdzl.spspd.items.scrolls.ScrollOfUpgrade; +import com.hmdzl.spspd.items.weapon.melee.special.Handcannon; +import com.hmdzl.spspd.items.weapon.melee.special.ShadowEater; +import com.hmdzl.spspd.levels.Room; +import com.hmdzl.spspd.levels.Room.Type; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.BlacksmithSprite; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.utils.GLog; +import com.hmdzl.spspd.windows.WndBlacksmith; +import com.hmdzl.spspd.windows.WndQuest; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public class Blacksmith extends 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, " + + "We're the only blacksmiths 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, " + + "We're the only blacksmiths 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"; + private static final String COLLECTED = "Finally, the TriForce. I will forge them for you..."; + + { + //name = "troll blacksmith named Bop"; + spriteClass = BlacksmithSprite.class; + properties.add(Property.TROLL); + properties.add(Property.IMMOVABLE); + } + + + @Override + protected boolean act() { + throwItem(); + return super.act(); + } + + @Override + public boolean interact() { + + sprite.turnTo(pos, Dungeon.hero.pos); + + if (checksan()){ + tell(Messages.get(this, "triforce")); + TriForce san = new TriForce(); + Dungeon.triforce = true; + Dungeon.level.drop(san, Dungeon.hero.pos).sprite.drop(); + } + + if (checkeater()){ + tell(Messages.get(this, "shadoweater")); + ShadowEater san = new ShadowEater(); + Dungeon.level.drop(san, Dungeon.hero.pos).sprite.drop(); + } + + + if (!Quest.given) { + + GameScene.show(new WndQuest(this, + Quest.alternative ? Messages.get(this, "blood_1") : Messages.get(this, "gold_1")) { + + @Override + public void onBackPressed() { + super.onBackPressed(); + + Quest.given = true; + Quest.completed = false; + + Pickaxe pick = new Pickaxe(); + + 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(Messages.get(this, "lost_pick")); + } else if (!pick.bloodStained) { + tell(Messages.get(this, "blood_2")); + } else { + //if (pick.isEquipped(Dungeon.hero)) { + // pick.doUnequip(Dungeon.hero, false); + //} + //pick.detach(Dungeon.hero.belongings.backpack); + yell( Messages.get(this, "keeppickaxe")); + tell(Messages.get(this, "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(Messages.get(this, "lost_pick")); + } else if (gold == null || gold.quantity() < 15) { + tell(Messages.get(this, "gold_2")); + } else { + //if (pick.isEquipped(Dungeon.hero)) { + // pick.doUnequip(Dungeon.hero, false); + //} + //pick.detach(Dungeon.hero.belongings.backpack); + yell( Messages.get(this, "keeppickaxe")); + tell( Messages.get(this, "completed")); + + Quest.completed = true; + Quest.reforged = false; + } + + } + } else if (!Quest.reforged) { + + GameScene.show(new WndBlacksmith(this, Dungeon.hero)); + + } else { + + tell(Messages.get(this, "get_lost")); + + + } + return false; + } + + private void tell(String text) { + GameScene.show(new WndQuest(this, text)); + } + + public static String verify(Item item1, Item item2) { + + if (item1 == item2) { + return Messages.get(Blacksmith.class, "same_item"); + } + + //if (item1.getClass() != item2.getClass()) { + // return "Select 2 items of the same type!"; + //} + + if (!item1.isIdentified() || !item2.isIdentified()) { + return Messages.get(Blacksmith.class, "un_ided"); + } + + if (item1.cursed || item2.cursed) { + return Messages.get(Blacksmith.class, "cursed"); + } + + if (item1.level < 0 || item2.level < 1) { + return Messages.get(Blacksmith.class, "degraded"); + } + + if ((item1.level + item2.level > 15) && !item1.isReinforced()) { + return Messages.get(Blacksmith.class, "need_reinforced"); + } + + if (!item1.isUpgradable() || !item2.isUpgradable()) { + return Messages.get(Blacksmith.class, "cant_reforge"); + } + + return null; + } + + private static float upgradeChance = 0.5f; + public static void upgrade(Item item1, Item item2) { + + Item first, second; + + 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); + } + + DarkGold gold = Dungeon.hero.belongings.getItem(DarkGold.class); + if (gold!=null){ + upgradeChance = (upgradeChance + (gold.quantity()*0.05f)); + } + if (first != null) { + for(int i=0; i rooms) { + //if (!spawned && Dungeon.depth > 11 && Random.Int( 15 - Dungeon.depth ) == 0) { + if (!spawned ) { + + 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; + + Handcannon saw = Dungeon.hero.belongings.getItem(Handcannon.class); + if (saw==null){ + alternative = Random.Int(2) == 0; + } else { + alternative = false; + } + given = false; + + break; + } + } + } + return spawned; + } + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/npcs/Blacksmith2.java b/java/com/hmdzl/spspd/actors/mobs/npcs/Blacksmith2.java new file mode 100644 index 00000000..58b472be --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/npcs/Blacksmith2.java @@ -0,0 +1,200 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs.npcs; + +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.items.AdamantArmor; +import com.hmdzl.spspd.items.AdamantRing; +import com.hmdzl.spspd.items.AdamantWand; +import com.hmdzl.spspd.items.AdamantWeapon; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.armor.Armor; +import com.hmdzl.spspd.items.quest.DarkGold; +import com.hmdzl.spspd.items.rings.Ring; +import com.hmdzl.spspd.items.wands.Wand; +import com.hmdzl.spspd.items.weapon.guns.GunWeapon; +import com.hmdzl.spspd.items.weapon.melee.MeleeWeapon; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ElectricwelderSprite; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.utils.GLog; +import com.hmdzl.spspd.windows.WndBlacksmith2; +import com.hmdzl.spspd.windows.WndQuest; + +public class Blacksmith2 extends NPC { + + + private static final String TXT_LOOKS_BETTER = "your %s pulsates with magical energy. "; + private static final String TXT_GET_LOST = "I'm busy. Get lost!"; + private static final String TXT2 = "My brother and I make all the items in this dungeon. " + +"He melts down two upgraded items to enhance one of them. " + +"My specialty is reinforcing items with adamantite. " + +"Come back to me when you have 50 dark gold and some adamantite for me to work with. " ; + + private static final String TXT3 = "Oh ho! Looks like you have some adamantite there. " + +"I can reinforce an item with adamantite if you wish. " + +"Reinforced items can handle higher levels of magical upgrade. " + +"It'll cost you though!. " + +"Come back to me when you have 50 dark gold. " ; + + + + { + //name = "troll blacksmith named Bip"; + spriteClass = ElectricwelderSprite.class; + properties.add(Property.TROLL); + properties.add(Property.IMMOVABLE); + } + + + @Override + protected boolean act() { + throwItem(); + return super.act(); + } + + @Override + public boolean interact() { + + sprite.turnTo(pos, Dungeon.hero.pos); + + + DarkGold gold = Dungeon.hero.belongings.getItem(DarkGold.class); + if (!checkAdamant()) { + tell(Messages.get(Blacksmith2.class, "himself")); + } else if (gold == null || gold.quantity() < 50) { + tell(Messages.get(Blacksmith2.class, "adamantite")); + } else if (checkAdamant() && gold != null && gold.quantity() > 49){ + GameScene.show(new WndBlacksmith2(this, Dungeon.hero)); + } else { + tell(Messages.get(Blacksmith2.class, "himself")); + } + return false; + } + + public static String verify(Item item1, Item item2) { + + if (item1 == item2) { + return Messages.get(Blacksmith2.class, "same_item"); + } + + if (!item1.isIdentified()) { + return Messages.get(Blacksmith2.class, "un_ided"); + } + + if (item1.cursed) { + return Messages.get(Blacksmith2.class, "cursed"); + } + + if (item1.reinforced) { + return Messages.get(Blacksmith2.class, "already_reforge"); + } + + if (item1.level < 0) { + return Messages.get(Blacksmith2.class, "degraded"); + } + + if (!item1.isUpgradable()) { + return Messages.get(Blacksmith2.class, "cant_reforge"); + } + + if(item1 instanceof Armor && item2 instanceof AdamantArmor){ + return null; + } + + if(item1 instanceof MeleeWeapon && item2 instanceof AdamantWeapon){ + return null; + } + + if(item1 instanceof GunWeapon && item2 instanceof AdamantWeapon){ + return null; + } + + if(item1 instanceof Wand && item2 instanceof AdamantWand){ + return null; + } + + if(item1 instanceof Ring && item2 instanceof AdamantRing){ + return null; + } + + return Messages.get(Blacksmith2.class, "cant_work"); + + } + + public static void upgrade(Item item1, Item item2) { + + item1.reinforced=true; + item2.detach(Dungeon.hero.belongings.backpack); + DarkGold gold = Dungeon.hero.belongings.getItem(DarkGold.class); + if (gold != null && gold.quantity() > 49 ) { + gold.detach(Dungeon.hero.belongings.backpack,50); + if(!(Dungeon.hero.belongings.getItem(DarkGold.class).quantity() > 0)){ + gold.detachAll(Dungeon.hero.belongings.backpack); + } + } + + GLog.p(TXT_LOOKS_BETTER, item1.name()); + Dungeon.hero.spendAndNext(2f); + Badges.validateItemLevelAquired(item1); + + } + + + private void tell(String text) { + GameScene.show(new WndQuest(this, text)); + } + + + public static boolean checkAdamant() { + AdamantArmor armor1 = Dungeon.hero.belongings.getItem(AdamantArmor.class); + AdamantWeapon weapon1 = Dungeon.hero.belongings.getItem(AdamantWeapon.class); + AdamantRing ring1 = Dungeon.hero.belongings.getItem(AdamantRing.class); + AdamantWand wand1 = Dungeon.hero.belongings.getItem(AdamantWand.class); + + if(armor1!=null || weapon1!=null || ring1!=null || wand1!=null) { + return true; + } + return false; + } + + + + + @Override + public int evadeSkill(Char enemy) { + return 1000; + } + + @Override + public void damage(int dmg, Object src) { + } + + @Override + public void add(Buff buff) { + } + + @Override + public boolean reset() { + return true; + } + +} diff --git a/java/com/hmdzl/spspd/actors/mobs/npcs/Coconut.java b/java/com/hmdzl/spspd/actors/mobs/npcs/Coconut.java new file mode 100644 index 00000000..2ac86db1 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/npcs/Coconut.java @@ -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 + */ +package com.hmdzl.spspd.actors.mobs.npcs; + + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.sprites.CoconutSprite; +import com.hmdzl.spspd.messages.Messages; +import com.watabou.utils.Random; + +public class Coconut extends NPC { + + { + //name = Messages.get(this,"name"); + spriteClass = CoconutSprite.class; + properties.add(Property.MECH); + + } + + @Override + protected boolean act() { + throwItem(); + return super.act(); + } + + @Override + public int evadeSkill(Char enemy) { + return 1000; + } + + + @Override + protected Char chooseEnemy() { + return null; + } + + @Override + public void damage(int dmg, Object src) { + } + + @Override + public void add(Buff buff) { + } + + @Override + public boolean reset() { + return true; + } + + + + @Override + public boolean interact() { + + sprite.turnTo(pos, Dungeon.hero.pos); + switch (Random.Int (3)) { + case 0: + yell(Messages.get(this, "yell1")); + break; + case 1: + yell(Messages.get(this, "yell2")); + break; + case 2: + yell(Messages.get(this, "yell3")); + break; + } + return true; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/npcs/Coconut2.java b/java/com/hmdzl/spspd/actors/mobs/npcs/Coconut2.java new file mode 100644 index 00000000..ec82756d --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/npcs/Coconut2.java @@ -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 + */ +package com.hmdzl.spspd.actors.mobs.npcs; + + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.sprites.CoconutSprite; +import com.hmdzl.spspd.messages.Messages; +import com.watabou.utils.Random; + +public class Coconut2 extends NPC { + + { + //name = Messages.get(this,"name"); + spriteClass = CoconutSprite.class; + properties.add(Property.MECH); + + } + + @Override + protected boolean act() { + throwItem(); + return super.act(); + } + + @Override + public int evadeSkill(Char enemy) { + return 1000; + } + + + @Override + protected Char chooseEnemy() { + return null; + } + + @Override + public void damage(int dmg, Object src) { + } + + @Override + public void add(Buff buff) { + } + + @Override + public boolean reset() { + return true; + } + + + + @Override + public boolean interact() { + + sprite.turnTo(pos, Dungeon.hero.pos); + switch (Random.Int (3)) { + case 0: + yell(Messages.get(this, "yell1")); + break; + case 1: + yell(Messages.get(this, "yell2")); + break; + case 2: + yell(Messages.get(this, "yell3")); + break; + } + return true; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/npcs/ConsideredHamster.java b/java/com/hmdzl/spspd/actors/mobs/npcs/ConsideredHamster.java new file mode 100644 index 00000000..e0e02a96 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/npcs/ConsideredHamster.java @@ -0,0 +1,82 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2014 Oleg Dolya + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.actors.mobs.npcs; + + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.sprites.MimicSprite; +import com.hmdzl.spspd.messages.Messages; +import com.watabou.utils.Random; + +public class ConsideredHamster extends NPC { + + { + //name = "Mimic"; + spriteClass = MimicSprite.class; + properties.add(Property.UNKNOW); + } + + @Override + protected boolean act() { + throwItem(); + return super.act(); + } + + @Override + public int evadeSkill(Char enemy) { + return 1000; + } + + + @Override + protected Char chooseEnemy() { + return null; + } + + @Override + public void damage(int dmg, Object src) { + } + + @Override + public void add(Buff buff) { + } + + @Override + public boolean reset() { + return true; + } + + + + @Override + public boolean interact() { + + sprite.turnTo(pos, Dungeon.hero.pos); + switch (Random.Int (2)) { + case 0: + yell(Messages.get(this, "yell1")); + break; + case 1: + yell(Messages.get(this, "yell2")); + break; + } + return true; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/npcs/Dachhack.java b/java/com/hmdzl/spspd/actors/mobs/npcs/Dachhack.java new file mode 100644 index 00000000..45164128 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/npcs/Dachhack.java @@ -0,0 +1,85 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs.npcs; + + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.sprites.DachhackSprite; +import com.hmdzl.spspd.messages.Messages; +import com.watabou.utils.Random; + +public class Dachhack extends NPC { + + { + //name = "dachhack"; + spriteClass = DachhackSprite.class; + properties.add(Property.PLANT); + } + + @Override + protected boolean act() { + throwItem(); + return super.act(); + } + + @Override + public int evadeSkill(Char enemy) { + return 1000; + } + + + @Override + protected Char chooseEnemy() { + return null; + } + + @Override + public void damage(int dmg, Object src) { + } + + @Override + public void add(Buff buff) { + } + + @Override + public boolean reset() { + return true; + } + + + + @Override + public boolean interact() { + + sprite.turnTo(pos, Dungeon.hero.pos); + switch (Random.Int (3)) { + case 0: + yell(Messages.get(this, "yell1")); + break; + case 1: + yell(Messages.get(this, "yell2")); + break; + case 2: + yell(Messages.get(this, "yell3")); + break; + } + return true; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/npcs/DreamPlayer.java b/java/com/hmdzl/spspd/actors/mobs/npcs/DreamPlayer.java new file mode 100644 index 00000000..49415a30 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/npcs/DreamPlayer.java @@ -0,0 +1,92 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs.npcs; + + +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.DreamPlayerSprite; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.windows.WndDream; +import com.hmdzl.spspd.windows.WndSaidBySun; +import com.watabou.utils.Random; + +public class DreamPlayer extends NPC { + + { + //name = "DreamPlayer"; + spriteClass = DreamPlayerSprite.class; + state = WANDERING; + properties.add(Property.ELEMENT); + } + + /*@Override + protected boolean act() { + throwItem(); + return super.act(); + } */ + + @Override + public int evadeSkill(Char enemy) { + return 1000; + } + + + @Override + protected Char chooseEnemy() { + return null; + } + + @Override + public void damage(int dmg, Object src) { + } + + @Override + public void add(Buff buff) { + } + + @Override + public boolean reset() { + return true; + } + + + + @Override + public boolean interact() { + + sprite.turnTo(pos, Dungeon.hero.pos); + switch (Random.Int (3)) { + case 0: + yell(Messages.get(this, "yell1")); + break; + case 1: + yell(Messages.get(this, "yell2")); + break; + case 2: + if (Badges.checkOtilukeRescued()) + GameScene.show(new WndDream()); + break; + } + return true; + } + +} diff --git a/java/com/hmdzl/spspd/actors/mobs/npcs/Evan.java b/java/com/hmdzl/spspd/actors/mobs/npcs/Evan.java new file mode 100644 index 00000000..09165b3b --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/npcs/Evan.java @@ -0,0 +1,82 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2014 Oleg Dolya + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.actors.mobs.npcs; + + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.sprites.EvanSprite; +import com.hmdzl.spspd.messages.Messages; +import com.watabou.utils.Random; + +public class Evan extends NPC { + + { + //name = "Shattered Pixel Dungeon"; + spriteClass = EvanSprite.class; + properties.add(Property.MECH); + } + + @Override + protected boolean act() { + throwItem(); + return super.act(); + } + + @Override + public int evadeSkill(Char enemy) { + return 1000; + } + + + @Override + protected Char chooseEnemy() { + return null; + } + + @Override + public void damage(int dmg, Object src) { + } + + @Override + public void add(Buff buff) { + } + + @Override + public boolean reset() { + return true; + } + + + + @Override + public boolean interact() { + + sprite.turnTo(pos, Dungeon.hero.pos); + switch (Random.Int (2)) { + case 0: + yell(Messages.get(this, "yell1")); + break; + case 1: + yell(Messages.get(this, "yell2")); + break; + } + return true; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/npcs/FruitCat.java b/java/com/hmdzl/spspd/actors/mobs/npcs/FruitCat.java new file mode 100644 index 00000000..22c5cdb8 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/npcs/FruitCat.java @@ -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 + */ +package com.hmdzl.spspd.actors.mobs.npcs; + + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.sprites.FruitCatSprite; +import com.hmdzl.spspd.messages.Messages; +import com.watabou.utils.Random; + +public class FruitCat extends NPC { + + { + //name = Messages.get(this,"name"); + spriteClass = FruitCatSprite.class; + properties.add(Property.BEAST); + } + + @Override + protected boolean act() { + throwItem(); + return super.act(); + } + + @Override + public int evadeSkill(Char enemy) { + return 1000; + } + + + @Override + protected Char chooseEnemy() { + return null; + } + + @Override + public void damage(int dmg, Object src) { + } + + @Override + public void add(Buff buff) { + } + + @Override + public boolean reset() { + return true; + } + + + + @Override + public boolean interact() { + + sprite.turnTo(pos, Dungeon.hero.pos); + switch (Random.Int (2)) { + case 0: + yell(Messages.get(this, "yell1")); + break; + case 1: + yell(Messages.get(this, "yell2")); + break; + } + return true; + } + +} diff --git a/java/com/hmdzl/spspd/actors/mobs/npcs/G2159687.java b/java/com/hmdzl/spspd/actors/mobs/npcs/G2159687.java new file mode 100644 index 00000000..b297152b --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/npcs/G2159687.java @@ -0,0 +1,87 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs.npcs; + + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.G2159687Sprite; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.windows.WndHotel; +import com.watabou.utils.Random; + +public class G2159687 extends NPC { + + { + //name = "G2159687"; + spriteClass = G2159687Sprite.class; + properties.add(Property.UNKNOW); + } + + @Override + protected boolean act() { + throwItem(); + return super.act(); + } + + @Override + public int evadeSkill(Char enemy) { + return 1000; + } + + + @Override + protected Char chooseEnemy() { + return null; + } + + @Override + public void damage(int dmg, Object src) { + } + + @Override + public void add(Buff buff) { + } + + @Override + public boolean reset() { + return true; + } + + + + @Override + public boolean interact() { + + sprite.turnTo(pos, Dungeon.hero.pos); + switch (Random.Int (3)) { + case 0: + yell(Messages.get(this, "yell1")); + break; + case 1: + yell(Messages.get(this, "yell2")); + break; + case 2: + GameScene.show(new WndHotel()); + break; + } + return true; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/npcs/Ghost.java b/java/com/hmdzl/spspd/actors/mobs/npcs/Ghost.java new file mode 100644 index 00000000..f6914ed3 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/npcs/Ghost.java @@ -0,0 +1,355 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs.npcs; + +import java.util.HashSet; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.Journal; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Paralysis; +import com.hmdzl.spspd.actors.buffs.Roots; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.actors.mobs.FetidRat; +import com.hmdzl.spspd.actors.mobs.GnollTrickster; +import com.hmdzl.spspd.actors.mobs.GreatCrab; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.armor.Armor; +import com.hmdzl.spspd.items.weapon.Weapon; +import com.hmdzl.spspd.items.weapon.missiles.MissileWeapon; +import com.hmdzl.spspd.levels.SewerLevel; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.GhostSprite; +import com.hmdzl.spspd.utils.GLog; + +import com.hmdzl.spspd.windows.WndQuest; +import com.hmdzl.spspd.windows.WndSadGhost; +import com.hmdzl.spspd.messages.Messages; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public class Ghost extends NPC { + + { + //name = "sad ghost"; + spriteClass = GhostSprite.class; + + flying = true; + + state = WANDERING; + properties.add(Property.UNDEAD); + } + + private static final String TXT_RAT1 = "Hello %s... Once I was like you - strong and confident... " + + "But I was slain by a foul beast... I can't leave this place... Not until I have my revenge... " + + "Slay the _fetid rat_, that has taken my life...\n\n" + + "It stalks this floor... Spreading filth everywhere... " + + "_Beware its cloud of stink and corrosive bite, the acid dissolves in water..._ "; + + private static final String TXT_RAT2 = "Please... Help me... Slay the abomination...\n\n" + + "_Fight it near water... Avoid the stench..._"; + + private static final String TXT_GNOLL1 = "Hello %s... Once I was like you - strong and confident... " + + "But I was slain by a devious foe... I can't leave this place... Not until I have my revenge... " + + "Slay the _gnoll trickster_, that has taken my life...\n\n" + + "It is not like the other gnolls... It hides and uses thrown weapons... " + + "_Beware its poisonous and incendiary darts, don't attack from a distance..._"; + + private static final String TXT_GNOLL2 = "Please... Help me... Slay the trickster...\n\n" + + "_Don't let it hit you... Get near to it..._"; + + private static final String TXT_CRAB1 = "Hello %s... Once I was like you - strong and confident... " + + "But I was slain by an ancient creature... I can't leave this place... Not until I have my revenge... " + + "Slay the _great crab_, that has taken my life...\n\n" + + "It is unnaturally old... With a massive single claw and a thick shell... " + + "_Beware its claw, you must surprise the crab or it will block with it..._"; + + private static final String TXT_CRAB2 = "Please... Help me... Slay the Crustacean...\n\n" + + "_It will always block... When it sees you coming..._"; + + public Ghost() { + super(); + + Sample.INSTANCE.load(Assets.SND_GHOST); + } + + @Override + public int evadeSkill(Char enemy) { + return 1000; + } + + //@Override + //public String defenseVerb() { + // return "evaded"; + //} + + @Override + public float speed() { + return 0.5f; + } + + @Override + protected Char chooseEnemy() { + return null; + } + + @Override + public void damage(int dmg, Object src) { + } + + @Override + public void add(Buff buff) { + } + + @Override + public boolean reset() { + return true; + } + + @Override + public boolean interact() { + sprite.turnTo(pos, Dungeon.hero.pos); + + Sample.INSTANCE.play(Assets.SND_GHOST); + + if (Quest.given) { + if (Quest.weapon != null) { + if (Quest.processed) { + GameScene.show(new WndSadGhost(this, Quest.type)); + } else { + switch (Quest.type) { + case 1: + default: + GameScene.show(new WndQuest(this, Messages.get(this, "rat_2"))); + break; + case 2: + GameScene.show(new WndQuest(this, Messages.get(this, "gnoll_2"))); + break; + case 3: + GameScene.show(new WndQuest(this, Messages.get(this, "crab_2"))); + break; + } + + 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 { + Mob questBoss; + String txt_quest; + + switch (Quest.type){ + case 1: default: + questBoss = new FetidRat(); + txt_quest = Messages.get(this, "rat_1", Dungeon.hero.givenName()); break; + case 2: + questBoss = new GnollTrickster(); + txt_quest = Messages.get(this, "gnoll_1", Dungeon.hero.givenName()); break; + case 3: + questBoss = new GreatCrab(); + txt_quest = Messages.get(this, "crab_1", Dungeon.hero.givenName()); break; + } + + questBoss.pos = Dungeon.level.randomRespawnCell(); + + if (questBoss.pos != -1) { + GameScene.add(questBoss); + GameScene.show(new WndQuest(this, txt_quest)); + Quest.given = true; + Journal.add(Journal.Feature.GHOST); + } + + } + return false; + } + + private static final HashSet> IMMUNITIES = new HashSet>(); + static { + IMMUNITIES.add(Paralysis.class); + IMMUNITIES.add(Roots.class); + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } + + public static class Quest { + + private static boolean spawned; + + private static int type; + + private static boolean given; + public static boolean processed; + + private static int depth; + + 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 TYPE = "type"; + 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(TYPE, type); + + 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))) { + + type = node.getInt(TYPE); + given = node.getBoolean(GIVEN); + processed = node.getBoolean(PROCESSED); + + depth = node.getInt(DEPTH); + + 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; + // dungeon depth determines type of quest. + // depth2=fetid rat, 3=gnoll trickster, 4=great crab + type = Dungeon.depth - 1; + + given = false; + processed = false; + depth = Dungeon.depth; + + do { + weapon = Generator.randomWeapon(10); + } while (weapon instanceof MissileWeapon); + armor = Generator.randomArmor(10); + + for (int i = 1; i <= 3; i++) { + Item another; + do { + another = Generator.randomWeapon(10 + i); + } while (another instanceof MissileWeapon); + if (another.level >= weapon.level) { + weapon = (Weapon) another; + } + another = Generator.randomArmor(10 + i); + if (another.level >= armor.level) { + armor = (Armor) another; + } + } + + weapon.identify(); + armor.identify(); + } + } + + public static void process() { + if (spawned && given && !processed && (depth == Dungeon.depth)) { + GLog.n(Messages.get(Ghost.class, "find_me")); + for (Mob m : Dungeon.level.mobs){ + if (m instanceof Ghost) + m.beckon(Dungeon.hero.pos); + } + Sample.INSTANCE.play(Assets.SND_GHOST); + processed = true; + Generator.Category.ARTIFACT.probs[10] = 1; // flags the dried + // rose as + // spawnable. + } + } + + public static void complete() { + weapon = null; + armor = null; + + Journal.remove(Journal.Feature.GHOST); + } + + public static boolean completed(){ + return spawned && processed; + } + } + +} diff --git a/java/com/hmdzl/spspd/actors/mobs/npcs/GoblinPlayer.java b/java/com/hmdzl/spspd/actors/mobs/npcs/GoblinPlayer.java new file mode 100644 index 00000000..2f2c2d1b --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/npcs/GoblinPlayer.java @@ -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 + */ +package com.hmdzl.spspd.actors.mobs.npcs; + + +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.Challenges; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.Statistics; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.GoblinPlayerSprite; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.windows.WndGoblin; +import com.hmdzl.spspd.windows.WndSaidBySun; +import com.watabou.utils.Random; + +public class GoblinPlayer extends NPC { + + { + //name = "GoblinPlayer"; + spriteClass = GoblinPlayerSprite.class; + //state = WANDERING; + properties.add(Property.GOBLIN); + } + + /*@Override + protected boolean act() { + throwItem(); + return super.act(); + } */ + + @Override + public int evadeSkill(Char enemy) { + return 1000; + } + + + @Override + protected Char chooseEnemy() { + return null; + } + + @Override + public void damage(int dmg, Object src) { + } + + @Override + public void add(Buff buff) { + } + + @Override + public boolean reset() { + return true; + } + + + + @Override + public boolean interact() { + + sprite.turnTo(pos, Dungeon.hero.pos); + switch (Random.Int (3)) { + case 0: + yell(Messages.get(this, "yell1")); + break; + case 1: + yell(Messages.get(this, "yell2")); + break; + case 2: + if (Badges.checkOtilukeRescued()) + GameScene.show(new WndGoblin()); + break; + } + return true; + } + +} diff --git a/java/com/hmdzl/spspd/actors/mobs/npcs/HBB.java b/java/com/hmdzl/spspd/actors/mobs/npcs/HBB.java new file mode 100644 index 00000000..b85f8fb1 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/npcs/HBB.java @@ -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 + */ +package com.hmdzl.spspd.actors.mobs.npcs; + + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.sprites.HBBSprite; +import com.hmdzl.spspd.messages.Messages; +import com.watabou.utils.Random; + +public class HBB extends NPC { + + { + //name = "Rawberry"; + name = Messages.get(this,"name"); + spriteClass = HBBSprite.class; + properties.add(Property.BEAST); + } + + @Override + protected boolean act() { + throwItem(); + return super.act(); + } + + @Override + public int evadeSkill(Char enemy) { + return 1000; + } + + + @Override + protected Char chooseEnemy() { + return null; + } + + @Override + public void damage(int dmg, Object src) { + } + + @Override + public void add(Buff buff) { + } + + @Override + public boolean reset() { + return true; + } + + + + @Override + public boolean interact() { + + sprite.turnTo(pos, Dungeon.hero.pos); + switch (Random.Int (3)) { + case 0: + yell(Messages.get(this, "yell1")); + break; + case 1: + yell(Messages.get(this, "yell2")); + break; + case 2: + yell(Messages.get(this, "yell3")); + break; + //case 3: + //Dungeon.level.drop(new Flag(), Dungeon.hero.pos).sprite.drop(); + //break; + } + return false; + } + +} diff --git a/java/com/hmdzl/spspd/actors/mobs/npcs/HateSokoban.java b/java/com/hmdzl/spspd/actors/mobs/npcs/HateSokoban.java new file mode 100644 index 00000000..165daabc --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/npcs/HateSokoban.java @@ -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 + */ +package com.hmdzl.spspd.actors.mobs.npcs; + + +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.HateSokobanSprite; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.windows.WndHate; +import com.hmdzl.spspd.windows.WndSaidBySun; +import com.watabou.utils.Random; + +public class HateSokoban extends NPC { + + { + //name = Messages.get(this,"name"); + spriteClass = HateSokobanSprite.class; + properties.add(Property.BEAST); + } + + @Override + protected boolean act() { + throwItem(); + return super.act(); + } + + @Override + public int evadeSkill(Char enemy) { + return 1000; + } + + + @Override + protected Char chooseEnemy() { + return null; + } + + @Override + public void damage(int dmg, Object src) { + } + + @Override + public void add(Buff buff) { + } + + @Override + public boolean reset() { + return true; + } + + @Override + public boolean interact() { + + sprite.turnTo(pos, Dungeon.hero.pos); + switch (Random.Int (3)) { + case 0: + yell(Messages.get(this, "yell1")); + break; + case 1: + yell(Messages.get(this, "yell2")); + break; + case 2: + if (Badges.checkOtilukeRescued()) + GameScene.show(new WndHate()); + break; + } + return false; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/npcs/HeXA.java b/java/com/hmdzl/spspd/actors/mobs/npcs/HeXA.java new file mode 100644 index 00000000..0354cb9b --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/npcs/HeXA.java @@ -0,0 +1,82 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2014 Oleg Dolya + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.actors.mobs.npcs; + + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.sprites.HeXASprite; +import com.hmdzl.spspd.messages.Messages; +import com.watabou.utils.Random; + +public class HeXA extends NPC { + + { + //name = "UNIST HeXA"; + spriteClass = HeXASprite.class; + properties.add(Property.ELEMENT); + } + + @Override + protected boolean act() { + throwItem(); + return super.act(); + } + + @Override + public int evadeSkill(Char enemy) { + return 1000; + } + + + @Override + protected Char chooseEnemy() { + return null; + } + + @Override + public void damage(int dmg, Object src) { + } + + @Override + public void add(Buff buff) { + } + + @Override + public boolean reset() { + return true; + } + + + + @Override + public boolean interact() { + + sprite.turnTo(pos, Dungeon.hero.pos); + switch (Random.Int (2)) { + case 0: + yell(Messages.get(this, "yell1")); + break; + case 1: + yell(Messages.get(this, "yell2")); + break; + } + return false; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/npcs/Hmdzl001.java b/java/com/hmdzl/spspd/actors/mobs/npcs/Hmdzl001.java new file mode 100644 index 00000000..07aa10c8 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/npcs/Hmdzl001.java @@ -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 + */ +package com.hmdzl.spspd.actors.mobs.npcs; + + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.Hmdzl001Sprite; +import com.watabou.utils.Random; + +public class Hmdzl001 extends NPC { + + { + //name = Messages.get(this,"name"); + spriteClass = Hmdzl001Sprite.class; + properties.add(Property.PLANT); + + } + + @Override + protected boolean act() { + throwItem(); + return super.act(); + } + + @Override + public int evadeSkill(Char enemy) { + return 1000; + } + + + @Override + protected Char chooseEnemy() { + return null; + } + + @Override + public void damage(int dmg, Object src) { + } + + @Override + public void add(Buff buff) { + } + + @Override + public boolean reset() { + return true; + } + + + + @Override + public boolean interact() { + + sprite.turnTo(pos, Dungeon.hero.pos); + switch (Random.Int (3)) { + case 0: + yell(Messages.get(this, "yell1")); + break; + case 1: + yell(Messages.get(this, "yell2")); + break; + case 2: + yell(Messages.get(this, "yell3")); + break; + } + return true; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/npcs/HoneyPoooot.java b/java/com/hmdzl/spspd/actors/mobs/npcs/HoneyPoooot.java new file mode 100644 index 00000000..e7e2dc6f --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/npcs/HoneyPoooot.java @@ -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 + */ +package com.hmdzl.spspd.actors.mobs.npcs; + + +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.items.Amulet; +import com.hmdzl.spspd.items.PotKey; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.HoneyPooootSprite; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.windows.WndDream; +import com.watabou.utils.Random; + +public class HoneyPoooot extends NPC { + + { + //name = "HoneyPoooot"; + spriteClass = HoneyPooootSprite.class; + //state = WANDERING; + properties.add(Property.ELF); + } + + /*@Override + protected boolean act() { + throwItem(); + return super.act(); + } */ + + @Override + public int evadeSkill(Char enemy) { + return 1000; + } + + + @Override + protected Char chooseEnemy() { + return null; + } + + @Override + public void damage(int dmg, Object src) { + } + + @Override + public void add(Buff buff) { + } + + @Override + public boolean reset() { + return true; + } + + + + @Override + public boolean interact() { + + sprite.turnTo(pos, Dungeon.hero.pos); + switch (Random.Int (3)) { + case 0: + yell(Messages.get(this, "yell1")); + break; + case 1: + yell(Messages.get(this, "yell2")); + break; + case 2: + if (Badges.checkOtilukeRescued()) + Dungeon.level.drop(new PotKey(), Dungeon.hero.pos).sprite.drop(); + break; + } + return true; + } + +} diff --git a/java/com/hmdzl/spspd/actors/mobs/npcs/Ice13.java b/java/com/hmdzl/spspd/actors/mobs/npcs/Ice13.java new file mode 100644 index 00000000..bf002d31 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/npcs/Ice13.java @@ -0,0 +1,104 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs.npcs; + + +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.Ice13Sprite; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.windows.WndSaidBySun; +import com.hmdzl.spspd.windows.Wndice13; +import com.watabou.utils.Random; + +public class Ice13 extends NPC { + + { + //name = "Ice13"; + spriteClass = Ice13Sprite.class; + //state = WANDERING; + properties.add(Property.HUMAN); + } + + /*@Override + protected boolean act() { + throwItem(); + return super.act(); + } */ + + @Override + public int evadeSkill(Char enemy) { + return 1000; + } + + + @Override + protected Char chooseEnemy() { + return null; + } + + @Override + public void damage(int dmg, Object src) { + } + + @Override + public void add(Buff buff) { + } + + @Override + public boolean reset() { + return true; + } + + + + @Override + public boolean interact() { + + sprite.turnTo(pos, Dungeon.hero.pos); + switch (Random.Int (7)) { + case 0: + yell(Messages.get(this, "yell1")); + break; + case 1: + yell(Messages.get(this, "yell2")); + break; + case 2: + yell(Messages.get(this, "yell3")); + break; + case 3: + yell(Messages.get(this, "yell4")); + break; + case 4: + yell(Messages.get(this, "yell5")); + break; + case 5: + yell(Messages.get(this, "yell6")); + break; + case 6: + if (Badges.checkOtilukeRescued()) + GameScene.show(new Wndice13()); + break; + } + return true; + } + +} diff --git a/java/com/hmdzl/spspd/actors/mobs/npcs/Imp.java b/java/com/hmdzl/spspd/actors/mobs/npcs/Imp.java new file mode 100644 index 00000000..7a18c060 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/npcs/Imp.java @@ -0,0 +1,227 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs.npcs; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.Journal; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.mobs.Golem; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.actors.mobs.Monk; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.items.quest.DwarfToken; +import com.hmdzl.spspd.items.rings.Ring; +import com.hmdzl.spspd.levels.CityLevel; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ImpSprite; + +import com.hmdzl.spspd.windows.WndImp; +import com.hmdzl.spspd.windows.WndQuest; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public class Imp extends NPC { + + { + //name = "ambitious imp"; + spriteClass = ImpSprite.class; + properties.add(Property.DEMONIC); + properties.add(Property.IMMOVABLE); + } + + private boolean seenBefore = false; + + @Override + protected boolean act() { + + if (!Quest.given && Dungeon.visible[pos]) { + if (!seenBefore) { + yell( Messages.get(this, "hey", Dungeon.hero.givenName())); + } + seenBefore = true; + } else { + seenBefore = false; + } + + throwItem(); + + return super.act(); + } + + @Override + public int evadeSkill(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 boolean 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 ? + Messages.get(this, "monks_2", Dungeon.hero.givenName()) + : Messages.get(this, "golems_2", Dungeon.hero.givenName())); + } + + } else { + tell(Quest.alternative ? Messages.get(this, "monks_1") : Messages.get(this, "golems_1")); + Quest.given = true; + Quest.completed = false; + + Journal.add(Journal.Feature.IMP); + } + return false; + } + + private void tell( String text ) { + GameScene.show( + new WndQuest( this, text )); + } + + public void flee() { + + yell(Messages.get(this, "cya", Dungeon.hero.givenName())); + + destroy(); + sprite.die(); + } + + 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) { + if (!spawned && Dungeon.depth > 16 + ) { + + 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; + } + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/npcs/ImpShopkeeper.java b/java/com/hmdzl/spspd/actors/mobs/npcs/ImpShopkeeper.java new file mode 100644 index 00000000..09eea7b1 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/npcs/ImpShopkeeper.java @@ -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 + */ +package com.hmdzl.spspd.actors.mobs.npcs; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.Statistics; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.sprites.ImpSprite; + +import com.hmdzl.spspd.messages.Messages; + +public class ImpShopkeeper extends Shopkeeper { + + { + //name = "ambitious imp"; + spriteClass = ImpSprite.class; + properties.remove(Property.HUMAN); + properties.add(Property.DEMONIC); + properties.add(Property.IMMOVABLE); + } + + private boolean seenBefore = false; + private boolean killedYog = false; + + @Override + protected boolean act() { + + if (!seenBefore && Dungeon.visible[pos]) { + yell(Messages.get(this, "greeting", Dungeon.hero.givenName())); + seenBefore = true; + } + + if (Statistics.amuletObtained && !killedYog && Dungeon.visible[pos]) { + yell(Messages.get(this, "greeting2", Dungeon.hero.givenName())); + killedYog = true; + } + + return super.act(); + } + + @Override + public int evadeSkill(Char enemy) { + return 1000; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/npcs/Jinkeloid.java b/java/com/hmdzl/spspd/actors/mobs/npcs/Jinkeloid.java new file mode 100644 index 00000000..eadf6ec6 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/npcs/Jinkeloid.java @@ -0,0 +1,84 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs.npcs; + + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.sprites.JinkeloidSprite; +import com.hmdzl.spspd.messages.Messages; +import com.watabou.utils.Random; + +public class Jinkeloid extends NPC { + + { + //name = "In vitro rose"; + //name = Messages.get(this,"name"); + spriteClass = JinkeloidSprite.class; + properties.add(Property.ELEMENT); + } + + @Override + protected boolean act() { + throwItem(); + return super.act(); + } + + @Override + public int evadeSkill(Char enemy) { + return 1000; + } + + + @Override + protected Char chooseEnemy() { + return null; + } + + @Override + public void damage(int dmg, Object src) { + } + + @Override + public void add(Buff buff) { + } + + @Override + public boolean reset() { + return true; + } + + + + @Override + public boolean interact() { + + sprite.turnTo(pos, Dungeon.hero.pos); + switch (Random.Int (2)) { + case 0: + yell(Messages.get(this, "yell1")); + break; + case 1: + //yell("Developer is in there... 576115291 "); + yell(Messages.get(this, "yell2")); + break; + } + return true; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/npcs/Juh9870.java b/java/com/hmdzl/spspd/actors/mobs/npcs/Juh9870.java new file mode 100644 index 00000000..203f713a --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/npcs/Juh9870.java @@ -0,0 +1,82 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2014 Oleg Dolya + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.actors.mobs.npcs; + + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.sprites.Juh9870Sprite; +import com.hmdzl.spspd.messages.Messages; +import com.watabou.utils.Random; + +public class Juh9870 extends NPC { + + { + //name = "Juh9870"; + spriteClass = Juh9870Sprite.class; + properties.add(Property.GOBLIN); + } + + @Override + protected boolean act() { + throwItem(); + return super.act(); + } + + @Override + public int evadeSkill(Char enemy) { + return 1000; + } + + + @Override + protected Char chooseEnemy() { + return null; + } + + @Override + public void damage(int dmg, Object src) { + } + + @Override + public void add(Buff buff) { + } + + @Override + public boolean reset() { + return true; + } + + + + @Override + public boolean interact() { + + sprite.turnTo(pos, Dungeon.hero.pos); + switch (Random.Int (2)) { + case 0: + yell(Messages.get(this, "yell1")); + break; + case 1: + yell(Messages.get(this, "yell2")); + break; + } + return true; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/npcs/Kostis12345.java b/java/com/hmdzl/spspd/actors/mobs/npcs/Kostis12345.java new file mode 100644 index 00000000..cae1971e --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/npcs/Kostis12345.java @@ -0,0 +1,84 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs.npcs; + + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.sprites.Kostis12345Sprite; +import com.hmdzl.spspd.messages.Messages; +import com.watabou.utils.Random; + +public class Kostis12345 extends NPC { + + { + //name = "kostis12345"; + spriteClass = Kostis12345Sprite.class; + //state = WANDERING; + properties.add(Property.UNKNOW); + } + + /*@Override + protected boolean act() { + throwItem(); + return super.act(); + } */ + + @Override + public int evadeSkill(Char enemy) { + return 1000; + } + + + @Override + protected Char chooseEnemy() { + return null; + } + + @Override + public void damage(int dmg, Object src) { + } + + @Override + public void add(Buff buff) { + } + + @Override + public boolean reset() { + return true; + } + + + + @Override + public boolean interact() { + + sprite.turnTo(pos, Dungeon.hero.pos); + switch (Random.Int (2)) { + case 0: + yell(Messages.get(this, "yell1")); + break; + case 1: + yell(Messages.get(this, "yell2")); + break; + } + return true; + } + +} diff --git a/java/com/hmdzl/spspd/actors/mobs/npcs/LaJi.java b/java/com/hmdzl/spspd/actors/mobs/npcs/LaJi.java new file mode 100644 index 00000000..dc54a7c0 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/npcs/LaJi.java @@ -0,0 +1,81 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs.npcs; + + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.sprites.LaJiSprite; +import com.hmdzl.spspd.messages.Messages; +import com.watabou.utils.Random; + +public class LaJi extends NPC { + + { + //name = Messages.get(this,"name"); + spriteClass = LaJiSprite.class; + state = WANDERING; + properties.add(Property.ORC); + } + + + @Override + public int evadeSkill(Char enemy) { + return 1000; + } + + + @Override + protected Char chooseEnemy() { + return null; + } + + @Override + public void damage(int dmg, Object src) { + } + + @Override + public void add(Buff buff) { + } + + @Override + public boolean reset() { + return true; + } + + + + @Override + public boolean interact() { + + sprite.turnTo(pos, Dungeon.hero.pos); + switch (Random.Int (3)) { + case 0: + yell(Messages.get(this, "yell1")); + break; + case 1: + yell(Messages.get(this, "yell2")); + break; + case 2: + yell(Messages.get(this, "yell3")); + break; + } + return true; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/npcs/Lery.java b/java/com/hmdzl/spspd/actors/mobs/npcs/Lery.java new file mode 100644 index 00000000..a40f1cf3 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/npcs/Lery.java @@ -0,0 +1,82 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2014 Oleg Dolya + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.actors.mobs.npcs; + + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.sprites.LerySprite; +import com.hmdzl.spspd.messages.Messages; +import com.watabou.utils.Random; + +public class Lery extends NPC { + + { + //name = "Lery"; + spriteClass = LerySprite.class; + properties.add(Property.ELEMENT); + } + + @Override + protected boolean act() { + throwItem(); + return super.act(); + } + + @Override + public int evadeSkill(Char enemy) { + return 1000; + } + + + @Override + protected Char chooseEnemy() { + return null; + } + + @Override + public void damage(int dmg, Object src) { + } + + @Override + public void add(Buff buff) { + } + + @Override + public boolean reset() { + return true; + } + + + + @Override + public boolean interact() { + + sprite.turnTo(pos, Dungeon.hero.pos); + switch (Random.Int (2)) { + case 0: + yell(Messages.get(this, "yell1")); + break; + case 1: + yell(Messages.get(this, "yell2")); + break; + } + return true; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/npcs/Locastan.java b/java/com/hmdzl/spspd/actors/mobs/npcs/Locastan.java new file mode 100644 index 00000000..7a0d7dc3 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/npcs/Locastan.java @@ -0,0 +1,85 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs.npcs; + + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.sprites.LocastanSprite; +import com.hmdzl.spspd.messages.Messages; +import com.watabou.utils.Random; + +public class Locastan extends NPC { + + { + //name = "Locastan"; + spriteClass = LocastanSprite.class; + properties.add(Property.GOBLIN); + } + + @Override + protected boolean act() { + throwItem(); + return super.act(); + } + + @Override + public int evadeSkill(Char enemy) { + return 1000; + } + + + @Override + protected Char chooseEnemy() { + return null; + } + + @Override + public void damage(int dmg, Object src) { + } + + @Override + public void add(Buff buff) { + } + + @Override + public boolean reset() { + return true; + } + + + + @Override + public boolean interact() { + + sprite.turnTo(pos, Dungeon.hero.pos); + switch (Random.Int (3)) { + case 0: + yell(Messages.get(this, "yell1")); + break; + case 1: + yell(Messages.get(this, "yell2")); + break; + case 2: + yell(Messages.get(this, "yell3")); + break; + } + return true; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/npcs/Lyn.java b/java/com/hmdzl/spspd/actors/mobs/npcs/Lyn.java new file mode 100644 index 00000000..441c6730 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/npcs/Lyn.java @@ -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 + */ +package com.hmdzl.spspd.actors.mobs.npcs; + + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.sprites.LynSprite; +import com.hmdzl.spspd.messages.Messages; +import com.watabou.utils.Random; + +public class Lyn extends NPC { + + { + //name = "Lyn-0401"; + spriteClass = LynSprite.class; + properties.add(Property.ELF); + properties.add(Property.DEMONIC); + } + + @Override + protected boolean act() { + throwItem(); + return super.act(); + } + + @Override + public int evadeSkill(Char enemy) { + return 1000; + } + + + @Override + protected Char chooseEnemy() { + return null; + } + + @Override + public void damage(int dmg, Object src) { + } + + @Override + public void add(Buff buff) { + } + + @Override + public boolean reset() { + return true; + } + + + + @Override + public boolean interact() { + + sprite.turnTo(pos, Dungeon.hero.pos); + switch (Random.Int (2)) { + case 0: + yell(Messages.get(this, "yell1")); + break; + case 1: + yell(Messages.get(this, "yell2")); + break; + } + return true; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/npcs/Lynn.java b/java/com/hmdzl/spspd/actors/mobs/npcs/Lynn.java new file mode 100644 index 00000000..fee6f80e --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/npcs/Lynn.java @@ -0,0 +1,82 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2014 Oleg Dolya + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.actors.mobs.npcs; + + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.sprites.LynnSprite; +import com.hmdzl.spspd.messages.Messages; +import com.watabou.utils.Random; + +public class Lynn extends NPC { + + { + //name = "Lynn"; + spriteClass = LynnSprite.class; + properties.add(Property.ELF); + } + + @Override + protected boolean act() { + throwItem(); + return super.act(); + } + + @Override + public int evadeSkill(Char enemy) { + return 1000; + } + + + @Override + protected Char chooseEnemy() { + return null; + } + + @Override + public void damage(int dmg, Object src) { + } + + @Override + public void add(Buff buff) { + } + + @Override + public boolean reset() { + return true; + } + + + + @Override + public boolean interact() { + + sprite.turnTo(pos, Dungeon.hero.pos); + switch (Random.Int (2)) { + case 0: + yell(Messages.get(this, "yell1")); + break; + case 1: + yell(Messages.get(this, "yell2")); + break; + } + return true; + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/mobs/npcs/MemoryOfSand.java b/java/com/hmdzl/spspd/actors/mobs/npcs/MemoryOfSand.java new file mode 100644 index 00000000..a99cb4da --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/npcs/MemoryOfSand.java @@ -0,0 +1,82 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2014 Oleg Dolya + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.actors.mobs.npcs; + + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.sprites.MemoryOfSandSprite; +import com.hmdzl.spspd.messages.Messages; +import com.watabou.utils.Random; + +public class MemoryOfSand extends NPC { + + { + //name = Messages.get(this,"name"); + spriteClass = MemoryOfSandSprite.class; + properties.add(Property.HUMAN); + } + + @Override + protected boolean act() { + throwItem(); + return super.act(); + } + + @Override + public int evadeSkill(Char enemy) { + return 1000; + } + + + @Override + protected Char chooseEnemy() { + return null; + } + + @Override + public void damage(int dmg, Object src) { + } + + @Override + public void add(Buff buff) { + } + + @Override + public boolean reset() { + return true; + } + + + + @Override + public boolean interact() { + + sprite.turnTo(pos, Dungeon.hero.pos); + switch (Random.Int (2)) { + case 0: + yell(Messages.get(this, "yell1")); + break; + case 1: + yell(Messages.get(this, "yell2")); + break; + } + return true; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/npcs/Millilitre.java b/java/com/hmdzl/spspd/actors/mobs/npcs/Millilitre.java new file mode 100644 index 00000000..ef6058f5 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/npcs/Millilitre.java @@ -0,0 +1,92 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs.npcs; + + +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.MillilitreSprite; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.windows.WndIssic; +import com.hmdzl.spspd.windows.WndSaidBySun; +import com.watabou.utils.Random; + +public class Millilitre extends NPC { + + { + //name = "Millilitre"; + spriteClass = MillilitreSprite.class; + //state = WANDERING; + properties.add(Property.HUMAN); + } + + /*@Override + protected boolean act() { + throwItem(); + return super.act(); + } */ + + @Override + public int evadeSkill(Char enemy) { + return 1000; + } + + + @Override + protected Char chooseEnemy() { + return null; + } + + @Override + public void damage(int dmg, Object src) { + } + + @Override + public void add(Buff buff) { + } + + @Override + public boolean reset() { + return true; + } + + + + @Override + public boolean interact() { + + sprite.turnTo(pos, Dungeon.hero.pos); + switch (Random.Int (3)) { + case 0: + yell(Messages.get(this, "yell1")); + break; + case 1: + yell(Messages.get(this, "yell2")); + break; + case 2: + if (Badges.checkOtilukeRescued()) + GameScene.show(new WndIssic()); + break; + } + return true; + } + +} diff --git a/java/com/hmdzl/spspd/actors/mobs/npcs/MirrorImage.java b/java/com/hmdzl/spspd/actors/mobs/npcs/MirrorImage.java new file mode 100644 index 00000000..36a04ddf --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/npcs/MirrorImage.java @@ -0,0 +1,163 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs.npcs; + +import java.util.HashSet; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.ToxicGas; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Burning; +import com.hmdzl.spspd.actors.buffs.MagicalSleep; +import com.hmdzl.spspd.actors.buffs.Paralysis; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.sprites.CharSprite; +import com.hmdzl.spspd.sprites.MirrorSprite; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public class MirrorImage extends NPC { + + { + //name = "mirror image"; + spriteClass = MirrorSprite.class; + + state = HUNTING; + + properties.add(Property.UNKNOW); + } + + public int skin; + + private int attack; + private int damage; + + private static final String SKIN = "skin"; + private static final String ATTACK = "attack"; + private static final String DAMAGE = "damage"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(SKIN, skin); + bundle.put(ATTACK, attack); + bundle.put(DAMAGE, damage); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + skin = bundle.getInt(SKIN); + attack = bundle.getInt(ATTACK); + damage = bundle.getInt(DAMAGE); + } + + public void duplicate(Hero hero) { + skin = hero.useskin(); + attack = hero.hitSkill(hero); + damage = hero.damageRoll(); + } + + @Override + public int hitSkill(Char target) { + return attack; + } + + @Override + public int damageRoll() { + return damage; + } + + @Override + public int attackProc(Char enemy, int damage) { + int dmg = super.attackProc(enemy, damage); + + destroy(); + sprite.die(); + + return dmg; + } + + @Override + protected Char chooseEnemy() { + + if (enemy == null || !enemy.isAlive()) { + HashSet enemies = new HashSet(); + for (Mob mob : Dungeon.level.mobs) { + if (mob.hostile && Level.fieldOfView[mob.pos]) { + enemies.add(mob); + } + } + + enemy = enemies.size() > 0 ? Random.element(enemies) : null; + } + + return enemy; + } + + @Override + public CharSprite sprite() { + CharSprite s = super.sprite(); + ((MirrorSprite) s).updateArmor(skin); + return s; + } + + + @Override + public boolean interact() { + if (!Dungeon.level.passable[pos]){ + return true; + } + if (this.buff(MagicalSleep.class) != null) { + Buff.detach(this, MagicalSleep.class); + } + + if (state == SLEEPING) { + state = HUNTING; + } + if (buff(Paralysis.class) != null) { + Buff.detach(this, Paralysis.class); + } + + int curPos = pos; + + moveSprite(pos, Dungeon.hero.pos); + move(Dungeon.hero.pos); + + Dungeon.hero.sprite.move(Dungeon.hero.pos, curPos); + Dungeon.hero.move(curPos); + + Dungeon.hero.spend(1 / Dungeon.hero.speed()); + Dungeon.hero.busy(); + return true; + } + + private static final HashSet> IMMUNITIES = new HashSet>(); + static { + IMMUNITIES.add(ToxicGas.class); + IMMUNITIES.add(Burning.class); + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/mobs/npcs/Mtree.java b/java/com/hmdzl/spspd/actors/mobs/npcs/Mtree.java new file mode 100644 index 00000000..36836051 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/npcs/Mtree.java @@ -0,0 +1,110 @@ + package com.hmdzl.spspd.actors.mobs.npcs; + + + import com.hmdzl.spspd.Dungeon; + import com.hmdzl.spspd.actors.Char; + import com.hmdzl.spspd.actors.buffs.Buff; + import com.hmdzl.spspd.actors.buffs.GrowSeed; + import com.hmdzl.spspd.actors.buffs.Poison; + import com.hmdzl.spspd.actors.mobs.Mob; + import com.hmdzl.spspd.levels.Level; + import com.hmdzl.spspd.sprites.PlantKingSprite; + import com.watabou.utils.Random; + + import java.util.HashSet; + + public class Mtree extends NPC { + + { + //name = "Mtree"; + spriteClass = PlantKingSprite.class; + + HP = 10; + HT = 10; + + viewDistance = 6; + ally=true; + flying = false; + state = WANDERING; + } + + + @Override + public int hitSkill(Char target) { + return 40; + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(10, 30); + } + + @Override + protected boolean canAttack(Char enemy) { + return super.canAttack(enemy); + } + + @Override + public int attackProc(Char enemy, int damage) { + if (Random.Int(10) == 0) { + Buff.affect(enemy, GrowSeed.class); + destroy(); + } + + return damage; + } + + @Override + protected boolean getCloser(int target) { + if (state == WANDERING + || Level.distance(target, Dungeon.hero.pos) > 6) + this.target = target = Dungeon.hero.pos; + return super.getCloser(target); + } + @Override + protected Char chooseEnemy() { + if (enemy == null || !enemy.isAlive() || state == WANDERING) { + + HashSet enemies = new HashSet(); + for (Mob mob : Dungeon.level.mobs) { + if (mob.hostile && Level.fieldOfView[mob.pos] + && mob.state != mob.PASSIVE) { + enemies.add(mob); + } + } + enemy = enemies.size() > 0 ? Random.element(enemies) : null; + } + return enemy; + } + + @Override + public boolean interact() { + if (Dungeon.level.passable[pos] || Dungeon.hero.flying) { + int curPos = pos; + + moveSprite(pos, Dungeon.hero.pos); + move(Dungeon.hero.pos); + + Dungeon.hero.sprite.move(Dungeon.hero.pos, curPos); + Dungeon.hero.move(curPos); + + Dungeon.hero.spend(1 / Dungeon.hero.speed()); + Dungeon.hero.busy(); + return true; + } else { + return false; + } + } + + private static final HashSet> IMMUNITIES = new HashSet>(); + + static { + IMMUNITIES.add(Poison.class); + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } + + } \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/mobs/npcs/NPC.java b/java/com/hmdzl/spspd/actors/mobs/npcs/NPC.java new file mode 100644 index 00000000..21c998fc --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/npcs/NPC.java @@ -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 + */ +package com.hmdzl.spspd.actors.mobs.npcs; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.items.Heap; +import com.hmdzl.spspd.levels.Level; +import com.watabou.utils.Random; + +public abstract class NPC extends Mob { + + { + HP = HT = 1; + EXP = 0; + + hostile = false; + state = PASSIVE; + + } + + protected void throwItem() { + Heap heap = Dungeon.level.heaps.get(pos); + if (heap != null && heap.type != Heap.Type.FOR_SALE) { + 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 boolean interact(); +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/mobs/npcs/NYRDS.java b/java/com/hmdzl/spspd/actors/mobs/npcs/NYRDS.java new file mode 100644 index 00000000..e3ad365d --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/npcs/NYRDS.java @@ -0,0 +1,80 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs.npcs; + + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.sprites.NYRDSSprite; +import com.hmdzl.spspd.messages.Messages; +import com.watabou.utils.Random; + +public class NYRDS extends NPC { + + { + //name = "nyrdie"; + spriteClass = NYRDSSprite.class; + properties.add(Property.UNKNOW); + } + + @Override + protected boolean act() { + throwItem(); + return super.act(); + } + + @Override + public int evadeSkill(Char enemy) { + return 1000; + } + + + @Override + protected Char chooseEnemy() { + return null; + } + + @Override + public void damage(int dmg, Object src) { + } + + @Override + public void add(Buff buff) { + } + + @Override + public boolean reset() { + return true; + } + + @Override + public boolean interact() { + + sprite.turnTo(pos, Dungeon.hero.pos); + switch (Random.Int (2)) { + case 0: + yell(Messages.get(this, "yell1")); + break; + case 1: + yell(Messages.get(this, "yell2")); + break; + } + return true; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/npcs/NewPlayer.java b/java/com/hmdzl/spspd/actors/mobs/npcs/NewPlayer.java new file mode 100644 index 00000000..90d64bc3 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/npcs/NewPlayer.java @@ -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 + */ +package com.hmdzl.spspd.actors.mobs.npcs; + + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.sprites.IceRabbitSprite; +import com.hmdzl.spspd.sprites.NewPlayerSprite; +import com.hmdzl.spspd.messages.Messages; +import com.watabou.utils.Random; + +public class NewPlayer extends NPC { + + { + //name = NewPlayer; + spriteClass = IceRabbitSprite.class; + state = WANDERING; + properties.add(Property.UNKNOW); + } + + + @Override + public int evadeSkill(Char enemy) { + return 1000; + } + + + @Override + protected Char chooseEnemy() { + return null; + } + + @Override + public void damage(int dmg, Object src) { + } + + @Override + public void add(Buff buff) { + } + + @Override + public boolean reset() { + return true; + } + + + + @Override + public boolean interact() { + + sprite.turnTo(pos, Dungeon.hero.pos); + switch (Random.Int (2)) { + case 0: + yell(Messages.get(this, "yell1")); + break; + case 1: + yell(Messages.get(this, "yell2")); + break; + } + return true; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/npcs/NutPainter.java b/java/com/hmdzl/spspd/actors/mobs/npcs/NutPainter.java new file mode 100644 index 00000000..13968c0b --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/npcs/NutPainter.java @@ -0,0 +1,84 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs.npcs; + + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.sprites.PainterSprite; +import com.hmdzl.spspd.messages.Messages; +import com.watabou.utils.Random; + +public class NutPainter extends NPC { + + { + //name = "NutPainter"; + spriteClass = PainterSprite.class; + //state = WANDERING; + properties.add(Property.HUMAN); + } + + /*@Override + protected boolean act() { + throwItem(); + return super.act(); + } */ + + @Override + public int evadeSkill(Char enemy) { + return 1000; + } + + + @Override + protected Char chooseEnemy() { + return null; + } + + @Override + public void damage(int dmg, Object src) { + } + + @Override + public void add(Buff buff) { + } + + @Override + public boolean reset() { + return true; + } + + + + @Override + public boolean interact() { + + sprite.turnTo(pos, Dungeon.hero.pos); + switch (Random.Int (2)) { + case 0: + yell(Messages.get(this, "yell1")); + break; + case 1: + yell(Messages.get(this, "yell2")); + break; + } + return true; + } + +} diff --git a/java/com/hmdzl/spspd/actors/mobs/npcs/OldNewStwist.java b/java/com/hmdzl/spspd/actors/mobs/npcs/OldNewStwist.java new file mode 100644 index 00000000..3809fa1b --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/npcs/OldNewStwist.java @@ -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 + */ +package com.hmdzl.spspd.actors.mobs.npcs; + + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.items.quest.GnollClothes; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.OldNewStwistSprite; +import com.hmdzl.spspd.windows.WndONS; + +public class OldNewStwist extends NPC { + + { + //name = "oldnewstwist"; + spriteClass = OldNewStwistSprite.class; + + state = SLEEPING; + properties.add(Property.ORC); + } + + @Override + public int evadeSkill(Char enemy) { + return 1000; + } + + @Override + protected Char chooseEnemy() { + return null; + } + + @Override + public void damage(int dmg, Object src) { + } + + @Override + public void add(Buff buff) { + } + + @Override + public boolean reset() { + return true; + } + + + + @Override + public boolean interact() { + + GnollClothes clothes = Dungeon.hero.belongings.getItem(GnollClothes.class); + + sprite.turnTo(pos, Dungeon.hero.pos); + if (state == SLEEPING && Dungeon.gnollmission==false) { + notice(); + yell(Messages.get(this, "yell1")); + yell(Messages.get(this, "yell2")); + state = PASSIVE; + } else if (Dungeon.gnollmission==false && clothes == null){ + yell(Messages.get(this, "yell3")); + } else if (Dungeon.gnollmission==false && clothes!=null ){ + yell(Messages.get(this, "yell4")); + GameScene.show(new WndONS(this, clothes)); + } else if (Dungeon.gnollmission==true && state == PASSIVE) { + yell(Messages.get(this, "yell5")); + } else { + notice(); + yell(Messages.get(this, "yell6")); + state = PASSIVE; + } + return true; + } + + @Override + public String description() { + return ((OldNewStwistSprite) sprite).gnollmission ? + Messages.get(this, "desc_gnollmission") : super.description(); + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/npcs/Omicronrg9.java b/java/com/hmdzl/spspd/actors/mobs/npcs/Omicronrg9.java new file mode 100644 index 00000000..053fb4c8 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/npcs/Omicronrg9.java @@ -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 + */ +package com.hmdzl.spspd.actors.mobs.npcs; + + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.sprites.Omicronrg9Sprite; +import com.hmdzl.spspd.messages.Messages; +import com.watabou.utils.Random; + +public class Omicronrg9 extends NPC { + + { + //name = "omicronrg9"; + spriteClass = Omicronrg9Sprite.class; + state = WANDERING; + properties.add(Property.HUMAN); + } + + /*@Override + protected boolean act() { + throwItem(); + return super.act(); + } */ + + @Override + public int evadeSkill(Char enemy) { + return 1000; + } + + + @Override + protected Char chooseEnemy() { + return null; + } + + @Override + public void damage(int dmg, Object src) { + } + + @Override + public void add(Buff buff) { + } + + @Override + public boolean reset() { + return true; + } + + + + @Override + public boolean interact() { + + sprite.turnTo(pos, Dungeon.hero.pos); + switch (Random.Int (6)) { + case 0: + yell(Messages.get(this, "yell1")); + break; + case 1: + yell(Messages.get(this, "yell2")); + break; + case 2: + yell(Messages.get(this, "yell3")); + break; + case 3: + yell(Messages.get(this, "yell4")); + break; + case 4: + yell(Messages.get(this, "yell5")); + break; + case 5: + yell(Messages.get(this, "yell6")); + break; + } + return true; + } + +} diff --git a/java/com/hmdzl/spspd/actors/mobs/npcs/OtilukeNPC.java b/java/com/hmdzl/spspd/actors/mobs/npcs/OtilukeNPC.java new file mode 100644 index 00000000..6c75d6be --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/npcs/OtilukeNPC.java @@ -0,0 +1,85 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs.npcs; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.items.Amulet; +import com.hmdzl.spspd.sprites.OtilukeNPCSprite; + +import com.hmdzl.spspd.messages.Messages; +import com.watabou.utils.Random; + +public class OtilukeNPC extends NPC { + + { + //name = "Otiluke"; + spriteClass = OtilukeNPCSprite.class; + properties.add(Property.HUMAN); + } + + @Override + protected boolean act() { + throwItem(); + return super.act(); + } + + @Override + public int evadeSkill(Char enemy) { + return 1000; + } + + @Override + protected Char chooseEnemy() { + return null; + } + + @Override + public void damage(int dmg, Object src) { + } + + @Override + public void add(Buff buff) { + } + + @Override + public boolean reset() { + return true; + } + + @Override + public boolean interact() { + + sprite.turnTo(pos, Dungeon.hero.pos); + switch (Random.Int (3)) { + case 0: + yell(Messages.get(this, "yell1")); + break; + case 1: + yell(Messages.get(this, "yell2")); + break; + case 2: + yell(Messages.get(this, "yell3")); + Dungeon.level.drop(new Amulet(), Dungeon.hero.pos).sprite.drop(); + break; + } + return true; + + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/npcs/RENnpc.java b/java/com/hmdzl/spspd/actors/mobs/npcs/RENnpc.java new file mode 100644 index 00000000..1036ea57 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/npcs/RENnpc.java @@ -0,0 +1,99 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs.npcs; + + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.Statistics; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.items.ChallengeBook; +import com.hmdzl.spspd.items.weapon.melee.special.Goei; +import com.hmdzl.spspd.sprites.RENSprite; +import com.hmdzl.spspd.messages.Messages; +import com.watabou.utils.Random; + +public class RENnpc extends NPC { + + { + //name = "RENnpc"; + spriteClass = RENSprite.class; + properties.add(Property.ELF);; + } + + @Override + protected boolean act() { + throwItem(); + return super.act(); + } + + @Override + public int evadeSkill(Char enemy) { + return 1000; + } + + + @Override + protected Char chooseEnemy() { + return null; + } + + @Override + public void damage(int dmg, Object src) { + } + + @Override + public void add(Buff buff) { + } + + @Override + public boolean reset() { + return true; + } + + + + @Override + public boolean interact() { + + sprite.turnTo(pos, Dungeon.hero.pos); + if(Dungeon.challengebookdrop == false) { + //Dungeon.limitedDrops.challengebook.dropped(); + Dungeon.level.drop(new ChallengeBook(), Dungeon.hero.pos).sprite.drop(); + Dungeon.challengebookdrop = true; + yell(Messages.get(this, "yell3")); + + } else if(Dungeon.goeidrop == false && (Statistics.archersKilled > 50 && Statistics.skeletonsKilled > 50 && Statistics.albinoPiranhasKilled > 50 && Statistics.goldThievesKilled > 50)){ + Dungeon.level.drop(new Goei(), Dungeon.hero.pos).sprite.drop(); + Dungeon.goeidrop = true; + yell(Messages.get(this, "yell5")); + } else + switch (Random.Int (3)) { + case 0: + yell(Messages.get(this, "yell1")); + break; + case 1: + yell(Messages.get(this, "yell2")); + break; + case 2: + yell(Messages.get(this, "yell4")); + break; + } + return true; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/npcs/RainTrainer.java b/java/com/hmdzl/spspd/actors/mobs/npcs/RainTrainer.java new file mode 100644 index 00000000..f065783c --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/npcs/RainTrainer.java @@ -0,0 +1,82 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2014 Oleg Dolya + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.actors.mobs.npcs; + + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.RainSprite; +import com.watabou.utils.Random; + +public class RainTrainer extends NPC { + + { + //name = "Rain"; + spriteClass = RainSprite.class; + properties.add(Property.ELEMENT); + } + + @Override + protected boolean act() { + throwItem(); + return super.act(); + } + + @Override + public int evadeSkill(Char enemy) { + return 1000; + } + + + @Override + protected Char chooseEnemy() { + return null; + } + + @Override + public void damage(int dmg, Object src) { + } + + @Override + public void add(Buff buff) { + } + + @Override + public boolean reset() { + return true; + } + + + + @Override + public boolean interact() { + + sprite.turnTo(pos, Dungeon.hero.pos); + switch (Random.Int (2)) { + case 0: + yell(Messages.get(this, "yell1")); + break; + case 1: + yell(Messages.get(this, "yell2")); + break; + } + return true; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/npcs/RatKing.java b/java/com/hmdzl/spspd/actors/mobs/npcs/RatKing.java new file mode 100644 index 00000000..994c0fbe --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/npcs/RatKing.java @@ -0,0 +1,119 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs.npcs; + + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.Statistics; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.items.Heap; +import com.hmdzl.spspd.items.weapon.melee.special.Spork; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.RatKingSprite; + +public class RatKing extends NPC { + + { + //name = "rat king"; + spriteClass = RatKingSprite.class; + + state = SLEEPING; + properties.add(Property.BEAST); + properties.add(Property.BOSS); + } + + @Override + public int evadeSkill(Char enemy) { + return 1000; + } + + @Override + public float speed() { + return 2f; + } + + @Override + protected Char chooseEnemy() { + return null; + } + + @Override + public void damage(int dmg, Object src) { + } + + @Override + public void add(Buff buff) { + } + + @Override + public boolean reset() { + return true; + } + + + + @Override + public boolean interact() { + + int checkChests = 2; + int length = Level.getLength(); + for (int i = 0; i < length; i++) { + Heap chest = Dungeon.level.heaps.get(i); + if(chest != null && chest.chestCheck()){checkChests++;} + } + + Spork spork = Dungeon.hero.belongings.getItem(Spork.class); + //RunicBlade runicblade = Dungeon.hero.belongings.getItem(RunicBlade.class); + + sprite.turnTo(pos, Dungeon.hero.pos); + if (state == SLEEPING) { + notice(); + yell(Messages.get(this, "not_sleeping")); + yell(Messages.get(this, "not_takeing")); + state = WANDERING; + //} else if (Statistics.deepestFloor>9 && checkChests >= Dungeon.ratChests && spork==null && runicblade==null){ + } else if (Statistics.deepestFloor>10 && checkChests >= Dungeon.ratChests && spork==null){ + yell(Messages.get(this, "thanks")); + Dungeon.sporkAvail = true; + } else if (checkChests < Dungeon.ratChests){ + Dungeon.sporkAvail = false; + yell(Messages.get(this, "why")); + } else if (spork!=null) { + //yell("You found my spork! Here, trade me for this old one."); + yell(Messages.get(this, "havefun")); + //if (spork.isEquipped(Dungeon.hero)) { + // spork.doUnequip(Dungeon.hero, false); + //} + //spork.detach(Dungeon.hero.belongings.backpack); + //Dungeon.level.drop(new RunicBlade().enchantNom(), pos).sprite.drop(); + //Dungeon.limitedDrops.runicblade.drop(); + + } else { + yell(Messages.get(this, "what_is_it")); + } + return true; + } + + @Override + public String description() { + return ((RatKingSprite) sprite).festive ? + Messages.get(this, "desc_festive") : super.description(); + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/npcs/RatKingDen.java b/java/com/hmdzl/spspd/actors/mobs/npcs/RatKingDen.java new file mode 100644 index 00000000..96f17f4c --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/npcs/RatKingDen.java @@ -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 + */ +package com.hmdzl.spspd.actors.mobs.npcs; + + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.RatKingSprite; + +public class RatKingDen extends NPC { + + { + //name = "rat king"; + spriteClass = RatKingSprite.class; + + state = SLEEPING; + properties.add(Property.BEAST); + properties.add(Property.BOSS); + } + + @Override + public int evadeSkill(Char enemy) { + return 1000; + } + + @Override + public float speed() { + return 2f; + } + + @Override + protected Char chooseEnemy() { + return null; + } + + @Override + public void damage(int dmg, Object src) { + } + + @Override + public void add(Buff buff) { + } + + @Override + public boolean reset() { + return true; + } + + + + @Override + public boolean interact() { + + sprite.turnTo(pos, Dungeon.hero.pos); + if (state == SLEEPING) { + notice(); + yell(Messages.get(this, "not_sleeping")); + state = WANDERING; + + } else { + yell(Messages.get(this, "what_is_it")); + } + return true; + } + + @Override + public String description() { + return ((RatKingSprite) sprite).festive ? + Messages.get(this, "desc_festive") + : super.description(); + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/npcs/Ravenwolf.java b/java/com/hmdzl/spspd/actors/mobs/npcs/Ravenwolf.java new file mode 100644 index 00000000..24667e41 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/npcs/Ravenwolf.java @@ -0,0 +1,84 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs.npcs; + + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.sprites.RavenwolfSprite; +import com.hmdzl.spspd.messages.Messages; +import com.watabou.utils.Random; + +public class Ravenwolf extends NPC { + + { + //name = "ravenwolf"; + spriteClass = RavenwolfSprite.class; + //state = WANDERING; + properties.add(Property.UNKNOW); + } + + /*@Override + protected boolean act() { + throwItem(); + return super.act(); + } */ + + @Override + public int evadeSkill(Char enemy) { + return 1000; + } + + + @Override + protected Char chooseEnemy() { + return null; + } + + @Override + public void damage(int dmg, Object src) { + } + + @Override + public void add(Buff buff) { + } + + @Override + public boolean reset() { + return true; + } + + + + @Override + public boolean interact() { + + sprite.turnTo(pos, Dungeon.hero.pos); + switch (Random.Int (2)) { + case 0: + yell(Messages.get(this, "yell1")); + break; + case 1: + yell(Messages.get(this, "yell2")); + break; + } + return true; + } + +} diff --git a/java/com/hmdzl/spspd/actors/mobs/npcs/Rustyblade.java b/java/com/hmdzl/spspd/actors/mobs/npcs/Rustyblade.java new file mode 100644 index 00000000..8aa6b6ed --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/npcs/Rustyblade.java @@ -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 + */ +package com.hmdzl.spspd.actors.mobs.npcs; + + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.sprites.RustybladeSprite; +import com.hmdzl.spspd.messages.Messages; +import com.watabou.utils.Random; + +public class Rustyblade extends NPC { + + { + //name = Messages.get(this,"name"); + spriteClass = RustybladeSprite.class; + properties.add(Property.HUMAN); + } + + @Override + protected boolean act() { + throwItem(); + return super.act(); + } + + @Override + public int evadeSkill(Char enemy) { + return 1000; + } + + + @Override + protected Char chooseEnemy() { + return null; + } + + @Override + public void damage(int dmg, Object src) { + } + + @Override + public void add(Buff buff) { + } + + @Override + public boolean reset() { + return true; + } + + + + @Override + public boolean interact() { + + sprite.turnTo(pos, Dungeon.hero.pos); + switch (Random.Int (2)) { + case 0: + yell(Messages.get(this, "yell1")); + break; + case 1: + yell(Messages.get(this, "yell2")); + break; + } + return true; + } + +} diff --git a/java/com/hmdzl/spspd/actors/mobs/npcs/SFB.java b/java/com/hmdzl/spspd/actors/mobs/npcs/SFB.java new file mode 100644 index 00000000..a9affaa6 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/npcs/SFB.java @@ -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 + */ +package com.hmdzl.spspd.actors.mobs.npcs; + + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.sprites.SFBSprite; +import com.hmdzl.spspd.messages.Messages; +import com.watabou.utils.Random; + +public class SFB extends NPC { + + { + //name = "Shattered Flame Blast"; + spriteClass = SFBSprite.class; + properties.add(Property.UNKNOW); + } + + @Override + protected boolean act() { + if (Dungeon.visible[pos]) { + + yell(Messages.get(this, "hello")); + } + throwItem(); + return super.act(); + } + + @Override + public int evadeSkill(Char enemy) { + return 1000; + } + + + @Override + protected Char chooseEnemy() { + return null; + } + + @Override + public void damage(int dmg, Object src) { + } + + @Override + public void add(Buff buff) { + } + + @Override + public boolean reset() { + return true; + } + + + + @Override + public boolean interact() { + + sprite.turnTo(pos, Dungeon.hero.pos); + switch (Random.Int (2)) { + case 0: + yell(Messages.get(this, "yell1")); + break; + case 1: + yell(Messages.get(this, "yell2")); + break; + } + return true; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/npcs/SP931.java b/java/com/hmdzl/spspd/actors/mobs/npcs/SP931.java new file mode 100644 index 00000000..c8ba20a6 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/npcs/SP931.java @@ -0,0 +1,84 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs.npcs; + + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.sprites.SP931Sprite; +import com.hmdzl.spspd.messages.Messages; +import com.watabou.utils.Random; + +public class SP931 extends NPC { + + { + //name = "931451545"; + spriteClass = SP931Sprite.class; + state = WANDERING; + properties.add(Property.UNKNOW); + } + + /*@Override + protected boolean act() { + throwItem(); + return super.act(); + } */ + + @Override + public int evadeSkill(Char enemy) { + return 1000; + } + + + @Override + protected Char chooseEnemy() { + return null; + } + + @Override + public void damage(int dmg, Object src) { + } + + @Override + public void add(Buff buff) { + } + + @Override + public boolean reset() { + return true; + } + + + + @Override + public boolean interact() { + + sprite.turnTo(pos, Dungeon.hero.pos); + switch (Random.Int (2)) { + case 0: + yell(Messages.get(this, "yell1")); + break; + case 1: + yell(Messages.get(this, "yell2")); + break; + } + return true; + } + +} diff --git a/java/com/hmdzl/spspd/actors/mobs/npcs/SadSaltan.java b/java/com/hmdzl/spspd/actors/mobs/npcs/SadSaltan.java new file mode 100644 index 00000000..731cbb57 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/npcs/SadSaltan.java @@ -0,0 +1,69 @@ +package com.hmdzl.spspd.actors.mobs.npcs; + + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.sprites.SadSaltanSprite; +import com.hmdzl.spspd.messages.Messages; +import com.watabou.utils.Random; + +public class SadSaltan extends NPC { + + { + //name = "SadSaltan"; + spriteClass = SadSaltanSprite.class; + state = WANDERING; + properties.add(Property.HUMAN); + } + + /*@Override + protected boolean act() { + throwItem(); + return super.act(); + }*/ + + @Override + public int evadeSkill(Char enemy) { + return 1000; + } + + + @Override + protected Char chooseEnemy() { + return null; + } + + @Override + public void damage(int dmg, Object src) { + } + + @Override + public void add(Buff buff) { + } + + @Override + public boolean reset() { + return true; + } + + + + @Override + public boolean interact() { + + sprite.turnTo(pos, Dungeon.hero.pos); + switch (Random.Int (3)) { + case 0: + yell(Messages.get(this, "yell1")); + break; + case 1: + yell(Messages.get(this, "yell2")); + break; + case 2: + yell(Messages.get(this, "yell3")); + break; + } + return true; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/npcs/SaidbySun.java b/java/com/hmdzl/spspd/actors/mobs/npcs/SaidbySun.java new file mode 100644 index 00000000..a7a9cc1a --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/npcs/SaidbySun.java @@ -0,0 +1,95 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs.npcs; + + +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.Challenges; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.Statistics; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.SaidbySunSprite; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.windows.WndHotel; +import com.hmdzl.spspd.windows.WndSadGhost; +import com.hmdzl.spspd.windows.WndSaidBySun; +import com.watabou.utils.Random; + +public class SaidbySun extends NPC { + + { + //name = "SaidbySun"; + spriteClass = SaidbySunSprite.class; + //state = WANDERING; + properties.add(Property.BEAST); + } + + /*@Override + protected boolean act() { + throwItem(); + return super.act(); + } */ + + @Override + public int evadeSkill(Char enemy) { + return 1000; + } + + + @Override + protected Char chooseEnemy() { + return null; + } + + @Override + public void damage(int dmg, Object src) { + } + + @Override + public void add(Buff buff) { + } + + @Override + public boolean reset() { + return true; + } + + + + @Override + public boolean interact() { + + sprite.turnTo(pos, Dungeon.hero.pos); + switch (Random.Int (3)) { + case 0: + yell(Messages.get(this, "yell1")); + break; + case 1: + yell(Messages.get(this, "yell2")); + break; + case 2: + if (Badges.checkOtilukeRescued()) + GameScene.show(new WndSaidBySun()); + break; + } + return true; + } + +} diff --git a/java/com/hmdzl/spspd/actors/mobs/npcs/Sheep.java b/java/com/hmdzl/spspd/actors/mobs/npcs/Sheep.java new file mode 100644 index 00000000..e577aeb6 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/npcs/Sheep.java @@ -0,0 +1,64 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2015 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.actors.mobs.npcs; + +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.SheepSprite; +import com.watabou.utils.Random; + +public class Sheep extends NPC { + + private static final String[] LINE_KEYS = {"Baa!", "Baa?", "Baa.", "Baa..."}; + + { + spriteClass = SheepSprite.class; + properties.add(Property.BEAST); + } + + public float lifespan; + + private boolean initialized = false; + + @Override + protected boolean act() { + if (initialized) { + HP = 0; + + destroy(); + sprite.die(); + + } else { + initialized = true; + spend( lifespan + Random.Float(2) ); + } + return true; + } + + @Override + public void damage( int dmg, Object src ) { + } + + @Override + public boolean interact() { + yell( Messages.get(this, Random.element(LINE_KEYS)) ); + return false; + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/mobs/npcs/SheepSokoban.java b/java/com/hmdzl/spspd/actors/mobs/npcs/SheepSokoban.java new file mode 100644 index 00000000..76ebcd82 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/npcs/SheepSokoban.java @@ -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 + */ +package com.hmdzl.spspd.actors.mobs.npcs; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.sprites.SokobanSheepSprite; + +public class SheepSokoban extends NPC { + + +{ +spriteClass = SokobanSheepSprite.class; +properties.add(Property.UNKNOW); +} + + +@Override +protected boolean act() { + throwItem(); + return super.act(); +} + +@Override +public void add(Buff buff) { +} + + @Override + public void beckon(int cell) { + // Do nothing + } + +@Override +public void damage(int dmg, Object src) { +} + +/* -W-1 -W -W+1 + * -1 P +1 + * W-1 W W+1 + * + */ + +@Override +public boolean interact() { + int curPos = pos; + int movPos = pos; + int width = Level.getWidth(); + boolean moved = false; + int posDif = Dungeon.hero.pos-curPos; + + if (posDif==1) { + movPos = curPos-1; + } else if(posDif==-1) { + movPos = curPos+1; + } else if(posDif==width) { + movPos = curPos-width; + } else if(posDif==-width) { + movPos = curPos+width; + } + + if (movPos != pos && (Level.passable[movPos] || Level.avoid[movPos]) && Actor.findChar(movPos) == null){ + + moveSprite(curPos,movPos); + move(movPos); + moved=true; + + } + + if(moved){ + Dungeon.hero.sprite.move(Dungeon.hero.pos, curPos); + Dungeon.hero.move(curPos); + } + + Dungeon.hero.spend(1 / Dungeon.hero.speed()); + Dungeon.hero.busy(); + return true; + //yell(Random.element(QUOTES)); + +} + +} diff --git a/java/com/hmdzl/spspd/actors/mobs/npcs/SheepSokobanBlack.java b/java/com/hmdzl/spspd/actors/mobs/npcs/SheepSokobanBlack.java new file mode 100644 index 00000000..c2feccc0 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/npcs/SheepSokobanBlack.java @@ -0,0 +1,106 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs.npcs; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.effects.particles.ShadowParticle; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.sprites.SokobanBlackSheepSprite; + +public class SheepSokobanBlack extends NPC { + +{ +spriteClass = SokobanBlackSheepSprite.class; + properties.add(Property.UNKNOW); +} + + +@Override +protected boolean act() { + throwItem(); + return super.act(); +} + +@Override +public void damage(int dmg, Object src) { +} +@Override +public void add(Buff buff) { +} + + @Override + public void beckon(int cell) { + // Do nothing + } + +@Override +public boolean interact() { + int traps = Dungeon.level.countFleeceTraps(pos, 5); + int newPos = -1; + int curPos = pos; + int count = 100; + int dist = 6; + boolean moved = false; + + if (traps>0){ + + do { + newPos = Dungeon.level.randomRespawnCellSheep(pos, 5); + dist = Level.distance(newPos, pos); + if (count-- <= 0) { + break; + } + } while (newPos == -1); + + } + + if (newPos == -1) { + + + //yell( Messages.get(Sheep.class, Random.element(LINE_KEYS))); + //yell("pos = " + dist); + destroy(); + sprite.killAndErase(); + sprite.emitter().burst(ShadowParticle.UP, 5); + moved=true; + + } else { + //yell( Messages.get(Sheep.class, Random.element(LINE_KEYS))); + //yell("pos = " + dist); + Actor.freeCell(pos); + CellEmitter.get(pos).start(Speck.factory(Speck.LIGHT), 0.2f, 3); + pos = newPos; + move(pos); + moved=true; + } + + if(moved){ + Dungeon.hero.sprite.move(Dungeon.hero.pos, curPos); + Dungeon.hero.move(curPos); + } + + Dungeon.hero.spend(1 / Dungeon.hero.speed()); + Dungeon.hero.busy(); + return true; + } + +} diff --git a/java/com/hmdzl/spspd/actors/mobs/npcs/SheepSokobanCorner.java b/java/com/hmdzl/spspd/actors/mobs/npcs/SheepSokobanCorner.java new file mode 100644 index 00000000..aa8dee88 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/npcs/SheepSokobanCorner.java @@ -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 + */ +package com.hmdzl.spspd.actors.mobs.npcs; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.sprites.SokobanCornerSheepSprite; + +public class SheepSokobanCorner extends NPC { + + +{ +spriteClass = SokobanCornerSheepSprite.class; + properties.add(Property.UNKNOW); +} + + +@Override +protected boolean act() { + throwItem(); + return super.act(); +} + +@Override +public void damage(int dmg, Object src) { +} + + @Override + public void beckon(int cell) { + // Do nothing + } + +@Override +public void add(Buff buff) { +} + +/* -W-1 -W -W+1 + * -1 P +1 + * W-1 W W+1 + * + */ + +@Override +public boolean interact() { + int curPos = pos; + int movPos = pos; + int width = Level.getWidth(); + boolean moved = false; + int posDif = Dungeon.hero.pos-curPos; + + if (posDif==1) { + movPos = curPos-1; + } else if(posDif==-1) { + movPos = curPos+1; + } else if(posDif==width) { + movPos = curPos-width; + } else if(posDif==-width) { + movPos = curPos+width; + } + + else if(posDif==-width+1) { + movPos = curPos+width-1; + + } else if(posDif==-width-1) { + movPos = curPos+width+1; + + } else if(posDif==width+1) { + movPos = curPos-(width+1); + + } else if(posDif==width-1) { + movPos = curPos-(width-1); + } + + if (movPos != pos && (Level.passable[movPos] || Level.avoid[movPos]) && Actor.findChar(movPos) == null){ + + moveSprite(curPos,movPos); + move(movPos); + moved=true; + + } + + if(moved){ + Dungeon.hero.sprite.move(Dungeon.hero.pos, curPos); + Dungeon.hero.move(curPos); + } + Dungeon.hero.spend(1 / Dungeon.hero.speed()); + Dungeon.hero.busy(); + return true; + //yell(Random.element(QUOTES)); + +} + +} diff --git a/java/com/hmdzl/spspd/actors/mobs/npcs/SheepSokobanStop.java b/java/com/hmdzl/spspd/actors/mobs/npcs/SheepSokobanStop.java new file mode 100644 index 00000000..60deef1d --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/npcs/SheepSokobanStop.java @@ -0,0 +1,64 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs.npcs; + +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.sprites.SheepSprite; +import com.hmdzl.spspd.messages.Messages; +import com.watabou.utils.Random; + +public class SheepSokobanStop extends NPC { + private static final String[] LINE_KEYS = {"Baa!", "Baa?", "Baa.", "Baa..."}; +{ +spriteClass = SheepSprite.class; + properties.add(Property.UNKNOW); +} + + +@Override +protected boolean act() { + throwItem(); + return super.act(); +} + +@Override +public void damage(int dmg, Object src) { +} + + @Override + public void beckon(int cell) { + // Do nothing + } + +@Override +public void add(Buff buff) { +} + +/* -W-1 -W -W+1 + * -1 P +1 + * W-1 W W+1 + * + */ + +@Override +public boolean interact() { + yell( Messages.get(this, Random.element(LINE_KEYS))); + return false; +} + +} diff --git a/java/com/hmdzl/spspd/actors/mobs/npcs/SheepSokobanSwitch.java b/java/com/hmdzl/spspd/actors/mobs/npcs/SheepSokobanSwitch.java new file mode 100644 index 00000000..63dafd43 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/npcs/SheepSokobanSwitch.java @@ -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 + */ +package com.hmdzl.spspd.actors.mobs.npcs; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.sprites.SokobanSheepSwitchSprite; + +public class SheepSokobanSwitch extends NPC { + +{ +spriteClass = SokobanSheepSwitchSprite.class; + properties.add(Property.UNKNOW); +} + + +@Override +protected boolean act() { + throwItem(); + return super.act(); +} + +@Override +public void damage(int dmg, Object src) { +} +@Override +public void add(Buff buff) { +} + + @Override + public void beckon(int cell) { + // Do nothing + } + +@Override +public boolean interact() { + int curPos = pos; + + //yell(Random.element(QUOTES)); + moveSprite(pos, Dungeon.hero.pos); + move(Dungeon.hero.pos); + + Dungeon.hero.sprite.move(Dungeon.hero.pos, curPos); + Dungeon.hero.move(curPos); + + Dungeon.hero.spend(1 / Dungeon.hero.speed()); + Dungeon.hero.busy(); + return true; + } + +} diff --git a/java/com/hmdzl/spspd/actors/mobs/npcs/Shopkeeper.java b/java/com/hmdzl/spspd/actors/mobs/npcs/Shopkeeper.java new file mode 100644 index 00000000..64996245 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/npcs/Shopkeeper.java @@ -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 + */ +package com.hmdzl.spspd.actors.mobs.npcs; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ShopkeeperSprite; +import com.hmdzl.spspd.windows.WndBag; +import com.hmdzl.spspd.windows.WndTradeItem; +import com.hmdzl.spspd.messages.Messages; + +public class Shopkeeper extends NPC { + + { + //name = "shopkeeper"; + spriteClass = ShopkeeperSprite.class; + properties.add(Property.HUMAN); + properties.add(Property.IMMOVABLE); + } + + @Override + protected boolean act() { + + throwItem(); + + sprite.turnTo(pos, Dungeon.hero.pos); + spend(TICK); + return true; + } + + @Override + public int evadeSkill(Char enemy) { + return 1000; + } + + @Override + public void damage(int dmg, Object src) { + } + + @Override + public void add(Buff buff) { + } + + @Override + public boolean reset() { + return true; + } + + public static WndBag sell() { + return GameScene.selectItem(itemSelector, WndBag.Mode.FOR_SALE, + Messages.get(Shopkeeper.class, "sell")); + } + + private static WndBag.Listener itemSelector = new WndBag.Listener() { + @Override + public void onSelect(Item item) { + if (item != null) { + + WndBag parentWnd = sell(); + GameScene.show(new WndTradeItem(item, parentWnd)); + } + } + }; + + @Override + public boolean interact() { + sell(); + return false; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/npcs/Shower.java b/java/com/hmdzl/spspd/actors/mobs/npcs/Shower.java new file mode 100644 index 00000000..04bb78bb --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/npcs/Shower.java @@ -0,0 +1,95 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs.npcs; + + +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ShowerSprite; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.windows.WndSaidBySun; +import com.hmdzl.spspd.windows.WndShower; +import com.watabou.utils.Random; + +public class Shower extends NPC { + + { + //name = "Shower"; + spriteClass = ShowerSprite.class; + state = WANDERING; + properties.add(Property.ELF); + } + + /*@Override + protected boolean act() { + throwItem(); + return super.act(); + } */ + + @Override + public int evadeSkill(Char enemy) { + return 1000; + } + + + @Override + protected Char chooseEnemy() { + return null; + } + + @Override + public void damage(int dmg, Object src) { + } + + @Override + public void add(Buff buff) { + } + + @Override + public boolean reset() { + return true; + } + + + + @Override + public boolean interact() { + + sprite.turnTo(pos, Dungeon.hero.pos); + switch (Random.Int (4)) { + case 0: + yell(Messages.get(this, "yell1")); + break; + case 1: + yell(Messages.get(this, "yell2")); + break; + case 2: + yell(Messages.get(this, "yell3")); + break; + case 3: + if (Badges.checkOtilukeRescued()) + GameScene.show(new WndShower()); + break; + } + return true; + } + +} diff --git a/java/com/hmdzl/spspd/actors/mobs/npcs/StormAndRain.java b/java/com/hmdzl/spspd/actors/mobs/npcs/StormAndRain.java new file mode 100644 index 00000000..92fddcab --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/npcs/StormAndRain.java @@ -0,0 +1,82 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2014 Oleg Dolya + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.actors.mobs.npcs; + + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.sprites.StormAndRainSprite; +import com.hmdzl.spspd.messages.Messages; +import com.watabou.utils.Random; + +public class StormAndRain extends NPC { + + { + //name = Messages.get(this,"name"); + spriteClass = StormAndRainSprite.class; + properties.add(Property.DEMONIC); + } + + @Override + protected boolean act() { + throwItem(); + return super.act(); + } + + @Override + public int evadeSkill(Char enemy) { + return 1000; + } + + + @Override + protected Char chooseEnemy() { + return null; + } + + @Override + public void damage(int dmg, Object src) { + } + + @Override + public void add(Buff buff) { + } + + @Override + public boolean reset() { + return true; + } + + + + @Override + public boolean interact() { + + sprite.turnTo(pos, Dungeon.hero.pos); + switch (Random.Int (2)) { + case 0: + yell(Messages.get(this, "yell1")); + break; + case 1: + yell(Messages.get(this, "yell2")); + break; + } + return true; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/npcs/Tempest102.java b/java/com/hmdzl/spspd/actors/mobs/npcs/Tempest102.java new file mode 100644 index 00000000..be700506 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/npcs/Tempest102.java @@ -0,0 +1,82 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2014 Oleg Dolya + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.actors.mobs.npcs; + + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.sprites.Tempest102Sprite; +import com.hmdzl.spspd.messages.Messages; +import com.watabou.utils.Random; + +public class Tempest102 extends NPC { + + { + //name = Messages.get(this,"name"); + spriteClass = Tempest102Sprite.class; + properties.add(Property.HUMAN); + } + + @Override + protected boolean act() { + throwItem(); + return super.act(); + } + + @Override + public int evadeSkill(Char enemy) { + return 1000; + } + + + @Override + protected Char chooseEnemy() { + return null; + } + + @Override + public void damage(int dmg, Object src) { + } + + @Override + public void add(Buff buff) { + } + + @Override + public boolean reset() { + return true; + } + + + + @Override + public boolean interact() { + + sprite.turnTo(pos, Dungeon.hero.pos); + switch (Random.Int (2)) { + case 0: + yell(Messages.get(this, "yell1")); + break; + case 1: + yell(Messages.get(this, "yell2")); + break; + } + return true; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/npcs/ThankList.java b/java/com/hmdzl/spspd/actors/mobs/npcs/ThankList.java new file mode 100644 index 00000000..612375c3 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/npcs/ThankList.java @@ -0,0 +1,201 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs.npcs; + + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.ThankListSprite; +import com.watabou.utils.Random; + +public class ThankList extends NPC { + + { + //name = "ThankList"; + spriteClass = ThankListSprite.class; + //state = WANDERING; + properties.add(Property.UNKNOW); + } + + /*@Override + protected boolean act() { + throwItem(); + return super.act(); + } */ + + @Override + public int evadeSkill(Char enemy) { + return 1000; + } + + + @Override + protected Char chooseEnemy() { + return null; + } + + @Override + public void damage(int dmg, Object src) { + } + + @Override + public void add(Buff buff) { + } + + @Override + public boolean reset() { + return true; + } + + + + @Override + public boolean interact() { + + sprite.turnTo(pos, Dungeon.hero.pos); + switch (Random.Int (46)) { + case 0: + yell("SuperSaiyan99"); + break; + case 1: + yell("‎Noodlemire"); + break; + case 3: + yell("猫佑薄荷"); + break; + case 4: + yell("RavenWolf"); + break; + case 5: + yell("Watabou"); + break; + case 6: + yell("‎Bilboldev"); + break; + case 7: + yell("‎ConsideredHamster"); + break; + case 8: + yell("‎Dachhack"); + break; + case 9: + yell("‎HeXA"); + break; + case 10: + yell("‎Juh9870"); + break; + case 11: + yell("Locastan"); + break; + case 12: + yell("‎NYRDS"); + break; + case 13: + yell("‎OldNewStwist"); + break; + case 14: + yell("‎SadSaltan"); + break; + case 15: + yell("Typedscroll"); + break; + case 16: + yell("‎Leppan"); + break; + case 17: + yell("Sharku2011"); + break; + case 18: + yell("‎老雷霆"); + break; + case 19: + yell("‎qi"); + break; + case 20: + yell("‎ian949"); + break; + case 22: + yell("‎RaiseDead"); + break; + case 23: + yell("‎指虎教徒"); + break; + case 25: + yell("白幽妹"); + break; + case 26: + yell("章华"); + break; + case 27: + yell("Hmorow12"); + break; + case 28: + yell("Eccentric_eye"); + break; + case 29: + yell("Ropuszka"); + break; + case 30: + yell("TrashboxBobylev"); + break; + case 31: + yell("Q1a2q1a2"); + break; + case 32: + yell("QueenOfTheMeowntain"); + break; + case 33: + yell("Buue2"); + break; + case 34: + yell("lighthouse64"); + break; + case 35: + yell("najecniv20"); + break; + case 36: + yell("Torian99"); + break; + case 37: + yell("deeperbroken"); + break; + case 38: + yell("DGN1"); + break; + case 39: + yell("Eldskutf"); + break; + case 41: + yell("SkyMuffin"); + break; + case 42: + yell("DragosCat1"); + break; + case 43: + yell("BlankDriver"); + break; + case 45: + yell(Messages.get(this, "yell1")); + break; + } + return true; + } + +} diff --git a/java/com/hmdzl/spspd/actors/mobs/npcs/Tinkerer1.java b/java/com/hmdzl/spspd/actors/mobs/npcs/Tinkerer1.java new file mode 100644 index 00000000..94e54913 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/npcs/Tinkerer1.java @@ -0,0 +1,95 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs.npcs; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.items.DewVial; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.quest.Mushroom; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.TinkererSprite; + +import com.hmdzl.spspd.windows.WndQuest; +import com.hmdzl.spspd.windows.WndTinkerer; +import com.hmdzl.spspd.messages.Messages; + +public class Tinkerer1 extends NPC { + + { + //name = "tinkerer"; + spriteClass = TinkererSprite.class; + properties.add(Property.HUMAN); + properties.add(Property.IMMOVABLE); + } + + private static final String TXT_DUNGEON = "Oh wow, have you seen this dungeon! This is an awesome dungeon. " + + "I'm here checking things out of course, but also scavenging for toadstool mushrooms. " + + "Could you bring me any toadstool mushrooms you find? "; + + private static final String TXT_DUNGEON2 = "Oh wow, have you seen this dungeon! This is an awesome dungeon. "; + + private static final String TXT_MUSH = "Any luck finding toadstool mushrooms, %s?"; + + @Override + protected boolean act() { + throwItem(); + return super.act(); + } + + @Override + public int evadeSkill(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 boolean interact() { + + sprite.turnTo(pos, Dungeon.hero.pos); + Item item = Dungeon.hero.belongings.getItem(Mushroom.class); + Item vial = Dungeon.hero.belongings.getItem(DewVial.class); + if (item != null && vial != null) { + GameScene.show(new WndTinkerer(this, item)); + } else if (item == null && vial != null) { + tell(Messages.get(this, "tell1")); + } else { + tell(Messages.get(this, "tell2")); + } + return false; + } + + private void tell( String text ) { + GameScene.show( + new WndQuest( this, text )); + } + +} diff --git a/java/com/hmdzl/spspd/actors/mobs/npcs/Tinkerer2.java b/java/com/hmdzl/spspd/actors/mobs/npcs/Tinkerer2.java new file mode 100644 index 00000000..a198169b --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/npcs/Tinkerer2.java @@ -0,0 +1,92 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs.npcs; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.items.summon.ActiveMrDestructo; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.quest.Mushroom; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.LynnSprite; + +import com.hmdzl.spspd.windows.WndQuest; +import com.hmdzl.spspd.windows.WndTinkerer2; +import com.hmdzl.spspd.messages.Messages; + +public class Tinkerer2 extends NPC { + + { + //name = "tinkerer"; + spriteClass = LynnSprite.class; + properties.add(Property.ELF); + properties.add(Property.IMMOVABLE); + } + + private static final String TXT_DUNGEON = "I'm scavenging for toadstool mushrooms. " + + "Could you bring me any toadstool mushrooms you find? "; + + + private static final String TXT_MUSH = "Any luck finding toadstool mushrooms, %s?"; + + @Override + protected boolean act() { + throwItem(); + return super.act(); + } + + @Override + public int evadeSkill(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 boolean interact() { + + sprite.turnTo(pos, Dungeon.hero.pos); + Item item = Dungeon.hero.belongings.getItem(Mushroom.class); + Item acmrd = Dungeon.hero.belongings.getItem(ActiveMrDestructo.class); + if (item != null && acmrd != null) { + GameScene.show(new WndTinkerer2(this, item, acmrd)); + } else if (item != null) { + GameScene.show(new WndTinkerer2(this, item, null)); + } else { + tell(Messages.get(this, "tell1")); + } + return false; + } + + private void tell( String text ) { + GameScene.show( + new WndQuest( this, text )); + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/npcs/Tinkerer3.java b/java/com/hmdzl/spspd/actors/mobs/npcs/Tinkerer3.java new file mode 100644 index 00000000..74982ad8 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/npcs/Tinkerer3.java @@ -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 + */ +package com.hmdzl.spspd.actors.mobs.npcs; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.items.DewVial; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.quest.Mushroom; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.TinkererSprite; + +import com.hmdzl.spspd.windows.WndQuest; +import com.hmdzl.spspd.windows.WndTinkerer3; +import com.hmdzl.spspd.messages.Messages; + +public class Tinkerer3 extends NPC { + + { + //name = "tinkerer"; + spriteClass = TinkererSprite.class; + properties.add(Property.HUMAN); + properties.add(Property.IMMOVABLE); + } + + private static final String TXT_DUNGEON = "I'm scavenging for toadstool mushrooms. " + + "Could you bring me any toadstool mushrooms you find? "; + + private static final String TXT_DUNGEON2 = "Oh wow, have you seen this dungeon! This is an awesome dungeon. "; + + private static final String TXT_MUSH = "Any luck finding toadstool mushrooms, %s?"; + + @Override + protected boolean act() { + throwItem(); + return super.act(); + } + + @Override + public int evadeSkill(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 boolean interact() { + + sprite.turnTo(pos, Dungeon.hero.pos); + Item item = Dungeon.hero.belongings.getItem(Mushroom.class); + Item vial = Dungeon.hero.belongings.getItem(DewVial.class); + if (item != null && vial != null) { + GameScene.show(new WndTinkerer3(this, item)); + } else if (item == null && vial != null) { + tell(Messages.get(this, "tell1")); + } else { + tell(Messages.get(this, "tell2")); + } + return false; + } + + private void tell( String text ) { + GameScene.show( + new WndQuest( this, text )); + } + +} diff --git a/java/com/hmdzl/spspd/actors/mobs/npcs/Tinkerer4.java b/java/com/hmdzl/spspd/actors/mobs/npcs/Tinkerer4.java new file mode 100644 index 00000000..4ad6ef7b --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/npcs/Tinkerer4.java @@ -0,0 +1,106 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs.npcs; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.NoodlemireSprite; + +import com.hmdzl.spspd.windows.WndQuest; +import com.hmdzl.spspd.messages.Messages; +import com.watabou.utils.Bundle; + +public class Tinkerer4 extends NPC { + + { + //name = "villager"; + spriteClass = NoodlemireSprite.class; + properties.add(Property.HUMAN); + } + + private static final String TXT_DUNGEON = "Otiluke? He came through here a few years ago.\n\n" + +"There used to be a mine to the Southwest of the town. " + +"It was overrun by demons and Otiluke sealed it off.\n\n" + +"We have not seen him since."; + + + private static final String TXT_DUNGEON2 = "The mine was covered up by bushes in the Southwest corner of the town. "; + + + @Override + protected boolean act() { + throwItem(); + return super.act(); + } + + private boolean first=true; + + private static final String FIRST = "first"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(FIRST, first); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + first = bundle.getBoolean(FIRST); + } + + @Override + protected Char chooseEnemy() { + return null; + } + @Override + public int evadeSkill(Char enemy) { + return 1000; + } + + @Override + public void damage(int dmg, Object src) { + } + + @Override + public void add(Buff buff) { + } + + @Override + public boolean interact() { + + sprite.turnTo(pos, Dungeon.hero.pos); + + if (first){ + tell(Messages.get(this, "tell1")); + first=false; + } else { + tell(Messages.get(this, "tell2")); + } + return true; + + } + + private void tell( String text ) { + GameScene.show( + new WndQuest( this, text )); + } + +} diff --git a/java/com/hmdzl/spspd/actors/mobs/npcs/Tinkerer5.java b/java/com/hmdzl/spspd/actors/mobs/npcs/Tinkerer5.java new file mode 100644 index 00000000..5ccb5ed8 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/npcs/Tinkerer5.java @@ -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 + */ +package com.hmdzl.spspd.actors.mobs.npcs; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.items.food.meatfood.ChargrilledMeat; +import com.hmdzl.spspd.scenes.GameScene; + +import com.hmdzl.spspd.sprites.Xavier251998Sprite; +import com.hmdzl.spspd.windows.WndQuest; +import com.hmdzl.spspd.messages.Messages; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public class Tinkerer5 extends NPC { + + { + //name = "villager"; + spriteClass = Xavier251998Sprite.class; + properties.add(Property.HUMAN); + } + + private static final String TXT_DUNGEON = "We used to mine stone ore out of the mines. " + +"But now a powerful dargon ruin the enter and watch in there." + +"Be careful if you enter its space."; + + + private static final String TXT_DUNGEON2 = "The building directly to the East from here houses the alter of the Gods. " + +"Bringing three Norn stones to the alter will be rewarded with a special treasure. "; + + private static final String TXT_DUNGEON3 = "You will need this food.Good luck!"; + + @Override + protected boolean act() { + throwItem(); + return super.act(); + } + + @Override + protected Char chooseEnemy() { + return null; + } + + private boolean first=true; + + private static final String FIRST = "first"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(FIRST, first); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + first = bundle.getBoolean(FIRST); + } + + @Override + public int evadeSkill(Char enemy) { + return 1000; + } + + + @Override + public void damage(int dmg, Object src) { + } + + @Override + public void add(Buff buff) { + } + + + @Override + public boolean interact() { + + sprite.turnTo(pos, Dungeon.hero.pos); + + if(first) { + first=false; + tell(Messages.get(this, "tell3")); + Dungeon.level.drop(new ChargrilledMeat(), Dungeon.hero.pos).sprite.drop(); + } else if (Random.Int(2)==0) { + tell(Messages.get(this, "tell1")); + } else { + tell(Messages.get(this, "tell2")); + } + + return true; + + } + + private void tell(String text ) { + GameScene.show(new WndQuest(this,text )); + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/npcs/TypedScroll.java b/java/com/hmdzl/spspd/actors/mobs/npcs/TypedScroll.java new file mode 100644 index 00000000..9ca7e9e6 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/npcs/TypedScroll.java @@ -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 + */ +package com.hmdzl.spspd.actors.mobs.npcs; + + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.sprites.TypedScrollSprite; +import com.hmdzl.spspd.messages.Messages; +import com.watabou.utils.Random; + +public class TypedScroll extends NPC { + + { + //name = "TypedScroll"; + spriteClass = TypedScrollSprite.class; + properties.add(Property.DEMONIC); + properties.add(Property.UNKNOW); + } + + @Override + protected boolean act() { + throwItem(); + return super.act(); + } + + @Override + public int evadeSkill(Char enemy) { + return 1000; + } + + + @Override + protected Char chooseEnemy() { + return null; + } + + @Override + public void damage(int dmg, Object src) { + } + + @Override + public void add(Buff buff) { + } + + @Override + public boolean reset() { + return true; + } + + + + @Override + public boolean interact() { + + sprite.turnTo(pos, Dungeon.hero.pos); + switch (Random.Int (2)) { + case 0: + yell(Messages.get(this, "yell1")); + break; + case 1: + yell(Messages.get(this, "yell2")); + break; + } + return true; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/npcs/Udawos.java b/java/com/hmdzl/spspd/actors/mobs/npcs/Udawos.java new file mode 100644 index 00000000..f344b58e --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/npcs/Udawos.java @@ -0,0 +1,80 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs.npcs; + + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.sprites.UdawosSprite; +import com.hmdzl.spspd.messages.Messages; +import com.watabou.utils.Random; + +public class Udawos extends NPC { + + { + //name = "Udawos"; + spriteClass = UdawosSprite.class; + properties.add(Property.DWARF); + } + + @Override + protected boolean act() { + throwItem(); + return super.act(); + } + + @Override + public int evadeSkill(Char enemy) { + return 1000; + } + + + @Override + protected Char chooseEnemy() { + return null; + } + + @Override + public void damage(int dmg, Object src) { + } + + @Override + public void add(Buff buff) { + } + + @Override + public boolean reset() { + return true; + } + + + + @Override + public boolean interact() { + + switch (Random.Int (2)) { + case 0: + yell(Messages.get(this, "yell1")); + break; + case 1: + yell(Messages.get(this, "yell2")); + break; + } + return true; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/npcs/UncleS.java b/java/com/hmdzl/spspd/actors/mobs/npcs/UncleS.java new file mode 100644 index 00000000..c58a981f --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/npcs/UncleS.java @@ -0,0 +1,74 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs.npcs; + + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.UncleSSprite; + +public class UncleS extends NPC { + + { + spriteClass = UncleSSprite.class; + properties.add(Property.HUMAN); + + } + + @Override + protected boolean act() { + throwItem(); + return super.act(); + } + + @Override + public int evadeSkill(Char enemy) { + return 1000; + } + + + @Override + protected Char chooseEnemy() { + return null; + } + + @Override + public void damage(int dmg, Object src) { + } + + @Override + public void add(Buff buff) { + } + + @Override + public boolean reset() { + return true; + } + + + + @Override + public boolean interact() { + + sprite.turnTo(pos, Dungeon.hero.pos); + yell(Messages.get(this, "yell1")); + return true; + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/mobs/npcs/Wandmaker.java b/java/com/hmdzl/spspd/actors/mobs/npcs/Wandmaker.java new file mode 100644 index 00000000..4c087560 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/npcs/Wandmaker.java @@ -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 + */ +package com.hmdzl.spspd.actors.mobs.npcs; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.Journal; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.items.Heap; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.quest.CorpseDust; +import com.hmdzl.spspd.items.wands.Wand; +import com.hmdzl.spspd.items.wands.WandOfAcid; +import com.hmdzl.spspd.items.wands.WandOfCharm; +import com.hmdzl.spspd.items.wands.WandOfFlock; +import com.hmdzl.spspd.items.wands.WandOfMagicMissile; +import com.hmdzl.spspd.items.wands.WandOfMeteorite; +import com.hmdzl.spspd.items.wands.WandOfBlood; +import com.hmdzl.spspd.items.wands.WandOfDisintegration; +import com.hmdzl.spspd.items.wands.WandOfFirebolt; +import com.hmdzl.spspd.items.wands.WandOfLightning; +import com.hmdzl.spspd.items.wands.WandOfPoison; +import com.hmdzl.spspd.items.wands.WandOfLight; +import com.hmdzl.spspd.items.wands.WandOfFreeze; +import com.hmdzl.spspd.items.wands.WandOfFlow; +import com.hmdzl.spspd.items.wands.WandOfTCloud; +import com.hmdzl.spspd.levels.PrisonLevel; +import com.hmdzl.spspd.levels.Room; +import com.hmdzl.spspd.levels.Terrain; +import com.hmdzl.spspd.plants.Rotberry; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.WandmakerSprite; + +import com.hmdzl.spspd.windows.WndQuest; +import com.hmdzl.spspd.windows.WndWandmaker; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; +import com.hmdzl.spspd.messages.Messages; + +public class Wandmaker extends NPC { + + { + //name = "old wandmaker"; + spriteClass = WandmakerSprite.class; + properties.add(Property.HUMAN); + properties.add(Property.IMMOVABLE); + } + + private static final String TXT_BERRY1 = "Oh, what a pleasant surprise to meet a decent person in such place! I came here for a rare ingredient - " + + "a _Rotberry seed_. Being a magic user, I'm quite able to defend myself against local monsters, " + + "but I'm getting lost in no time, it's very embarrassing. Probably you could help me? I would be " + + "happy to pay for your service with one of my best wands."; + + private static final String TXT_DUST1 = "Oh, what a pleasant surprise to meet a decent person in such place! I came here for a rare ingredient - " + + "_corpse dust_. It can be gathered from skeletal remains and there is an ample number of them in the dungeon. " + + "Being a magic user, I'm quite able to defend myself against local monsters, but I'm getting lost in no time, " + + "it's very embarrassing. Probably you could help me? I would be happy to pay for your service with one of my best wands."; + + private static final String TXT_BERRY2 = "Any luck with a Rotberry seed, %s? No? Don't worry, I'm not in a hurry."; + + private static final String TXT_DUST2 = "Any luck with corpse dust, %s? Bone piles are the most obvious places to look."; + + @Override + protected boolean act() { + throwItem(); + return super.act(); + } + + @Override + public int evadeSkill(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 boolean interact() { + + sprite.turnTo(pos, Dungeon.hero.pos); + if (Quest.given) { + + Item item = Quest.alternative ? Dungeon.hero.belongings + .getItem(CorpseDust.class) : Dungeon.hero.belongings + .getItem(Rotberry.Seed.class); + if (item != null) { + GameScene.show(new WndWandmaker(this, item)); + } else { + tell(Quest.alternative ? + Messages.get(this, "dust_2", Dungeon.hero.givenName()) + : Messages.get(this, "berry_2" , Dungeon.hero.givenName())); + } + + } else { + + Quest.placeItem(); + + if (Quest.given) + tell(Quest.alternative ? Messages.get(this, "dust_1") : Messages.get(this, "berry_1")); + + Journal.add(Journal.Feature.WANDMAKER); + } + return false; + } + + private void tell(String text) { + GameScene.show(new WndQuest(this,text)); + } + + public static class Quest { + + private static boolean spawned; + + private static boolean alternative; + + private static boolean given; + + public static Wand wand1; + public static Wand wand2; + + public static void reset() { + spawned = false; + + wand1 = null; + wand2 = null; + } + + private static final String NODE = "wandmaker"; + + private static final String SPAWNED = "spawned"; + private static final String ALTERNATIVE = "alternative"; + private static final String GIVEN = "given"; + private static final String WAND1 = "wand1"; + private static final String WAND2 = "wand2"; + + public static void storeInBundle(Bundle bundle) { + + Bundle node = new Bundle(); + + node.put(SPAWNED, spawned); + + if (spawned) { + + node.put(ALTERNATIVE, alternative); + + node.put(GIVEN, given); + + node.put(WAND1, wand1); + node.put(WAND2, wand2); + } + + bundle.put(NODE, node); + } + + public static void restoreFromBundle(Bundle bundle) { + + Bundle node = bundle.getBundle(NODE); + + if (!node.isNull() && (spawned = node.getBoolean(SPAWNED))) { + + alternative = node.getBoolean(ALTERNATIVE); + + given = node.getBoolean(GIVEN); + + wand1 = (Wand) node.get(WAND1); + wand2 = (Wand) node.get(WAND2); + } else { + reset(); + } + } + + public static void spawn(PrisonLevel level, Room room) { + if (!spawned && Dungeon.depth==7) { + + Wandmaker npc = new Wandmaker(); + do { + npc.pos = room.random(); + } while (level.map[npc.pos] == Terrain.ENTRANCE + || level.map[npc.pos] == Terrain.SIGN); + level.mobs.add(npc); + Actor.occupyCell(npc); + + spawned = true; + + //if (Dungeon.isChallenged(Challenges.NO_HERBALISM)){ + //alternative=true; + //} else { + alternative = Random.Int(2) == 0; + //} + + given = false; + + switch (Random.Int(7)) { + case 0: + wand1 = new WandOfLight(); + break; + case 1: + wand1 = new WandOfDisintegration(); + break; + case 2: + wand1 = new WandOfFirebolt(); + break; + case 3: + wand1 = new WandOfLightning(); + break; + case 4: + wand1 = new WandOfAcid(); + break; + case 5: + wand1 = new WandOfBlood(); + break; + case 6: + wand1 = new WandOfFreeze(); + break; + } + wand1.random().upgrade(); + + switch (Random.Int(7)) { + case 0: + wand2 = new WandOfCharm(); + break; + case 1: + wand2 = new WandOfFlock(); + break; + case 2: + wand2 = new WandOfPoison(); + break; + case 3: + wand2 = new WandOfMeteorite(); + break; + case 4: + wand2 = new WandOfFlow(); + break; + case 5: + wand2 = new WandOfTCloud(); + break; + case 6: + wand2 = new WandOfFlow(); + break; + case 7: + wand2 = new WandOfMagicMissile(); + break; + } + wand2.random().upgrade(); + } + } + + public static void placeItem() { + if (alternative /*|| Dungeon.isChallenged(Challenges.NO_HERBALISM)*/) { + + ArrayList candidates = new ArrayList(); + for (Heap heap : Dungeon.level.heaps.values()) { + if (heap.type == Heap.Type.SKELETON + && !Dungeon.visible[heap.pos]) { + candidates.add(heap); + } + } + + if (candidates.size() > 0) { + Random.element(candidates).drop(new CorpseDust()); + given = true; + } else { + int pos = Dungeon.level.randomRespawnCell(); + while (Dungeon.level.heaps.get(pos) != null) { + pos = Dungeon.level.randomRespawnCell(); + } + + if (pos != -1) { + Heap heap = Dungeon.level.drop(new CorpseDust(), pos); + heap.type = Heap.Type.SKELETON; + heap.sprite.link(); + given = true; + } + } + + } else { + + int shrubPos = Dungeon.level.randomRespawnCell(); + while (Dungeon.level.heaps.get(shrubPos) != null) { + shrubPos = Dungeon.level.randomRespawnCell(); + } + + if (shrubPos != -1) { + Dungeon.level.plant(new Rotberry.Seed(), shrubPos); + given = true; + } + + } + } + + public static void complete() { + wand1 = null; + wand2 = null; + + Journal.remove(Journal.Feature.WANDMAKER); + } + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/npcs/Watabou.java b/java/com/hmdzl/spspd/actors/mobs/npcs/Watabou.java new file mode 100644 index 00000000..1e18198a --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/npcs/Watabou.java @@ -0,0 +1,82 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2014 Oleg Dolya + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.actors.mobs.npcs; + + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.sprites.WatabouSprite; +import com.hmdzl.spspd.messages.Messages; +import com.watabou.utils.Random; + +public class Watabou extends NPC { + + { + //name = "Watabou"; + spriteClass = WatabouSprite.class; + properties.add(Property.DEMONIC); + } + + @Override + protected boolean act() { + throwItem(); + return super.act(); + } + + @Override + public int evadeSkill(Char enemy) { + return 1000; + } + + + @Override + protected Char chooseEnemy() { + return null; + } + + @Override + public void damage(int dmg, Object src) { + } + + @Override + public void add(Buff buff) { + } + + @Override + public boolean reset() { + return true; + } + + + + @Override + public boolean interact() { + + sprite.turnTo(pos, Dungeon.hero.pos); + switch (Random.Int (2)) { + case 0: + yell(Messages.get(this, "yell1")); + break; + case 1: + yell(Messages.get(this, "yell2")); + break; + } + return true; + } +} diff --git a/java/com/hmdzl/spspd/actors/mobs/npcs/WhiteGhost.java b/java/com/hmdzl/spspd/actors/mobs/npcs/WhiteGhost.java new file mode 100644 index 00000000..b88ab274 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/npcs/WhiteGhost.java @@ -0,0 +1,74 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs.npcs; + + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.WhiteGhostSprite; + +public class WhiteGhost extends NPC { + + { + spriteClass = WhiteGhostSprite.class; + properties.add(Property.UNKNOW); + + } + + @Override + protected boolean act() { + throwItem(); + return super.act(); + } + + @Override + public int evadeSkill(Char enemy) { + return 1000; + } + + + @Override + protected Char chooseEnemy() { + return null; + } + + @Override + public void damage(int dmg, Object src) { + } + + @Override + public void add(Buff buff) { + } + + @Override + public boolean reset() { + return true; + } + + + + @Override + public boolean interact() { + + sprite.turnTo(pos, Dungeon.hero.pos); + yell(Messages.get(this, "yell1")); + return true; + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/mobs/npcs/XixiZero.java b/java/com/hmdzl/spspd/actors/mobs/npcs/XixiZero.java new file mode 100644 index 00000000..c948e12a --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/npcs/XixiZero.java @@ -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 + */ +package com.hmdzl.spspd.actors.mobs.npcs; + + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.XixiZeroSprite; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.windows.WndEgoalInfo; +import com.watabou.utils.Random; + +public class XixiZero extends NPC { + + { + //name = "XixiZero"; + spriteClass = XixiZeroSprite.class; + //state = WANDERING; + properties.add(Property.BEAST); + } + + /*@Override + protected boolean act() { + throwItem(); + return super.act(); + } */ + + @Override + public int evadeSkill(Char enemy) { + return 1000; + } + + + @Override + protected Char chooseEnemy() { + return null; + } + + @Override + public void damage(int dmg, Object src) { + } + + @Override + public void add(Buff buff) { + } + + @Override + public boolean reset() { + return true; + } + + + + @Override + public boolean interact() { + + sprite.turnTo(pos, Dungeon.hero.pos); + switch (Random.Int (2)) { + case 0: + yell(Messages.get(this, "yell1")); + break; + case 1: + GameScene.show(new WndEgoalInfo(null)); + break; + } + return true; + } + +} diff --git a/java/com/hmdzl/spspd/actors/mobs/pets/BlueDragon.java b/java/com/hmdzl/spspd/actors/mobs/pets/BlueDragon.java new file mode 100644 index 00000000..7e1aa374 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/pets/BlueDragon.java @@ -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 + */ +package com.hmdzl.spspd.actors.mobs.pets; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Frost; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.particles.SnowParticle; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.BlueDragonSprite; +import com.hmdzl.spspd.sprites.CharSprite; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Callback; +import com.watabou.utils.Random; + +public class BlueDragon extends PET implements Callback{ + + { + //name = "blue dragon"; + spriteClass = BlueDragonSprite.class; + //flying=true; + state = HUNTING; + level = 1; + type = 7; + cooldown=500; + + properties.add(Property.DRAGON); + + } + private static final float TIME_TO_ZAP = 1f; + + //Frames 1-4 are idle, 5-8 are moving, 9-12 are attack and the last are for death + + //flame on! + //spits fire + //feed meat + + @Override + public void adjustStats(int level) { + this.level = level; + HT = 70 + level*10; + evadeSkill = 5 + level; + } + + + + + @Override + public int damageRoll() { + return Random.NormalIntRange((5+level), (5+level*3)); + } + + @Override + protected boolean act() { + + if (cooldown>0){ + cooldown=Math.max(cooldown-(1+9*((level-1)/19)),0); + if (cooldown==0) { + GLog.w(Messages.get(this,"ready")); + } + } + + + + return super.act(); + } + + + @Override + protected boolean canAttack(Char enemy) { + if (cooldown>0){ + return Level.adjacent(pos, enemy.pos); + } else { + return new Ballistica( pos, enemy.pos, Ballistica.MAGIC_BOLT).collisionPos == enemy.pos; + } + } + + @Override + 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) { + ((BlueDragonSprite) sprite).zap(enemy.pos); + } else { + zap(); + } + + return !visible; + } + } + + + private void zap() { + spend(TIME_TO_ZAP); + + cooldown=500; + + if (hit(this, enemy, true)) { + + int dmg = damageRoll()*2; + enemy.damage(dmg, this); + + Buff.prolong(enemy, Frost.class, Frost.duration(enemy)* Random.Float(1f, 1.5f)); + CellEmitter.get(enemy.pos).start(SnowParticle.FACTORY, 0.2f, 6); + + } else { + enemy.sprite.showStatus(CharSprite.NEUTRAL, enemy.defenseVerb()); + } + + } + + public void onZapComplete() { + zap(); + next(); + } + + @Override + public void call() { + next(); + } + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/mobs/pets/BugDragon.java b/java/com/hmdzl/spspd/actors/mobs/pets/BugDragon.java new file mode 100644 index 00000000..dc0640d1 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/pets/BugDragon.java @@ -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 + */ +package com.hmdzl.spspd.actors.mobs.pets; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.BugDragonSprite; +import com.hmdzl.spspd.sprites.CharSprite; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Callback; +import com.watabou.utils.Random; + +public class BugDragon extends PET implements Callback{ + + { + //name = "bug dragon"; + spriteClass = BugDragonSprite.class; + //flying=true; + state = HUNTING; + level = 1; + type = 11; + cooldown=500; + + properties.add(Property.DRAGON); + } + private static final float TIME_TO_ZAP = 1f; + + //Frames 1-4 are idle, 5-8 are moving, 9-12 are attack and the last are for death + + //flame on! + //spits fire + //feed meat + + @Override + public void adjustStats(int level) { + this.level = level; + HT = 200 + level*20; + evadeSkill = 20 + level; + } + + + + + @Override + public int damageRoll() { + return Random.NormalIntRange((20+level), (20+level*5)); + } + + @Override + protected boolean act() { + + if (cooldown>0){ + cooldown=Math.max(cooldown-(1+9*((level-1)/19)),0); + if (cooldown==0) { + GLog.w(Messages.get(this,"ready")); + } + } + + + + return super.act(); + } + + + @Override + protected boolean canAttack(Char enemy) { + if (cooldown>0){ + return Level.adjacent(pos, enemy.pos); + } else { + return new Ballistica( pos, enemy.pos, Ballistica.MAGIC_BOLT).collisionPos == enemy.pos; + } + } + + @Override + 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) { + ((BugDragonSprite) sprite).zap(enemy.pos); + } else { + zap(); + } + + return !visible; + } + } + + + private void zap() { + spend(TIME_TO_ZAP); + + cooldown=500; + + if (hit(this, enemy, true)) { + + int dmg = damageRoll()*5; + enemy.damage(dmg, this); + + } else { + enemy.sprite.showStatus(CharSprite.NEUTRAL, enemy.defenseVerb()); + } + + } + + public void onZapComplete() { + zap(); + next(); + } + + @Override + public void call() { + next(); + } + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/mobs/pets/Bunny.java b/java/com/hmdzl/spspd/actors/mobs/pets/Bunny.java new file mode 100644 index 00000000..9ada21ff --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/pets/Bunny.java @@ -0,0 +1,73 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs.pets; + +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.BunnySprite; +import com.hmdzl.spspd.utils.GLog; + +import com.watabou.utils.Random; + +public class Bunny extends PET{ + + { + //name = "bunny"; + spriteClass = BunnySprite.class; + state = HUNTING; + level = 1; + type = 9; + cooldown=500; + + properties.add(Property.BEAST); + } + + + @Override + public void adjustStats(int level) { + this.level = level; + HT = 70 + level*10; + evadeSkill = 5 + level; + } + + @Override + public int damageRoll() { + + int dmg=0; + if (cooldown==0){ + dmg=Random.NormalIntRange((5+level)*5, (5+level*3)*4); + cooldown=500; + } else { + dmg=Random.NormalIntRange((5+level), (5+level*3)) ; + } + return dmg; + + } + + @Override + protected boolean act() { + + if (cooldown>0){ + cooldown=Math.max(cooldown-(1+9*((level-1)/19)),0); + if (cooldown==0) {GLog.w(Messages.get(this,"ready"));} + } + + + + return super.act(); + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/mobs/pets/CocoCat.java b/java/com/hmdzl/spspd/actors/mobs/pets/CocoCat.java new file mode 100644 index 00000000..796e5fb4 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/pets/CocoCat.java @@ -0,0 +1,135 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs.pets; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.items.bombs.BuildBomb; +import com.hmdzl.spspd.sprites.CoconutSprite; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Random; + +import com.hmdzl.spspd.messages.Messages; + +public class CocoCat extends PET { + + { + //name = "scorpion"; + spriteClass = CoconutSprite.class; + //flying=false; + state = HUNTING; + level = 1; + type = 13; + cooldown=500; + + properties.add(Property.BEAST); + + } + + + + + @Override + public void adjustStats(int level) { + this.level = level; + HT = 10000; + evadeSkill = 5 + level; + } + + + + + @Override + public int damageRoll() { + return Random.NormalIntRange((5+level), (5+level*3)) ; + } + + @Override + protected boolean act() { + + if (cooldown>0){ + cooldown=Math.max(cooldown-(1+9*((level-1)/19)),0); + if (cooldown==0) {GLog.w(Messages.get(this,"ready"));} + } + + + + if (level > 5){ + yell(Messages.get(this,"thanks")); + destroy(); + //sprite.killAndErase(); + //CellEmitter.get(pos).burst(ElmoParticle.FACTORY, 6); + Dungeon.hero.haspet=false; + } + + return super.act(); + + } + + @Override + protected boolean canAttack(Char enemy) { + + return Dungeon.level.distance( pos, enemy.pos ) <= 4 ; + + } + + @Override + public int attackProc(Char enemy, int damage) { + if (cooldown==0) { + BuildBomb bomb = new BuildBomb(); + bomb.explode(enemy.pos); + cooldown=500; + } + + return damage; + } + + /*private static final HashSet> RESISTANCES = new HashSet>(); + private static final HashSet> IMMUNITIES = new HashSet>(); + static { + RESISTANCES.add(ToxicGas.class); + RESISTANCES.add(Poison.class); + RESISTANCES.add(EnchantmentDark.class); + IMMUNITIES.add(EnchantmentDark.class); + IMMUNITIES.add(Ooze.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); + IMMUNITIES.add(Vertigo.class); + IMMUNITIES.add(Paralysis.class); + IMMUNITIES.add(Bleeding.class); + IMMUNITIES.add(CorruptGas.class); + + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } + + @Override + public HashSet> resistances() { + return RESISTANCES; + }*/ + + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/mobs/pets/Fairy.java b/java/com/hmdzl/spspd/actors/mobs/pets/Fairy.java new file mode 100644 index 00000000..20ef8c6c --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/pets/Fairy.java @@ -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 + */ +package com.hmdzl.spspd.actors.mobs.pets; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.ResultDescriptions; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.effects.particles.SparkParticle; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.CharSprite; +import com.hmdzl.spspd.sprites.FairySprite; +import com.hmdzl.spspd.utils.GLog; + +import com.watabou.noosa.Camera; +import com.watabou.utils.Callback; +import com.watabou.utils.Random; + +public class Fairy extends PET implements Callback{ + + { + //name = "fairy"; + spriteClass = FairySprite.class; + //flying=true; + state = HUNTING; + level = 1; + type = 10; + cooldown=500; + + properties.add(Property.UNKNOW); + } + private static final float TIME_TO_ZAP = 2f; + private static final String TXT_LIGHTNING_KILLED = "%s's lightning bolt killed you..."; + + @Override + protected float attackDelay() { + return 0.5f; + } + + //Frames 0,2 are idle, 0,1,2 are moving, 0,3,4,1 are attack and 5,6,7 are for death + + @Override + public void adjustStats(int level) { + this.level = level; + HT = 70 + level*10; + evadeSkill = 5 + level; + } + + + + + @Override + public int damageRoll() { + return Random.NormalIntRange((5+level), (5+level*3)); + } + + @Override + protected boolean act() { + + if (cooldown>0){ + cooldown=Math.max(cooldown-(1+9*((level-1)/19)),0); + if (cooldown==0) {GLog.w(Messages.get(this,"ready"));} + } + + if (cooldown==0 && Level.adjacent(pos, Dungeon.hero.pos) && Random.Int(2)==0){ + + int bless = Random.Int(1+9*((level-1)/19)); + + Dungeon.hero.sprite.emitter().start(Speck.factory(Speck.HEALING), 0.4f, 1); + Dungeon.hero.sprite.showStatus(CharSprite.POSITIVE,Integer.toString(bless)); + + Dungeon.hero.HP = Math.min(Dungeon.hero.HT, Dungeon.hero.HP+bless); + } + + + + return super.act(); + } + + + @Override + protected boolean canAttack(Char enemy) { + return new Ballistica( pos, enemy.pos, Ballistica.MAGIC_BOLT).collisionPos == enemy.pos; + + } + + + + @Override + 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) { + ((FairySprite) sprite).zap(enemy.pos); + } + + spend(TIME_TO_ZAP); + cooldown=500; + + if (hit(this, enemy, true)) { + int dmg = damageRoll()*2; + if (Level.water[enemy.pos] && !enemy.flying) { + dmg *= 1.5f; + } + enemy.damage(dmg, this); + + 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( Messages.format(ResultDescriptions.NAMED)); + //GLog.n(TXT_LIGHTNING_KILLED, name); + } + } + } else { + enemy.sprite + .showStatus(CharSprite.NEUTRAL, enemy.defenseVerb()); + } + + return !visible; + } + } + + + + @Override + public void call() { + next(); + } + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/mobs/pets/Fly.java b/java/com/hmdzl/spspd/actors/mobs/pets/Fly.java new file mode 100644 index 00000000..a95a7190 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/pets/Fly.java @@ -0,0 +1,77 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs.pets; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Slow; +import com.hmdzl.spspd.sprites.FlySprite; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public class Fly extends PET { + + { + //name = "Fly"; + spriteClass = FlySprite.class; + //flying=true; + state = HUNTING; + level = 1; + type = 17; + + properties.add(Property.BEAST); + + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + adjustStats(level); + } + + @Override + public void adjustStats(int level) { + this.level = level; + evadeSkill = 5 + level; + HT = 90 + level*5; + } + + + + + @Override + public int damageRoll() { + return Random.NormalIntRange(10, (10+level*2)); + } + + @Override + protected boolean act() { + + + return super.act(); + } + + @Override + public int attackProc(Char enemy, int damage) { + if (Random.Int(10) == 0) { + Buff.affect(enemy, Slow.class, 5f); + } + + return damage; + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/mobs/pets/GentleCrab.java b/java/com/hmdzl/spspd/actors/mobs/pets/GentleCrab.java new file mode 100644 index 00000000..ef0a531f --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/pets/GentleCrab.java @@ -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 + */ +package com.hmdzl.spspd.actors.mobs.pets; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.ArmorBreak; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.sprites.GentleCrabSprite; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public class GentleCrab extends PET { + + { + //name = "GentleCrab"; + spriteClass = GentleCrabSprite.class; + //flying=true; + state = HUNTING; + level = 1; + type = 20; + baseSpeed = 3/2; + properties.add(Property.BEAST); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + adjustStats(level); + } + + @Override + public void adjustStats(int level) { + this.level = level; + evadeSkill = 5 + level; + HT = 90 + level*5; + } + + + + + @Override + public int damageRoll() { + return Random.NormalIntRange(10, (10+level*2)); + } + + @Override + protected boolean act() { + + + return super.act(); + } + + @Override + public int attackProc(Char enemy, int damage) { + if (Random.Int(10) == 0) { + Buff.prolong(enemy, ArmorBreak.class,5f).level(10); + } + + return damage; + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/mobs/pets/GoldDragon.java b/java/com/hmdzl/spspd/actors/mobs/pets/GoldDragon.java new file mode 100644 index 00000000..15306959 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/pets/GoldDragon.java @@ -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 + */ +package com.hmdzl.spspd.actors.mobs.pets; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.GoldDragonSprite; +import com.hmdzl.spspd.sprites.CharSprite; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Callback; +import com.watabou.utils.Random; + +public class GoldDragon extends PET implements Callback{ + + { + //name = "gold dragon"; + spriteClass = GoldDragonSprite.class; + //flying=true; + state = HUNTING; + level = 1; + type = 15; + cooldown=500; + + properties.add(Property.DRAGON); + } + private static final float TIME_TO_ZAP = 1f; + + //Frames 1-4 are idle, 5-8 are moving, 9-12 are attack and the last are for death + + //flame on! + //spits fire + //feed meat + + @Override + public void adjustStats(int level) { + this.level = level; + HT = 100 + level*10; + evadeSkill = 10 + level; + } + + + + + @Override + public int damageRoll() { + return Random.NormalIntRange((10+level), (10+level*5)); + } + + @Override + protected boolean act() { + + if (cooldown>0){ + cooldown=Math.max(cooldown-(1+9*((level-1)/19)),0); + if (cooldown==0) { + GLog.w(Messages.get(this,"ready")); + } + } + + + + return super.act(); + } + + + @Override + protected boolean canAttack(Char enemy) { + if (cooldown>0){ + return Level.adjacent(pos, enemy.pos); + } else { + return new Ballistica( pos, enemy.pos, Ballistica.MAGIC_BOLT).collisionPos == enemy.pos; + } + } + + @Override + 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) { + ((GoldDragonSprite) sprite).zap(enemy.pos); + } else { + zap(); + } + + return !visible; + } + } + + + private void zap() { + spend(TIME_TO_ZAP); + + cooldown=500; + + if (hit(this, enemy, true)) { + + int dmg = damageRoll()*5; + enemy.damage(dmg, this); + + } else { + enemy.sprite.showStatus(CharSprite.NEUTRAL, enemy.defenseVerb()); + } + + } + + public void onZapComplete() { + zap(); + next(); + } + + @Override + public void call() { + next(); + } + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/mobs/pets/GreenDragon.java b/java/com/hmdzl/spspd/actors/mobs/pets/GreenDragon.java new file mode 100644 index 00000000..882887bf --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/pets/GreenDragon.java @@ -0,0 +1,155 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs.pets; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.ResultDescriptions; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.effects.particles.SparkParticle; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.CharSprite; +import com.hmdzl.spspd.sprites.GreenDragonSprite; +import com.hmdzl.spspd.utils.GLog; + +import com.watabou.noosa.Camera; +import com.watabou.utils.Callback; +import com.watabou.utils.Random; + +public class GreenDragon extends PET implements Callback{ + + { + //name = "green dragon"; + spriteClass = GreenDragonSprite.class; + //flying=true; + state = HUNTING; + level = 1; + type = 5; + cooldown=500; + + properties.add(Property.DRAGON); + } + private static final float TIME_TO_ZAP = 2f; + private static final String TXT_LIGHTNING_KILLED = "%s's lightning bolt killed you..."; + + @Override + protected float attackDelay() { + return 0.8f; + } + + //Frames 1-4 are idle, 5-8 are moving, 9-12 are attack and the last are for death + + //flame on! + //spits fire + //feed meat + + @Override + public void adjustStats(int level) { + this.level = level; + HT = 70 + level*10; + evadeSkill = 5 + level; + } + + + + + @Override + public int damageRoll() { + return Random.NormalIntRange((5+level), (5+level*3)); + } + + @Override + protected boolean act() { + + if (cooldown>0){ + cooldown=Math.max(cooldown-(1+9*((level-1)/19)),0); + if (cooldown==0) {GLog.w(Messages.get(this,"ready"));} + } + + + + return super.act(); + } + + + @Override + protected boolean canAttack(Char enemy) { + if (cooldown>0){ + return Level.adjacent(pos, enemy.pos); + } else { + return new Ballistica( pos, enemy.pos, Ballistica.MAGIC_BOLT).collisionPos == enemy.pos; + } + } + + + + @Override + 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) { + ((GreenDragonSprite) sprite).zap(enemy.pos); + } + + spend(TIME_TO_ZAP); + cooldown=500; + + if (hit(this, enemy, true)) { + int dmg = damageRoll()*2; + if (Level.water[enemy.pos] && !enemy.flying) { + dmg *= 1.5f; + } + enemy.damage(dmg, this); + + 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(Messages.format(ResultDescriptions.NAMED)); + //GLog.n(TXT_LIGHTNING_KILLED, name); + } + } + } else { + enemy.sprite + .showStatus(CharSprite.NEUTRAL, enemy.defenseVerb()); + } + + return !visible; + } + } + + + + @Override + public void call() { + next(); + } + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/mobs/pets/LeryFire.java b/java/com/hmdzl/spspd/actors/mobs/pets/LeryFire.java new file mode 100644 index 00000000..e1cd1efe --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/pets/LeryFire.java @@ -0,0 +1,209 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs.pets; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.ResultDescriptions; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.Blob; +import com.hmdzl.spspd.actors.blobs.Fire; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Frost; +import com.hmdzl.spspd.actors.buffs.Poison; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.particles.SnowParticle; +import com.hmdzl.spspd.effects.particles.SparkParticle; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.LerySprite; +import com.hmdzl.spspd.sprites.CharSprite; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.noosa.Camera; +import com.watabou.utils.Callback; +import com.watabou.utils.Random; + +public class LeryFire extends PET implements Callback{ + + { + //name = "blue dragon"; + spriteClass = LerySprite.class; + //flying=true; + state = HUNTING; + level = 1; + type = 14; + cooldown=500; + + properties.add(Property.ELEMENT); + + } + private static final float TIME_TO_ZAP = 1f; + + + + @Override + public void adjustStats(int level) { + this.level = level; + HT = 70 + level*10; + evadeSkill = 5 + level; + } + + + + + @Override + public int damageRoll() { + return Random.NormalIntRange((5+level), (5+level*3)); + } + + @Override + protected boolean act() { + + if (cooldown>0){ + cooldown=Math.max(cooldown-(1+9*((level-1)/19)),0); + if (cooldown==0) { + GLog.w(Messages.get(this,"ready")); + } + } + + + + return super.act(); + } + + + @Override + protected boolean canAttack(Char enemy) { + if (cooldown>0){ + return Level.adjacent(pos, enemy.pos); + } else { + return new Ballistica( pos, enemy.pos, Ballistica.MAGIC_BOLT).collisionPos == enemy.pos; + } + } + + @Override + 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) { + ((LerySprite) sprite).zap(enemy.pos); + } else { + zap(); + } + + return !visible; + } + } + + + private void zap() { + spend(TIME_TO_ZAP); + + cooldown=500; + switch (Random.Int (5)) { + case 0: + if (hit(this, enemy, true)) { + int dmg = damageRoll()*2; + enemy.damage(dmg, this); + Buff.prolong(enemy, Frost.class, Frost.duration(enemy)* Random.Float(1f, 1.5f)); + CellEmitter.get(enemy.pos).start(SnowParticle.FACTORY, 0.2f, 6); + } else { + enemy.sprite.showStatus(CharSprite.NEUTRAL, enemy.defenseVerb()); + } + return; + case 1: + if (hit(this, enemy, true)) { + + int dmg = damageRoll()*2; + enemy.damage(dmg, this); + + Buff.affect(enemy,Poison.class).set(Poison.durationFactor(enemy) * (level + 1)); + + } else { + enemy.sprite.showStatus(CharSprite.NEUTRAL, enemy.defenseVerb()); + } + return; + case 2: + if (hit(this, enemy, true)) { + + int dmg = damageRoll()*2; + enemy.damage(dmg, this); + + if (Random.Int(dmg) + */ +package com.hmdzl.spspd.actors.mobs.pets; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Blindness; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.LightDragonSprite; +import com.hmdzl.spspd.utils.GLog; + +import com.watabou.utils.Random; + +public class LightDragon extends PET{ + + { + //name = "LightDragon"; + spriteClass = LightDragonSprite.class; + //flying=true; + state = HUNTING; + level = 1; + type = 10; + cooldown=500; + + properties.add(Property.DRAGON); + } + private static final float TIME_TO_ZAP = 2f; + + @Override + protected float attackDelay() { + return 1f; + } + + //Frames 0,2 are idle, 0,1,2 are moving, 0,3,4,1 are attack and 5,6,7 are for death + + @Override + public void adjustStats(int level) { + this.level = level; + HT = 70 + level*10; + evadeSkill = 5 + level; + } + + + + + @Override + public int damageRoll() { + return Random.NormalIntRange((5+level), (5+level*3)); + } + + @Override + protected boolean act() { + + if (cooldown>0){ + cooldown=Math.max(cooldown-(1+9*((level-1)/19)),0); + if (cooldown==0) {GLog.w(Messages.get(this,"ready"));} + } + + return super.act(); + } + + + @Override + protected boolean canAttack(Char enemy) { + if (cooldown>0){ + return Level.adjacent(pos, enemy.pos); + } else { + return new Ballistica( pos, enemy.pos, Ballistica.MAGIC_BOLT).collisionPos == enemy.pos; + } + + } + + @Override + public int attackProc(Char enemy, int damage) { + if (cooldown == 0) { + cooldown=500; + enemy.damage((int)(enemy.HP/4),this); + Buff.affect(enemy, Blindness.class, 10f); + } + return damage; + } + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/mobs/pets/Monkey.java b/java/com/hmdzl/spspd/actors/mobs/pets/Monkey.java new file mode 100644 index 00000000..39f37e9e --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/pets/Monkey.java @@ -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 + */ +package com.hmdzl.spspd.actors.mobs.pets; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.sprites.MonkeySprite; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public class Monkey extends PET { + + { + //name = "Monkey"; + spriteClass = MonkeySprite.class; + //flying=true; + state = HUNTING; + level = 1; + type = 19; + + properties.add(Property.ELEMENT); + + } + + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + adjustStats(level); + } + + @Override + public void adjustStats(int level) { + this.level = level; + evadeSkill = 5 + level; + HT = 90 + level*5; + } + + + + + @Override + public int damageRoll() { + return Random.NormalIntRange(10, (10+level*2)); + } + + @Override + protected boolean act() { + + + return super.act(); + } + + @Override + public int attackProc(Char enemy, int damage) { + if (Random.Int(100) == 0) { + Dungeon.level.drop(Generator.random(), pos).sprite.drop(); + } + + return damage; + } + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/mobs/pets/PET.java b/java/com/hmdzl/spspd/actors/mobs/pets/PET.java new file mode 100644 index 00000000..b802337d --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/pets/PET.java @@ -0,0 +1,381 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs.pets; + +import java.util.ArrayList; +import java.util.HashSet; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.Statistics; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.CorruptGas; +import com.hmdzl.spspd.actors.blobs.ToxicGas; +import com.hmdzl.spspd.actors.blobs.VenomGas; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Burning; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.actors.mobs.npcs.NPC; +import com.hmdzl.spspd.items.Heap; +import com.hmdzl.spspd.items.scrolls.ScrollOfPsionicBlast; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public abstract class PET extends NPC { + + { + HP = HT = 1; + EXP = 0; + + //WANDERING = new Wandering(); + //HUNTING = new Hunting(); + + + flying = true; + hostile = false; + state = HUNTING; + enemy = null; + ally=true; + + properties.add(Property.MINIBOSS); + properties.add(Property.IMMOVABLE); + } + + @Override + public int drRoll(){ + return level; + } + + @Override + public int hitSkill(Char target) { + return level + 10; + } + + public int level; + public int type; + public int experience; + public int cooldown; + public boolean callback = false; + public boolean stay = false; + /* + type + 1 = + 2 = bee + 3 = + 4 = + 5 = + + */ + + private static final String LEVEL = "level"; + private static final String TYPE = "type"; + private static final String EXPERIENCE = "experience"; + private static final String COOLDOWN = "cooldown"; + private static final String CALLBACK = "callback"; + private static final String STAY = "stay"; + + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(LEVEL, level); + bundle.put(TYPE, type); + bundle.put(EXPERIENCE, experience); + bundle.put(COOLDOWN, cooldown); + bundle.put(CALLBACK, callback); + bundle.put(STAY, stay); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + level = bundle.getInt(LEVEL); + type = bundle.getInt(TYPE); + experience = bundle.getInt(EXPERIENCE); + cooldown = bundle.getInt(COOLDOWN); + callback = bundle.getBoolean(CALLBACK); + stay = bundle.getBoolean(STAY); + adjustStats(level); + } + + 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); + } + } + + public void adjustStats(int level) { + } + + public void spawn(int level) { + this.level = level; + adjustStats(level); + } + + @Override + protected boolean act() { + + assignPet(this); + + if (experience >= level*(level+1) && level < 30){ + experience-=level*(level+1); + level++; + GLog.p(Messages.get(this,"levelup")); + adjustStats(level); + + } + + if ( HP 8 + || state == WANDERING) { + + HashSet enemies = new HashSet<>(); + for (Mob mob : Dungeon.level.mobs) { + if (mob.hostile + && Level.fieldOfView[mob.pos] + && Dungeon.level.distance(mob.pos, Dungeon.hero.pos) <= 8 + && mob.state != mob.PASSIVE) { + enemies.add(mob); + } + } + + //go for closest enemy + Char closest = null; + for (Char curr : enemies){ + if (closest == null + || Dungeon.level.distance(pos, curr.pos) < Dungeon.level.distance(pos, closest.pos)){ + closest = curr; + } + } + return closest; + } + return enemy; +} + + @Override + protected boolean getCloser(int target) { + if (stay) { + return false; + } else if (state == WANDERING + || Level.distance(target, Dungeon.hero.pos) > 6) + this.target = target = Dungeon.hero.pos; + return super.getCloser(target); + } + + public int wanderLocation(){ + int newPos = -1; + ArrayList candidates = new ArrayList(); + boolean[] passable = Level.passable; + + for (int n : Level.NEIGHBOURS8) { + int c = pos + n; + if (passable[c] && Actor.findChar(c) == null) { + candidates.add(c); + } + } + + newPos = candidates.size() > 0 ? Random.element(candidates) : -1; + + return newPos; + } + + @Override + public void aggro(Char ch) { + } + + @Override + public void beckon(int cell) { + } + + + private void assignPet(PET pet){ + + Dungeon.hero.petType=pet.type; + Dungeon.hero.petLevel=pet.level; + + Dungeon.hero.petHP=pet.HP; + Dungeon.hero.petExperience=pet.experience; + Dungeon.hero.petCooldown=pet.cooldown; + } + + @Override + public void add( Buff buff ) { + //in other words, can't be directly affected by buffs/debuffs. + } + + + @Override + public boolean interact() { + //int curPos = pos; + //moveSprite( pos, Dungeon.hero.pos ); + //move( Dungeon.hero.pos ); + //Dungeon.hero.sprite.move( Dungeon.hero.pos, curPos ); + //Dungeon.hero.move( curPos ); + //Dungeon.hero.spend( 1 / Dungeon.hero.speed() ); + //Dungeon.hero.busy(); + + + + if (!Dungeon.level.passable[pos]){ + return true; + } + + if (state == SLEEPING) { + state = HUNTING; + } + int curPos = pos; + + moveSprite( pos, Dungeon.hero.pos ); + move( Dungeon.hero.pos ); + + Dungeon.hero.sprite.move( Dungeon.hero.pos, curPos ); + Dungeon.hero.move( curPos ); + + Dungeon.hero.spend( 1 / Dungeon.hero.speed() ); + Dungeon.hero.busy(); + return true; + + } + + private static final HashSet> IMMUNITIES = new HashSet>(); + static { + IMMUNITIES.add( ToxicGas.class ); + IMMUNITIES.add( VenomGas.class ); + IMMUNITIES.add( Burning.class ); + IMMUNITIES.add( ScrollOfPsionicBlast.class ); + IMMUNITIES.add( CorruptGas.class ); + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } + + /*private class Wandering extends Mob.Wandering { + + @Override + public boolean act( boolean enemyInFOV, boolean justAlerted ) { + if ( enemyInFOV ) { + + enemySeen = true; + + notice(); + state = HUNTING; + target = enemy.pos; + + } else { + + enemySeen = false; + + int oldPos = pos; + //always move towards the hero when wandering + if (getCloser( target = Dungeon.hero.pos )) { + //moves 2 tiles at a time when returning to the hero from a distance + if (!Dungeon.level.adjacent(Dungeon.hero.pos, pos)){ + getCloser( target = Dungeon.hero.pos ); + } + spend( 1 / speed() ); + return moveSprite( oldPos, pos ); + } else { + spend( TICK ); + } + + } + return true; + } + + } + + private class Hunting extends Mob.Hunting { + + @Override + public boolean act( boolean enemyInFOV, boolean justAlerted ) { + + enemySeen = enemyInFOV; + if (enemyInFOV && !isCharmedBy( enemy ) && canAttack( enemy )) { + + return doAttack( enemy ); + + } else { + + if (enemyInFOV) { + target = enemy.pos; + } + + int oldPos = pos; + if (enemyInFOV && getCloser( target )) { + + spend( 1 / speed() ); + return moveSprite( oldPos, pos ); + + } else { + + //don't lose a turn due to the transition, immediately act instead + state = WANDERING; + return state.act( false, justAlerted ); + + } + } + } + + }*/ +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/mobs/pets/RedDragon.java b/java/com/hmdzl/spspd/actors/mobs/pets/RedDragon.java new file mode 100644 index 00000000..4109409f --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/pets/RedDragon.java @@ -0,0 +1,140 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs.pets; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.Blob; +import com.hmdzl.spspd.actors.blobs.Fire; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.CharSprite; +import com.hmdzl.spspd.sprites.RedDragonSprite; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Callback; +import com.watabou.utils.Random; + +public class RedDragon extends PET implements Callback{ + + { + //name = "red dragon"; + spriteClass = RedDragonSprite.class; + //flying=true; + state = HUNTING; + level = 1; + type = 4; + cooldown=500; + + properties.add(Property.DRAGON); + + } + private static final float TIME_TO_ZAP = 1f; + + //Frames 1-4 are idle, 5-8 are moving, 9-12 are attack and the last are for death + + //flame on! + //spits fire + //feed meat + + @Override + public void adjustStats(int level) { + this.level = level; + HT = 70 + level*10; + evadeSkill = 5 + level; + } + + + + + @Override + public int damageRoll() { + return Random.NormalIntRange((5+level), (5+level*3)); + } + + @Override + protected boolean act() { + + if (cooldown>0){ + cooldown=Math.max(cooldown-(1+9*((level-1)/19)),0); + if (cooldown==0) {GLog.w(Messages.get(this,"ready"));} + } + + return super.act(); + } + + + @Override + protected boolean canAttack(Char enemy) { + if (cooldown>0){ + return Level.adjacent(pos, enemy.pos); + } else { + return new Ballistica( pos, enemy.pos, Ballistica.MAGIC_BOLT).collisionPos == enemy.pos; + } + } + + @Override + 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) { + ((RedDragonSprite) sprite).zap(enemy.pos); + } else { + zap(); + } + + return !visible; + } + } + + + private void zap() { + spend(TIME_TO_ZAP); + + cooldown=500; + + if (hit(this, enemy, true)) { + + int dmg = damageRoll()*2; + enemy.damage(dmg, this); + + if (Random.Int(dmg) + */ +package com.hmdzl.spspd.actors.mobs.pets; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.sprites.GreyRatSprite; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public class RibbonRat extends PET { + + { + //name = "RibbonRat"; + spriteClass = GreyRatSprite.class; + //flying=true; + state = HUNTING; + level = 1; + type = 21; + + properties.add(Property.BEAST); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + adjustStats(level); + } + + @Override + public void adjustStats(int level) { + this.level = level; + evadeSkill = 5 + level; + HT = 90 + level*5; + } + + + + @Override + public int damageRoll() { + return Random.NormalIntRange(10, (10+level*2)); + } + + @Override + protected boolean act() { + + + return super.act(); + } + + @Override + public int attackProc(Char enemy, int damage) { + if (Random.Int(10) == 0) { + HP= Math.min(HT, HP+damage/10); + } + return damage; + } + +/* + @Override + protected Char chooseEnemy() { + + if(enemy != null && !enemy.isAlive()){ + kills++; + } + + if (enemy == null || !enemy.isAlive()) { + HashSet enemies = new HashSet(); + for (Mob mob : Dungeon.level.mobs) { + if (!(mob instanceof PET) && mob.hostile && Level.fieldOfView[mob.pos]) { + enemies.add(mob); + } + } + + enemy = enemies.size() > 0 ? Random.element(enemies) : null; + } + + return enemy; +} +*/ +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/mobs/pets/Scorpion.java b/java/com/hmdzl/spspd/actors/mobs/pets/Scorpion.java new file mode 100644 index 00000000..33739eda --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/pets/Scorpion.java @@ -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 + */ +package com.hmdzl.spspd.actors.mobs.pets; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Ooze; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.CharSprite; +import com.hmdzl.spspd.sprites.ScorpionSprite; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Random; + +public class Scorpion extends PET { + + { + //name = "scorpion"; + spriteClass = ScorpionSprite.class; + //flying=false; + state = HUNTING; + level = 1; + type = 8; + cooldown=500; + + properties.add(Property.BEAST); + } + + @Override + public void adjustStats(int level) { + this.level = level; + HT = 70 + level*10; + evadeSkill = 5 + level; + } + + + + + @Override + public int damageRoll() { + return Random.NormalIntRange((5+level), (5+level*3)) ; + } + + @Override + protected boolean act() { + + if (cooldown>0){ + cooldown=Math.max(cooldown-(1+9*((level-1)/19)),0); + if (cooldown==0) {GLog.w(Messages.get(this,"ready"));} + } + + + + return super.act(); + } + + @Override + public int attackProc(Char enemy, int damage) { + if (cooldown>0 && Random.Int(10) == 0) { + Buff.affect(enemy, Ooze.class); + } + if (cooldown==0) { + Buff.affect(enemy, Ooze.class); + + sprite.emitter().start(Speck.factory(Speck.HEALING), 0.4f, 1); + sprite.showStatus(CharSprite.POSITIVE,Integer.toString(damage)); + + HP = Math.min(HT, HP+damage); + + Dungeon.hero.sprite.emitter().start(Speck.factory(Speck.HEALING), 0.4f, 1); + Dungeon.hero.sprite.showStatus(CharSprite.POSITIVE,Integer.toString(damage)); + + Dungeon.hero.HP = Math.min(Dungeon.hero.HT, Dungeon.hero.HP+damage); + + damage+=damage; + cooldown=500; + } + + return damage; + } + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/mobs/pets/ShadowDragon.java b/java/com/hmdzl/spspd/actors/mobs/pets/ShadowDragon.java new file mode 100644 index 00000000..d462ce60 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/pets/ShadowDragon.java @@ -0,0 +1,143 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs.pets; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.ShadowDragonSprite; +import com.hmdzl.spspd.sprites.CharSprite; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Callback; +import com.watabou.utils.Random; + +public class ShadowDragon extends PET implements Callback{ + + { + //name = "shadow dragon"; + spriteClass = ShadowDragonSprite.class; + //flying=true; + state = HUNTING; + level = 1; + type = 12; + cooldown=500; + + properties.add(Property.DRAGON); + + } + private static final float TIME_TO_ZAP = 1f; + + //Frames 1-4 are idle, 5-8 are moving, 9-12 are attack and the last are for death + + //flame on! + //spits fire + //feed meat + + @Override + public void adjustStats(int level) { + this.level = level; + HT = 70 + level*10; + evadeSkill = 5 + level; + } + + + + + @Override + public int damageRoll() { + return Random.NormalIntRange((5+level), (5+level*3)); + } + + @Override + protected boolean act() { + + if (cooldown>0){ + cooldown=Math.max(cooldown-(1+9*((level-1)/19)),0); + if (cooldown==0) { + GLog.w(Messages.get(this,"ready")); + } + } + + + + return super.act(); + } + + + @Override + protected boolean canAttack(Char enemy) { + if (cooldown>0){ + return Level.adjacent(pos, enemy.pos); + } else { + return new Ballistica( pos, enemy.pos, Ballistica.MAGIC_BOLT).collisionPos == enemy.pos; + } + } + + @Override + 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) { + ((ShadowDragonSprite) sprite).zap(enemy.pos); + } else { + zap(); + } + + return !visible; + } + } + + + private void zap() { + spend(TIME_TO_ZAP); + + cooldown=500; + + if (hit(this, enemy, true)) { + + int dmg = damageRoll()*3; + enemy.damage(dmg, this); + + } else { + enemy.sprite.showStatus(CharSprite.NEUTRAL, enemy.defenseVerb()); + } + + } + + public void onZapComplete() { + zap(); + next(); + } + + @Override + public void call() { + next(); + } + + + + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/mobs/pets/Snake.java b/java/com/hmdzl/spspd/actors/mobs/pets/Snake.java new file mode 100644 index 00000000..b72aa0f1 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/pets/Snake.java @@ -0,0 +1,100 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs.pets; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Poison; +import com.hmdzl.spspd.sprites.SnakeSprite; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public class Snake extends PET { + + { + //name = "Snake"; + spriteClass = SnakeSprite.class; + //flying=true; + state = HUNTING; + level = 1; + type = 16; + + properties.add(Property.BEAST); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + adjustStats(level); + } + + @Override + public void adjustStats(int level) { + this.level = level; + evadeSkill = 5 + level; + HT = 90 + level*5; + } + + + + + @Override + public int damageRoll() { + return Random.NormalIntRange(10, (10+level*2)); + } + + @Override + protected boolean act() { + + + return super.act(); + } + + @Override + public int attackProc(Char enemy, int damage) { + if (Random.Int(10) == 0) { + Buff.affect(enemy, Poison.class).set( + Random.Int(5, 7) * Poison.durationFactor(enemy)); + } + + return damage; + } + +/* + @Override + protected Char chooseEnemy() { + + if(enemy != null && !enemy.isAlive()){ + kills++; + } + + if (enemy == null || !enemy.isAlive()) { + HashSet enemies = new HashSet(); + for (Mob mob : Dungeon.level.mobs) { + if (!(mob instanceof PET) && mob.hostile && Level.fieldOfView[mob.pos]) { + enemies.add(mob); + } + } + + enemy = enemies.size() > 0 ? Random.element(enemies) : null; + } + + return enemy; +} +*/ +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/mobs/pets/Spider.java b/java/com/hmdzl/spspd/actors/mobs/pets/Spider.java new file mode 100644 index 00000000..9737c44b --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/pets/Spider.java @@ -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 + */ +package com.hmdzl.spspd.actors.mobs.pets; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.Blob; +import com.hmdzl.spspd.actors.blobs.Web; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Poison; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.SpiderSprite; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Random; + +public class Spider extends PET { + + { + //name = "spider"; + spriteClass = SpiderSprite.class; + //flying=false; + state = HUNTING; + level = 1; + type = 1; + cooldown=500; + + properties.add(Property.BEAST); + + } + + @Override + public void adjustStats(int level) { + this.level = level; + HT = 70 + level*10; + evadeSkill = 5 + level; + } + + + + + @Override + public int damageRoll() { + return Random.NormalIntRange((5+level), (5+level*3)) ; + } + + @Override + protected boolean act() { + + if (cooldown>0){ + cooldown=Math.max(cooldown-(1+9*((level-1)/19)),0); + if (cooldown==0) {GLog.w(Messages.get(this,"ready"));} + } + + + + return super.act(); + } + + @Override + public int attackProc(Char enemy, int damage) { + if (cooldown>0 && Random.Int(10) == 0) { + Buff.affect(enemy, Poison.class).set(Random.Int(7, 9) * Poison.durationFactor(enemy)); + GameScene.add(Blob.seed(enemy.pos, Random.Int(5, 7), Web.class)); + } + if (cooldown==0) { + Buff.affect(enemy, Poison.class).set(Random.Int(10, 25) * Poison.durationFactor(enemy)); + GameScene.add(Blob.seed(enemy.pos, Random.Int(8, 9), Web.class)); + damage+=damage; + cooldown=500; + } + + return damage; + } + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/mobs/pets/Stone.java b/java/com/hmdzl/spspd/actors/mobs/pets/Stone.java new file mode 100644 index 00000000..f78e1214 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/pets/Stone.java @@ -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 + */ +package com.hmdzl.spspd.actors.mobs.pets; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Paralysis; +import com.hmdzl.spspd.sprites.StoneSprite; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public class Stone extends PET { + + { + //name = "Stone"; + spriteClass = StoneSprite.class; + //flying=true; + state = HUNTING; + level = 1; + type = 18; + + properties.add(Property.ELEMENT); + } + + + + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + adjustStats(level); + } + + @Override + public void adjustStats(int level) { + this.level = level; + evadeSkill = 5 + level; + HT = 90 + level*5; + } + + + + + @Override + public int damageRoll() { + return Random.NormalIntRange(10, (10+level*2)); + } + + @Override + protected boolean act() { + + + return super.act(); + } + + @Override + public int attackProc(Char enemy, int damage) { + if (Random.Int(20) == 0) { + Buff.affect(enemy, Paralysis.class, 3f); + } + + return damage; + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/mobs/pets/SugarplumFairy.java b/java/com/hmdzl/spspd/actors/mobs/pets/SugarplumFairy.java new file mode 100644 index 00000000..d3eed201 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/pets/SugarplumFairy.java @@ -0,0 +1,167 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs.pets; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.ResultDescriptions; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.effects.particles.SparkParticle; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.CharSprite; +import com.hmdzl.spspd.sprites.SugarplumFairySprite; +import com.hmdzl.spspd.utils.GLog; + +import com.watabou.noosa.Camera; +import com.watabou.utils.Callback; +import com.watabou.utils.Random; + +public class SugarplumFairy extends PET implements Callback{ + + { + //name = "sugarplum fairy"; + spriteClass = SugarplumFairySprite.class; + //flying=true; + state = HUNTING; + level = 1; + type = 11; + cooldown=500; + + properties.add(Property.UNKNOW); + } + private static final float TIME_TO_ZAP = 2f; + + @Override + protected float attackDelay() { + return 0.5f; + } + + //Frames 0,2 are idle, 0,1,2 are moving, 0,3,4,1 are attack and 5,6,7 are for death + + + + + + @Override + public void adjustStats(int level) { + this.level = level; + HT = 70 + level*10; + evadeSkill = 5 + level; + } + + + + + @Override + public int damageRoll() { + return Random.NormalIntRange(evadeSkill/2, evadeSkill); + } + + @Override + protected boolean act() { + + if (cooldown>0){ + cooldown=Math.max(cooldown-(1+9*((level-1)/19)),0); + if (cooldown==0) {GLog.w(Messages.get(this,"ready"));} + } + + if (cooldown==0 && Level.adjacent(pos, Dungeon.hero.pos) && Random.Int(1)==0){ + + int bless = Random.Int(1+9*((level-1)/19)); + + Dungeon.hero.sprite.emitter().start(Speck.factory(Speck.HEALING), 0.4f, 1); + Dungeon.hero.sprite.showStatus(CharSprite.POSITIVE,Integer.toString(bless)); + + Dungeon.hero.HP = Math.min(Dungeon.hero.HT, Dungeon.hero.HP+bless); + + if (Random.Int(20)==0){ + Dungeon.hero.HT += 1; + Dungeon.hero.sprite.showStatus(CharSprite.POSITIVE, Messages.get(this,"ht")); + cooldown=500; + } + } + + + + return super.act(); + } + + + @Override + protected boolean canAttack(Char enemy) { + return new Ballistica( pos, enemy.pos, Ballistica.MAGIC_BOLT).collisionPos == enemy.pos; + + } + + + + @Override + 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) { + ((SugarplumFairySprite) sprite).zap(enemy.pos); + } + + spend(TIME_TO_ZAP); + cooldown=500; + + if (hit(this, enemy, true)) { + int dmg = damageRoll()*2; + if (Level.water[enemy.pos] && !enemy.flying) { + dmg *= 1.5f; + } + enemy.damage(dmg, this); + + 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( Messages.format(ResultDescriptions.NAMED)); + //GLog.n(TXT_LIGHTNING_KILLED, name); + } + } + } else { + enemy.sprite + .showStatus(CharSprite.NEUTRAL, enemy.defenseVerb()); + } + + return !visible; + } + } + + + + @Override + public void call() { + next(); + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/mobs/pets/Velocirooster.java b/java/com/hmdzl/spspd/actors/mobs/pets/Velocirooster.java new file mode 100644 index 00000000..b2389930 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/pets/Velocirooster.java @@ -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 + */ +package com.hmdzl.spspd.actors.mobs.pets; + +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.VelociroosterSprite; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Random; + +public class Velocirooster extends PET { + + { + //name = "velocirooster"; + spriteClass = VelociroosterSprite.class; + //flying=false; + state = HUNTING; + level = 1; + type = 3; + cooldown=500; + + properties.add(Property.BEAST); + + } + + @Override + public void adjustStats(int level) { + this.level = level; + HT = 70 + level*10; + evadeSkill = 5 + level; + } + + + + @Override + public int damageRoll() { + + int dmg=0; + if (cooldown==0){ + dmg=Random.NormalIntRange((5+level)*5/2, (5+level*3)*2); + cooldown=500; + } else { + dmg=Random.NormalIntRange((5+level), (5+level*3)) ; + } + return dmg; + + } + + @Override + protected boolean act() { + + if (cooldown>0){ + cooldown=Math.max(cooldown-(1+9*((level-1)/19)),0); + if (cooldown==0) {GLog.w(Messages.get(this,"ready"));} + } + + + + return super.act(); + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/mobs/pets/VioletDragon.java b/java/com/hmdzl/spspd/actors/mobs/pets/VioletDragon.java new file mode 100644 index 00000000..0b35f190 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/pets/VioletDragon.java @@ -0,0 +1,146 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs.pets; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Poison; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.CharSprite; +import com.hmdzl.spspd.sprites.VioletDragonSprite; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Callback; +import com.watabou.utils.Random; + +public class VioletDragon extends PET implements Callback{ + + { + //name = "violet dragon"; + spriteClass = VioletDragonSprite.class; + //flying=true; + state = HUNTING; + level = 1; + type = 6; + cooldown=500; + + properties.add(Property.DRAGON); + + } + private static final float TIME_TO_ZAP = 1f; + + //Frames 1-4 are idle, 5-8 are moving, 9-12 are attack and the last are for death + + //flame on! + //spits fire + //feed meat + + @Override + protected float attackDelay() { + return 0.8f; + } + + @Override + public void adjustStats(int level) { + this.level = level; + HT = 70 + level*10; + evadeSkill = 5 + level; + } + + + + + @Override + public int damageRoll() { + return Random.NormalIntRange((5+level), (5+level*3)); + } + + @Override + protected boolean act() { + + if (cooldown>0){ + cooldown=Math.max(cooldown-(1+9*((level-1)/19)),0); + if (cooldown==0) {GLog.w(Messages.get(this,"ready"));} + } + + + + return super.act(); + } + + + @Override + protected boolean canAttack(Char enemy) { + if (cooldown>0){ + return Level.adjacent(pos, enemy.pos); + } else { + return new Ballistica( pos, enemy.pos, Ballistica.MAGIC_BOLT).collisionPos == enemy.pos; + } + } + + @Override + 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) { + ((VioletDragonSprite) sprite).zap(enemy.pos); + } else { + zap(); + } + + return !visible; + } + } + + + private void zap() { + spend(TIME_TO_ZAP); + + cooldown=500; + + if (hit(this, enemy, true)) { + + int dmg = damageRoll()*2; + enemy.damage(dmg, this); + + Buff.affect(enemy,Poison.class).set(Poison.durationFactor(enemy) * (level + 1)); + + } else { + enemy.sprite.showStatus(CharSprite.NEUTRAL, enemy.defenseVerb()); + } + + } + + public void onZapComplete() { + zap(); + next(); + } + + @Override + public void call() { + next(); + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/actors/mobs/pets/YearPet.java b/java/com/hmdzl/spspd/actors/mobs/pets/YearPet.java new file mode 100644 index 00000000..43fdcb50 --- /dev/null +++ b/java/com/hmdzl/spspd/actors/mobs/pets/YearPet.java @@ -0,0 +1,73 @@ +/* + * 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 + */ +package com.hmdzl.spspd.actors.mobs.pets; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.sprites.BeastYearSprite; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public class YearPet extends PET { + + { + //name = "year"; + spriteClass = BeastYearSprite.class; + //flying=true; + state = HUNTING; + level = 1; + type = 22; + + properties.add(Property.BEAST); + + } + + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + adjustStats(level); + } + + @Override + public void adjustStats(int level) { + this.level = level; + evadeSkill = 50; + HT = 1000; + } + + + + + @Override + public int damageRoll() { + return Random.NormalIntRange(10, (10+level*2)); + } + + @Override + protected boolean act() { + + + return super.act(); + } + + @Override + public int attackProc(Char enemy, int damage) { + return damage; + } + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/effects/BadgeBanner.java b/java/com/hmdzl/spspd/effects/BadgeBanner.java new file mode 100644 index 00000000..ad85f557 --- /dev/null +++ b/java/com/hmdzl/spspd/effects/BadgeBanner.java @@ -0,0 +1,287 @@ +/* + * 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 + */ +package com.hmdzl.spspd.effects; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.Game; +import com.watabou.noosa.Image; +import com.watabou.noosa.TextureFilm; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.PointF; + +public class BadgeBanner extends Image { + + private enum State { + FADE_IN, STATIC, FADE_OUT + }; + + private State state; + + private static final float DEFAULT_SCALE = 3; + + private static final float FADE_IN_TIME = 0.2f; + private static final float STATIC_TIME = 1f; + private static final float FADE_OUT_TIME = 1.0f; + + private int index; + private float time; + + private static TextureFilm atlas; + + private static BadgeBanner current; + + private BadgeBanner(int index) { + + super(Assets.BADGES); + + if (atlas == null) { + atlas = new TextureFilm(texture, 16, 16); + } + + this.index = index; + + frame(atlas.get(index)); + origin.set(width / 2, height / 2); + + alpha(0); + scale.set(2 * DEFAULT_SCALE); + + state = State.FADE_IN; + time = FADE_IN_TIME; + + Sample.INSTANCE.play(Assets.SND_BADGE); + } + + @Override + public void update() { + super.update(); + + time -= Game.elapsed; + if (time >= 0) { + + switch (state) { + case FADE_IN: + float p = time / FADE_IN_TIME; + scale.set((1 + p) * DEFAULT_SCALE); + alpha(1 - p); + break; + case STATIC: + break; + case FADE_OUT: + alpha(time / FADE_OUT_TIME); + break; + } + + } else { + + switch (state) { + case FADE_IN: + time = STATIC_TIME; + state = State.STATIC; + scale.set(DEFAULT_SCALE); + alpha(1); + highlight(this, index); + break; + case STATIC: + time = FADE_OUT_TIME; + state = State.FADE_OUT; + break; + case FADE_OUT: + killAndErase(); + break; + } + + } + } + + @Override + public void kill() { + if (current == this) { + current = null; + } + super.kill(); + } + + public static void highlight(Image image, int index) { + + PointF p = new PointF(); + + switch (index) { + case 0: + case 1: + case 2: + case 3: + p.offset(7, 3); + break; + case 4: + case 5: + case 6: + case 7: + p.offset(6, 5); + break; + case 8: + case 9: + case 10: + case 11: + p.offset(6, 3); + break; + case 12: + case 13: + case 14: + case 15: + p.offset(7, 4); + break; + case 16: + p.offset(6, 3); + break; + case 17: + p.offset(5, 4); + break; + case 18: + p.offset(7, 3); + break; + case 20: + p.offset(7, 3); + break; + case 21: + p.offset(7, 3); + break; + case 22: + p.offset(6, 4); + break; + case 23: + p.offset(4, 5); + break; + case 24: + p.offset(6, 4); + break; + case 25: + p.offset(6, 5); + break; + case 26: + p.offset(5, 5); + break; + case 27: + p.offset(6, 4); + break; + case 28: + p.offset(3, 5); + break; + case 29: + p.offset(5, 4); + break; + case 30: + p.offset(5, 4); + break; + case 31: + p.offset(5, 5); + break; + case 32: + case 33: + p.offset(7, 4); + break; + case 34: + p.offset(6, 4); + break; + case 35: + p.offset(6, 4); + break; + case 36: + p.offset(6, 5); + break; + case 37: + p.offset(4, 4); + break; + case 38: + p.offset(5, 5); + break; + case 39: + p.offset(5, 4); + break; + case 40: + case 41: + case 42: + case 43: + p.offset(5, 4); + break; + case 44: + case 45: + case 46: + case 47: + p.offset(5, 5); + break; + case 48: + case 49: + case 50: + case 51: + p.offset(7, 4); + break; + case 52: + case 53: + case 54: + case 55: + p.offset(4, 4); + break; + case 56: + p.offset(3, 7); + break; + case 57: + p.offset(4, 5); + break; + case 58: + p.offset(6, 4); + break; + case 59: + p.offset(7, 4); + break; + case 60: + case 61: + case 62: + case 63: + p.offset(4, 4); + break; + } + + p.x *= image.scale.x; + p.y *= image.scale.y; + p.offset(-image.origin.x * (image.scale.x - 1), -image.origin.y + * (image.scale.y - 1)); + p.offset(image.point()); + + Speck star = new Speck(); + star.reset(0, p.x, p.y, Speck.DISCOVER); + star.camera = image.camera(); + image.parent.add(star); + } + + public static BadgeBanner show(int image) { + if (current != null) { + current.killAndErase(); + } + return (current = new BadgeBanner(image)); + } + + public static Image image(int index) { + Image image = new Image(Assets.BADGES); + if (atlas == null) { + atlas = new TextureFilm(image.texture, 16, 16); + } + image.frame(atlas.get(index)); + return image; + } +} diff --git a/java/com/hmdzl/spspd/effects/BannerSprites.java b/java/com/hmdzl/spspd/effects/BannerSprites.java new file mode 100644 index 00000000..875e27c3 --- /dev/null +++ b/java/com/hmdzl/spspd/effects/BannerSprites.java @@ -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 + */ +package com.hmdzl.spspd.effects; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.Image; + +public class BannerSprites { + + public enum Type { + PIXEL_DUNGEON, BOSS_SLAIN, GAME_OVER, SELECT_YOUR_HERO, PIXEL_DUNGEON_SIGNS, CLEARED + }; + + public static Image get(Type type) { + Image icon = new Image(Assets.BANNERS); + switch (type) { + case PIXEL_DUNGEON: + icon.frame(icon.texture.uvRect(0, 0, 128, 70)); + break; + case BOSS_SLAIN: + icon.frame(icon.texture.uvRect(0, 70, 128, 105)); + break; + case GAME_OVER: + icon.frame(icon.texture.uvRect(0, 105, 128, 140)); + break; + case SELECT_YOUR_HERO: + icon.frame(icon.texture.uvRect(0, 140, 128, 161)); + break; + case PIXEL_DUNGEON_SIGNS: + icon.frame(icon.texture.uvRect(0, 161, 128, 218)); + break; + case CLEARED: + icon.frame(icon.texture.uvRect(0, 230, 128, 250)); + break; + } + return icon; + } +} diff --git a/java/com/hmdzl/spspd/effects/Beam.java b/java/com/hmdzl/spspd/effects/Beam.java new file mode 100644 index 00000000..77450323 --- /dev/null +++ b/java/com/hmdzl/spspd/effects/Beam.java @@ -0,0 +1,102 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2015 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.effects; + +import javax.microedition.khronos.opengles.GL10; + +import android.opengl.GLES20; + +import com.watabou.noosa.Game; +import com.watabou.noosa.Image; +import com.watabou.noosa.audio.Sample; +import com.hmdzl.spspd.Assets; +import com.watabou.utils.PointF; + +public class Beam extends Image { + + private static final double A = 180 / Math.PI; + + private float duration; + + private float timeLeft; + + private Beam(PointF s, PointF e, Effects.Type asset, float duration) { + super( Effects.get( asset ) ); + + origin.set( 0, height / 2 ); + + x = s.x - origin.x; + y = s.y - origin.y; + + float dx = e.x - s.x; + float dy = e.y - s.y; + angle = (float)(Math.atan2( dy, dx ) * A); + scale.x = (float)Math.sqrt( dx * dx + dy * dy ) / width; + + Sample.INSTANCE.play( Assets.SND_RAY ); + + timeLeft = this.duration = duration; + } + + public static class DeathRay extends Beam{ + public DeathRay(PointF s, PointF e){ + super(s, e, Effects.Type.DEATH_RAY, 0.5f); + } + } + + public static class LightRay extends Beam{ + public LightRay(PointF s, PointF e){ + super(s, e, Effects.Type.LIGHT_RAY, 1f); + } + } + + public static class HealthRay extends Beam{ + public HealthRay(PointF s, PointF e){ + super(s, e, Effects.Type.HEALTH_RAY, 0.75f); + } + } + + public static class WaterRay extends Beam{ + public WaterRay(PointF s, PointF e){ + super(s, e, Effects.Type.WATER_RAY, 0.75f); + } + } + + @Override + public void update() { + super.update(); + + float p = timeLeft / duration; + alpha( p ); + scale.set( scale.x, p ); + + if ((timeLeft -= Game.elapsed) <= 0) { + killAndErase(); + } + } + + @Override + public void draw() { + GLES20.glBlendFunc( GL10.GL_SRC_ALPHA, GL10.GL_ONE ); + super.draw(); + GLES20.glBlendFunc( GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA ); + } +} diff --git a/java/com/hmdzl/spspd/effects/BlobEmitter.java b/java/com/hmdzl/spspd/effects/BlobEmitter.java new file mode 100644 index 00000000..d52122ff --- /dev/null +++ b/java/com/hmdzl/spspd/effects/BlobEmitter.java @@ -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 + */ +package com.hmdzl.spspd.effects; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.DungeonTilemap; +import com.hmdzl.spspd.actors.blobs.Blob; +import com.watabou.noosa.particles.Emitter; +import com.watabou.utils.Random; + +public class BlobEmitter extends Emitter { + + private static final int WIDTH = Blob.WIDTH; + private static final int LENGTH = Blob.LENGTH; + + private Blob blob; + + public BlobEmitter(Blob blob) { + + super(); + + this.blob = blob; + blob.use(this); + } + + @Override + protected void emit(int index) { + + if (blob.volume <= 0) { + return; + } + + int[] map = blob.cur; + float size = DungeonTilemap.SIZE; + + for (int i = 0; i < LENGTH; i++) { + if (map[i] > 0 && Dungeon.visible[i]) { + float x = ((i % WIDTH) + Random.Float()) * size; + float y = ((i / WIDTH) + Random.Float()) * size; + factory.emit(this, index, x, y); + } + } + } +} diff --git a/java/com/hmdzl/spspd/effects/CellEmitter.java b/java/com/hmdzl/spspd/effects/CellEmitter.java new file mode 100644 index 00000000..1193f4b6 --- /dev/null +++ b/java/com/hmdzl/spspd/effects/CellEmitter.java @@ -0,0 +1,57 @@ +/* + * 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 + */ +package com.hmdzl.spspd.effects; + +import com.hmdzl.spspd.DungeonTilemap; +import com.hmdzl.spspd.scenes.GameScene; +import com.watabou.noosa.particles.Emitter; +import com.watabou.utils.PointF; + +public class CellEmitter { + + public static Emitter get(int cell) { + + PointF p = DungeonTilemap.tileToWorld(cell); + + Emitter emitter = GameScene.emitter(); + emitter.pos(p.x, p.y, DungeonTilemap.SIZE, DungeonTilemap.SIZE); + + return emitter; + } + + public static Emitter center(int cell) { + + PointF p = DungeonTilemap.tileToWorld(cell); + + Emitter emitter = GameScene.emitter(); + emitter.pos(p.x + DungeonTilemap.SIZE / 2, p.y + DungeonTilemap.SIZE + / 2); + + return emitter; + } + + public static Emitter bottom(int cell) { + + PointF p = DungeonTilemap.tileToWorld(cell); + + Emitter emitter = GameScene.emitter(); + emitter.pos(p.x, p.y + DungeonTilemap.SIZE, DungeonTilemap.SIZE, 0); + + return emitter; + } +} diff --git a/java/com/hmdzl/spspd/effects/Chains.java b/java/com/hmdzl/spspd/effects/Chains.java new file mode 100644 index 00000000..789b5d99 --- /dev/null +++ b/java/com/hmdzl/spspd/effects/Chains.java @@ -0,0 +1,101 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2015 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.effects; + +import com.hmdzl.spspd.DungeonTilemap; +import com.watabou.noosa.Game; +import com.watabou.noosa.Group; +import com.watabou.noosa.Image; +import com.watabou.utils.Callback; +import com.watabou.utils.PointF; + +public class Chains extends Group { + + private static final double A = 180 / Math.PI; + + private float spent = 0f; + private float duration; + + private Callback callback; + + private Image[] chains; + private int numChains; + private float distance; + private float rotation = 0; + + private PointF from, to; + + public Chains(int from, int to, Callback callback){ + this(DungeonTilemap.tileCenterToWorld(from), + DungeonTilemap.tileCenterToWorld(to), + callback); + } + + public Chains(PointF from, PointF to, Callback callback){ + super(); + + this.callback = callback; + + this.from = from; + this.to = to; + + float dx = to.x - from.x; + float dy = to.y - from.y; + distance = (float)Math.hypot(dx, dy); + + + duration = distance/300f + 0.1f; + + rotation = (float)(Math.atan2( dy, dx ) * A) + 90f; + + numChains = Math.round(distance/6f)+1; + + chains = new Image[numChains]; + for (int i = 0; i < chains.length; i++){ + chains[i] = new Image(Effects.get(Effects.Type.CHAIN)); + chains[i].angle = rotation; + chains[i].origin.set( chains[i].width()/ 2, chains[i].height() ); + add(chains[i]); + } + } + + @Override + public void update() { + if ((spent += Game.elapsed) > duration) { + + killAndErase(); + if (callback != null) { + callback.call(); + } + + } else { + float dx = to.x - from.x; + float dy = to.y - from.y; + for (int i = 0; i < chains.length; i++) { + chains[i].center(new PointF( + from.x + ((dx * (i / (float)chains.length)) * (spent/duration)), + from.y + ((dy * (i / (float)chains.length)) * (spent/duration)) + )); + } + } + } + +} diff --git a/java/com/hmdzl/spspd/effects/CheckedCell.java b/java/com/hmdzl/spspd/effects/CheckedCell.java new file mode 100644 index 00000000..c3027864 --- /dev/null +++ b/java/com/hmdzl/spspd/effects/CheckedCell.java @@ -0,0 +1,49 @@ +/* + * 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 + */ +package com.hmdzl.spspd.effects; + +import com.hmdzl.spspd.DungeonTilemap; +import com.watabou.gltextures.TextureCache; +import com.watabou.noosa.Game; +import com.watabou.noosa.Image; + +public class CheckedCell extends Image { + + private float alpha; + + public CheckedCell(int pos) { + super(TextureCache.createSolid(0xFF55AAFF)); + + origin.set(0.5f); + + point(DungeonTilemap.tileToWorld(pos).offset(DungeonTilemap.SIZE / 2, + DungeonTilemap.SIZE / 2)); + + alpha = 0.8f; + } + + @Override + public void update() { + if ((alpha -= Game.elapsed) > 0) { + alpha(alpha); + scale.set(DungeonTilemap.SIZE * alpha); + } else { + killAndErase(); + } + } +} diff --git a/java/com/hmdzl/spspd/effects/CircleArc.java b/java/com/hmdzl/spspd/effects/CircleArc.java new file mode 100644 index 00000000..50dd64e9 --- /dev/null +++ b/java/com/hmdzl/spspd/effects/CircleArc.java @@ -0,0 +1,191 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2018 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ + +package com.hmdzl.spspd.effects; + +import com.watabou.gltextures.SmartTexture; +import com.watabou.gltextures.TextureCache; +import com.watabou.glwrap.Blending; +import com.watabou.noosa.Game; +import com.watabou.noosa.Group; +import com.watabou.noosa.NoosaScript; +import com.watabou.noosa.Visual; +import com.watabou.utils.PointF; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.FloatBuffer; +import java.nio.ShortBuffer; + +public class CircleArc extends Visual { + + private float duration = 0; + private float lifespan; + + //1f is an entire 360 degree sweep + private float sweep; + private boolean dirty; + + private boolean lightMode = true; + + private SmartTexture texture; + + private FloatBuffer vertices; + private ShortBuffer indices; + + private int nTris; + private float rad; + + //more triangles means a more precise visual + public CircleArc( int triangles, float radius ) { + + super( 0, 0, 0, 0 ); + + texture = TextureCache.createSolid( 0xFFFFFFFF ); + + this.nTris = triangles; + this.rad = radius; + + vertices = ByteBuffer. + allocateDirect( (nTris * 2 + 1) * 4 * (Float.SIZE / 8) ). + order( ByteOrder.nativeOrder() ). + asFloatBuffer(); + + indices = ByteBuffer. + allocateDirect( nTris * 3 * Short.SIZE / 8 ). + order( ByteOrder.nativeOrder() ). + asShortBuffer(); + + sweep = 1f; + updateTriangles(); + } + + public CircleArc color( int color, boolean lightMode ) { + this.lightMode = lightMode; + hardlight( color ); + + return this; + } + + public CircleArc show( Visual visual, float duration ) { + point( visual.center() ); + visual.parent.addToBack( this ); + + lifespan = this.duration = duration; + + return this; + } + + public CircleArc show(Group parent, PointF pos, float duration ) { + point( pos ); + parent.add( this ); + + lifespan = this.duration = duration; + + return this; + } + + public void setSweep( float sweep ){ + this.sweep = sweep; + dirty = true; + } + + private void updateTriangles(){ + + dirty = false; + float v[] = new float[4]; + + indices.position( 0 ); + vertices.position( 0 ); + + v[0] = 0; + v[1] = 0; + v[2] = 0.25f; + v[3] = 0; + vertices.put( v ); + + v[2] = 0.75f; + v[3] = 0; + + //starting position is very top by default, use angle to adjust this. + double start = 2 * (Math.PI - Math.PI*sweep) - Math.PI/2.0; + + for (int i = 0; i < nTris; i++) { + + double a = start + i * Math.PI * 2 / nTris * sweep; + v[0] = (float)Math.cos( a ) * rad; + v[1] = (float)Math.sin( a ) * rad; + vertices.put( v ); + + a += 3.1415926f * 2 / nTris * sweep; + v[0] = (float)Math.cos( a ) * rad; + v[1] = (float)Math.sin( a ) * rad; + vertices.put( v ); + + indices.put( (short)0 ); + indices.put( (short)(1 + i * 2) ); + indices.put( (short)(2 + i * 2) ); + } + + indices.position( 0 ); + } + + @Override + public void update() { + super.update(); + + if (duration > 0) { + if ((lifespan -= Game.elapsed) > 0) { + sweep = lifespan/duration; + dirty = true; + + } else { + killAndErase(); + } + } + } + + @Override + public void draw() { + + super.draw(); + + if (dirty) { + updateTriangles(); + } + + if (lightMode) Blending.setLightMode(); + + NoosaScript script = NoosaScript.get(); + + texture.bind(); + + script.uModel.valueM4( matrix ); + script.lighting( + rm, gm, bm, am, + ra, ga, ba, aa ); + + script.camera( camera ); + script.drawElements( vertices, indices, nTris * 3 ); + + if (lightMode) Blending.setNormalMode(); + } +} diff --git a/java/com/hmdzl/spspd/effects/DarkBlock.java b/java/com/hmdzl/spspd/effects/DarkBlock.java new file mode 100644 index 00000000..2e7f88f6 --- /dev/null +++ b/java/com/hmdzl/spspd/effects/DarkBlock.java @@ -0,0 +1,67 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2015 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.effects; + +import com.hmdzl.spspd.sprites.CharSprite; +import com.watabou.noosa.Game; +import com.watabou.noosa.Gizmo; + +public class DarkBlock extends Gizmo{ + private float phase; + private CharSprite target; + + public DarkBlock( CharSprite target ) { + super(); + + this.target = target; + } + + @Override + public void update() { + super.update(); + + //target.brightness(0.4f); + + if ((phase += Game.elapsed * 2) < 1) { + target.tint(0.83f, 1.17f, 1.33f, phase * 0.4f); + } else { + target.tint(0.83f, 1.17f, 1.33f, 0.4f); + } + + } + + public void lighten() { + + target.resetColor(); + killAndErase(); + + } + + public static DarkBlock darken( CharSprite sprite ) { + + DarkBlock darkBlock = new DarkBlock( sprite ); + if (sprite.parent != null) + sprite.parent.add( darkBlock ); + + return darkBlock; + } + +} diff --git a/java/com/hmdzl/spspd/effects/DeathRay.java b/java/com/hmdzl/spspd/effects/DeathRay.java new file mode 100644 index 00000000..e4082dfa --- /dev/null +++ b/java/com/hmdzl/spspd/effects/DeathRay.java @@ -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 + */ +package com.hmdzl.spspd.effects; + +import javax.microedition.khronos.opengles.GL10; + +import android.opengl.GLES20; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.Game; +import com.watabou.noosa.Image; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.PointF; + +public class DeathRay extends Image { + + private static final double A = 180 / Math.PI; + + private static final float DURATION = 0.5f; + + private float timeLeft; + + public DeathRay(PointF s, PointF e) { + super(Effects.get(Effects.Type.DEATH_RAY)); + + origin.set(0, height / 2); + + x = s.x - origin.x; + y = s.y - origin.y; + + float dx = e.x - s.x; + float dy = e.y - s.y; + angle = (float) (Math.atan2(dy, dx) * A); + scale.x = (float) Math.sqrt(dx * dx + dy * dy) / width; + + Sample.INSTANCE.play(Assets.SND_RAY); + + timeLeft = DURATION; + } + + @Override + public void update() { + super.update(); + + float p = timeLeft / DURATION; + alpha(p); + scale.set(scale.x, p); + + if ((timeLeft -= Game.elapsed) <= 0) { + killAndErase(); + } + } + + @Override + public void draw() { + GLES20.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE); + super.draw(); + GLES20.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA); + } +} diff --git a/java/com/hmdzl/spspd/effects/Degradation.java b/java/com/hmdzl/spspd/effects/Degradation.java new file mode 100644 index 00000000..495172dc --- /dev/null +++ b/java/com/hmdzl/spspd/effects/Degradation.java @@ -0,0 +1,119 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 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 + */ +package com.hmdzl.spspd.effects; + +import javax.microedition.khronos.opengles.GL10; + +import android.opengl.GLES20; + +import com.watabou.noosa.Group; +import com.watabou.noosa.particles.PixelParticle; +import com.watabou.utils.PointF; +import com.watabou.utils.Random; + +public class Degradation extends Group { + + private static int[] WEAPON = { +2, -2, +1, -1, 0, 0, -1, +1, -2, +2, -2, + 0, 0, +2 }; + + private static int[] ARMOR = { -2, -1, -1, -1, +1, -1, +2, -1, -2, 0, -1, + 0, 0, 0, +1, 0, +2, 0, -1, +1, +1, +1, -1, +2, 0, +2, +1, +2 }; + + private static int[] RING = { 0, -1, -1, 0, 0, 0, +1, 0, -1, +1, +1, +1, + -1, +2, 0, +2, +1, +2 }; + + private static int[] WAND = { +2, -2, +1, -1, 0, 0, -1, +1, -2, +2, +1, -2, + +2, -1 }; + + public static Degradation weapon(PointF p) { + return new Degradation(p, WEAPON); + } + + public static Degradation armor(PointF p) { + return new Degradation(p, ARMOR); + } + + public static Degradation ring(PointF p) { + return new Degradation(p, RING); + } + + public static Degradation wand(PointF p) { + return new Degradation(p, WAND); + } + + private Degradation(PointF p, int[] matrix) { + + for (int i = 0; i < matrix.length; i += 2) { + add(new Speck(p.x, p.y, matrix[i], matrix[i + 1])); + add(new Speck(p.x, p.y, matrix[i], matrix[i + 1])); + } + } + + @Override + public void update() { + super.update(); + if (countLiving() == 0) { + killAndErase(); + } + } + + @Override + public void draw() { + GLES20.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE); + super.draw(); + GLES20.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA); + } + + public static class Speck extends PixelParticle { + + private static final int COLOR = 0xFF4422; + private static final int SIZE = 3; + + public Speck(float x0, float y0, int mx, int my) { + + super(); + color(COLOR); + + float x1 = x0 + mx * SIZE; + float y1 = y0 + my * SIZE; + + PointF p = new PointF().polar(Random.Float(2 * PointF.PI), 8); + x0 += p.x; + y0 += p.y; + + float dx = x1 - x0; + float dy = y1 - y0; + + x = x0; + y = y0; + speed.set(dx, dy); + acc.set(-dx / 4, -dy / 4); + + left = lifespan = 2f; + } + + @Override + public void update() { + super.update(); + + am = 1 - Math.abs(left / lifespan - 0.5f) * 2; + am *= am; + size(am * SIZE); + } + } +} diff --git a/java/com/hmdzl/spspd/effects/Effects.java b/java/com/hmdzl/spspd/effects/Effects.java new file mode 100644 index 00000000..c7efe8d9 --- /dev/null +++ b/java/com/hmdzl/spspd/effects/Effects.java @@ -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 + */ +package com.hmdzl.spspd.effects; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.Image; + +public class Effects { + + public enum Type { + RIPPLE, + LIGHTNING, + WOUND, + EXCLAMATION, + CHAIN, + DEATH_RAY, + LIGHT_RAY, + HEALTH_RAY, + WATER_RAY + }; + + public static Image get( Type type ) { + Image icon = new Image( Assets.EFFECTS ); + switch (type) { + case RIPPLE: + icon.frame(icon.texture.uvRect(0, 0, 16, 16)); + break; + case LIGHTNING: + icon.frame(icon.texture.uvRect(16, 0, 32, 8)); + break; + case WOUND: + icon.frame(icon.texture.uvRect(16, 8, 32, 16)); + break; + case EXCLAMATION: + icon.frame(icon.texture.uvRect(0, 16, 6, 25)); + break; + case CHAIN: + icon.frame(icon.texture.uvRect(6, 16, 11, 22)); + break; + case DEATH_RAY: + icon.frame(icon.texture.uvRect(16, 16, 32, 24)); + break; + case LIGHT_RAY: + icon.frame(icon.texture.uvRect(16, 23, 32, 31)); + break; + case HEALTH_RAY: + icon.frame(icon.texture.uvRect(16, 30, 32, 38)); + break; + case WATER_RAY: + icon.frame(icon.texture.uvRect(16, 37, 32, 45)); + break; + } + return icon; + } +} diff --git a/java/com/hmdzl/spspd/effects/EmoIcon.java b/java/com/hmdzl/spspd/effects/EmoIcon.java new file mode 100644 index 00000000..c5afe0da --- /dev/null +++ b/java/com/hmdzl/spspd/effects/EmoIcon.java @@ -0,0 +1,116 @@ +/* + * 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 + */ +package com.hmdzl.spspd.effects; + +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.CharSprite; +import com.hmdzl.spspd.ui.Icons; +import com.watabou.noosa.Game; +import com.watabou.noosa.Image; +import com.watabou.utils.Random; + +public class EmoIcon extends Image { + + protected float maxSize = 2; + protected float timeScale = 1; + + protected boolean growing = true; + + protected CharSprite owner; + + public EmoIcon(CharSprite owner) { + super(); + + this.owner = owner; + GameScene.add(this); + } + + @Override + public void update() { + super.update(); + + if (visible) { + if (growing) { + scale.set(Math.min(scale.x + Game.elapsed * timeScale, maxSize)); + if (scale.x >= maxSize) { + growing = false; + } + } else { + scale.set(Math.max(scale.x - Game.elapsed * timeScale, 1f)); + if (scale.x <= 1) { + growing = true; + } + } + + x = owner.x + owner.width - width / 2; + y = owner.y - height; + } + } + + public static class Sleep extends EmoIcon { + + public Sleep(CharSprite owner) { + + super(owner); + + copy(Icons.get(Icons.SLEEP)); + + maxSize = 1.2f; + timeScale = 0.5f; + + origin.set(width / 2, height / 2); + scale.set(Random.Float(1, maxSize)); + } + } + + public static class Alert extends EmoIcon { + + public Alert(CharSprite owner) { + + super(owner); + + copy(Icons.get(Icons.ALERT)); + + maxSize = 1.3f; + timeScale = 2; + + origin.set(2.5f, height - 2.5f); + scale.set(Random.Float(1, maxSize)); + } + } + + public static class Lost extends EmoIcon { + + public Lost( CharSprite owner ){ + super( owner ); + + copy( Icons.get( Icons.LOST ) ); + + maxSize = 1.25f; + timeScale = 1; + + origin.set( 2.5f, height - 2.5f ); + scale.set( Random.Float( 1, maxSize ) ); + + x = owner.x + owner.width - width / 2; + y = owner.y - height; + } + + } + +} diff --git a/java/com/hmdzl/spspd/effects/Fireball.java b/java/com/hmdzl/spspd/effects/Fireball.java new file mode 100644 index 00000000..9e2c6fff --- /dev/null +++ b/java/com/hmdzl/spspd/effects/Fireball.java @@ -0,0 +1,161 @@ +/* + * 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 + */ +package com.hmdzl.spspd.effects; + +import javax.microedition.khronos.opengles.GL10; + +import android.graphics.RectF; +import android.opengl.GLES20; + +import com.hmdzl.spspd.Assets; +import com.watabou.glwrap.Texture; +import com.watabou.noosa.Game; +import com.watabou.noosa.Group; +import com.watabou.noosa.Image; +import com.watabou.noosa.particles.Emitter; +import com.watabou.noosa.particles.PixelParticle; +import com.watabou.noosa.ui.Component; +import com.watabou.utils.ColorMath; +import com.watabou.utils.Random; + +public class Fireball extends Component { + + private static final RectF BLIGHT = new RectF(0, 0, 0.25f, 1); + private static final RectF FLIGHT = new RectF(0.25f, 0, 0.5f, 1); + private static final RectF FLAME1 = new RectF(0.50f, 0, 0.75f, 1); + private static final RectF FLAME2 = new RectF(0.75f, 0, 1.00f, 1); + + private static final int COLOR = 0xFF66FF; + + private Image bLight; + private Image fLight; + private Emitter emitter; + private Group sparks; + + @Override + protected void createChildren() { + + sparks = new Group(); + add(sparks); + + bLight = new Image(Assets.FIREBALL); + bLight.frame(BLIGHT); + bLight.origin.set(bLight.width / 2); + bLight.angularSpeed = -90; + add(bLight); + + emitter = new Emitter(); + emitter.pour(new Emitter.Factory() { + @Override + public void emit(Emitter emitter, int index, float x, float y) { + Flame p = (Flame) emitter.recycle(Flame.class); + p.reset(); + p.x = x - p.width / 2; + p.y = y - p.height / 2; + } + }, 0.1f); + add(emitter); + + fLight = new Image(Assets.FIREBALL); + fLight.frame(FLIGHT); + fLight.origin.set(fLight.width / 2); + fLight.angularSpeed = 360; + add(fLight); + + bLight.texture.filter(Texture.LINEAR, Texture.LINEAR); + } + + @Override + protected void layout() { + + bLight.x = x - bLight.width / 2; + bLight.y = y - bLight.height / 2; + + emitter.pos(x - bLight.width / 4, y - bLight.height / 4, + bLight.width / 2, bLight.height / 2); + + fLight.x = x - fLight.width / 2; + fLight.y = y - fLight.height / 2; + } + + @Override + public void update() { + + super.update(); + + if (Random.Float() < Game.elapsed) { + PixelParticle spark = (PixelParticle) sparks + .recycle(PixelParticle.Shrinking.class); + spark.reset(x, y, ColorMath.random(COLOR, 0x66FF66), 2, + Random.Float(0.5f, 1.0f)); + spark.speed.set(Random.Float(-40, +40), Random.Float(-60, +20)); + spark.acc.set(0, +80); + sparks.add(spark); + } + } + + @Override + public void draw() { + GLES20.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE); + super.draw(); + GLES20.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA); + } + + public static class Flame extends Image { + + private static float LIFESPAN = 1f; + + private static float SPEED = -40f; + private static float ACC = -20f; + + private float timeLeft; + + public Flame() { + + super(Assets.FIREBALL); + + frame(Random.Int(2) == 0 ? FLAME1 : FLAME2); + origin.set(width / 2, height / 2); + acc.set(0, ACC); + } + + public void reset() { + revive(); + timeLeft = LIFESPAN; + speed.set(0, SPEED); + } + + @Override + public void update() { + + super.update(); + + if ((timeLeft -= Game.elapsed) <= 0) { + + kill(); + + } else { + + float p = timeLeft / LIFESPAN; + scale.set(p); + alpha(p > 0.8f ? (1 - p) * 5f : p * 1.25f); + + } + } + } +} diff --git a/java/com/hmdzl/spspd/effects/Flare.java b/java/com/hmdzl/spspd/effects/Flare.java new file mode 100644 index 00000000..6ffc30e0 --- /dev/null +++ b/java/com/hmdzl/spspd/effects/Flare.java @@ -0,0 +1,162 @@ +/* + * 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 + */ +package com.hmdzl.spspd.effects; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.FloatBuffer; +import java.nio.ShortBuffer; + +import javax.microedition.khronos.opengles.GL10; + +import android.annotation.SuppressLint; +import android.opengl.GLES20; +import android.util.FloatMath; + +import com.watabou.gltextures.Gradient; +import com.watabou.gltextures.SmartTexture; +import com.watabou.noosa.Game; +import com.watabou.noosa.NoosaScript; +import com.watabou.noosa.Visual; + +public class Flare extends Visual { + + private float duration = 0; + private float lifespan; + + private boolean lightMode = true; + + private SmartTexture texture; + + private FloatBuffer vertices; + private ShortBuffer indices; + + private int nRays; + + @SuppressLint("FloatMath") + public Flare(int nRays, float radius) { + + super(0, 0, 0, 0); + + int gradient[] = { 0xFFFFFFFF, 0x00FFFFFF }; + texture = new Gradient(gradient); + + this.nRays = nRays; + + angle = 45; + angularSpeed = 180; + + vertices = ByteBuffer + .allocateDirect((nRays * 2 + 1) * 4 * (Float.SIZE / 8)) + .order(ByteOrder.nativeOrder()).asFloatBuffer(); + + indices = ByteBuffer.allocateDirect(nRays * 3 * Short.SIZE / 8) + .order(ByteOrder.nativeOrder()).asShortBuffer(); + + float v[] = new float[4]; + + v[0] = 0; + v[1] = 0; + v[2] = 0.25f; + v[3] = 0; + vertices.put(v); + + v[2] = 0.75f; + v[3] = 0; + + for (int i = 0; i < nRays; i++) { + + float a = i * 3.1415926f * 2 / nRays; + v[0] = (float)Math.cos(a) * radius; + v[1] = (float)Math.sin(a) * radius; + vertices.put(v); + + a += 3.1415926f * 2 / nRays / 2; + v[0] = (float)Math.cos(a) * radius; + v[1] = (float)Math.sin(a) * radius; + vertices.put(v); + + indices.put((short) 0); + indices.put((short) (1 + i * 2)); + indices.put((short) (2 + i * 2)); + } + + indices.position(0); + } + + public Flare color(int color, boolean lightMode) { + this.lightMode = lightMode; + hardlight(color); + + return this; + } + + public Flare show(Visual visual, float duration) { + point(visual.center()); + visual.parent.addToBack(this); + + lifespan = this.duration = duration; + + return this; + } + + @Override + public void update() { + super.update(); + + if (duration > 0) { + if ((lifespan -= Game.elapsed) > 0) { + + float p = 1 - lifespan / duration; // 0 -> 1 + p = p < 0.25f ? p * 4 : (1 - p) * 1.333f; + scale.set(p); + alpha(p); + + } else { + killAndErase(); + } + } + } + + @Override + public void draw() { + + super.draw(); + + if (lightMode) { + GLES20.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE); + drawRays(); + GLES20.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA); + } else { + drawRays(); + } + } + + private void drawRays() { + + NoosaScript script = NoosaScript.get(); + + texture.bind(); + + script.uModel.valueM4(matrix); + script.lighting(rm, gm, bm, am, ra, ga, ba, aa); + + script.camera(camera); + script.drawElements(vertices, indices, nRays * 3); + } +} diff --git a/java/com/hmdzl/spspd/effects/FloatingText.java b/java/com/hmdzl/spspd/effects/FloatingText.java new file mode 100644 index 00000000..77e52a76 --- /dev/null +++ b/java/com/hmdzl/spspd/effects/FloatingText.java @@ -0,0 +1,138 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2014 Oleg Dolya + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.effects; + +import java.util.ArrayList; + +import com.hmdzl.spspd.DungeonTilemap; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.scenes.PixelScene; +import com.watabou.noosa.RenderedText; +import com.watabou.noosa.Camera; +import com.watabou.noosa.Game; +import com.watabou.utils.SparseArray; + +public class FloatingText extends RenderedText { + + private static final float LIFESPAN = 1f; + private static final float DISTANCE = DungeonTilemap.SIZE; + + private float timeLeft; + + private int key = -1; + + private float cameraZoom = -1; + + private static SparseArray> stacks = new SparseArray>(); + + public FloatingText() { + super(); + speed.y = -DISTANCE / LIFESPAN; + } + + @Override + public void update() { + super.update(); + + if (timeLeft > 0) { + if ((timeLeft -= Game.elapsed) <= 0) { + kill(); + } else { + float p = timeLeft / LIFESPAN; + alpha(p > 0.5f ? 1 : p * 2); + } + } + } + + @Override + public void kill() { + if (key != -1) { + stacks.get(key).remove(this); + key = -1; + } + super.kill(); + } + + @Override + public void destroy() { + kill(); + super.destroy(); + } + + public void reset(float x, float y, String text, int color) { + + revive(); + + if (cameraZoom != Camera.main.zoom) { + cameraZoom = Camera.main.zoom; + PixelScene.chooseFont(9, cameraZoom); + size( 9 * (int)cameraZoom); + scale.set( 1 /cameraZoom ); + } + + text(text); + hardlight(color); + + //measure(); + this.x = PixelScene.align(x - width() / 2); + this.y = y - height(); + + timeLeft = LIFESPAN; + } + + /* STATIC METHODS */ + + public static void show(float x, float y, String text, int color) { + GameScene.status().reset(x, y, text, color); + } + + public static void show(float x, float y, int key, String text, int color) { + FloatingText txt = GameScene.status(); + txt.reset(x, y, text, color); + push(txt, key); + } + + private static void push(FloatingText txt, int key) { + + txt.key = key; + + ArrayList stack = stacks.get(key); + if (stack == null) { + stack = new ArrayList(); + stacks.put(key, stack); + } + + if (stack.size() > 0) { + FloatingText below = txt; + int aboveIndex = stack.size() - 1; + while (aboveIndex >= 0) { + FloatingText above = stack.get(aboveIndex); + if (above.y + above.height() > below.y) { + above.y = below.y - above.height(); + + below = above; + aboveIndex--; + } else { + break; + } + } + } + + stack.add(txt); + } +} diff --git a/java/com/hmdzl/spspd/effects/Halo.java b/java/com/hmdzl/spspd/effects/Halo.java new file mode 100644 index 00000000..7c711d79 --- /dev/null +++ b/java/com/hmdzl/spspd/effects/Halo.java @@ -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 + */ +package com.hmdzl.spspd.effects; + +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Paint; + +import com.watabou.gltextures.SmartTexture; +import com.watabou.gltextures.TextureCache; +import com.watabou.noosa.Image; + +public class Halo extends Image { + + private static final Object CACHE_KEY = Halo.class; + + protected static final int RADIUS = 64; + + protected float radius = RADIUS; + protected float brightness = 1; + + public Halo() { + super(); + + if (!TextureCache.contains(CACHE_KEY)) { + Bitmap bmp = Bitmap.createBitmap(RADIUS * 2, RADIUS * 2, + Bitmap.Config.ARGB_8888); + Canvas canvas = new Canvas(bmp); + Paint paint = new Paint(); + paint.setColor(0xFFFFFFFF); + canvas.drawCircle(RADIUS, RADIUS, RADIUS * 0.75f, paint); + paint.setColor(0x88FFFFFF); + canvas.drawCircle(RADIUS, RADIUS, RADIUS, paint); + TextureCache.add(CACHE_KEY, new SmartTexture(bmp)); + } + + texture(CACHE_KEY); + + origin.set(RADIUS); + } + + public Halo(float radius, int color, float brightness) { + + this(); + + hardlight(color); + alpha(this.brightness = brightness); + radius(radius); + } + + public Halo point(float x, float y) { + this.x = x - RADIUS; + this.y = y - RADIUS; + return this; + } + + public void radius(float value) { + scale.set((this.radius = value) / RADIUS); + } +} diff --git a/java/com/hmdzl/spspd/effects/IceBlock.java b/java/com/hmdzl/spspd/effects/IceBlock.java new file mode 100644 index 00000000..85f44930 --- /dev/null +++ b/java/com/hmdzl/spspd/effects/IceBlock.java @@ -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 + */ +package com.hmdzl.spspd.effects; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.sprites.CharSprite; +import com.watabou.noosa.Game; +import com.watabou.noosa.Gizmo; +import com.watabou.noosa.audio.Sample; + +public class IceBlock extends Gizmo { + + private float phase; + + private CharSprite target; + + public IceBlock(CharSprite target) { + super(); + + this.target = target; + phase = 0; + } + + @Override + public void update() { + super.update(); + + if ((phase += Game.elapsed * 2) < 1) { + target.tint(0.83f, 1.17f, 1.33f, phase * 0.6f); + } else { + target.tint(0.83f, 1.17f, 1.33f, 0.6f); + } + } + + public void melt() { + + target.resetColor(); + killAndErase(); + + if (visible) { + Splash.at(target.center(), 0xFFB2D6FF, 5); + Sample.INSTANCE.play(Assets.SND_SHATTER); + } + } + + public static IceBlock freeze(CharSprite sprite) { + + IceBlock iceBlock = new IceBlock(sprite); + sprite.parent.add(iceBlock); + + return iceBlock; + } +} diff --git a/java/com/hmdzl/spspd/effects/Identification.java b/java/com/hmdzl/spspd/effects/Identification.java new file mode 100644 index 00000000..665bc7b1 --- /dev/null +++ b/java/com/hmdzl/spspd/effects/Identification.java @@ -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 + */ +package com.hmdzl.spspd.effects; + +import javax.microedition.khronos.opengles.GL10; + +import android.opengl.GLES20; + +import com.watabou.noosa.Group; +import com.watabou.noosa.particles.PixelParticle; +import com.watabou.utils.PointF; +import com.watabou.utils.Random; + +public class Identification extends Group { + + private static int[] DOTS = { -1, -3, 0, -3, +1, -3, -1, -2, +1, -2, +1, + -1, 0, 0, +1, 0, 0, +1, 0, +3 }; + + public Identification(PointF p) { + + for (int i = 0; i < DOTS.length; i += 2) { + add(new Speck(p.x, p.y, DOTS[i], DOTS[i + 1])); + add(new Speck(p.x, p.y, DOTS[i], DOTS[i + 1])); + } + } + + @Override + public void update() { + super.update(); + if (countLiving() == 0) { + killAndErase(); + } + } + + @Override + public void draw() { + GLES20.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE); + super.draw(); + GLES20.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA); + } + + public static class Speck extends PixelParticle { + + private static final int COLOR = 0x4488CC; + private static final int SIZE = 3; + + public Speck(float x0, float y0, int mx, int my) { + + super(); + color(COLOR); + + float x1 = x0 + mx * SIZE; + float y1 = y0 + my * SIZE; + + PointF p = new PointF().polar(Random.Float(2 * PointF.PI), 8); + x0 += p.x; + y0 += p.y; + + float dx = x1 - x0; + float dy = y1 - y0; + + x = x0; + y = y0; + speed.set(dx, dy); + acc.set(-dx / 4, -dy / 4); + + left = lifespan = 2f; + } + + @Override + public void update() { + super.update(); + + am = 1 - Math.abs(left / lifespan - 0.5f) * 2; + am *= am; + size(am * SIZE); + } + } +} diff --git a/java/com/hmdzl/spspd/effects/Lightning.java b/java/com/hmdzl/spspd/effects/Lightning.java new file mode 100644 index 00000000..a4d84731 --- /dev/null +++ b/java/com/hmdzl/spspd/effects/Lightning.java @@ -0,0 +1,143 @@ +/* + * 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 + */ +package com.hmdzl.spspd.effects; + +import javax.microedition.khronos.opengles.GL10; + +import android.opengl.GLES20; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.DungeonTilemap; +import com.watabou.noosa.Game; +import com.watabou.noosa.Group; +import com.watabou.noosa.Image; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Callback; +import com.watabou.utils.PointF; +import com.watabou.utils.Random; + +import java.util.Arrays; +import java.util.List; + +public class Lightning extends Group { + + private static final float DURATION = 0.3f; + + private float life; + + private List arcs; + + private Callback callback; + + public Lightning(int from, int to, Callback callback){ + this(Arrays.asList(new Arc(from, to)), callback); + } + + public Lightning( List arcs, Callback callback ) { + + super(); + + this.arcs = arcs; + for (Arc arc : this.arcs) + add(arc); + + this.callback = callback; + + life = DURATION; + + Sample.INSTANCE.play( Assets.SND_LIGHTNING ); + } + + private static final double A = 180 / Math.PI; + + @Override + public void update() { + if ((life -= Game.elapsed) < 0) { + + killAndErase(); + if (callback != null) { + callback.call(); + } + + } else { + + float alpha = life / DURATION; + + for (Arc arc : arcs) { + arc.alpha(alpha); + } + + super.update(); + } + } + + @Override + public void draw() { + GLES20.glBlendFunc( GL10.GL_SRC_ALPHA, GL10.GL_ONE ); + super.draw(); + GLES20.glBlendFunc( GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA ); + } + + //A lightning object is meant to be loaded up with arcs. + //these act as a means of easily expressing lighting between two points. + public static class Arc extends Group { + + private Image arc1, arc2; + + //starting and ending x/y values + private PointF start, end; + + public Arc(int from, int to){ + start = DungeonTilemap.tileCenterToWorld(from); + end = DungeonTilemap.tileCenterToWorld(to); + + arc1 = new Image(Effects.get(Effects.Type.LIGHTNING)); + arc1.x = start.x - arc1.origin.x; + arc1.y = start.y - arc1.origin.y; + arc1.origin.set( 0, arc1.height()/2 ); + add( arc1 ); + + arc2 = new Image(Effects.get(Effects.Type.LIGHTNING)); + arc2.origin.set( 0, arc2.height()/2 ); + add( arc2 ); + + } + + public void alpha(float alpha) { + arc1.am = arc2.am = alpha; + } + + @Override + public void update() { + float x2 = (start.x + end.x) / 2 + Random.Float( -4, +4 ); + float y2 = (start.y + end.y) / 2 + Random.Float( -4, +4 ); + + float dx = x2 - start.x; + float dy = y2 - start.y; + arc1.angle = (float)(Math.atan2( dy, dx ) * A); + arc1.scale.x = (float)Math.sqrt( dx * dx + dy * dy ) / arc1.width; + + dx = end.x - x2; + dy = end.y - y2; + arc2.angle = (float)(Math.atan2( dy, dx ) * A); + arc2.scale.x = (float)Math.sqrt( dx * dx + dy * dy ) / arc2.width; + arc2.x = x2 - arc2.origin.x; + arc2.y = y2 - arc2.origin.x; + } + } +} diff --git a/java/com/hmdzl/spspd/effects/MagicMissile.java b/java/com/hmdzl/spspd/effects/MagicMissile.java new file mode 100644 index 00000000..b13c4cf1 --- /dev/null +++ b/java/com/hmdzl/spspd/effects/MagicMissile.java @@ -0,0 +1,449 @@ +/* + * 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 + */ +package com.hmdzl.spspd.effects; + +import com.hmdzl.spspd.DungeonTilemap; +import com.hmdzl.spspd.effects.particles.FlameParticle; +import com.hmdzl.spspd.effects.particles.LeafParticle; +import com.hmdzl.spspd.effects.particles.PoisonParticle; +import com.hmdzl.spspd.effects.particles.PurpleParticle; +import com.hmdzl.spspd.effects.particles.RainbowParticle; +import com.hmdzl.spspd.effects.particles.ShadowParticle; +import com.hmdzl.spspd.effects.particles.WoolParticle; +import com.watabou.noosa.Game; +import com.watabou.noosa.Group; +import com.watabou.noosa.particles.Emitter; +import com.watabou.noosa.particles.PixelParticle; +import com.watabou.utils.Callback; +import com.watabou.utils.ColorMath; +import com.watabou.utils.PointF; +import com.watabou.utils.Random; + +public class MagicMissile extends Emitter { + + private static final float SPEED = 200f; + + private Callback callback; + + private float sx; + private float sy; + private float time; + + public void reset(int from, int to, Callback callback) { + this.callback = callback; + + revive(); + + PointF pf = DungeonTilemap.tileCenterToWorld(from); + PointF pt = DungeonTilemap.tileCenterToWorld(to); + + x = pf.x; + y = pf.y; + width = 0; + height = 0; + + PointF d = PointF.diff(pt, pf); + PointF speed = new PointF(d).normalize().scale(SPEED); + sx = speed.x; + sy = speed.y; + time = d.length() / SPEED; + } + + public void size(float size) { + x -= size / 2; + y -= size / 2; + width = height = size; + } + + public static void coldLight(Group group, int from, int to, + Callback callback) { + MagicMissile missile = ((MagicMissile) group + .recycle(MagicMissile.class)); + missile.reset(from, to, callback); + missile.pour(MagicParticle.FACTORY, 0.01f); + } + + public static void fire(Group group, int from, int to, Callback callback) { + MagicMissile missile = ((MagicMissile) group + .recycle(MagicMissile.class)); + missile.reset(from, to, callback); + missile.size(4); + missile.pour(FlameParticle.FACTORY, 0.01f); + } + + public static void firesmall(Group group, int from, int to, Callback callback) { + MagicMissile missile = ((MagicMissile) group + .recycle(MagicMissile.class)); + missile.reset(from, to, callback); + missile.size(2); + missile.pour(FlameParticle.FACTORY, 0.01f); + } + + public static void firelarge(Group group, int from, int to, Callback callback) { + MagicMissile missile = ((MagicMissile) group + .recycle(MagicMissile.class)); + missile.reset(from, to, callback); + missile.size(8); + missile.pour(FlameParticle.FACTORY, 0.01f); + } + + public static void earth(Group group, int from, int to, Callback callback) { + MagicMissile missile = ((MagicMissile) group + .recycle(MagicMissile.class)); + missile.reset(from, to, callback); + missile.size(2); + missile.pour(EarthParticle.FACTORY, 0.01f); + } + + public static void purpleLight(Group group, int from, int to, + Callback callback) { + MagicMissile missile = ((MagicMissile) group + .recycle(MagicMissile.class)); + missile.reset(from, to, callback); + missile.size(2); + missile.pour(PurpleParticle.MISSILE, 0.01f); + } + + public static void whiteLight(Group group, int from, int to, + Callback callback) { + MagicMissile missile = ((MagicMissile) group + .recycle(MagicMissile.class)); + missile.reset(from, to, callback); + missile.size(4); + missile.pour(WhiteParticle.FACTORY, 0.01f); + } + + public static void wool(Group group, int from, int to, Callback callback) { + MagicMissile missile = ((MagicMissile) group + .recycle(MagicMissile.class)); + missile.reset(from, to, callback); + missile.size(3); + missile.pour(WoolParticle.FACTORY, 0.01f); + } + + public static void poison(Group group, int from, int to, Callback callback) { + MagicMissile missile = ((MagicMissile) group + .recycle(MagicMissile.class)); + missile.reset(from, to, callback); + missile.size(3); + missile.pour(PoisonParticle.MISSILE, 0.01f); + } + + public static void foliage(Group group, int from, int to, Callback callback) { + MagicMissile missile = ((MagicMissile) group + .recycle(MagicMissile.class)); + missile.reset(from, to, callback); + missile.size(4); + missile.pour(LeafParticle.GENERAL, 0.01f); + } + + public static void slowness(Group group, int from, int to, Callback callback) { + MagicMissile missile = ((MagicMissile) group + .recycle(MagicMissile.class)); + missile.reset(from, to, callback); + missile.pour(SlowParticle.FACTORY, 0.01f); + } + + public static void force(Group group, int from, int to, Callback callback) { + MagicMissile missile = ((MagicMissile) group + .recycle(MagicMissile.class)); + missile.reset(from, to, callback); + missile.size(4); + missile.pour(ForceParticle.FACTORY, 0.01f); + } + + public static void blueLight(Group group, int from, int to, + Callback callback) { + MagicMissile missile = ((MagicMissile) group + .recycle(MagicMissile.class)); + missile.reset(from, to, callback); + missile.size(4); + missile.pour(ColdParticle.FACTORY, 0.01f); + } + + public static void shadow(Group group, int from, int to, Callback callback) { + MagicMissile missile = ((MagicMissile) group + .recycle(MagicMissile.class)); + missile.reset(from, to, callback); + missile.size(4); + missile.pour(ShadowParticle.MISSILE, 0.01f); + } + + public static void rainbow( Group group, int from, int to, Callback callback ) { + MagicMissile missile = ((MagicMissile)group.recycle( MagicMissile.class )); + missile.reset( from, to, callback ); + missile.size( 4 ); + missile.pour( RainbowParticle.BURST, 0.01f ); + } + + @Override + public void update() { + super.update(); + if (on) { + float d = Game.elapsed; + x += sx * d; + y += sy * d; + if ((time -= d) <= 0) { + on = false; + callback.call(); + } + } + } + + public static class MagicParticle extends PixelParticle { + + public static final Emitter.Factory FACTORY = new Factory() { + @Override + public void emit(Emitter emitter, int index, float x, float y) { + ((MagicParticle) emitter.recycle(MagicParticle.class)).reset(x, + y); + } + + @Override + public boolean lightMode() { + return true; + }; + }; + + public MagicParticle() { + super(); + + color(0x88CCFF); + lifespan = 0.5f; + + speed.set(Random.Float(-10, +10), Random.Float(-10, +10)); + } + + public void reset(float x, float y) { + revive(); + + this.x = x; + this.y = y; + + left = lifespan; + } + + @Override + public void update() { + super.update(); + // alpha: 1 -> 0; size: 1 -> 4 + size(4 - (am = left / lifespan) * 3); + } + } + + public static class EarthParticle extends PixelParticle.Shrinking { + + public static final Emitter.Factory FACTORY = new Factory() { + @Override + public void emit(Emitter emitter, int index, float x, float y) { + ((EarthParticle) emitter.recycle(EarthParticle.class)).reset(x, + y); + } + }; + + public EarthParticle() { + super(); + + lifespan = 0.5f; + + color(ColorMath.random(0x555555, 0x777766)); + + acc.set(0, +40); + } + + public void reset(float x, float y) { + revive(); + + this.x = x; + this.y = y; + + left = lifespan; + size = 4; + + speed.set(Random.Float(-10, +10), Random.Float(-10, +10)); + } + } + + public static class WhiteParticle extends PixelParticle { + + public static final Emitter.Factory FACTORY = new Factory() { + @Override + public void emit(Emitter emitter, int index, float x, float y) { + ((WhiteParticle) emitter.recycle(WhiteParticle.class)).reset(x, + y); + } + + @Override + public boolean lightMode() { + return true; + }; + }; + + public WhiteParticle() { + super(); + + lifespan = 0.4f; + + am = 0.5f; + } + + public void reset(float x, float y) { + revive(); + + this.x = x; + this.y = y; + + left = lifespan; + } + + @Override + public void update() { + super.update(); + // size: 3 -> 0 + size((left / lifespan) * 3); + } + } + + public static class SlowParticle extends PixelParticle { + + private Emitter emitter; + + public static final Emitter.Factory FACTORY = new Factory() { + @Override + public void emit(Emitter emitter, int index, float x, float y) { + ((SlowParticle) emitter.recycle(SlowParticle.class)).reset(x, + y, emitter); + } + + @Override + public boolean lightMode() { + return true; + }; + }; + + public SlowParticle() { + super(); + + lifespan = 0.6f; + + color(0x664422); + size(2); + } + + public void reset(float x, float y, Emitter emitter) { + revive(); + + this.x = x; + this.y = y; + this.emitter = emitter; + + left = lifespan; + + acc.set(0); + speed.set(Random.Float(-20, +20), Random.Float(-20, +20)); + } + + @Override + public void update() { + super.update(); + + am = left / lifespan; + acc.set((emitter.x - x) * 10, (emitter.y - y) * 10); + } + } + + public static class ForceParticle extends PixelParticle { + + public static final Emitter.Factory FACTORY = new Factory() { + @Override + public void emit(Emitter emitter, int index, float x, float y) { + ((ForceParticle) emitter.recycle(ForceParticle.class)).reset(x, + y); + } + }; + + public ForceParticle() { + super(); + + lifespan = 0.6f; + + size(4); + } + + public void reset(float x, float y) { + revive(); + + this.x = x; + this.y = y; + + left = lifespan; + + acc.set(0); + speed.set(Random.Float(-40, +40), Random.Float(-40, +40)); + } + + @Override + public void update() { + super.update(); + + am = (left / lifespan) / 2; + acc.set(-speed.x * 10, -speed.y * 10); + } + } + + public static class ColdParticle extends PixelParticle.Shrinking { + + public static final Emitter.Factory FACTORY = new Factory() { + @Override + public void emit(Emitter emitter, int index, float x, float y) { + ((ColdParticle) emitter.recycle(ColdParticle.class)) + .reset(x, y); + } + + @Override + public boolean lightMode() { + return true; + }; + }; + + public ColdParticle() { + super(); + + lifespan = 0.6f; + + color(0x2244FF); + } + + public void reset(float x, float y) { + revive(); + + this.x = x; + this.y = y; + + left = lifespan; + size = 8; + } + + @Override + public void update() { + super.update(); + + am = 1 - left / lifespan; + } + } +} diff --git a/java/com/hmdzl/spspd/effects/Pushing.java b/java/com/hmdzl/spspd/effects/Pushing.java new file mode 100644 index 00000000..f4413d54 --- /dev/null +++ b/java/com/hmdzl/spspd/effects/Pushing.java @@ -0,0 +1,115 @@ +/* + * 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 + */ +package com.hmdzl.spspd.effects; + +import com.watabou.noosa.Game; +import com.watabou.noosa.Visual; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.sprites.CharSprite; +import com.watabou.utils.Callback; +import com.watabou.utils.PointF; + +public class Pushing extends Actor { + + private CharSprite sprite; + private int from; + private int to; + + private Effect effect; + + private Callback callback; + + public Pushing( Char ch, int from, int to ) { + sprite = ch.sprite; + this.from = from; + this.to = to; + this.callback = null; + } + + public Pushing( Char ch, int from, int to, Callback callback ) { + this(ch, from, to); + this.callback = callback; + } + + @Override + protected boolean act() { + if (sprite != null) { + + if (effect == null) { + new Effect(); + } + } + + Actor.remove( Pushing.this ); + + //so that all pushing effects at the same time go simultaneously + for ( Actor actor : Actor.all() ){ + if (actor instanceof Pushing && ((Pushing) actor).cooldown() == 0) + return true; + } + return false; + + } + + public class Effect extends Visual { + + private static final float DELAY = 0.15f; + + private PointF end; + + private float delay; + + public Effect() { + super( 0, 0, 0, 0 ); + + point( sprite.worldToCamera( from ) ); + end = sprite.worldToCamera( to ); + + speed.set( 2 * (end.x - x) / DELAY, 2 * (end.y - y) / DELAY ); + acc.set( -speed.x / DELAY, -speed.y / DELAY ); + + delay = 0; + + if (sprite.parent != null) + sprite.parent.add( this ); + } + + @Override + public void update() { + super.update(); + + if ((delay += Game.elapsed) < DELAY) { + + sprite.x = x; + sprite.y = y; + + } else { + + sprite.point(end); + + killAndErase(); + Actor.remove(Pushing.this); + if (callback != null) callback.call(); + + next(); + } + } + } + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/effects/Ripple.java b/java/com/hmdzl/spspd/effects/Ripple.java new file mode 100644 index 00000000..44ea0b63 --- /dev/null +++ b/java/com/hmdzl/spspd/effects/Ripple.java @@ -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 + */ +package com.hmdzl.spspd.effects; + +import com.hmdzl.spspd.DungeonTilemap; +import com.hmdzl.spspd.levels.Level; +import com.watabou.noosa.Game; +import com.watabou.noosa.Image; + +public class Ripple extends Image { + + private static final float TIME_TO_FADE = 0.5f; + + private float time; + + public Ripple() { + super(Effects.get(Effects.Type.RIPPLE)); + } + + public void reset(int p) { + revive(); + + x = (p % Level.getWidth()) * DungeonTilemap.SIZE; + y = (p / Level.getWidth()) * DungeonTilemap.SIZE; + + origin.set(width / 2, height / 2); + scale.set(0); + + time = TIME_TO_FADE; + } + + @Override + public void update() { + super.update(); + + if ((time -= Game.elapsed) <= 0) { + kill(); + } else { + float p = time / TIME_TO_FADE; + scale.set(1 - p); + alpha(p); + } + } +} diff --git a/java/com/hmdzl/spspd/effects/ShadowBox.java b/java/com/hmdzl/spspd/effects/ShadowBox.java new file mode 100644 index 00000000..759000b4 --- /dev/null +++ b/java/com/hmdzl/spspd/effects/ShadowBox.java @@ -0,0 +1,46 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 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 + */ +package com.hmdzl.spspd.effects; + +import com.hmdzl.spspd.Assets; +import com.watabou.glwrap.Texture; +import com.watabou.noosa.NinePatch; + +public class ShadowBox extends NinePatch { + + public static final float SIZE = 16; + + public ShadowBox() { + super(Assets.SHADOW, 1); + + texture.filter(Texture.LINEAR, Texture.LINEAR); + + scale.set(SIZE, SIZE); + } + + @Override + public void size(float width, float height) { + super.size(width / SIZE, height / SIZE); + } + + public void boxRect(float x, float y, float width, float height) { + this.x = x - SIZE; + this.y = y - SIZE; + size(width + SIZE * 2, height + SIZE * 2); + } +} diff --git a/java/com/hmdzl/spspd/effects/ShieldHalo.java b/java/com/hmdzl/spspd/effects/ShieldHalo.java new file mode 100644 index 00000000..b8e3cbc9 --- /dev/null +++ b/java/com/hmdzl/spspd/effects/ShieldHalo.java @@ -0,0 +1,80 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2019 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ + +package com.hmdzl.spspd.effects; + +import com.hmdzl.spspd.sprites.CharSprite; +import com.watabou.glwrap.Blending; +import com.watabou.noosa.Game; +import com.watabou.noosa.Halo; +import com.watabou.utils.PointF; + +public class ShieldHalo extends Halo { + + private CharSprite target; + + private float phase; + + public ShieldHalo( CharSprite sprite ) { + + //rectangular sprite to circular radius. Pythagorean theorem + super( (float)Math.sqrt(Math.pow(sprite.width()/2f, 2) + Math.pow(sprite.height()/2f, 2)), 0xBBAACC, 1f ); + + am = -0.33f; + aa = +0.33f; + + target = sprite; + + phase = 1; + } + + @Override + public void update() { + super.update(); + + if (phase < 1) { + if ((phase -= Game.elapsed) <= 0) { + killAndErase(); + } else { + scale.set( (2 - phase) * radius / RADIUS ); + am = phase * (-1); + aa = phase * (+1); + } + } + + if (visible = target.visible) { + PointF p = target.center(); + point( p.x, p.y ); + } + } + + @Override + public void draw() { + Blending.setLightMode(); + super.draw(); + Blending.setNormalMode(); + } + + public void putOut() { + phase = 0.999f; + } + +} diff --git a/java/com/hmdzl/spspd/effects/Speck.java b/java/com/hmdzl/spspd/effects/Speck.java new file mode 100644 index 00000000..055621b9 --- /dev/null +++ b/java/com/hmdzl/spspd/effects/Speck.java @@ -0,0 +1,520 @@ +/* + * 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 + */ +package com.hmdzl.spspd.effects; + +import android.annotation.SuppressLint; +import android.util.SparseArray; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.Game; +import com.watabou.noosa.Image; +import com.watabou.noosa.TextureFilm; +import com.watabou.noosa.particles.Emitter; +import com.watabou.utils.ColorMath; +import com.watabou.utils.PointF; +import com.watabou.utils.Random; + +public class Speck extends Image { + + public static final int HEALING = 0; + public static final int STAR = 1; + public static final int LIGHT = 2; + public static final int QUESTION = 3; + public static final int UP = 4; + public static final int SCREAM = 5; + public static final int BONE = 6; + public static final int WOOL = 7; + public static final int ROCK = 8; + public static final int NOTE = 9; + public static final int CHANGE = 10; + public static final int HEART = 11; + public static final int BUBBLE = 12; + public static final int STEAM = 13; + public static final int COIN = 14; + public static final int COBWEB = 15; + + public static final int DISCOVER = 101; + public static final int EVOKE = 102; + public static final int MASTERY = 103; + public static final int KIT = 104; + public static final int RATTLE = 105; + public static final int JET = 106; + public static final int TOXIC = 107; + public static final int PARALYSIS = 108; + public static final int DUST = 109; + public static final int STENCH = 110; + public static final int FORGE = 111; + public static final int CONFUSION = 112; + public static final int FROST = 113; + public static final int TARGAS = 114; + public static final int DARKNESS = 115; + public static final int CORRUPT = 116; + public static final int VENOM = 117; + + private static final int SIZE = 7; + + private int type; + private float lifespan; + private float left; + + private static TextureFilm film; + + private static SparseArray factories = new SparseArray(); + + public Speck() { + super(); + + texture(Assets.SPECKS); + if (film == null) { + film = new TextureFilm(texture, SIZE, SIZE); + } + + origin.set(SIZE / 2f); + } + + public void reset(int index, float x, float y, int type) { + revive(); + + this.type = type; + switch (type) { + case DISCOVER: + frame(film.get(LIGHT)); + break; + case EVOKE: + case MASTERY: + case KIT: + case FORGE: + frame(film.get(STAR)); + break; + case RATTLE: + frame(film.get(BONE)); + break; + case JET: + case TOXIC: + case PARALYSIS: + case STENCH: + case CONFUSION: + case DUST: + case CORRUPT: + case FROST: + case TARGAS: + case DARKNESS: + case VENOM: + frame(film.get(STEAM)); + break; + default: + frame(film.get(type)); + } + + this.x = x - origin.x; + this.y = y - origin.y; + + resetColor(); + scale.set(1); + speed.set(0); + acc.set(0); + angle = 0; + angularSpeed = 0; + + switch (type) { + + case HEALING: + speed.set(0, -20); + lifespan = 1f; + break; + + case STAR: + speed.polar(Random.Float(2 * 3.1415926f), Random.Float(128)); + acc.set(0, 128); + angle = Random.Float(360); + angularSpeed = Random.Float(-360, +360); + lifespan = 1f; + break; + + case FORGE: + speed.polar(Random.Float(-3.1415926f), Random.Float(64)); + acc.set(0, 128); + angle = Random.Float(360); + angularSpeed = Random.Float(-360, +360); + lifespan = 0.51f; + break; + + case EVOKE: + speed.polar(Random.Float(-3.1415926f), 50); + acc.set(0, 50); + angle = Random.Float(360); + angularSpeed = Random.Float(-180, +180); + lifespan = 1f; + break; + + case KIT: + speed.polar(index * 3.1415926f / 5, 50); + acc.set(-speed.x, -speed.y); + angle = index * 36; + angularSpeed = 360; + lifespan = 1f; + break; + + case MASTERY: + speed.set( + Random.Int(2) == 0 ? Random.Float(-128, -64) : Random + .Float(+64, +128), 0); + angularSpeed = speed.x < 0 ? -180 : +180; + acc.set(-speed.x, 0); + lifespan = 0.5f; + break; + + case LIGHT: + angle = Random.Float(360); + angularSpeed = 90; + lifespan = 1f; + break; + + case DISCOVER: + angle = Random.Float(360); + angularSpeed = 90; + lifespan = 0.5f; + am = 0; + break; + + case QUESTION: + lifespan = 0.8f; + break; + + case UP: + speed.set(0, -20); + lifespan = 1f; + break; + + case SCREAM: + lifespan = 0.9f; + break; + + case BONE: + lifespan = 0.2f; + speed.polar(Random.Float(2 * 3.1415926f), 24 / lifespan); + acc.set(0, 128); + angle = Random.Float(360); + angularSpeed = 360; + break; + + case RATTLE: + lifespan = 0.5f; + speed.set(0, -200); + acc.set(0, -2 * speed.y / lifespan); + angle = Random.Float(360); + angularSpeed = 360; + break; + + case WOOL: + lifespan = 0.5f; + speed.set(0, -50); + angle = Random.Float(360); + angularSpeed = Random.Float(-360, +360); + break; + + case ROCK: + angle = Random.Float(360); + angularSpeed = Random.Float(-360, +360); + scale.set(Random.Float(1, 2)); + speed.set(0, 64); + lifespan = 0.2f; + y -= speed.y * lifespan; + break; + + case NOTE: + angularSpeed = Random.Float(-30, +30); + speed.polar((angularSpeed - 90) * PointF.G2R, 30); + lifespan = 1f; + break; + + case CHANGE: + angle = Random.Float(360); + speed.polar((angle - 90) * PointF.G2R, Random.Float(4, 12)); + lifespan = 1.5f; + break; + + case HEART: + speed.set(Random.Int(-10, +10), -40); + angularSpeed = Random.Float(-45, +45); + lifespan = 1f; + break; + + case BUBBLE: + speed.set(0, -15); + scale.set(Random.Float(0.8f, 1)); + lifespan = Random.Float(0.8f, 1.5f); + break; + + case STEAM: + speed.y = -Random.Float(20, 30); + angularSpeed = Random.Float(+180); + angle = Random.Float(360); + lifespan = 1f; + break; + + case JET: + speed.y = +32; + acc.y = -64; + angularSpeed = Random.Float(180, 360); + angle = Random.Float(360); + lifespan = 0.5f; + break; + + case TOXIC: + hardlight(0x50FF60); + angularSpeed = 30; + angle = Random.Float(360); + lifespan = Random.Float(1f, 3f); + break; + + case CORRUPT: + hardlight(0xFF0000); + angularSpeed = 30; + angle = Random.Float(360); + lifespan = Random.Float(1f, 3f); + break; + + case VENOM: + hardlight( 0x8844FF ); + angularSpeed = 30; + angle = Random.Float( 360 ); + lifespan = Random.Float( 1f, 3f ); + break; + + case FROST: + hardlight(0x99FFFF); + angularSpeed = 30; + angle = Random.Float(360); + lifespan = Random.Float(1f, 3f); + break; + + case TARGAS: + hardlight(0x996600); + angularSpeed = 30; + angle = Random.Float(360); + lifespan = Random.Float(1f, 3f); + break; + + case DARKNESS: + hardlight(0x22); + angularSpeed = 30; + angle = Random.Float(360); + lifespan = Random.Float(1f, 3f); + break; + + case PARALYSIS: + hardlight(0xFFFF66); + angularSpeed = -30; + angle = Random.Float(360); + lifespan = Random.Float(1f, 3f); + break; + + case STENCH: + hardlight(0x003300); + angularSpeed = -30; + angle = Random.Float(360); + lifespan = Random.Float(1f, 3f); + break; + + case CONFUSION: + hardlight(Random.Int(0x1000000) | 0x000080); + angularSpeed = Random.Float(-20, +20); + angle = Random.Float(360); + lifespan = Random.Float(1f, 3f); + break; + + case DUST: + hardlight(0xFFFF66); + angle = Random.Float(360); + speed.polar(Random.Float(2 * 3.1415926f), Random.Float(16, 48)); + lifespan = 0.5f; + break; + + case COIN: + speed.polar(-PointF.PI * Random.Float(0.3f, 0.7f), + Random.Float(48, 96)); + acc.y = 256; + lifespan = -speed.y / acc.y * 2; + break; + + case COBWEB: + angularSpeed = 0; + angle = Random.Float(360); + lifespan = Random.Float(1f, 3f); + break; + } + + left = lifespan; + } + + @SuppressLint("FloatMath") + @Override + public void update() { + super.update(); + + left -= Game.elapsed; + if (left <= 0) { + + kill(); + + } else { + + float p = 1 - left / lifespan; // 0 -> 1 + + switch (type) { + + case STAR: + case FORGE: + scale.set(1 - p); + am = p < 0.2f ? p * 5f : (1 - p) * 1.25f; + break; + + case KIT: + case MASTERY: + am = 1 - p * p; + break; + + case EVOKE: + + case HEALING: + am = p < 0.5f ? 1 : 2 - p * 2; + break; + + case LIGHT: + am = scale.set(p < 0.2f ? p * 5f : (1 - p) * 1.25f).x; + break; + + case DISCOVER: + am = 1 - p; + scale.set((p < 0.5f ? p : 1 - p) * 2); + break; + + case QUESTION: + scale.set((float) (Math.sqrt(p < 0.5f ? p : 1 - p) * 3)); + break; + + case UP: + scale.set((float) (Math.sqrt(p < 0.5f ? p : 1 - p) * 2)); + break; + + case SCREAM: + am = (float) Math.sqrt((p < 0.5f ? p : 1 - p) * 2f); + scale.set(p * 7); + break; + + case BONE: + case RATTLE: + am = p < 0.9f ? 1 : (1 - p) * 10; + break; + + case ROCK: + am = p < 0.2f ? p * 5 : 1; + break; + + case NOTE: + am = 1 - p * p; + break; + + case WOOL: + scale.set(1 - p); + break; + + case CHANGE: + am = (float)Math.sqrt((p < 0.5f ? p : 1 - p) * 2); + scale.y = (1 + p) * 0.5f; + scale.x = scale.y * (float)Math.cos(left * 15); + break; + + case HEART: + scale.set(1 - p); + am = 1 - p * p; + break; + + case BUBBLE: + am = p < 0.2f ? p * 5 : 1; + break; + + case STEAM: + case TOXIC: + case PARALYSIS: + case CONFUSION: + case CORRUPT: + case FROST: + case TARGAS: + case DARKNESS: + case DUST: + am = p < 0.5f ? p : 1 - p; + scale.set(1 + p * 2); + break; + + case VENOM: + hardlight( ColorMath.interpolate( 0x8844FF, 0x00FF00 , p )); + + case STENCH: + am = (p < 0.5f ? p : 1 - p) * 2; + scale.set(1 + p * 2); + break; + + case COBWEB: + am = p < 0.5f ? p : 1 - p; + scale.set( 1 + p ); + break; + + case JET: + am = (p < 0.5f ? p : 1 - p) * 2; + scale.set(p * 1.5f); + break; + + case COIN: + scale.x = (float)Math.cos(left * 5); + rm = gm = bm = (Math.abs(scale.x) + 1) * 0.5f; + am = p < 0.9f ? 1 : (1 - p) * 10; + break; + } + } + } + + public static Emitter.Factory factory(final int type) { + return factory(type, false); + } + + public static Emitter.Factory factory(final int type, + final boolean lightMode) { + + Emitter.Factory factory = factories.get(type); + + if (factory == null) { + factory = new Emitter.Factory() { + @Override + public void emit(Emitter emitter, int index, float x, float y) { + Speck p = (Speck) emitter.recycle(Speck.class); + p.reset(index, x, y, type); + } + + @Override + public boolean lightMode() { + return lightMode; + } + }; + factories.put(type, factory); + } + + return factory; + } +} diff --git a/java/com/hmdzl/spspd/effects/SpellSprite.java b/java/com/hmdzl/spspd/effects/SpellSprite.java new file mode 100644 index 00000000..279d5694 --- /dev/null +++ b/java/com/hmdzl/spspd/effects/SpellSprite.java @@ -0,0 +1,135 @@ +/* + * 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 + */ +package com.hmdzl.spspd.effects; + +import java.util.HashMap; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.scenes.GameScene; +import com.watabou.noosa.Game; +import com.watabou.noosa.Image; +import com.watabou.noosa.TextureFilm; + +public class SpellSprite extends Image { + + public static final int FOOD = 0; + public static final int MAP = 1; + public static final int CHARGE = 2; + public static final int MASTERY = 3; + + private static final int SIZE = 16; + + private enum Phase { + FADE_IN, STATIC, FADE_OUT + }; + + private static final float FADE_IN_TIME = 0.2f; + private static final float STATIC_TIME = 0.8f; + private static final float FADE_OUT_TIME = 0.4f; + + private static TextureFilm film; + + private Char target; + + private Phase phase; + private float duration; + private float passed; + + private static HashMap all = new HashMap(); + + public SpellSprite() { + super(Assets.SPELL_ICONS); + + if (film == null) { + film = new TextureFilm(texture, SIZE); + } + } + + public void reset(int index) { + frame(film.get(index)); + origin.set(width / 2, height / 2); + + phase = Phase.FADE_IN; + + duration = FADE_IN_TIME; + passed = 0; + } + + @Override + public void update() { + super.update(); + + x = target.sprite.center().x - SIZE / 2; + y = target.sprite.y - SIZE; + + switch (phase) { + case FADE_IN: + alpha(passed / duration); + scale.set(passed / duration); + break; + case STATIC: + break; + case FADE_OUT: + alpha(1 - passed / duration); + break; + } + + if ((passed += Game.elapsed) > duration) { + switch (phase) { + case FADE_IN: + phase = Phase.STATIC; + duration = STATIC_TIME; + break; + case STATIC: + phase = Phase.FADE_OUT; + duration = FADE_OUT_TIME; + break; + case FADE_OUT: + kill(); + break; + } + + passed = 0; + } + } + + @Override + public void kill() { + super.kill(); + all.remove(target); + } + + public static void show(Char ch, int index) { + + if (!ch.sprite.visible) { + return; + } + + SpellSprite old = all.get(ch); + if (old != null) { + old.kill(); + } + + SpellSprite sprite = GameScene.spellSprite(); + sprite.revive(); + sprite.reset(index); + sprite.target = ch; + all.put(ch, sprite); + } +} diff --git a/java/com/hmdzl/spspd/effects/Splash.java b/java/com/hmdzl/spspd/effects/Splash.java new file mode 100644 index 00000000..879a5f58 --- /dev/null +++ b/java/com/hmdzl/spspd/effects/Splash.java @@ -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 + */ +package com.hmdzl.spspd.effects; + +import com.hmdzl.spspd.DungeonTilemap; +import com.hmdzl.spspd.scenes.GameScene; +import com.watabou.noosa.particles.Emitter; +import com.watabou.noosa.particles.PixelParticle; +import com.watabou.utils.PointF; +import com.watabou.utils.Random; + +public class Splash { + + public static void at(int cell, final int color, int n) { + at(DungeonTilemap.tileCenterToWorld(cell), color, n); + } + + public static void at(PointF p, final int color, int n) { + + if (n <= 0) { + return; + } + + Emitter emitter = GameScene.emitter(); + emitter.pos(p); + + FACTORY.color = color; + FACTORY.dir = -3.1415926f / 2; + FACTORY.cone = 3.1415926f; + emitter.burst(FACTORY, n); + } + + public static void at(PointF p, final float dir, final float cone, + final int color, int n) { + + if (n <= 0) { + return; + } + + Emitter emitter = GameScene.emitter(); + emitter.pos(p); + + FACTORY.color = color; + FACTORY.dir = dir; + FACTORY.cone = cone; + emitter.burst(FACTORY, n); + } + + private static final SplashFactory FACTORY = new SplashFactory(); + + private static class SplashFactory extends Emitter.Factory { + + public int color; + public float dir; + public float cone; + + @Override + public void emit(Emitter emitter, int index, float x, float y) { + PixelParticle p = (PixelParticle) emitter + .recycle(PixelParticle.Shrinking.class); + + p.reset(x, y, color, 4, Random.Float(0.5f, 1.0f)); + p.speed.polar(Random.Float(dir - cone / 2, dir + cone / 2), + Random.Float(40, 80)); + p.acc.set(0, +100); + } + } +} diff --git a/java/com/hmdzl/spspd/effects/Surprise.java b/java/com/hmdzl/spspd/effects/Surprise.java new file mode 100644 index 00000000..ac03b2b9 --- /dev/null +++ b/java/com/hmdzl/spspd/effects/Surprise.java @@ -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 + */ +package com.hmdzl.spspd.effects; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.DungeonTilemap; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.levels.Level; +import com.watabou.noosa.Game; +import com.watabou.noosa.Group; +import com.watabou.noosa.Image; + +public class Surprise extends Image { + + +private static final float TIME_TO_FADE = 0.8f; + + private float time; + + public Surprise() { + super(Effects.get(Effects.Type.EXCLAMATION)); + origin.set(width / 2, height / 2); + } + + public void reset(int p) { + revive(); + + x = (p % Level.getWidth()) * DungeonTilemap.SIZE + (DungeonTilemap.SIZE - width) / 2; + y = (p / Level.getWidth()) * DungeonTilemap.SIZE + (DungeonTilemap.SIZE - height) / 2; + + time = TIME_TO_FADE; + } + + @Override + public void update() { + super.update(); + + if ((time -= Game.elapsed) <= 0) { + kill(); + } else { + float p = time / TIME_TO_FADE; + alpha(p); + scale.y = 1 + p/2; + } + } + + public static void hit(Char ch) { + hit(ch, 0); + } + + public static void hit(Char ch, float angle) { + if (ch.sprite.parent != null) { + Surprise s = (Surprise) ch.sprite.parent.recycle(Surprise.class); + ch.sprite.parent.bringToFront(s); + s.reset(ch.pos); + s.angle = angle; + } + } + + public static void hit(int pos) { + hit(pos, 0); + } + + public static void hit(int pos, float angle) { + Group parent = Dungeon.hero.sprite.parent; + Wound w = (Wound) parent.recycle(Wound.class); + parent.bringToFront(w); + w.reset(pos); + w.angle = angle; + } +} diff --git a/java/com/hmdzl/spspd/effects/TorchHalo.java b/java/com/hmdzl/spspd/effects/TorchHalo.java new file mode 100644 index 00000000..652b6011 --- /dev/null +++ b/java/com/hmdzl/spspd/effects/TorchHalo.java @@ -0,0 +1,71 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2014 Oleg Dolya + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.effects; + +import javax.microedition.khronos.opengles.GL10; + +import android.opengl.GLES20; + +import com.hmdzl.spspd.sprites.CharSprite; +import com.watabou.noosa.Game; + +public class TorchHalo extends Halo { + + private CharSprite target; + + private float phase = 0; + + public TorchHalo(CharSprite sprite) { + super(24, 0xFFDDCC, 0.15f); + target = sprite; + am = 0; + } + + @Override + public void update() { + super.update(); + + if (phase < 0) { + if ((phase += Game.elapsed) >= 0) { + killAndErase(); + } else { + scale.set((2 + phase) * radius / RADIUS); + am = -phase * brightness; + } + } else if (phase < 1) { + if ((phase += Game.elapsed) >= 1) { + phase = 1; + } + scale.set(phase * radius / RADIUS); + am = phase * brightness; + } + + point(target.x + target.width / 2, target.y + target.height / 2); + } + + @Override + public void draw() { + GLES20.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE); + super.draw(); + GLES20.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA); + } + + public void putOut() { + phase = -1; + } +} diff --git a/java/com/hmdzl/spspd/effects/Wound.java b/java/com/hmdzl/spspd/effects/Wound.java new file mode 100644 index 00000000..cf9479a1 --- /dev/null +++ b/java/com/hmdzl/spspd/effects/Wound.java @@ -0,0 +1,87 @@ +/* + * 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 + */ +package com.hmdzl.spspd.effects; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.DungeonTilemap; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.levels.Level; +import com.watabou.noosa.Game; +import com.watabou.noosa.Group; +import com.watabou.noosa.Image; + +public class Wound extends Image { + + private static final float TIME_TO_FADE = 0.8f; + + private float time; + + public Wound() { + super(Effects.get(Effects.Type.WOUND)); + origin.set(width / 2, height / 2); + } + + public void reset(int p) { + revive(); + + x = (p % Level.getWidth()) * DungeonTilemap.SIZE + + (DungeonTilemap.SIZE - width) / 2; + y = (p / Level.getWidth()) * DungeonTilemap.SIZE + + (DungeonTilemap.SIZE - height) / 2; + + time = TIME_TO_FADE; + } + + @Override + public void update() { + super.update(); + + if ((time -= Game.elapsed) <= 0) { + kill(); + } else { + float p = time / TIME_TO_FADE; + alpha(p); + scale.x = 1 + p; + } + } + + public static void hit(Char ch) { + hit(ch, 0); + } + + public static void hit(Char ch, float angle) { + if (ch.sprite.parent != null) { + Wound w = (Wound) ch.sprite.parent.recycle(Wound.class); + ch.sprite.parent.bringToFront(w); + w.reset(ch.pos); + w.angle = angle; + } + } + + public static void hit(int pos) { + hit(pos, 0); + } + + public static void hit(int pos, float angle) { + Group parent = Dungeon.hero.sprite.parent; + Wound w = (Wound) parent.recycle(Wound.class); + parent.bringToFront(w); + w.reset(pos); + w.angle = angle; + } +} diff --git a/java/com/hmdzl/spspd/effects/particles/BlastParticle.java b/java/com/hmdzl/spspd/effects/particles/BlastParticle.java new file mode 100644 index 00000000..6d0bd649 --- /dev/null +++ b/java/com/hmdzl/spspd/effects/particles/BlastParticle.java @@ -0,0 +1,63 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 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 + */ +package com.hmdzl.spspd.effects.particles; + +import com.watabou.noosa.particles.Emitter; +import com.watabou.noosa.particles.Emitter.Factory; +import com.watabou.noosa.particles.PixelParticle; +import com.watabou.utils.Random; + +public class BlastParticle extends PixelParticle.Shrinking { + + public static final Factory FACTORY = new Factory() { + @Override + public void emit(Emitter emitter, int index, float x, float y) { + ((BlastParticle) emitter.recycle(BlastParticle.class)).reset(x, y); + } + + @Override + public boolean lightMode() { + return true; + }; + }; + + public BlastParticle() { + super(); + + color(0xEE7722); + acc.set(0, +50); + } + + public void reset(float x, float y) { + revive(); + + this.x = x; + this.y = y; + + left = lifespan = Random.Float(); + + size = 8; + speed.polar(-Random.Float(3.1415926f), Random.Float(32, 64)); + } + + @Override + public void update() { + super.update(); + am = left > 0.8f ? (1 - left) * 5 : 1; + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/effects/particles/BloodParticle.java b/java/com/hmdzl/spspd/effects/particles/BloodParticle.java new file mode 100644 index 00000000..7ed34261 --- /dev/null +++ b/java/com/hmdzl/spspd/effects/particles/BloodParticle.java @@ -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 + */ +package com.hmdzl.spspd.effects.particles; + +import com.watabou.noosa.particles.Emitter; +import com.watabou.noosa.particles.Emitter.Factory; +import com.watabou.noosa.particles.PixelParticle; + +public class BloodParticle extends PixelParticle.Shrinking { + + public static final Emitter.Factory FACTORY = new Factory() { + @Override + public void emit(Emitter emitter, int index, float x, float y) { + ((BloodParticle) emitter.recycle(BloodParticle.class)).reset(x, y); + } + }; + + public BloodParticle() { + super(); + + color(0xFFFFFF); + lifespan = 0.8f; + + acc.set(0, +40); + } + + public void reset(float x, float y) { + revive(); + + this.x = x; + this.y = y; + + left = lifespan; + + size = 4; + speed.set(0); + } + + @Override + public void update() { + super.update(); + float p = left / lifespan; + am = p > 0.6f ? (1 - p) * 2.5f : 1; + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/effects/particles/DeadParticle.java b/java/com/hmdzl/spspd/effects/particles/DeadParticle.java new file mode 100644 index 00000000..d48695ab --- /dev/null +++ b/java/com/hmdzl/spspd/effects/particles/DeadParticle.java @@ -0,0 +1,69 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Yet Another Pixel Dungeon + * Copyright (C) 2015-2016 Considered Hamster + * + * 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 + */ +package com.hmdzl.spspd.effects.particles; + +import com.watabou.noosa.particles.Emitter; +import com.watabou.noosa.particles.Emitter.Factory; +import com.watabou.noosa.particles.PixelParticle; +import com.watabou.utils.Random; + +public class DeadParticle extends PixelParticle { + + public static final Factory FACTORY = new Factory() { + @Override + public void emit( Emitter emitter, int index, float x, float y ) { + ((DeadParticle)emitter.recycle( DeadParticle.class )).reset( x, y ); + } + @Override + public boolean lightMode() { + return true; + } + }; + + public DeadParticle() { + super(); + color(0x222222); + lifespan = 1f; + speed.set( 0, 8 ); + } + + private float offs; + + public void reset( float x, float y ) { + revive(); + + this.x = x; + this.y = y; + + offs = -Random.Float( lifespan ); + left = lifespan - offs; + } + + @Override + public void update() { + super.update(); + + float p = left / lifespan; + am = p < 0.5f ? p : 1 - p; + scale.x = (1 - p) * 2; + scale.y = 16 + (1 - p) * 16; + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/effects/particles/EarthParticle.java b/java/com/hmdzl/spspd/effects/particles/EarthParticle.java new file mode 100644 index 00000000..8d511659 --- /dev/null +++ b/java/com/hmdzl/spspd/effects/particles/EarthParticle.java @@ -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 + */ +package com.hmdzl.spspd.effects.particles; + +import com.watabou.noosa.particles.Emitter; +import com.watabou.noosa.particles.Emitter.Factory; +import com.watabou.noosa.particles.PixelParticle; +import com.watabou.utils.ColorMath; +import com.watabou.utils.Random; + +public class EarthParticle extends PixelParticle { + + public static final Emitter.Factory FACTORY = new Factory() { + @Override + public void emit(Emitter emitter, int index, float x, float y) { + ((EarthParticle) emitter.recycle(EarthParticle.class)).reset(x, y); + } + }; + + public EarthParticle() { + super(); + + color(ColorMath.random(0x444444, 0x777766)); + angle = Random.Float(-30, 30); + + lifespan = 0.5f; + } + + public void reset(float x, float y) { + revive(); + + this.x = x; + this.y = y; + + left = lifespan; + } + + @Override + public void update() { + super.update(); + + float p = left / lifespan; + size((p < 0.5f ? p : 1 - p) * 16); + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/effects/particles/ElmoParticle.java b/java/com/hmdzl/spspd/effects/particles/ElmoParticle.java new file mode 100644 index 00000000..88ad9586 --- /dev/null +++ b/java/com/hmdzl/spspd/effects/particles/ElmoParticle.java @@ -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 + */ +package com.hmdzl.spspd.effects.particles; + +import com.watabou.noosa.particles.Emitter; +import com.watabou.noosa.particles.Emitter.Factory; +import com.watabou.noosa.particles.PixelParticle; + +public class ElmoParticle extends PixelParticle.Shrinking { + + public static final Emitter.Factory FACTORY = new Factory() { + @Override + public void emit(Emitter emitter, int index, float x, float y) { + ((ElmoParticle) emitter.recycle(ElmoParticle.class)).reset(x, y); + } + + @Override + public boolean lightMode() { + return true; + }; + }; + + public ElmoParticle() { + super(); + + color(0x22EE66); + lifespan = 0.6f; + + acc.set(0, -80); + } + + public void reset(float x, float y) { + revive(); + + this.x = x; + this.y = y; + + left = lifespan; + + size = 4; + speed.set(0); + } + + @Override + public void update() { + super.update(); + float p = left / lifespan; + am = p > 0.8f ? (1 - p) * 5 : 1; + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/effects/particles/EnergyParticle.java b/java/com/hmdzl/spspd/effects/particles/EnergyParticle.java new file mode 100644 index 00000000..974c964d --- /dev/null +++ b/java/com/hmdzl/spspd/effects/particles/EnergyParticle.java @@ -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 + */ +package com.hmdzl.spspd.effects.particles; + +import com.watabou.noosa.particles.Emitter; +import com.watabou.noosa.particles.Emitter.Factory; +import com.watabou.noosa.particles.PixelParticle; +import com.watabou.utils.PointF; +import com.watabou.utils.Random; + +public class EnergyParticle extends PixelParticle { + + public static final Emitter.Factory FACTORY = new Factory() { + @Override + public void emit(Emitter emitter, int index, float x, float y) { + ((EnergyParticle) emitter.recycle(EnergyParticle.class)) + .reset(x, y); + } + + @Override + public boolean lightMode() { + return true; + }; + }; + + public EnergyParticle() { + super(); + + lifespan = 1f; + color(0xFFFFAA); + + speed.polar(Random.Float(PointF.PI2), Random.Float(24, 32)); + } + + public void reset(float x, float y) { + revive(); + + left = lifespan; + + this.x = x - speed.x * lifespan; + this.y = y - speed.y * lifespan; + } + + @Override + public void update() { + super.update(); + + float p = left / lifespan; + am = p < 0.5f ? p * p * 4 : (1 - p) * 2; + size(Random.Float(5 * left / lifespan)); + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/effects/particles/FlameParticle.java b/java/com/hmdzl/spspd/effects/particles/FlameParticle.java new file mode 100644 index 00000000..ecca2cb5 --- /dev/null +++ b/java/com/hmdzl/spspd/effects/particles/FlameParticle.java @@ -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 + */ +package com.hmdzl.spspd.effects.particles; + +import com.watabou.noosa.particles.Emitter; +import com.watabou.noosa.particles.Emitter.Factory; +import com.watabou.noosa.particles.PixelParticle; + +public class FlameParticle extends PixelParticle.Shrinking { + + public static final Emitter.Factory FACTORY = new Factory() { + @Override + public void emit(Emitter emitter, int index, float x, float y) { + ((FlameParticle) emitter.recycle(FlameParticle.class)).reset(x, y); + } + + @Override + public boolean lightMode() { + return true; + }; + }; + + public FlameParticle() { + super(); + + color(0xEE7722); + lifespan = 0.6f; + + acc.set(0, -80); + } + + public void reset(float x, float y) { + revive(); + + this.x = x; + this.y = y; + + left = lifespan; + + size = 4; + speed.set(0); + } + + @Override + public void update() { + super.update(); + float p = left / lifespan; + am = p > 0.8f ? (1 - p) * 5 : 1; + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/effects/particles/FlowParticle.java b/java/com/hmdzl/spspd/effects/particles/FlowParticle.java new file mode 100644 index 00000000..720af57d --- /dev/null +++ b/java/com/hmdzl/spspd/effects/particles/FlowParticle.java @@ -0,0 +1,109 @@ +/* + * 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 + */ +package com.hmdzl.spspd.effects.particles; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.DungeonTilemap; +import com.watabou.noosa.Game; +import com.watabou.noosa.Group; +import com.watabou.noosa.particles.Emitter; +import com.watabou.noosa.particles.Emitter.Factory; +import com.watabou.noosa.particles.PixelParticle; +import com.watabou.utils.PointF; +import com.watabou.utils.Random; + +public class FlowParticle extends PixelParticle { + + public static final Emitter.Factory FACTORY = new Factory() { + @Override + public void emit(Emitter emitter, int index, float x, float y) { + ((FlowParticle) emitter.recycle(FlowParticle.class)).reset(x, y); + } + }; + + public FlowParticle() { + super(); + + lifespan = 0.6f; + acc.set(0, 32); + angularSpeed = Random.Float(-360, +360); + } + + public void reset(float x, float y) { + revive(); + + left = lifespan; + + this.x = x; + this.y = y; + + am = 0; + size(0); + speed.set(0); + } + + @Override + public void update() { + super.update(); + + float p = left / lifespan; + am = (p < 0.5f ? p : 1 - p) * 0.6f; + size((1 - p) * 4); + } + + public static class Flow extends Group { + + private static final float DELAY = 0.1f; + + private int pos; + + private float x; + private float y; + + private float delay; + + public Flow(int pos) { + super(); + + this.pos = pos; + + PointF p = DungeonTilemap.tileToWorld(pos); + x = p.x; + y = p.y + DungeonTilemap.SIZE - 1; + + delay = Random.Float(DELAY); + } + + @Override + public void update() { + + if (visible = Dungeon.visible[pos]) { + + super.update(); + + if ((delay -= Game.elapsed) <= 0) { + + delay = Random.Float(DELAY); + + ((FlowParticle) recycle(FlowParticle.class)).reset(x + + Random.Float(DungeonTilemap.SIZE), y); + } + } + } + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/effects/particles/LeafParticle.java b/java/com/hmdzl/spspd/effects/particles/LeafParticle.java new file mode 100644 index 00000000..e628ac2a --- /dev/null +++ b/java/com/hmdzl/spspd/effects/particles/LeafParticle.java @@ -0,0 +1,71 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2014 Oleg Dolya + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.effects.particles; + +import com.hmdzl.spspd.Dungeon; +import com.watabou.noosa.particles.Emitter; +import com.watabou.noosa.particles.Emitter.Factory; +import com.watabou.noosa.particles.PixelParticle; +import com.watabou.utils.ColorMath; +import com.watabou.utils.Random; + +public class LeafParticle extends PixelParticle.Shrinking { + + public static int color1; + public static int color2; + + public static final Emitter.Factory GENERAL = new Factory() { + @Override + public void emit(Emitter emitter, int index, float x, float y) { + LeafParticle p = ((LeafParticle) emitter + .recycle(LeafParticle.class)); + p.color(ColorMath.random(0x004400, 0x88CC44)); + p.reset(x, y); + } + }; + + public static final Emitter.Factory LEVEL_SPECIFIC = new Factory() { + @Override + public void emit(Emitter emitter, int index, float x, float y) { + LeafParticle p = ((LeafParticle) emitter + .recycle(LeafParticle.class)); + p.color(ColorMath + .random(Dungeon.level.color1, Dungeon.level.color2)); + p.reset(x, y); + } + }; + + public LeafParticle() { + super(); + + lifespan = 1.2f; + acc.set(0, 25); + } + + public void reset(float x, float y) { + revive(); + + this.x = x; + this.y = y; + + speed.set(Random.Float(-8, +8), -20); + + left = lifespan; + size = Random.Float(2, 3); + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/effects/particles/MemoryParticle.java b/java/com/hmdzl/spspd/effects/particles/MemoryParticle.java new file mode 100644 index 00000000..7a7b1314 --- /dev/null +++ b/java/com/hmdzl/spspd/effects/particles/MemoryParticle.java @@ -0,0 +1,65 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 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 + */ +package com.hmdzl.spspd.effects.particles; + +import com.watabou.noosa.particles.Emitter; +import com.watabou.noosa.particles.PixelParticle; +import com.watabou.noosa.particles.Emitter.Factory; + +public class MemoryParticle extends PixelParticle.Shrinking { + + public static final Emitter.Factory FACTORY = new Factory() { + @Override + public void emit( Emitter emitter, int index, float x, float y ) { + ((MemoryParticle)emitter.recycle( MemoryParticle.class )).reset( x, y ); + } + @Override + public boolean lightMode() { + return true; + }; + }; + + public MemoryParticle() { + super(); + + //color( 0x4488EE ); + color( 0x22CC44 ); + lifespan = 0.6f; + + acc.set( 0, -100 ); + } + + public void reset( float x, float y ) { + revive(); + + this.x = x; + this.y = y - 4; + + left = lifespan; + + size = 4; + speed.set( 0 ); + } + + @Override + public void update() { + super.update(); + float p = left / lifespan; + am = p > 0.75f ? (1 - p) * 4 : 1; + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/effects/particles/PoisonParticle.java b/java/com/hmdzl/spspd/effects/particles/PoisonParticle.java new file mode 100644 index 00000000..e24326db --- /dev/null +++ b/java/com/hmdzl/spspd/effects/particles/PoisonParticle.java @@ -0,0 +1,92 @@ +/* + * 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 + */ +package com.hmdzl.spspd.effects.particles; + +import com.watabou.noosa.particles.Emitter; +import com.watabou.noosa.particles.Emitter.Factory; +import com.watabou.noosa.particles.PixelParticle; +import com.watabou.utils.ColorMath; +import com.watabou.utils.Random; + +public class PoisonParticle extends PixelParticle { + + public static final Emitter.Factory MISSILE = new Factory() { + @Override + public void emit(Emitter emitter, int index, float x, float y) { + ((PoisonParticle) emitter.recycle(PoisonParticle.class)) + .resetMissile(x, y); + } + + @Override + public boolean lightMode() { + return true; + }; + }; + + public static final Emitter.Factory SPLASH = new Factory() { + @Override + public void emit(Emitter emitter, int index, float x, float y) { + ((PoisonParticle) emitter.recycle(PoisonParticle.class)) + .resetSplash(x, y); + } + + @Override + public boolean lightMode() { + return true; + }; + }; + + public PoisonParticle() { + super(); + + lifespan = 0.6f; + + acc.set(0, +30); + } + + public void resetMissile(float x, float y) { + revive(); + + this.x = x; + this.y = y; + + left = lifespan; + + speed.polar(-Random.Float(3.1415926f), Random.Float(6)); + } + + public void resetSplash(float x, float y) { + revive(); + + this.x = x; + this.y = y; + + left = lifespan; + + speed.polar(Random.Float(3.1415926f), Random.Float(10, 20)); + } + + @Override + public void update() { + super.update(); + // alpha: 1 -> 0; size: 1 -> 4 + size(4 - (am = left / lifespan) * 3); + // color: 0x8844FF -> 0x00FF00 + color(ColorMath.interpolate(0x00FF00, 0x8844FF, am)); + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/effects/particles/PurpleParticle.java b/java/com/hmdzl/spspd/effects/particles/PurpleParticle.java new file mode 100644 index 00000000..3259ae39 --- /dev/null +++ b/java/com/hmdzl/spspd/effects/particles/PurpleParticle.java @@ -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 + */ +package com.hmdzl.spspd.effects.particles; + +import com.watabou.noosa.particles.Emitter; +import com.watabou.noosa.particles.Emitter.Factory; +import com.watabou.noosa.particles.PixelParticle; +import com.watabou.utils.ColorMath; +import com.watabou.utils.PointF; +import com.watabou.utils.Random; + +public class PurpleParticle extends PixelParticle { + + public static final Emitter.Factory MISSILE = new Factory() { + @Override + public void emit(Emitter emitter, int index, float x, float y) { + ((PurpleParticle) emitter.recycle(PurpleParticle.class)) + .reset(x, y); + } + }; + + public static final Emitter.Factory BURST = new Factory() { + @Override + public void emit(Emitter emitter, int index, float x, float y) { + ((PurpleParticle) emitter.recycle(PurpleParticle.class)) + .resetBurst(x, y); + } + + @Override + public boolean lightMode() { + return true; + } + }; + + public PurpleParticle() { + super(); + + lifespan = 0.5f; + } + + public void reset(float x, float y) { + revive(); + + this.x = x; + this.y = y; + + speed.set(Random.Float(-5, +5), Random.Float(-5, +5)); + + left = lifespan; + } + + public void resetBurst(float x, float y) { + revive(); + + this.x = x; + this.y = y; + + speed.polar(Random.Float(PointF.PI2), Random.Float(16, 32)); + + left = lifespan; + } + + @Override + public void update() { + super.update(); + // alpha: 1 -> 0; size: 1 -> 5 + size(5 - (am = left / lifespan) * 4); + // color: 0xFF0044 -> 0x220066 + color(ColorMath.interpolate(0x220066, 0xFF0044, am)); + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/effects/particles/RainParticle.java b/java/com/hmdzl/spspd/effects/particles/RainParticle.java new file mode 100644 index 00000000..d7107d2c --- /dev/null +++ b/java/com/hmdzl/spspd/effects/particles/RainParticle.java @@ -0,0 +1,69 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Yet Another Pixel Dungeon + * Copyright (C) 2015-2016 Considered Hamster + * + * 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 + */ +package com.hmdzl.spspd.effects.particles; + +import com.watabou.noosa.particles.Emitter; +import com.watabou.noosa.particles.Emitter.Factory; +import com.watabou.noosa.particles.PixelParticle; +import com.watabou.utils.Random; + +public class RainParticle extends PixelParticle { + + public static final Factory FACTORY = new Factory() { + @Override + public void emit( Emitter emitter, int index, float x, float y ) { + ((RainParticle)emitter.recycle( RainParticle.class )).reset( x, y ); + } + @Override + public boolean lightMode() { + return true; + } + }; + + public RainParticle() { + super(); + color(0x0088AA); + lifespan = 1f; + speed.set( 0, 8 ); + } + + private float offs; + + public void reset( float x, float y ) { + revive(); + + this.x = x; + this.y = y; + + offs = -Random.Float( lifespan ); + left = lifespan - offs; + } + + @Override + public void update() { + super.update(); + + float p = left / lifespan; + am = p < 0.5f ? p : 1 - p; + scale.x = (1 - p) * 2; + scale.y = 16 + (1 - p) * 16; + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/effects/particles/RainbowParticle.java b/java/com/hmdzl/spspd/effects/particles/RainbowParticle.java new file mode 100644 index 00000000..dae66dcb --- /dev/null +++ b/java/com/hmdzl/spspd/effects/particles/RainbowParticle.java @@ -0,0 +1,77 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2015 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.effects.particles; + +import com.watabou.noosa.particles.Emitter; +import com.watabou.noosa.particles.PixelParticle; +import com.watabou.utils.PointF; +import com.watabou.utils.Random; + +public class RainbowParticle extends PixelParticle { + + public static final Emitter.Factory BURST = new Emitter.Factory() { + @Override + public void emit( Emitter emitter, int index, float x, float y ) { + ((RainbowParticle)emitter.recycle( RainbowParticle.class )).resetBurst( x, y ); + } + @Override + public boolean lightMode() { + return true; + } + }; + + + public RainbowParticle() { + super(); + color( Random.Int( 0x1000000 ) ); + lifespan = 0.5f; + } + + + public void reset( float x, float y ) { + revive(); + + this.x = x; + this.y = y; + + speed.set( Random.Float(-5, +5), Random.Float( -5, +5 ) ); + + left = lifespan; + } + + public void resetBurst( float x, float y ) { + revive(); + + this.x = x; + this.y = y; + + speed.polar( Random.Float( PointF.PI2 ), Random.Float( 16, 32 ) ); + + left = lifespan; + } + + @Override + public void update() { + super.update(); + // alpha: 1 -> 0; size: 1 -> 5 + size( 5 - (am = left / lifespan) * 4 ); + } +} diff --git a/java/com/hmdzl/spspd/effects/particles/SandParticle.java b/java/com/hmdzl/spspd/effects/particles/SandParticle.java new file mode 100644 index 00000000..59bd4e09 --- /dev/null +++ b/java/com/hmdzl/spspd/effects/particles/SandParticle.java @@ -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 + */ +package com.hmdzl.spspd.effects.particles; + +import com.watabou.noosa.particles.Emitter; +import com.watabou.noosa.particles.Emitter.Factory; +import com.watabou.noosa.particles.PixelParticle; +import com.watabou.utils.Random; + +public class SandParticle extends PixelParticle { + + public static final Emitter.Factory FACTORY = new Factory() { + @Override + public void emit(Emitter emitter, int index, float x, float y) { + ((SandParticle) emitter.recycle(SandParticle.class)).reset(x, y); + } + }; + + public SandParticle() { + super(); + color(0xFFCC00); + speed.set(0, Random.Float(5, 8)); + lifespan = 1.2f; + } + + public void reset(float x, float y) { + revive(); + + this.x = x; + this.y = y - speed.y * lifespan; + + left = lifespan; + } + + @Override + public void update() { + super.update(); + float p = left / lifespan; + am = (p < 0.5f ? p : 1 - p) * 1.5f; + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/effects/particles/ShadowParticle.java b/java/com/hmdzl/spspd/effects/particles/ShadowParticle.java new file mode 100644 index 00000000..c49d35a0 --- /dev/null +++ b/java/com/hmdzl/spspd/effects/particles/ShadowParticle.java @@ -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 + */ +package com.hmdzl.spspd.effects.particles; + +import com.watabou.noosa.particles.Emitter; +import com.watabou.noosa.particles.Emitter.Factory; +import com.watabou.noosa.particles.PixelParticle; +import com.watabou.utils.ColorMath; +import com.watabou.utils.PointF; +import com.watabou.utils.Random; + +public class ShadowParticle extends PixelParticle.Shrinking { + + public static final Emitter.Factory MISSILE = new Factory() { + @Override + public void emit(Emitter emitter, int index, float x, float y) { + ((ShadowParticle) emitter.recycle(ShadowParticle.class)) + .reset(x, y); + } + }; + + public static final Emitter.Factory CURSE = new Factory() { + @Override + public void emit(Emitter emitter, int index, float x, float y) { + ((ShadowParticle) emitter.recycle(ShadowParticle.class)) + .resetCurse(x, y); + } + }; + + public static final Emitter.Factory UP = new Factory() { + @Override + public void emit(Emitter emitter, int index, float x, float y) { + ((ShadowParticle) emitter.recycle(ShadowParticle.class)).resetUp(x, + y); + } + }; + + public void reset(float x, float y) { + revive(); + + this.x = x; + this.y = y; + + speed.set(Random.Float(-5, +5), Random.Float(-5, +5)); + + size = 6; + left = lifespan = 0.5f; + } + + public void resetCurse(float x, float y) { + revive(); + + size = 8; + left = lifespan = 0.5f; + + speed.polar(Random.Float(PointF.PI2), Random.Float(16, 32)); + this.x = x - speed.x * lifespan; + this.y = y - speed.y * lifespan; + } + + public void resetUp(float x, float y) { + revive(); + + speed.set(Random.Float(-8, +8), Random.Float(-32, -48)); + this.x = x; + this.y = y; + + size = 6; + left = lifespan = 1f; + } + + @Override + public void update() { + super.update(); + + float p = left / lifespan; + // alpha: 0 -> 1 -> 0; size: 6 -> 0; color: 0x660044 -> 0x000000 + color(ColorMath.interpolate(0x000000, 0x440044, p)); + am = p < 0.5f ? p * p * 4 : (1 - p) * 2; + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/effects/particles/ShaftParticle.java b/java/com/hmdzl/spspd/effects/particles/ShaftParticle.java new file mode 100644 index 00000000..81b39035 --- /dev/null +++ b/java/com/hmdzl/spspd/effects/particles/ShaftParticle.java @@ -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 + */ +package com.hmdzl.spspd.effects.particles; + +import com.watabou.noosa.particles.Emitter; +import com.watabou.noosa.particles.Emitter.Factory; +import com.watabou.noosa.particles.PixelParticle; +import com.watabou.utils.Random; + +public class ShaftParticle extends PixelParticle { + + public static final Emitter.Factory FACTORY = new Factory() { + @Override + public void emit(Emitter emitter, int index, float x, float y) { + ((ShaftParticle) emitter.recycle(ShaftParticle.class)).reset(x, y); + } + + @Override + public boolean lightMode() { + return true; + } + }; + + public ShaftParticle() { + super(); + + lifespan = 1.2f; + speed.set(0, -6); + } + + private float offs; + + public void reset(float x, float y) { + revive(); + + this.x = x; + this.y = y; + + offs = -Random.Float(lifespan); + left = lifespan - offs; + } + + @Override + public void update() { + super.update(); + + float p = left / lifespan; + am = p < 0.5f ? p : 1 - p; + scale.x = (1 - p) * 4; + scale.y = 16 + (1 - p) * 16; + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/effects/particles/ShockWebParticle.java b/java/com/hmdzl/spspd/effects/particles/ShockWebParticle.java new file mode 100644 index 00000000..11925b27 --- /dev/null +++ b/java/com/hmdzl/spspd/effects/particles/ShockWebParticle.java @@ -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 + */ +package com.hmdzl.spspd.effects.particles; + +import com.watabou.noosa.particles.Emitter; +import com.watabou.noosa.particles.Emitter.Factory; +import com.watabou.noosa.particles.PixelParticle; +import com.watabou.utils.Random; +import com.hmdzl.spspd.effects.Speck; + +public class ShockWebParticle extends PixelParticle { + + public static final Emitter.Factory FACTORY = new Factory() { + @Override + public void emit ( Emitter emitter, int index, float x, float y ) { + ((Speck)emitter.recycle( Speck.class )).reset( index, x, y, Speck.COBWEB ); + } + }; + + public ShockWebParticle() { + super(); + + color( 0x000CC ); + lifespan = 5f; + } + + public void reset( float x, float y ) { + revive(); + + this.x = x; + this.y = y; + + left = lifespan; + angle = Random.Float( 360 ); + } + + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/effects/particles/SmokeParticle.java b/java/com/hmdzl/spspd/effects/particles/SmokeParticle.java new file mode 100644 index 00000000..2ad2b173 --- /dev/null +++ b/java/com/hmdzl/spspd/effects/particles/SmokeParticle.java @@ -0,0 +1,60 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 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 + */ +package com.hmdzl.spspd.effects.particles; + +import com.watabou.noosa.particles.Emitter; +import com.watabou.noosa.particles.Emitter.Factory; +import com.watabou.noosa.particles.PixelParticle; +import com.watabou.utils.Random; + +public class SmokeParticle extends PixelParticle { + + public static final Factory FACTORY = new Factory() { + @Override + public void emit(Emitter emitter, int index, float x, float y) { + ((SmokeParticle) emitter.recycle(SmokeParticle.class)).reset(x, y); + } + }; + + public SmokeParticle() { + super(); + + color(0x222222); + + acc.set(0, -40); + } + + public void reset(float x, float y) { + revive(); + + this.x = x; + this.y = y; + + left = lifespan = Random.Float(0.6f, 1f); + speed.set(Random.Float(-4, +4), Random.Float(-8, +8)); + } + + @Override + public void update() { + super.update(); + + float p = left / lifespan; + am = p > 0.8f ? 2 - 2 * p : p * 0.5f; + size(16 - p * 8); + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/effects/particles/SnowParticle.java b/java/com/hmdzl/spspd/effects/particles/SnowParticle.java new file mode 100644 index 00000000..73034f1e --- /dev/null +++ b/java/com/hmdzl/spspd/effects/particles/SnowParticle.java @@ -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 + */ +package com.hmdzl.spspd.effects.particles; + +import com.watabou.noosa.particles.Emitter; +import com.watabou.noosa.particles.Emitter.Factory; +import com.watabou.noosa.particles.PixelParticle; +import com.watabou.utils.Random; + +public class SnowParticle extends PixelParticle { + + public static final Emitter.Factory FACTORY = new Factory() { + @Override + public void emit(Emitter emitter, int index, float x, float y) { + ((SnowParticle) emitter.recycle(SnowParticle.class)).reset(x, y); + } + }; + + public SnowParticle() { + super(); + speed.set(0, Random.Float(5, 8)); + lifespan = 1.2f; + } + + public void reset(float x, float y) { + revive(); + + this.x = x; + this.y = y - speed.y * lifespan; + + left = lifespan; + } + + @Override + public void update() { + super.update(); + float p = left / lifespan; + am = (p < 0.5f ? p : 1 - p) * 1.5f; + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/effects/particles/SparkParticle.java b/java/com/hmdzl/spspd/effects/particles/SparkParticle.java new file mode 100644 index 00000000..04c38873 --- /dev/null +++ b/java/com/hmdzl/spspd/effects/particles/SparkParticle.java @@ -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 + */ +package com.hmdzl.spspd.effects.particles; + +import com.watabou.noosa.particles.Emitter; +import com.watabou.noosa.particles.Emitter.Factory; +import com.watabou.noosa.particles.PixelParticle; +import com.watabou.utils.Random; + +public class SparkParticle extends PixelParticle { + + public static final Emitter.Factory FACTORY = new Factory() { + @Override + public void emit(Emitter emitter, int index, float x, float y) { + ((SparkParticle) emitter.recycle(SparkParticle.class)).reset(x, y); + } + + @Override + public boolean lightMode() { + return true; + }; + }; + + public SparkParticle() { + super(); + + size(2); + + acc.set(0, +50); + } + + public void reset(float x, float y) { + revive(); + + this.x = x; + this.y = y; + + left = lifespan = Random.Float(0.5f, 1.0f); + + speed.polar(-Random.Float(3.1415926f), Random.Float(20, 40)); + } + + @Override + public void update() { + super.update(); + size(Random.Float(5 * left / lifespan)); + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/effects/particles/WebParticle.java b/java/com/hmdzl/spspd/effects/particles/WebParticle.java new file mode 100644 index 00000000..b36b8a55 --- /dev/null +++ b/java/com/hmdzl/spspd/effects/particles/WebParticle.java @@ -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 + */ +package com.hmdzl.spspd.effects.particles; + +import com.watabou.noosa.particles.Emitter; +import com.watabou.noosa.particles.Emitter.Factory; +import com.watabou.noosa.particles.PixelParticle; +import com.watabou.utils.Random; +import com.hmdzl.spspd.effects.Speck; + +public class WebParticle extends PixelParticle { + + /*public static final Emitter.Factory FACTORY = new Factory() { + @Override + public void emit(Emitter emitter, int index, float x, float y) { + for (int i = 0; i < 3; i++) { + ((WebParticle) emitter.recycle(WebParticle.class)).reset(x, y); + } + } + };*/ + + public static final Emitter.Factory FACTORY = new Factory() { + @Override + public void emit ( Emitter emitter, int index, float x, float y ) { + ((Speck)emitter.recycle( Speck.class )).reset( index, x, y, Speck.COBWEB ); + } + }; + + public WebParticle() { + super(); + + color( 0xFFFFF ); + lifespan = 5f; + } + + public void reset( float x, float y ) { + revive(); + + this.x = x; + this.y = y; + + left = lifespan; + angle = Random.Float( 360 ); + } + + /*@Override + public void update() { + super.update(); + + float p = left / lifespan; + am = p < 0.5f ? p : 1 - p; + scale.y = 16 + p * 8; + }*/ +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/effects/particles/WindParticle.java b/java/com/hmdzl/spspd/effects/particles/WindParticle.java new file mode 100644 index 00000000..e2702027 --- /dev/null +++ b/java/com/hmdzl/spspd/effects/particles/WindParticle.java @@ -0,0 +1,112 @@ +/* + * 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 + */ +package com.hmdzl.spspd.effects.particles; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.DungeonTilemap; +import com.watabou.noosa.Game; +import com.watabou.noosa.Group; +import com.watabou.noosa.particles.Emitter; +import com.watabou.noosa.particles.Emitter.Factory; +import com.watabou.noosa.particles.PixelParticle; +import com.watabou.utils.PointF; +import com.watabou.utils.Random; + +public class WindParticle extends PixelParticle { + + public static final Emitter.Factory FACTORY = new Factory() { + @Override + public void emit(Emitter emitter, int index, float x, float y) { + ((WindParticle) emitter.recycle(WindParticle.class)).reset(x, y); + } + }; + + private static float angle = Random.Float(PointF.PI2); + private static PointF speed = new PointF().polar(angle, 5); + + public WindParticle() { + super(); + + lifespan = Random.Float(1, 2); + scale.set(size = Random.Float(3)); + } + + public void reset(float x, float y) { + revive(); + + left = lifespan; + + super.speed.set(WindParticle.speed); + super.speed.scale(size); + + this.x = x - super.speed.x * lifespan / 2; + this.y = y - super.speed.y * lifespan / 2; + + angle += Random.Float(-0.1f, +0.1f); + speed = new PointF().polar(angle, 5); + + am = 0; + } + + @Override + public void update() { + super.update(); + + float p = left / lifespan; + am = (p < 0.5f ? p : 1 - p) * size * 0.2f; + } + + public static class Wind extends Group { + + private int pos; + + private float x; + private float y; + + private float delay; + + public Wind(int pos) { + super(); + + this.pos = pos; + PointF p = DungeonTilemap.tileToWorld(pos); + x = p.x; + y = p.y; + + delay = Random.Float(5); + } + + @Override + public void update() { + + if (visible = Dungeon.visible[pos]) { + + super.update(); + + if ((delay -= Game.elapsed) <= 0) { + + delay = Random.Float(5); + + ((WindParticle) recycle(WindParticle.class)).reset(x + + Random.Float(DungeonTilemap.SIZE), + y + Random.Float(DungeonTilemap.SIZE)); + } + } + } + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/effects/particles/WoolParticle.java b/java/com/hmdzl/spspd/effects/particles/WoolParticle.java new file mode 100644 index 00000000..c94fae8a --- /dev/null +++ b/java/com/hmdzl/spspd/effects/particles/WoolParticle.java @@ -0,0 +1,54 @@ +/* + * 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 + */ +package com.hmdzl.spspd.effects.particles; + +import com.watabou.noosa.particles.Emitter; +import com.watabou.noosa.particles.Emitter.Factory; +import com.watabou.noosa.particles.PixelParticle; +import com.watabou.utils.ColorMath; +import com.watabou.utils.Random; + +public class WoolParticle extends PixelParticle.Shrinking { + + public static final Emitter.Factory FACTORY = new Factory() { + @Override + public void emit(Emitter emitter, int index, float x, float y) { + ((WoolParticle) emitter.recycle(WoolParticle.class)).reset(x, y); + } + }; + + public WoolParticle() { + super(); + + color(ColorMath.random(0x999999, 0xEEEEE0)); + + acc.set(0, -40); + } + + public void reset(float x, float y) { + revive(); + + this.x = x; + this.y = y; + + left = lifespan = Random.Float(0.6f, 1f); + size = 5; + + speed.set(Random.Float(-10, +10), Random.Float(-10, +10)); + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/AdamantArmor.java b/java/com/hmdzl/spspd/items/AdamantArmor.java new file mode 100644 index 00000000..f5fd9221 --- /dev/null +++ b/java/com/hmdzl/spspd/items/AdamantArmor.java @@ -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 + */ +package com.hmdzl.spspd.items; + +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class AdamantArmor extends Item { + + { + //name = "adamantite armor"; + image = ItemSpriteSheet.ARMOR_ADAMANT; + + unique = true; + } + + + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + @Override + public int price() { + return 300 * quantity; + } + +} diff --git a/java/com/hmdzl/spspd/items/AdamantRing.java b/java/com/hmdzl/spspd/items/AdamantRing.java new file mode 100644 index 00000000..cfd3de73 --- /dev/null +++ b/java/com/hmdzl/spspd/items/AdamantRing.java @@ -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 + */ +package com.hmdzl.spspd.items; + +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class AdamantRing extends Item { + + { + //name = "adamantite ring"; + image = ItemSpriteSheet.RING_ADAMANT; + + unique = true; + } + + + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + @Override + public int price() { + return 200 * quantity; + } + +} diff --git a/java/com/hmdzl/spspd/items/AdamantWand.java b/java/com/hmdzl/spspd/items/AdamantWand.java new file mode 100644 index 00000000..7e14b6f5 --- /dev/null +++ b/java/com/hmdzl/spspd/items/AdamantWand.java @@ -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 + */ +package com.hmdzl.spspd.items; + +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class AdamantWand extends Item { + + { + //name = "adamantite wand"; + image = ItemSpriteSheet.WAND_ADAMANT; + + unique = true; + } + + + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + @Override + public int price() { + return 150 * quantity; + } + +} diff --git a/java/com/hmdzl/spspd/items/AdamantWeapon.java b/java/com/hmdzl/spspd/items/AdamantWeapon.java new file mode 100644 index 00000000..e13f48d5 --- /dev/null +++ b/java/com/hmdzl/spspd/items/AdamantWeapon.java @@ -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 + */ +package com.hmdzl.spspd.items; + +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class AdamantWeapon extends Item { + + { + //name = "adamantite weapon"; + image = ItemSpriteSheet.ADAMANT_WEAPON; + + unique = true; + } + + + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + @Override + public int price() { + return 250 * quantity; + } +} diff --git a/java/com/hmdzl/spspd/items/Amulet.java b/java/com/hmdzl/spspd/items/Amulet.java new file mode 100644 index 00000000..cf91b1d0 --- /dev/null +++ b/java/com/hmdzl/spspd/items/Amulet.java @@ -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 + */ +package com.hmdzl.spspd.items; + +import java.io.IOException; +import java.util.ArrayList; + +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.Statistics; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.scenes.AmuletScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.noosa.Game; + +public class Amulet extends Item { + + private static final String AC_END = "END"; + + { + //name = "Amulet of Yendor"; + image = ItemSpriteSheet.AMULET; + + unique = true; + } + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + actions.add(AC_END); + return actions; + } + + @Override + public void execute(Hero hero, String action) { + if (action == AC_END) { + + showAmuletScene(); + + } else { + + super.execute(hero, action); + + } + } + + @Override + public boolean doPickUp(Hero hero) { + if (super.doPickUp(hero)) { + showAmuletScene(); + if (!Statistics.amuletObtained) { + Statistics.amuletObtained = true; + Badges.validateVictory(); + } + return true; + } else { + return false; + } + } + + private void showAmuletScene() { + try { + Dungeon.saveAll(); + Game.switchScene(AmuletScene.class); + } catch (IOException e) { + } + } + + @Override + public boolean isIdentified() { + return true; + } + + @Override + public boolean isUpgradable() { + return false; + } +} diff --git a/java/com/hmdzl/spspd/items/AncientCoin.java b/java/com/hmdzl/spspd/items/AncientCoin.java new file mode 100644 index 00000000..30621023 --- /dev/null +++ b/java/com/hmdzl/spspd/items/AncientCoin.java @@ -0,0 +1,149 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.items.artifacts.TimekeepersHourglass; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.InterlevelScene; +import com.hmdzl.spspd.sprites.ItemSprite.Glowing; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.noosa.Game; +import com.watabou.utils.Bundle; + +public class AncientCoin extends Item { + + public static final float TIME_TO_USE = 1; + + public static final String AC_PORT = "PORT"; + + private int specialLevel = 40; + private int returnDepth = -1; + private int returnPos; + + { + //name = "ancient coin"; + image = ItemSpriteSheet.COIN; + + stackable = false; + unique = true; + } + + private static final String DEPTH = "depth"; + private static final String POS = "pos"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(DEPTH, returnDepth); + if (returnDepth != -1) { + bundle.put(POS, returnPos); + } + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + returnDepth = bundle.getInt(DEPTH); + returnPos = bundle.getInt(POS); + } + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + actions.add(AC_PORT); + + return actions; + } + + @Override + public void execute(Hero hero, String action) { + + if (action == AC_PORT) { + + if ((Dungeon.bossLevel() || Dungeon.depth==1 || Dungeon.depth>25 || hero.petfollow) && Dungeon.depth!=specialLevel) { + hero.spend(TIME_TO_USE); + GLog.w(Messages.get(Item.class, "not_here")); + return; + } + + if (Dungeon.depth==specialLevel && !Dungeon.banditkingkilled && !Dungeon.level.reset) { + hero.spend(TIME_TO_USE); + GLog.w(Messages.get(Item.class, "boss_first")); + return; + } + + } + + if (action == AC_PORT) { + + + hero.spend(TIME_TO_USE); + + Buff buff = Dungeon.hero + .buff(TimekeepersHourglass.timeFreeze.class); + if (buff != null) + buff.detach(); + + if (Dungeon.depth<25 && !Dungeon.bossLevel()){ + + returnDepth = Dungeon.depth; + returnPos = hero.pos; + InterlevelScene.mode = InterlevelScene.Mode.PORTCOIN; + } else { + this.doDrop(hero); + InterlevelScene.mode = InterlevelScene.Mode.RETURN; + } + InterlevelScene.returnDepth = returnDepth; + InterlevelScene.returnPos = returnPos; + Game.switchScene(InterlevelScene.class); + + } else { + + super.execute(hero, action); + + } + } + + public void reset() { + returnDepth = -1; + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + + private static final Glowing BLACK = new Glowing(0x00000); + + @Override + public Glowing glowing() { + return BLACK; + } +} diff --git a/java/com/hmdzl/spspd/items/Ankh.java b/java/com/hmdzl/spspd/items/Ankh.java new file mode 100644 index 00000000..0cbdb294 --- /dev/null +++ b/java/com/hmdzl/spspd/items/Ankh.java @@ -0,0 +1,131 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.sprites.ItemSprite.Glowing; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Bundle; + +public class Ankh extends Item { + + public static final String AC_BLESS = "BLESS"; + + { + //name = "Ankh"; + image = ItemSpriteSheet.ANKH; + stackable = true; + + // You tell the ankh no, don't revive me, and then it comes back to + // revive you again in another run. + // I'm not sure if that's enthusiasm or passive-aggression. + + } + + private Boolean blessed = true; + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + DewVial vial = hero.belongings.getItem(DewVial.class); + if (vial != null && vial.isFullBless() && !blessed) + actions.add(AC_BLESS); + return actions; + } + + @Override + public void execute(final Hero hero, String action) { + if (action.equals(AC_BLESS)) { + + DewVial vial = hero.belongings.getItem(DewVial.class); + if (vial != null) { + blessed = true; + vial.empty(); + GLog.p(Messages.get(this, "bless")); + hero.spend(1f); + hero.busy(); + + Sample.INSTANCE.play(Assets.SND_DRINK); + CellEmitter.get(hero.pos).start(Speck.factory(Speck.LIGHT), + 0.2f, 3); + hero.sprite.operate(hero.pos); + } + } else { + + super.execute(hero, action); + + } + + } + + @Override + public String desc() { + if (blessed) + return Messages.get(this, "desc_blessed"); + else + return super.desc(); + } + + public Boolean isBlessed() { + return blessed; + } + + private static final Glowing WHITE = new Glowing(0xFFFFCC); + + @Override + public Glowing glowing() { + return isBlessed() ? WHITE : null; + } + + private static final String BLESSED = "blessed"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(BLESSED, blessed); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + blessed = bundle.getBoolean(BLESSED); + } + + @Override + public int price() { + return 50 * quantity; + } +} diff --git a/java/com/hmdzl/spspd/items/ArmorKit.java b/java/com/hmdzl/spspd/items/ArmorKit.java new file mode 100644 index 00000000..7c6166c3 --- /dev/null +++ b/java/com/hmdzl/spspd/items/ArmorKit.java @@ -0,0 +1,128 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.skills.ClassSkill; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.noosa.audio.Sample; + +public class ArmorKit extends Item { + + private static final float TIME_TO_UPGRADE = 2; + + private static final String AC_APPLY = "APPLY"; + + { + //name = "armor kit"; + image = ItemSpriteSheet.KIT; + + unique = true; + } + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + actions.add(AC_APPLY); + return actions; + } + + @Override + public void execute(Hero hero, String action) { + if (action == AC_APPLY) { + + curUser = hero; + //GameScene.selectItem(itemSelector, WndBag.Mode.ARMOR, + //Messages.get(this,"prompt")); + detach(curUser.belongings.backpack); + + curUser.sprite.centerEmitter().start(Speck.factory(Speck.KIT), 0.05f, + 10); + curUser.spend(TIME_TO_UPGRADE); + curUser.busy(); + + //GLog.w(Messages.get(this,"upgraded", armor.name())); + ClassSkill classSkill = ClassSkill.upgrade(curUser); + classSkill.collect(curUser.belongings.backpack); + + curUser.sprite.operate(curUser.pos); + Sample.INSTANCE.play(Assets.SND_EVOKE); + + } else { + + super.execute(hero, action); + + } + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + /*private void upgrade(Armor armor) { + + detach(curUser.belongings.backpack); + + curUser.sprite.centerEmitter().start(Speck.factory(Speck.KIT), 0.05f, + 10); + curUser.spend(TIME_TO_UPGRADE); + curUser.busy(); + + GLog.w(Messages.get(this,"upgraded", armor.name())); + + //ClassArmor classArmor = ClassArmor.upgrade(curUser, armor); + if (curUser.belongings.armor == armor) { + + curUser.belongings.armor = classArmor; + ((HeroSprite) curUser.sprite).updateArmor(); + + } else { + + armor.detach(curUser.belongings.backpack); + classArmor.collect(curUser.belongings.backpack); + + } + + curUser.sprite.operate(curUser.pos); + Sample.INSTANCE.play(Assets.SND_EVOKE); + } + + private final WndBag.Listener itemSelector = new WndBag.Listener() { + @Override + public void onSelect(Item item) { + if (item != null) { + ArmorKit.this.upgrade((Armor) item); + } + } + };*/ + + @Override + public int price() { + return 200 * quantity; + } +} diff --git a/java/com/hmdzl/spspd/items/Bone.java b/java/com/hmdzl/spspd/items/Bone.java new file mode 100644 index 00000000..4da62228 --- /dev/null +++ b/java/com/hmdzl/spspd/items/Bone.java @@ -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 + */ +package com.hmdzl.spspd.items; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.items.artifacts.TimekeepersHourglass; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.InterlevelScene; +import com.hmdzl.spspd.sprites.ItemSprite.Glowing; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.noosa.Game; +import com.watabou.utils.Bundle; + +public class Bone extends Item { + + public static final float TIME_TO_USE = 1; + + public static final String AC_PORT = "PORT"; + + private int specialLevel = 37; + private int returnDepth = -1; + private int returnPos; + + { + //name = "inscribed bone"; + image = ItemSpriteSheet.BONE; + + stackable = false; + unique = true; + } + + private static final String DEPTH = "depth"; + private static final String POS = "pos"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(DEPTH, returnDepth); + if (returnDepth != -1) { + bundle.put(POS, returnPos); + } + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + returnDepth = bundle.getInt(DEPTH); + returnPos = bundle.getInt(POS); + } + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + actions.add(AC_PORT); + + return actions; + } + + @Override + public void execute(Hero hero, String action) { + + if (action == AC_PORT) { + + if ((Dungeon.bossLevel() || Dungeon.depth==1 || Dungeon.depth>25 || hero.petfollow) && Dungeon.depth!=specialLevel) { + hero.spend(TIME_TO_USE); + GLog.w(Messages.get(Item.class, "not_here")); + return; + } + + if (Dungeon.depth==specialLevel && !Dungeon.skeletonkingkilled && !Dungeon.level.reset) { + hero.spend(TIME_TO_USE); + GLog.w(Messages.get(Item.class, "boss_first")); + return; + } + + } + + if (action == AC_PORT) { + + hero.spend(TIME_TO_USE); + + Buff buff = Dungeon.hero + .buff(TimekeepersHourglass.timeFreeze.class); + if (buff != null) + buff.detach(); + + if (Dungeon.depth<25 && !Dungeon.bossLevel()){ + returnDepth = Dungeon.depth; + returnPos = hero.pos; + InterlevelScene.mode = InterlevelScene.Mode.PORTBONE; + } else { + InterlevelScene.mode = InterlevelScene.Mode.RETURN; + detach(hero.belongings.backpack); + } + InterlevelScene.returnDepth = returnDepth; + InterlevelScene.returnPos = returnPos; + Game.switchScene(InterlevelScene.class); + + } else { + + super.execute(hero, action); + + } + } + + public void reset() { + returnDepth = -1; + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + + private static final Glowing BLACK = new Glowing(0x00000); + + @Override + public Glowing glowing() { + return BLACK; + } +} diff --git a/java/com/hmdzl/spspd/items/BossRush.java b/java/com/hmdzl/spspd/items/BossRush.java new file mode 100644 index 00000000..e3712b25 --- /dev/null +++ b/java/com/hmdzl/spspd/items/BossRush.java @@ -0,0 +1,135 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.items.artifacts.TimekeepersHourglass; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.InterlevelScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.noosa.Game; +import com.watabou.utils.Bundle; + +public class BossRush extends Item { + + public static final float TIME_TO_USE = 1; + + public static final String AC_PORT = "READ"; + + private int specialLevel = 71; + private int returnDepth = -1; + private int returnPos; + + { + //name = "Book of Bosses"; + image = ItemSpriteSheet.BOSSRUSH; + + unique = true; + } + + + private static final String DEPTH = "depth"; + private static final String POS = "pos"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(DEPTH, returnDepth); + if (returnDepth != -1) { + bundle.put(POS, returnPos); + } + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + returnDepth = bundle.getInt(DEPTH); + returnPos = bundle.getInt(POS); + } + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + actions.add(AC_PORT); + + return actions; + } + + @Override + public void execute(Hero hero, String action) { + + if (action == AC_PORT) { + + if ((Dungeon.bossLevel() || Dungeon.depth==1 || Dungeon.depth>25 || hero.petfollow) && Dungeon.depth!=specialLevel) { + hero.spend(TIME_TO_USE); + GLog.w(Messages.get(Item.class, "not_here")); + return; + } + } + + if (action == AC_PORT) { + + hero.spend(TIME_TO_USE); + + if (Dungeon.depth==specialLevel){ + this.doDrop(hero); + } + Buff buff = Dungeon.hero + .buff(TimekeepersHourglass.timeFreeze.class); + if (buff != null) + buff.detach(); + + if (Dungeon.depth<25 && !Dungeon.bossLevel()){ + returnDepth = Dungeon.depth; + returnPos = hero.pos; + InterlevelScene.mode = InterlevelScene.Mode.BOSSRUSH; + } else { + + InterlevelScene.mode = InterlevelScene.Mode.RETURN; + } + + InterlevelScene.returnDepth = returnDepth; + InterlevelScene.returnPos = returnPos; + Game.switchScene(InterlevelScene.class); + + } else { + + super.execute(hero, action); + + } + } + + public void reset() { + returnDepth = -1; + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } +} diff --git a/java/com/hmdzl/spspd/items/ChallengeBook.java b/java/com/hmdzl/spspd/items/ChallengeBook.java new file mode 100644 index 00000000..d1fa20f3 --- /dev/null +++ b/java/com/hmdzl/spspd/items/ChallengeBook.java @@ -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 + */ +package com.hmdzl.spspd.items; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.particles.ElmoParticle; +import com.hmdzl.spspd.items.challengelists.ChallengeList; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.scenes.InterlevelScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; +import com.hmdzl.spspd.windows.WndBag; +import com.hmdzl.spspd.windows.WndChallengeBook; +import com.hmdzl.spspd.messages.Messages; +import com.watabou.noosa.Game; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Bundle; + +public class ChallengeBook extends Item { + + public final float TIME_TO_USE = 1; + + public static final String AC_RETURN = "RETURN"; + public static final String AC_ADD = "ADD"; + public static final String AC_PORT = "READ"; + + protected WndBag.Mode mode = WndBag.Mode.CHALLENGELIST; + + + public int returnDepth = -1; + public int returnPos; + + + public boolean[] rooms = new boolean[10]; + public boolean[] firsts = new boolean[10]; + + { + //name = "Otiluke's journal"; + image = ItemSpriteSheet.CHALLENGE_BOOK; + + unique = true; + + //rooms[0] = true; + //firsts[0] = true; + } + + private static final String DEPTH = "depth"; + private static final String POS = "pos"; + private static final String ROOMS = "rooms"; + private static final String FIRSTS = "firsts"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(DEPTH, returnDepth); + bundle.put(ROOMS, rooms); + bundle.put(FIRSTS, firsts); + if (returnDepth != -1) { + bundle.put(POS, returnPos); + } + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + returnDepth = bundle.getInt(DEPTH); + returnPos = bundle.getInt(POS); + rooms = bundle.getBooleanArray(ROOMS); + firsts = bundle.getBooleanArray(FIRSTS); + } + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + + actions.add(AC_ADD); + + if (returnDepth > 0 && ( Dungeon.depth<35 && Dungeon.depth > 26) && !hero.petfollow){ + actions.add(AC_RETURN); + } + //charge >= reqCharges() && + if (Dungeon.depth<26 && !hero.petfollow /*&& (rooms[0])*/){ + actions.add(AC_PORT); + } + + return actions; + } + + @Override + public void execute(Hero hero, String action) { + + if (action == AC_PORT) { + if (Dungeon.bossLevel()) { + hero.spend(TIME_TO_USE); + GLog.w(Messages.get(Item.class, "not_here")); + return; + } + } + + if (action == AC_PORT) { + GameScene.show(new WndChallengeBook(rooms, this)); + } + + if (action == AC_RETURN) { + hero.spend(TIME_TO_USE); + updateQuickslot(); + InterlevelScene.mode = InterlevelScene.Mode.RETURN; + InterlevelScene.returnDepth = returnDepth; + InterlevelScene.returnPos = returnPos; + Game.switchScene(InterlevelScene.class); + returnDepth=-1; + } + + if (action == AC_ADD) { + + GameScene.selectItem(itemSelector, mode, Messages.get(this, "prompt")); + + } + + else { + + super.execute(hero, action); + + } + } + + @Override + public int price() { + return 0; + } + + public void reset() { + returnDepth = -1; + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + @Override + public String info() { + String info = desc(); + return info; + } + + protected WndBag.Listener itemSelector = new WndBag.Listener() { + @Override + public void onSelect(Item item) { + if (item != null && item instanceof ChallengeList) { + Hero hero = Dungeon.hero; + int room = ((ChallengeList) item).room; + + hero.sprite.operate(hero.pos); + hero.busy(); + hero.spend(2f); + Sample.INSTANCE.play(Assets.SND_BURNING); + hero.sprite.emitter().burst(ElmoParticle.FACTORY, 12); + + item.detach(hero.belongings.backpack); + GLog.h(Messages.get(ChallengeBook.class,"add_page")); + + rooms[room] = true; + firsts[room] = true; + + } + } + }; +} diff --git a/java/com/hmdzl/spspd/items/ChaosPack.java b/java/com/hmdzl/spspd/items/ChaosPack.java new file mode 100644 index 00000000..e28ded14 --- /dev/null +++ b/java/com/hmdzl/spspd/items/ChaosPack.java @@ -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 + */ +package com.hmdzl.spspd.items; + +import java.util.ArrayList; + +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.HighLight; +import com.hmdzl.spspd.actors.buffs.Light; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.particles.FlameParticle; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.noosa.particles.Emitter; + +public class ChaosPack extends Item { + + { + //name = "ChaosPack"; + image = ItemSpriteSheet.DEMO_SCROLL; + + stackable = false; + unique = true; + } + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + actions.remove(AC_DROP); + actions.remove(AC_THROW); + return actions; + } + + @Override + public void execute(Hero hero, String action) { + super.execute(hero, action); + + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } +} diff --git a/java/com/hmdzl/spspd/items/ConchShell.java b/java/com/hmdzl/spspd/items/ConchShell.java new file mode 100644 index 00000000..84db98ae --- /dev/null +++ b/java/com/hmdzl/spspd/items/ConchShell.java @@ -0,0 +1,146 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.items.artifacts.TimekeepersHourglass; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.InterlevelScene; +import com.hmdzl.spspd.sprites.ItemSprite.Glowing; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.noosa.Game; +import com.watabou.utils.Bundle; + +public class ConchShell extends Item { + + public static final float TIME_TO_USE = 1; + + public static final String AC_PORT = "PORT"; + + private int specialLevel = 38; + private int returnDepth = -1; + private int returnPos; + + { + //name = "conch shell"; + image = ItemSpriteSheet.SHELL; + + stackable = false; + unique = true; + } + + private static final String DEPTH = "depth"; + private static final String POS = "pos"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(DEPTH, returnDepth); + if (returnDepth != -1) { + bundle.put(POS, returnPos); + } + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + returnDepth = bundle.getInt(DEPTH); + returnPos = bundle.getInt(POS); + } + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + actions.add(AC_PORT); + + return actions; + } + + @Override + public void execute(Hero hero, String action) { + + if (action == AC_PORT) { + + if ((Dungeon.bossLevel() || Dungeon.depth==1 || Dungeon.depth>25 || hero.petfollow) && Dungeon.depth!=specialLevel) { + hero.spend(TIME_TO_USE); + GLog.w(Messages.get(Item.class, "not_here")); + return; + } + + if (Dungeon.depth==specialLevel && !Dungeon.crabkingkilled && !Dungeon.level.reset) { + hero.spend(TIME_TO_USE); + GLog.w(Messages.get(Item.class, "boss_first")); + return; + } + + } + + if (action == AC_PORT) { + + Buff buff = Dungeon.hero + .buff(TimekeepersHourglass.timeFreeze.class); + if (buff != null) + buff.detach(); + + if (Dungeon.depth<25 && !Dungeon.bossLevel()){ + + returnDepth = Dungeon.depth; + returnPos = hero.pos; + InterlevelScene.mode = InterlevelScene.Mode.PORTCRAB; + } else { + InterlevelScene.mode = InterlevelScene.Mode.RETURN; + detach(hero.belongings.backpack); + } + InterlevelScene.returnDepth = returnDepth; + InterlevelScene.returnPos = returnPos; + Game.switchScene(InterlevelScene.class); + + } else { + + super.execute(hero, action); + + } + } + + public void reset() { + returnDepth = -1; + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + + private static final Glowing BLACK = new Glowing(0x00000); + + @Override + public Glowing glowing() { + return BLACK; + } +} diff --git a/java/com/hmdzl/spspd/items/CurseBlood.java b/java/com/hmdzl/spspd/items/CurseBlood.java new file mode 100644 index 00000000..4dcf6e3f --- /dev/null +++ b/java/com/hmdzl/spspd/items/CurseBlood.java @@ -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 + */ +package com.hmdzl.spspd.items; + +import java.util.ArrayList; + +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.HighLight; +import com.hmdzl.spspd.actors.buffs.Light; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.particles.FlameParticle; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.noosa.particles.Emitter; + +public class CurseBlood extends Item { + + { + //name = "CurseBlood"; + image = ItemSpriteSheet.CURSE_BLOOD; + + stackable = false; + unique = true; + } + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + actions.remove(AC_DROP); + actions.remove(AC_THROW); + return actions; + } + + @Override + public void execute(Hero hero, String action) { + super.execute(hero, action); + + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } +} diff --git a/java/com/hmdzl/spspd/items/DewVial.java b/java/com/hmdzl/spspd/items/DewVial.java new file mode 100644 index 00000000..eae63f80 --- /dev/null +++ b/java/com/hmdzl/spspd/items/DewVial.java @@ -0,0 +1,622 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.Challenges; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.ResultDescriptions; +import com.hmdzl.spspd.Statistics; +import com.hmdzl.spspd.actors.blobs.Blob; +import com.hmdzl.spspd.actors.blobs.Water; +import com.hmdzl.spspd.actors.buffs.Bless; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Burning; +import com.hmdzl.spspd.actors.buffs.ExitFind; +import com.hmdzl.spspd.actors.buffs.Haste; +import com.hmdzl.spspd.actors.buffs.Invisibility; +import com.hmdzl.spspd.actors.buffs.Levitation; +import com.hmdzl.spspd.actors.buffs.Light; +import com.hmdzl.spspd.actors.buffs.MindVision; +import com.hmdzl.spspd.actors.buffs.Ooze; +import com.hmdzl.spspd.actors.buffs.Tar; +import com.hmdzl.spspd.actors.buffs.Vertigo; +import com.hmdzl.spspd.actors.buffs.Weakness; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.hero.HeroClass; +import com.hmdzl.spspd.actors.hero.HeroSubClass; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.effects.particles.ShadowParticle; +import com.hmdzl.spspd.items.bags.Bag; +import com.hmdzl.spspd.items.food.WaterItem; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.Terrain; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.CharSprite; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.utils.GLog; + +import com.hmdzl.spspd.windows.WndBag; +import com.hmdzl.spspd.windows.WndItem; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Bundle; +import com.watabou.utils.GameMath; +import com.watabou.utils.Random; + +public class DewVial extends Item { + + private static final int MAX_VOLUME = 120; + private static final int EXT_VOLUME = 350; + private static final int BLESS_VOLUME = 20; + + + private static final int MAX_VOLUME(){ + return Dungeon.wings ? EXT_VOLUME : MAX_VOLUME; + } + + + private static final String AC_DRINK = "DRINK"; + private static final String AC_WATER = "WATER"; + private static final String AC_SPLASH = "SPLASH"; + private static final String AC_BLESS = "BLESS"; + private static final String AC_LIGHT = "LIGHT"; + private static final String AC_POUR = "POUR"; + private static final String AC_PEEK = "PEEK"; + private static final String AC_REFINE = "REFINE"; + private static final String AC_CHOOSE = "CHOOSE"; + + private static final float TIME_TO_LIGHT = 1f; + private static final float TIME_TO_DRINK = 2f; + private static final float TIME_TO_WATER = 3f; + + private static final String TXT_STATUS = "%d"; + private static final String TXT_STATUS2 = "%d/%d"; + + { + //name = "dew vial"; + image = ItemSpriteSheet.VIAL; + + defaultAction = AC_CHOOSE; + unique = true; + } + + private int volume = 0; + + private int rejection = Dungeon.isChallenged(Challenges.DEW_REJECTION)? 10 : 0 ; + + public int checkVol () { + return volume; + } + + public void setVol (int vol) { + volume=vol; + } + + private static final String VOLUME = "volume"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(VOLUME, volume); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + volume = bundle.getInt(VOLUME); + } + + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + if (volume > 99) { + actions.add(AC_DRINK); + + if (Dungeon.dewWater || Dungeon.dewDraw){ + actions.add(AC_WATER); + actions.add(AC_BLESS); + } + if (Dungeon.dewNorn){ + actions.add(AC_POUR); + actions.add(AC_SPLASH); + } + actions.add(AC_LIGHT); + actions.add(AC_PEEK); + actions.add(AC_REFINE); + //actions.add(AC_ESCAPE); + } + else if (volume > 49) { + actions.add(AC_DRINK); + if (Dungeon.dewWater || Dungeon.dewDraw){ + actions.add(AC_WATER); + } + if (Dungeon.dewNorn){ + actions.add(AC_POUR); + actions.add(AC_SPLASH); + } + actions.add(AC_LIGHT); + actions.add(AC_PEEK); + actions.add(AC_REFINE); + } + + else if (volume > 29) { + actions.add(AC_DRINK); + if (Dungeon.dewNorn){ + actions.add(AC_SPLASH); + actions.add(AC_POUR); + } + actions.add(AC_LIGHT); + actions.add(AC_PEEK); + actions.add(AC_REFINE); + } + else if (volume > 1) { + actions.add(AC_DRINK); + } + return actions; + } + + @Override + public void execute(final Hero hero, String action) { + if (action.equals( AC_CHOOSE )) { + + GameScene.show(new WndItem(null, this, true)); + + } else if (action.equals(AC_DRINK)) { + if (volume > 350 ){ + hero.damage(hero.HT,this); + if (!hero.isAlive()) { + Dungeon.fail(Messages.format(ResultDescriptions.CHEAT)); + } + } + if (volume > 0) { + + //20 drops for a full heal normally, 15 for the warden + float dropHealPercent = hero.subClass == HeroSubClass.WARDEN ? 0.04f : 0.025f; + float missingHealthPercent = 1f - (hero.HP / (float)hero.HT); + + //trimming off 0.01 drops helps with floating point errors + int dropsNeeded = (int)Math.ceil((missingHealthPercent / dropHealPercent) - 0.01f); + dropsNeeded = (int) GameMath.gate(1, dropsNeeded, volume); + + int heal = Math.round( hero.HT * dropHealPercent * dropsNeeded ); + + int effect = Math.min( hero.HT - hero.HP, heal ); + if (effect > 0) { + if (Dungeon.hero.subClass == HeroSubClass.PASTOR) { + hero.HP += (int)(effect*1.5); + } else hero.HP += effect; + hero.sprite.emitter().burst( Speck.factory( Speck.HEALING ), 1 + dropsNeeded/5 ); + hero.sprite.showStatus( CharSprite.POSITIVE, Messages.get(this, "value", effect) ); + } + + volume -= dropsNeeded; + + hero.spend(TIME_TO_DRINK); + hero.busy(); + + Sample.INSTANCE.play(Assets.SND_DRINK); + hero.sprite.operate(hero.pos); + + updateQuickslot(); + + } else { + GLog.w(Messages.get(this, "empty")); + } + + } else if (action.equals(AC_WATER)) { + if (volume > 350 ){ + hero.damage(hero.HT,this); + if (!hero.isAlive()) { + Dungeon.fail(Messages.format(ResultDescriptions.CHEAT)); + } + } + Statistics.waters++; + int positive = 0; + int negative = 0; + + int distance = 1 + positive + negative; + + if (distance <= 0) { + level /= 2 - distance; + distance = 1; + } + + int cx = hero.pos % Level.getWidth(); + int cy = hero.pos / Level.getWidth(); + int ax = cx - distance; + if (ax < 0) { + ax = 0; + } + int bx = cx + distance; + if (bx >= Level.getWidth()) { + bx = Level.getWidth() - 1; + } + int ay = cy - distance; + if (ay < 0) { + ay = 0; + } + int by = cy + distance; + if (by >= Level.HEIGHT) { + by = Level.HEIGHT - 1; + } + + + for (int y = ay; y <= by; y++) { + for (int x = ax, p = ax + y * Level.getWidth(); x <= bx; x++, p++) { + + if (Dungeon.visible[p]) { + int c = Dungeon.level.map[p]; + + if (c == Terrain.GRASS) { + GameScene.add(Blob.seed(p, (2) * 20, Water.class)); + } + } + } + } + volume = volume - 15 - rejection; + GLog.i(Messages.get(this, "watered")); + hero.sprite.operate(hero.pos); + hero.busy(); + hero.spend(TIME_TO_WATER); + updateQuickslot(); + + } else if (action.equals(AC_SPLASH)) { + if (volume > 350 ){ + hero.damage(hero.HT,this); + if (!hero.isAlive()) { + Dungeon.fail(Messages.format(ResultDescriptions.CHEAT)); + } + } + Buff.affect(hero, Haste.class, Haste.DURATION); + //Buff.affect(hero, Invisibility.class, Invisibility.DURATION); + if(Dungeon.wings && Dungeon.depth<51 ){ + Buff.affect(hero, Levitation.class, Levitation.DURATION); + GLog.i(Messages.get(this, "fly")); + } + //GLog.i(Messages.get(this, "invisible")); + GLog.i(Messages.get(this, "fast")); + volume = volume - 15 - rejection; + updateQuickslot(); + + } else if (action.equals(AC_BLESS) && !Dungeon.dewDraw) { + if (volume > 350 ){ + hero.damage(hero.HT,this); + if (!hero.isAlive()) { + Dungeon.fail(Messages.format(ResultDescriptions.CHEAT)); + } + } + boolean procced = uncurse(hero, hero.belongings.backpack.items.toArray(new Item[0])); + procced = uncurse(hero, hero.belongings.weapon, + hero.belongings.armor, hero.belongings.misc1, + hero.belongings.misc2, hero.belongings.misc3) + || procced; + + if (procced) { + GLog.p(Messages.get(this, "remove_curse")); + } else { + GLog.i(Messages.get(this, "curse")); + } + + volume = volume - 70 - rejection; + updateQuickslot(); + + } else if (action.equals(AC_BLESS) && Dungeon.dewDraw) { + if (volume > 350 ){ + hero.damage(hero.HT,this); + if (!hero.isAlive()) { + Dungeon.fail(Messages.format(ResultDescriptions.CHEAT)); + } + } + curUser = hero; + GameScene.selectItem(itemSelector, WndBag.Mode.UPGRADEDEW, Messages.get(DewVial.class, "select")); + //updateQuickslot(); + + } else if (action.equals(AC_LIGHT)) { + if (volume > 350 ){ + hero.damage(hero.HT,this); + if (!hero.isAlive()) { + Dungeon.fail(Messages.format(ResultDescriptions.CHEAT)); + } + } + Buff.affect(hero, Light.class, 80f); + Buff.affect(hero, Invisibility.class, 20f); + GLog.i(Messages.get(this, "light")); + hero.spend(TIME_TO_LIGHT); + volume = volume - 10 - rejection; + updateQuickslot(); + + } else if (action.equals(AC_POUR)) { + if (volume > 350 ){ + hero.damage(hero.HT,this); + if (!hero.isAlive()) { + Dungeon.fail(Messages.format(ResultDescriptions.CHEAT)); + } + } + Buff.detach(hero, Burning.class); + Buff.detach(hero, Ooze.class); + Buff.detach(hero, Tar.class); + Buff.detach(hero, Weakness.class); + Buff.detach(hero, Vertigo.class); + + if (Random.Int(8) == 0) { + volume = volume - 20 - rejection; + Buff.affect(hero, Bless.class, 30f); + hero.sprite.operate(hero.pos); + hero.busy(); + hero.spend(TIME_TO_WATER); + } else { volume = volume - 5 - rejection; + hero.sprite.operate(hero.pos); + hero.busy(); + hero.spend(TIME_TO_WATER);} + + updateQuickslot(); + + } else if (action.equals(AC_PEEK)) { + if (volume > 350 ){ + hero.damage(hero.HT,this); + if (!hero.isAlive()) { + Dungeon.fail(Messages.format(ResultDescriptions.CHEAT)); + } + } + Buff.affect(hero, MindVision.class, 2f); + Buff.affect(hero, ExitFind.class, 2f); + volume = volume - 5 - rejection; + hero.sprite.operate(hero.pos); + hero.busy(); + hero.spend(TIME_TO_LIGHT); + updateQuickslot(); + } else if (action.equals(AC_REFINE)) { + if (volume > 350 ){ + hero.damage(hero.HT,this); + if (!hero.isAlive()) { + Dungeon.fail(Messages.format(ResultDescriptions.CHEAT)); + } + } + volume = volume - 10 - rejection; + hero.sprite.operate(hero.pos); + hero.busy(); + hero.spend(TIME_TO_DRINK); + WaterItem wateritem = new WaterItem(); + if (wateritem.doPickUp(Dungeon.hero)) { + GLog.i( Messages.get(Dungeon.hero, "you_now_have", wateritem.name())); + } else { + Dungeon.level.drop(wateritem, hero.pos).sprite + .drop(); + } + updateQuickslot(); + // } else if (action.equals(AC_ESCAPE)) { + //if (Dungeon.depth < 26){ + //GLog.n(Messages.get(this,"not_escape")); + //} else { + //volume = volume - volume; + //InterlevelScene.mode = InterlevelScene.Mode.SOKOBANFAIL; + //Game.switchScene(InterlevelScene.class);} + }else { + super.execute(hero, action); + } + } + + public static boolean uncurse(Hero hero, Item... items) { + + + int levelLimit = Math.max(2, 2+Math.round(Statistics.deepestFloor/3)); + if (hero.heroClass == HeroClass.MAGE){levelLimit++;} + + float lvlchance = 0.33f; + if (hero.heroClass == HeroClass.MAGE){lvlchance = 0.38f;} + + boolean procced = false; + boolean proccedUp = false; + for (int i = 0; i < items.length; i++) { + Item item = items[i]; + if (item != null && item.cursed) { + item.uncurse(); + if(item.level<0){item.upgrade(-item.level);} //upgrade to even + if (item.cursed==false) {procced = true;} + hero.sprite.emitter().start(ShadowParticle.UP, 0.05f, 10); + } + + if (item != null && Random.Float()= BLESS_VOLUME; + } + + + public boolean isFull() { + return volume >= MAX_VOLUME(); + } + + public void collectDew(Dewdrop dew) { + + //GLog.i(Messages.get(DewVial.class, "collected")); + volume += dew.quantity; + if (volume >= MAX_VOLUME()) { + volume = MAX_VOLUME(); + GLog.p(Messages.get(DewVial.class, "full")); + } + + updateQuickslot(); + } + + public void collectDew(RedDewdrop dew) { + + //GLog.i(Messages.get(DewVial.class, "collect")); + volume += (dew.quantity*10); + if (volume >= MAX_VOLUME()) { + volume = MAX_VOLUME(); + GLog.p(Messages.get(DewVial.class, "full")); + } + + updateQuickslot(); + } + + public void collectDew(YellowDewdrop dew) { + + //GLog.i(Messages.get(DewVial.class, "collect")); + volume += (dew.quantity*5); + if (volume >= MAX_VOLUME()) { + volume = MAX_VOLUME(); + GLog.p(Messages.get(DewVial.class, "full")); + } + + updateQuickslot(); + } + + public void collectDew(VioletDewdrop dew) { + + //GLog.i(Messages.get(DewVial.class, "collect")); + volume += (dew.quantity*50); + if (volume >= MAX_VOLUME()) { + volume = MAX_VOLUME(); + GLog.p(Messages.get(DewVial.class, "full")); + } + + updateQuickslot(); + } + + + public void fill() { + volume = MAX_VOLUME(); + updateQuickslot(); + } + + // removed as people need a bigger distinction to realize the dew vial + // doesn't revive. + /* + * private static final Glowing WHITE = new Glowing( 0xFFFFCC ); + * + * @Override public Glowing glowing() { return isFull() ? WHITE : null; } + */ + + @Override + public String status() { + return Messages.format(TXT_STATUS, volume); + } + + public String status2() { + return Messages.format(TXT_STATUS2, volume, MAX_VOLUME()); + } + @Override + public String toString() { + return super.toString() + " (" + status2() + ")"; + } + + @Override + public String info() { + + String desc = desc(); + + if (Dungeon.dewWater || Dungeon.dewDraw) + desc += "\n" + Messages.get(this, "desc_v1"); + + if(Dungeon.dewNorn) + desc += "\n" + Messages.get(this, "desc_v2"); + + if(Dungeon.wings) + desc += "\n" + Messages.get(this, "desc_v3"); + + return desc; + + } + +} diff --git a/java/com/hmdzl/spspd/items/Dewdrop.java b/java/com/hmdzl/spspd/items/Dewdrop.java new file mode 100644 index 00000000..2d771db9 --- /dev/null +++ b/java/com/hmdzl/spspd/items/Dewdrop.java @@ -0,0 +1,71 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2014 Oleg Dolya + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.items; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.hero.HeroClass; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.CharSprite; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.noosa.audio.Sample; + +public class Dewdrop extends Item { + + private static final String TXT_VALUE = "%+dHP"; + + { + //name = "dewdrop"; + image = ItemSpriteSheet.DEWDROP; + + stackable = true; + } + + @Override + public boolean doPickUp(Hero hero) { + + DewVial vial = hero.belongings.getItem(DewVial.class); + + if (vial == null || vial.isFull()) { + + int value = 1 + (Dungeon.depth - 1) / 5; + if (hero.heroClass == HeroClass.HUNTRESS) { + value++; + } + + int effect = Math.min(hero.HT - hero.HP, value * quantity); + if (effect > 0) { + hero.HP += effect; + hero.sprite.emitter().burst(Speck.factory(Speck.HEALING), 1); + hero.sprite.showStatus(CharSprite.POSITIVE, Messages.get(this, "value", effect)); + } + + } else if (vial != null) { + + vial.collectDew(this); + + } + + Sample.INSTANCE.play(Assets.SND_DEWDROP); + hero.spendAndNext(TIME_TO_PICK_UP); + + return true; + } +} diff --git a/java/com/hmdzl/spspd/items/DolyaSlate.java b/java/com/hmdzl/spspd/items/DolyaSlate.java new file mode 100644 index 00000000..7ab2aa7e --- /dev/null +++ b/java/com/hmdzl/spspd/items/DolyaSlate.java @@ -0,0 +1,240 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.particles.ElmoParticle; +import com.hmdzl.spspd.items.journalpages.JournalPage; +import com.hmdzl.spspd.items.keys.IronKey; +import com.hmdzl.spspd.items.misc.Spectacles.MagicSight; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.scenes.InterlevelScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; +import com.hmdzl.spspd.windows.WndBag; +import com.hmdzl.spspd.windows.WndOtiluke; +import com.hmdzl.spspd.messages.Messages; +import com.watabou.noosa.Game; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Bundle; + +public class DolyaSlate extends Item { + + public final float TIME_TO_USE = 1; + public final int fullCharge = 1000; + + + public static final String AC_RETURN = "RETURN"; + public static final String AC_ADD = "ADD"; + public static final String AC_PORT = "READ"; + + protected WndBag.Mode mode = WndBag.Mode.JOURNALPAGES; + + + public int returnDepth = -1; + public int returnPos; + + public int charge = 0; + public int level = 1; + + public int checkReading(){ + int lvl=1; + if (Dungeon.hero.buff(MagicSight.class) != null){ + lvl+=1; + } + return lvl; + } + + public int reqCharges(){ + + int calcCharges = Math.round(fullCharge); + return calcCharges; + + } + + + public boolean[] rooms = new boolean[10]; + public boolean[] firsts = new boolean[10]; + + { + //name = "Otiluke's journal"; + image = ItemSpriteSheet.OTILUKES_JOURNAL; + + unique = true; + + //rooms[0] = true; + //firsts[0] = true; + } + + private static final String DEPTH = "depth"; + private static final String POS = "pos"; + private static final String ROOMS = "rooms"; + private static final String FIRSTS = "firsts"; + private static final String CHARGE = "charge"; + private static final String LEVEL = "level"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(DEPTH, returnDepth); + bundle.put(ROOMS, rooms); + bundle.put(CHARGE, charge); + bundle.put(FIRSTS, firsts); + bundle.put(LEVEL, level); + if (returnDepth != -1) { + bundle.put(POS, returnPos); + } + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + returnDepth = bundle.getInt(DEPTH); + returnPos = bundle.getInt(POS); + charge = bundle.getInt(CHARGE); + level = bundle.getInt(LEVEL); + rooms = bundle.getBooleanArray(ROOMS); + firsts = bundle.getBooleanArray(FIRSTS); + } + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + + actions.add(AC_ADD); + + if (returnDepth > 0 && (Dungeon.depth<56 || Dungeon.depth==66 || Dungeon.depth==67) && Dungeon.depth>49 && !hero.petfollow){ + actions.add(AC_RETURN); + } + //charge >= reqCharges() && + if ((charge >= 500 || Badges.checkOtilukeRescued() )&& Dungeon.depth<26 && !hero.petfollow && (level>1 || rooms[0])){ + actions.add(AC_PORT); + } + + return actions; + } + + @Override + public void execute(Hero hero, String action) { + + if (action == AC_PORT) { + if (Dungeon.bossLevel()) { + hero.spend(TIME_TO_USE); + GLog.w(Messages.get(Item.class, "not_here")); + return; + } + } + + if (action == AC_PORT) { + GameScene.show(new WndOtiluke(rooms, this)); + } + + if (action == AC_RETURN) { + hero.spend(TIME_TO_USE); + IronKey key = hero.belongings.getKey(IronKey.class, Dungeon.depth); + if (key!=null){key.detachAll(Dungeon.hero.belongings.backpack);} + updateQuickslot(); + + InterlevelScene.mode = InterlevelScene.Mode.RETURN; + InterlevelScene.returnDepth = returnDepth; + InterlevelScene.returnPos = returnPos; + Game.switchScene(InterlevelScene.class); + returnDepth=-1; + } + + if (action == AC_ADD) { + + GameScene.selectItem(itemSelector, mode, Messages.get(this, "prompt")); + + } + + else { + + super.execute(hero, action); + + } + } + + @Override + public int price() { + return 300*quantity; + } + + public void reset() { + returnDepth = -1; + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + @Override + public String info() { + String info = desc(); + info += "\n\n" + Messages.get(this, "charge",charge,reqCharges()); + return info; + } + + protected WndBag.Listener itemSelector = new WndBag.Listener() { + @Override + public void onSelect(Item item) { + if (item != null && item instanceof JournalPage) { + Hero hero = Dungeon.hero; + int room = ((JournalPage) item).room; + + hero.sprite.operate(hero.pos); + hero.busy(); + hero.spend(2f); + Sample.INSTANCE.play(Assets.SND_BURNING); + hero.sprite.emitter().burst(ElmoParticle.FACTORY, 12); + + item.detach(hero.belongings.backpack); + GLog.h(Messages.get(DolyaSlate.class,"add_page")); + level++; + + if(charge<(fullCharge-500)){ + charge=fullCharge; + } else { + charge+=500; + } + + rooms[room] = true; + firsts[room] = true; + + } + } + }; + + @Override + public String status() { + return Messages.format("%d%%", charge/10); + } + + +} diff --git a/java/com/hmdzl/spspd/items/DwarfHammer.java b/java/com/hmdzl/spspd/items/DwarfHammer.java new file mode 100644 index 00000000..26d8d530 --- /dev/null +++ b/java/com/hmdzl/spspd/items/DwarfHammer.java @@ -0,0 +1,106 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.levels.Terrain; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; + +public class DwarfHammer extends Item { + + public static final float TIME_TO_USE = 1; + + public static final String AC_BREAK = "BREAK"; + + { + //name = "dwarf demon hammer"; + image = ItemSpriteSheet.DWARFHAMMER; + unique = true; + + } + + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + actions.add(AC_BREAK); + + return actions; + } + + @Override + public void execute(Hero hero, String action) { + + if (action == AC_BREAK) { + + if (Dungeon.bossLevel() || Dungeon.depth > 25 || Dungeon.depth < 22) { + hero.spend(DwarfHammer.TIME_TO_USE); + GLog.w(Messages.get(this, "prevent")); + return; + } + + if (!Dungeon.visible[Dungeon.level.exit]) { + hero.spend(DwarfHammer.TIME_TO_USE); + GLog.w(Messages.get(this, "prevent")); + return; + } + + + } + + if (action == AC_BREAK) { + + if (hero.pos != Dungeon.level.exit) { + detach(Dungeon.hero.belongings.backpack); + + Dungeon.level.sealedlevel=false; + + //Dungeon.level.map[Dungeon.level.exit]=Terrain.EMPTY; + //GameScene.updateMap(Dungeon.level.exit); + //Dungeon.observe(); + + Dungeon.level.map[Dungeon.level.exit]=Terrain.EXIT; + GameScene.updateMap(Dungeon.level.exit); + Dungeon.observe(); + + GLog.w(Messages.get(this,"unseal")); + + } + + } else { + GLog.w(Messages.get(this, "prevent")); + super.execute(hero, action); + } + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } +} diff --git a/java/com/hmdzl/spspd/items/Elevator.java b/java/com/hmdzl/spspd/items/Elevator.java new file mode 100644 index 00000000..336c9f6f --- /dev/null +++ b/java/com/hmdzl/spspd/items/Elevator.java @@ -0,0 +1,77 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.scenes.InterlevelScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.noosa.Game; + +import java.util.ArrayList; + +public class Elevator extends Item { + + public static final String AC_UP = "UP"; + + public static final String AC_DOWN = "DOWN"; + + + { + //name = "Elevator"; + image = ItemSpriteSheet.ELEVATOR; + + stackable = true; + + } + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + if (Dungeon.depth < 26 && Dungeon.depth > 1 ){ + actions.add(AC_UP); + actions.add(AC_DOWN);} + return actions; + } + + @Override + public void execute(Hero hero, String action) { + + if (action.equals(AC_UP)) { + InterlevelScene.mode = InterlevelScene.Mode.ASCEND; + Game.switchScene(InterlevelScene.class); + } else if (action.equals(AC_DOWN)) { + InterlevelScene.mode = InterlevelScene.Mode.DESCEND; + Game.switchScene(InterlevelScene.class); + } else { + super.execute(hero, action); + + } + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + +} diff --git a/java/com/hmdzl/spspd/items/EmptyBody.java b/java/com/hmdzl/spspd/items/EmptyBody.java new file mode 100644 index 00000000..c019efc3 --- /dev/null +++ b/java/com/hmdzl/spspd/items/EmptyBody.java @@ -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 + */ +package com.hmdzl.spspd.items; + +import java.util.ArrayList; + +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.HighLight; +import com.hmdzl.spspd.actors.buffs.Light; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.particles.FlameParticle; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.noosa.particles.Emitter; + +public class EmptyBody extends Item { + + { + //name = "EmptyBody"; + image = ItemSpriteSheet.TENGU_SWORD; + + stackable = false; + unique = true; + } + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + actions.remove(AC_DROP); + actions.remove(AC_THROW); + return actions; + } + + @Override + public void execute(Hero hero, String action) { + super.execute(hero, action); + + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } +} diff --git a/java/com/hmdzl/spspd/items/EquipableItem.java b/java/com/hmdzl/spspd/items/EquipableItem.java new file mode 100644 index 00000000..1c6d48ed --- /dev/null +++ b/java/com/hmdzl/spspd/items/EquipableItem.java @@ -0,0 +1,111 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.particles.ShadowParticle; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.noosa.audio.Sample; + +public abstract class EquipableItem extends Item { + + public static final String AC_EQUIP = "EQUIP"; + public static final String AC_UNEQUIP = "UNEQUIP"; + + { + + } + + @Override + public void execute(Hero hero, String action) { + if (action.equals(AC_EQUIP)) { + // In addition to equipping itself, item reassigns itself to the + // quickslot + // This is a special case as the item is being removed from + // inventory, but is staying with the hero. + int slot = Dungeon.quickslot.getSlot(this); + doEquip(hero); + if (slot != -1) { + Dungeon.quickslot.setSlot(slot, this); + updateQuickslot(); + } + } else if (action.equals(AC_UNEQUIP)) { + doUnequip(hero, true); + } else { + super.execute(hero, action); + } + } + + @Override + public void doDrop(Hero hero) { + if (!isEquipped(hero) || doUnequip(hero, false, false)) { + super.doDrop(hero); + } + } + + @Override + public void cast(final Hero user, int dst) { + + if (isEquipped(user)) { + if (quantity == 1 && !this.doUnequip(user, false, false)) { + return; + } + } + + super.cast(user, dst); + } + + public static void equipCursed(Hero hero) { + hero.sprite.emitter().burst(ShadowParticle.CURSE, 6); + Sample.INSTANCE.play(Assets.SND_CURSED); + } + + protected float time2equip(Hero hero) { + return 1; + } + + public abstract boolean doEquip(Hero hero); + + public boolean doUnequip(Hero hero, boolean collect, boolean single) { + + if (cursed) { + GLog.w(Messages.get(this,"unequip_cursed", name())); + return false; + } + + if (single) { + hero.spendAndNext(time2equip(hero)); + } else { + hero.spend(time2equip(hero)); + } + + if (collect && !collect(hero.belongings.backpack)) { + Dungeon.level.drop(this, hero.pos); + } + + return true; + } + + final public boolean doUnequip(Hero hero, boolean collect) { + return doUnequip(hero, collect, true); + } + +} diff --git a/java/com/hmdzl/spspd/items/ExpOre.java b/java/com/hmdzl/spspd/items/ExpOre.java new file mode 100644 index 00000000..8d8b5f00 --- /dev/null +++ b/java/com/hmdzl/spspd/items/ExpOre.java @@ -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 + */ +package com.hmdzl.spspd.items; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.hero.HeroClass; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.utils.Random; + +public class ExpOre extends Item { + + public static final String AC_USE = "USE"; + { + //name = "exp ore"; + image = ItemSpriteSheet.STONE; + + stackable=true; + defaultAction = AC_USE; + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + actions.add(AC_USE); + return actions; + } + + @Override + public void execute(Hero hero, String action) { + + if (action.equals(AC_USE)) { + curUser = hero; + hero.earnExp(hero.maxExp()); + if (!(Dungeon.hero.heroClass == HeroClass.FOLLOWER ) || (Dungeon.hero.heroClass == HeroClass.FOLLOWER && Random.Int(10)>=1 )) + detach(curUser.belongings.backpack); + } else { + super.execute(hero, action); + + } + } + + @Override + public int price() { + return 100 * quantity; + } +} diff --git a/java/com/hmdzl/spspd/items/Flag.java b/java/com/hmdzl/spspd/items/Flag.java new file mode 100644 index 00000000..f248c73a --- /dev/null +++ b/java/com/hmdzl/spspd/items/Flag.java @@ -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 + */ +package com.hmdzl.spspd.items; + +import java.util.ArrayList; + +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.HighLight; +import com.hmdzl.spspd.actors.buffs.Light; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.particles.FlameParticle; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.noosa.particles.Emitter; + +public class Flag extends Item { + + { + //name = "flag"; + image = ItemSpriteSheet.FLAG; + + stackable = false; + unique = true; + } + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + actions.remove(AC_DROP); + actions.remove(AC_THROW); + return actions; + } + + @Override + public void execute(Hero hero, String action) { + super.execute(hero, action); + + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } +} diff --git a/java/com/hmdzl/spspd/items/Generator.java b/java/com/hmdzl/spspd/items/Generator.java new file mode 100644 index 00000000..352b64f9 --- /dev/null +++ b/java/com/hmdzl/spspd/items/Generator.java @@ -0,0 +1,737 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items; + +import java.util.HashMap; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.items.armor.normalarmor.BulletArmor; +import com.hmdzl.spspd.items.armor.normalarmor.CDArmor; +import com.hmdzl.spspd.items.armor.normalarmor.CeramicsArmor; +import com.hmdzl.spspd.items.armor.normalarmor.MachineArmor; +import com.hmdzl.spspd.items.armor.normalarmor.MultiplelayerArmor; +import com.hmdzl.spspd.items.armor.normalarmor.PhantomArmor; +import com.hmdzl.spspd.items.armor.normalarmor.ProtectiveclothingArmor; +import com.hmdzl.spspd.items.armor.normalarmor.RubberArmor; +import com.hmdzl.spspd.items.armor.normalarmor.StoneArmor; +import com.hmdzl.spspd.items.armor.normalarmor.StyrofoamArmor; +import com.hmdzl.spspd.items.armor.normalarmor.VestArmor; +import com.hmdzl.spspd.items.armor.normalarmor.WoodenArmor; +import com.hmdzl.spspd.items.artifacts.AlienBag; +import com.hmdzl.spspd.items.artifacts.EtherealChains; +import com.hmdzl.spspd.items.artifacts.GlassTotem; +import com.hmdzl.spspd.items.artifacts.RobotDMT; +import com.hmdzl.spspd.items.bombs.Bomb; +import com.hmdzl.spspd.items.bombs.BuildBomb; +import com.hmdzl.spspd.items.bombs.DarkBomb; +import com.hmdzl.spspd.items.bombs.DungeonBomb; +import com.hmdzl.spspd.items.bombs.EarthBomb; +import com.hmdzl.spspd.items.bombs.FireBomb; +import com.hmdzl.spspd.items.bombs.FishingBomb; +import com.hmdzl.spspd.items.bombs.HugeBomb; +import com.hmdzl.spspd.items.bombs.IceBomb; +import com.hmdzl.spspd.items.bombs.LightBomb; +import com.hmdzl.spspd.items.bombs.MiniBomb; +import com.hmdzl.spspd.items.bombs.StormBomb; +import com.hmdzl.spspd.items.eggs.BlueDragonEgg; +import com.hmdzl.spspd.items.eggs.CocoCatEgg; +import com.hmdzl.spspd.items.eggs.EasterEgg; +import com.hmdzl.spspd.items.eggs.Egg; +import com.hmdzl.spspd.items.eggs.GoldDragonEgg; +import com.hmdzl.spspd.items.eggs.GreenDragonEgg; +import com.hmdzl.spspd.items.eggs.LeryFireEgg; +import com.hmdzl.spspd.items.eggs.LightDragonEgg; +import com.hmdzl.spspd.items.eggs.RandomEgg; +import com.hmdzl.spspd.items.eggs.RedDragonEgg; +import com.hmdzl.spspd.items.eggs.ScorpionEgg; +import com.hmdzl.spspd.items.eggs.ShadowDragonEgg; +import com.hmdzl.spspd.items.eggs.SpiderEgg; +import com.hmdzl.spspd.items.eggs.VelociroosterEgg; +import com.hmdzl.spspd.items.eggs.VioletDragonEgg; +import com.hmdzl.spspd.items.food.completefood.Chickennugget; +import com.hmdzl.spspd.items.food.completefood.Chocolate; +import com.hmdzl.spspd.items.food.completefood.Foamedbeverage; +import com.hmdzl.spspd.items.food.completefood.FoodFans; +import com.hmdzl.spspd.items.food.completefood.Frenchfries; +import com.hmdzl.spspd.items.food.completefood.Fruitsalad; +import com.hmdzl.spspd.items.food.completefood.Gel; +import com.hmdzl.spspd.items.food.completefood.Hamburger; +import com.hmdzl.spspd.items.food.completefood.Herbmeat; +import com.hmdzl.spspd.items.food.completefood.HoneyGel; +import com.hmdzl.spspd.items.food.completefood.HoneyWater; +import com.hmdzl.spspd.items.food.completefood.Honeymeat; +import com.hmdzl.spspd.items.food.completefood.Honeyrice; +import com.hmdzl.spspd.items.food.completefood.Icecream; +import com.hmdzl.spspd.items.food.completefood.Kebab; +import com.hmdzl.spspd.items.food.completefood.Meatroll; +import com.hmdzl.spspd.items.food.completefood.PerfectFood; +import com.hmdzl.spspd.items.food.completefood.Porksoup; +import com.hmdzl.spspd.items.food.completefood.Ricefood; +import com.hmdzl.spspd.items.food.completefood.Vegetablekebab; +import com.hmdzl.spspd.items.food.completefood.Vegetableroll; +import com.hmdzl.spspd.items.food.completefood.Vegetablesoup; +import com.hmdzl.spspd.items.food.staplefood.NormalRation; +import com.hmdzl.spspd.items.medicine.Hardpill; +import com.hmdzl.spspd.items.medicine.Magicpill; +import com.hmdzl.spspd.items.medicine.Musicpill; +import com.hmdzl.spspd.items.medicine.Pill; +import com.hmdzl.spspd.items.medicine.Powerpill; +import com.hmdzl.spspd.items.medicine.Shootpill; +import com.hmdzl.spspd.items.medicine.Smashpill; +import com.hmdzl.spspd.items.medicine.PixieParasol; +import com.hmdzl.spspd.items.medicine.GreenSpore; +import com.hmdzl.spspd.items.medicine.GoldenJelly; +import com.hmdzl.spspd.items.medicine.Earthstar; +import com.hmdzl.spspd.items.medicine.DeathCap; +import com.hmdzl.spspd.items.medicine.JackOLantern; +import com.hmdzl.spspd.items.medicine.BlueMilk; +import com.hmdzl.spspd.items.rings.RingOfEnergy; +import com.hmdzl.spspd.items.scrolls.ScrollOfSacrifice; +import com.hmdzl.spspd.items.summon.ActiveMrDestructo; +import com.hmdzl.spspd.items.summon.FairyCard; +import com.hmdzl.spspd.items.summon.Mobile; +import com.hmdzl.spspd.items.wands.WandOfFlow; +import com.hmdzl.spspd.items.wands.WandOfLight; +import com.hmdzl.spspd.items.wands.WandOfMeteorite; +import com.hmdzl.spspd.items.wands.WandOfTCloud; +import com.hmdzl.spspd.items.weapon.guns.GunA; +import com.hmdzl.spspd.items.weapon.guns.GunB; +import com.hmdzl.spspd.items.weapon.guns.GunC; +import com.hmdzl.spspd.items.weapon.guns.GunD; +import com.hmdzl.spspd.items.weapon.guns.GunE; +import com.hmdzl.spspd.items.weapon.melee.Club; +import com.hmdzl.spspd.items.weapon.melee.FightGloves; +import com.hmdzl.spspd.items.weapon.melee.Flute; +import com.hmdzl.spspd.items.weapon.melee.Harp; +import com.hmdzl.spspd.items.weapon.melee.HolyWater; +import com.hmdzl.spspd.items.weapon.melee.Lance; +import com.hmdzl.spspd.items.weapon.melee.Mace; +import com.hmdzl.spspd.items.weapon.melee.PrayerWheel; +import com.hmdzl.spspd.items.weapon.melee.Rapier; +import com.hmdzl.spspd.items.weapon.melee.StoneCross; +import com.hmdzl.spspd.items.weapon.melee.Triangolo; +import com.hmdzl.spspd.items.weapon.melee.Trumpet; +import com.hmdzl.spspd.items.weapon.melee.Wardurm; +import com.hmdzl.spspd.items.weapon.melee.WoodenStaff; +import com.hmdzl.spspd.items.weapon.melee.special.Handcannon; +import com.hmdzl.spspd.items.weapon.melee.special.Pumpkin; +import com.hmdzl.spspd.items.weapon.melee.special.RunicBlade; +import com.hmdzl.spspd.items.weapon.missiles.EmpBola; +import com.hmdzl.spspd.items.weapon.missiles.EscapeKnive; +import com.hmdzl.spspd.items.weapon.missiles.HugeShuriken; +import com.hmdzl.spspd.items.weapon.missiles.NormalBomb; +import com.hmdzl.spspd.items.weapon.missiles.RiceBall; +import com.hmdzl.spspd.items.weapon.missiles.ShatteredAmmo; +import com.hmdzl.spspd.items.weapon.missiles.Skull; +import com.hmdzl.spspd.items.weapon.missiles.Smoke; +import com.hmdzl.spspd.items.weapon.missiles.Wave; +import com.hmdzl.spspd.plants.Rotberry; +import com.hmdzl.spspd.items.armor.Armor; +import com.hmdzl.spspd.items.armor.normalarmor.ClothArmor; +import com.hmdzl.spspd.items.armor.normalarmor.LeatherArmor; +import com.hmdzl.spspd.items.armor.normalarmor.MailArmor; +import com.hmdzl.spspd.items.armor.normalarmor.PlateArmor; +import com.hmdzl.spspd.items.armor.normalarmor.DiscArmor; +import com.hmdzl.spspd.items.armor.normalarmor.ScaleArmor; +import com.hmdzl.spspd.items.armor.normalarmor.ErrorArmor; +import com.hmdzl.spspd.items.artifacts.AlchemistsToolkit; +import com.hmdzl.spspd.items.artifacts.Artifact; +import com.hmdzl.spspd.items.artifacts.CapeOfThorns; +import com.hmdzl.spspd.items.artifacts.ChaliceOfBlood; +import com.hmdzl.spspd.items.artifacts.CloakOfShadows; +import com.hmdzl.spspd.items.artifacts.DriedRose; +import com.hmdzl.spspd.items.artifacts.HornOfPlenty; +import com.hmdzl.spspd.items.artifacts.MasterThievesArmband; +import com.hmdzl.spspd.items.artifacts.EyeOfSkadi; +import com.hmdzl.spspd.items.artifacts.SandalsOfNature; +import com.hmdzl.spspd.items.artifacts.TalismanOfForesight; +import com.hmdzl.spspd.items.artifacts.TimekeepersHourglass; +import com.hmdzl.spspd.items.artifacts.UnstableSpellbook; +import com.hmdzl.spspd.items.bags.Bag; +import com.hmdzl.spspd.items.food.fruit.Blackberry; +import com.hmdzl.spspd.items.food.fruit.Blueberry; +import com.hmdzl.spspd.items.food.fruit.Cloudberry; +import com.hmdzl.spspd.items.food.Food; +import com.hmdzl.spspd.items.food.fruit.Moonberry; +import com.hmdzl.spspd.items.food.staplefood.Pasty; +import com.hmdzl.spspd.items.food.staplefood.OverpricedRation; +import com.hmdzl.spspd.items.nornstone.BlueNornStone; +import com.hmdzl.spspd.items.nornstone.GreenNornStone; +import com.hmdzl.spspd.items.nornstone.NornStone; +import com.hmdzl.spspd.items.nornstone.OrangeNornStone; +import com.hmdzl.spspd.items.nornstone.PurpleNornStone; +import com.hmdzl.spspd.items.nornstone.YellowNornStone; +import com.hmdzl.spspd.items.potions.Potion; +import com.hmdzl.spspd.items.potions.PotionOfExperience; +import com.hmdzl.spspd.items.potions.PotionOfFrost; +import com.hmdzl.spspd.items.potions.PotionOfHealing; +import com.hmdzl.spspd.items.potions.PotionOfInvisibility; +import com.hmdzl.spspd.items.potions.PotionOfLevitation; +import com.hmdzl.spspd.items.potions.PotionOfLiquidFlame; +import com.hmdzl.spspd.items.potions.PotionOfMending; +import com.hmdzl.spspd.items.potions.PotionOfMight; +import com.hmdzl.spspd.items.potions.PotionOfMindVision; +import com.hmdzl.spspd.items.potions.PotionOfOverHealing; +import com.hmdzl.spspd.items.potions.PotionOfParalyticGas; +import com.hmdzl.spspd.items.potions.PotionOfPurity; +import com.hmdzl.spspd.items.potions.PotionOfStrength; +import com.hmdzl.spspd.items.potions.PotionOfToxicGas; +import com.hmdzl.spspd.items.rings.Ring; +import com.hmdzl.spspd.items.rings.RingOfAccuracy; +import com.hmdzl.spspd.items.rings.RingOfElements; +import com.hmdzl.spspd.items.rings.RingOfEvasion; +import com.hmdzl.spspd.items.rings.RingOfForce; +import com.hmdzl.spspd.items.rings.RingOfFuror; +import com.hmdzl.spspd.items.rings.RingOfHaste; +import com.hmdzl.spspd.items.rings.RingOfMagic; +import com.hmdzl.spspd.items.rings.RingOfMight; +import com.hmdzl.spspd.items.rings.RingOfSharpshooting; +import com.hmdzl.spspd.items.rings.RingOfTenacity; +import com.hmdzl.spspd.items.scrolls.Scroll; +import com.hmdzl.spspd.items.scrolls.ScrollOfIdentify; +import com.hmdzl.spspd.items.scrolls.ScrollOfLullaby; +import com.hmdzl.spspd.items.scrolls.ScrollOfMagicMapping; +import com.hmdzl.spspd.items.scrolls.ScrollOfMagicalInfusion; +import com.hmdzl.spspd.items.scrolls.ScrollOfMirrorImage; +import com.hmdzl.spspd.items.scrolls.ScrollOfPsionicBlast; +import com.hmdzl.spspd.items.scrolls.ScrollOfRage; +import com.hmdzl.spspd.items.scrolls.ScrollOfRecharging; +import com.hmdzl.spspd.items.scrolls.ScrollOfRegrowth; +import com.hmdzl.spspd.items.scrolls.ScrollOfRemoveCurse; +import com.hmdzl.spspd.items.scrolls.ScrollOfTeleportation; +import com.hmdzl.spspd.items.scrolls.ScrollOfTerror; +import com.hmdzl.spspd.items.scrolls.ScrollOfUpgrade; +import com.hmdzl.spspd.items.wands.Wand; +import com.hmdzl.spspd.items.wands.WandOfCharm; +import com.hmdzl.spspd.items.wands.WandOfBlood; +import com.hmdzl.spspd.items.wands.WandOfDisintegration; +import com.hmdzl.spspd.items.wands.WandOfFirebolt; +import com.hmdzl.spspd.items.wands.WandOfFlock; +import com.hmdzl.spspd.items.wands.WandOfLightning; +import com.hmdzl.spspd.items.wands.WandOfMagicMissile; +import com.hmdzl.spspd.items.wands.WandOfPoison; +import com.hmdzl.spspd.items.wands.WandOfFreeze; +import com.hmdzl.spspd.items.wands.WandOfAcid; +import com.hmdzl.spspd.items.wands.WandOfError; +import com.hmdzl.spspd.items.weapon.Weapon; +import com.hmdzl.spspd.items.weapon.melee.BattleAxe; +import com.hmdzl.spspd.items.weapon.melee.Dualknive; +import com.hmdzl.spspd.items.weapon.melee.MageBook; +import com.hmdzl.spspd.items.weapon.melee.Nunchakus; +import com.hmdzl.spspd.items.weapon.melee.Dagger; +import com.hmdzl.spspd.items.weapon.melee.Glaive; +import com.hmdzl.spspd.items.weapon.melee.Knuckles; +import com.hmdzl.spspd.items.weapon.melee.AssassinsBlade; +import com.hmdzl.spspd.items.weapon.melee.Scimitar; +import com.hmdzl.spspd.items.weapon.melee.Handaxe; +import com.hmdzl.spspd.items.weapon.melee.ShortSword; +import com.hmdzl.spspd.items.weapon.melee.Spear; +import com.hmdzl.spspd.items.weapon.melee.special.Spork; +import com.hmdzl.spspd.items.weapon.melee.Whip; +import com.hmdzl.spspd.items.weapon.melee.WarHammer; +import com.hmdzl.spspd.items.weapon.melee.Gsword; +import com.hmdzl.spspd.items.weapon.melee.Halberd; +import com.hmdzl.spspd.items.weapon.melee.special.ErrorW; +import com.hmdzl.spspd.items.weapon.melee.special.TekkoKagi; +import com.hmdzl.spspd.items.weapon.melee.special.WraithBreath; +import com.hmdzl.spspd.items.weapon.missiles.Boomerang; +import com.hmdzl.spspd.items.weapon.missiles.PoisonDart; +import com.hmdzl.spspd.items.weapon.missiles.IncendiaryDart; +import com.hmdzl.spspd.items.weapon.missiles.Tamahawk; +import com.hmdzl.spspd.plants.BlandfruitBush; +import com.hmdzl.spspd.plants.Blindweed; +import com.hmdzl.spspd.plants.Dewcatcher; +import com.hmdzl.spspd.plants.Dreamfoil; +import com.hmdzl.spspd.plants.Earthroot; +import com.hmdzl.spspd.plants.Fadeleaf; +import com.hmdzl.spspd.plants.Firebloom; +import com.hmdzl.spspd.plants.Flytrap; +import com.hmdzl.spspd.plants.Icecap; +import com.hmdzl.spspd.plants.Phaseshift; +import com.hmdzl.spspd.plants.Seedpod; +import com.hmdzl.spspd.plants.Plant; +import com.hmdzl.spspd.plants.Sorrowmoss; +import com.hmdzl.spspd.plants.Starflower; +import com.hmdzl.spspd.plants.Stormvine; +import com.hmdzl.spspd.plants.Sungrass; +import com.watabou.utils.Random; + +public class Generator { + + public static enum Category { + WEAPON(150, Weapon.class), MELEEWEAPON( 20,Weapon.class),OLDWEAPON(0,Weapon.class),RANGEWEAPON(20,Weapon.class),GUNWEAPON(0,Weapon.class),ARMOR(100, Armor.class), + POTION(500, Potion.class), SCROLL(400, Scroll.class), WAND(40, Wand.class), RING(15, Ring.class), + ARTIFACT(20, Artifact.class), SEED(5, Plant.Seed.class), SEED2(0, Plant.Seed.class),SEED3(0, Plant.Seed.class), + FOOD(10, Food.class), GOLD(500, Gold.class), BERRY(50, Food.class), MUSHROOM(50, Food.class), BOMBS(20, Bomb.class), + NORNSTONE(0,NornStone.class), EGGS(0, Egg.class), HIGHFOOD(0,Food.class), SUMMONED(1,Item.class), PILL(1, Pill.class),LINKDROP(0, Item.class),MUSICWEAPON(0,Weapon.class); + + public Class[] classes; + public float[] probs; + + public float prob; + public Class superClass; + + private Category(float prob, Class superClass) { + this.prob = prob; + this.superClass = superClass; + } + + public static int order(Item item) { + for (int i = 0; i < values().length; i++) { + if (values()[i].superClass.isInstance(item)) { + return i; + } + } + + return item instanceof Bag ? Integer.MAX_VALUE + : Integer.MAX_VALUE - 1; + } + }; + + private static HashMap categoryProbs = new HashMap(); + + //private static final float[] INITIAL_ARTIFACT_PROBS = new float[]{ 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; + + static { + + Category.GOLD.classes = new Class[] { Gold.class }; + Category.GOLD.probs = new float[] { 1 }; + + Category.SCROLL.classes = new Class[] { ScrollOfIdentify.class, + ScrollOfTeleportation.class, ScrollOfRemoveCurse.class, + ScrollOfUpgrade.class, ScrollOfRecharging.class, + ScrollOfMagicMapping.class, ScrollOfRage.class, + ScrollOfTerror.class, ScrollOfLullaby.class, + ScrollOfMagicalInfusion.class, ScrollOfPsionicBlast.class, + ScrollOfMirrorImage.class, ScrollOfRegrowth.class, ScrollOfSacrifice.class}; + Category.SCROLL.probs = new float[] { 30, 10, 15, 0, 10, 20, 10, 8, 8, + 0, 3, 6, 0, 0 }; + + Category.POTION.classes = new Class[] { PotionOfHealing.class, + PotionOfExperience.class, PotionOfToxicGas.class, + PotionOfParalyticGas.class, PotionOfLiquidFlame.class, + PotionOfLevitation.class, PotionOfStrength.class, + PotionOfMindVision.class, PotionOfPurity.class, + PotionOfInvisibility.class, PotionOfMight.class, + PotionOfFrost.class, PotionOfMending.class, + PotionOfOverHealing.class, Egg.class}; + Category.POTION.probs = new float[] { 10, 4, 15, 10, 15, 10, 0, 20, 12, + 10, 0, 10, 45, 4, 10}; + + Category.WAND.classes = new Class[] { WandOfAcid.class, + WandOfFreeze.class, WandOfFirebolt.class, + WandOfLight.class, WandOfPoison.class, WandOfBlood.class, + WandOfLightning.class, WandOfCharm.class, + WandOfFlow.class, WandOfFlock.class, + WandOfMagicMissile.class, WandOfDisintegration.class, + WandOfMeteorite.class, WandOfError.class, WandOfTCloud.class}; + Category.WAND.probs = new float[] { 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 0, 5 }; + + Category.WEAPON.classes = new Class[] { ErrorW.class,Pumpkin.class,TekkoKagi.class, + Dagger.class, Knuckles.class, ShortSword.class, MageBook.class, + Handaxe.class, Spear.class, Dualknive.class,WraithBreath.class, FightGloves.class, + Nunchakus.class, Scimitar.class,Whip.class,Spork.class, Rapier.class, + AssassinsBlade.class,BattleAxe.class,Glaive.class,Handcannon.class,Club.class, + Gsword.class, Halberd.class, WarHammer.class, RunicBlade.class, Lance.class, + Triangolo.class, Flute.class, Wardurm.class, Trumpet.class, Harp.class, + WoodenStaff.class, Mace.class, HolyWater.class, PrayerWheel.class, StoneCross.class + }; + Category.WEAPON.probs = new float[] { + 0,0,0, + 1,1,1,1, + 1,1,1,0,1, + 1,1,1,0,1, + 1,1,1,0,1, + 1,1,1,0,1, + 1,1,1,1,1, + 1,1,1,1,1, + }; + + Category.RANGEWEAPON.classes = new Class[] { + EmpBola.class ,EscapeKnive.class,PoisonDart.class,Smoke.class,IncendiaryDart.class,Tamahawk.class, + Skull.class, RiceBall.class, Wave.class, ShatteredAmmo.class, HugeShuriken.class, NormalBomb.class, + Boomerang.class}; + Category.RANGEWEAPON.probs = new float[] { + 1,1,1,1,1,1, + 1,1,1,1,1,1, + 0 + }; + + Category.MELEEWEAPON.classes = new Class[] { + Dagger.class, Knuckles.class, ShortSword.class, MageBook.class, + Handaxe.class, Spear.class, Dualknive.class, FightGloves.class, + Nunchakus.class, Scimitar.class,Whip.class, Rapier.class, + AssassinsBlade.class,BattleAxe.class,Glaive.class,Club.class, + Gsword.class, Halberd.class, WarHammer.class, Lance.class, + Triangolo.class, Flute.class, Wardurm.class, Trumpet.class, Harp.class, + WoodenStaff.class, Mace.class, HolyWater.class, PrayerWheel.class, StoneCross.class}; + Category.MELEEWEAPON.probs = new float[] { + 1,1,1,1, + 1,1,1,1, + 1,1,1,1, + 1,1,1,1, + 1,1,1,1, + 1,1,1,1,1, + 1,1,1,1,1, + }; + + Category.OLDWEAPON.classes = new Class[] { + Dagger.class, Knuckles.class, ShortSword.class, MageBook.class, + Handaxe.class, Spear.class, Dualknive.class, FightGloves.class, + Nunchakus.class, Scimitar.class,Whip.class, Rapier.class, + AssassinsBlade.class,BattleAxe.class,Glaive.class,Club.class, + Gsword.class, Halberd.class, WarHammer.class, Lance.class,}; + Category.OLDWEAPON.probs = new float[] { + 1,1,1,1, + 1,1,1,1, + 1,1,1,1, + 1,1,1,1, + 1,1,1,1, + }; + + Category.GUNWEAPON.classes = new Class[] { + GunA.class, GunB.class, GunC.class, GunD.class, GunE.class}; + Category.GUNWEAPON.probs = new float[] { + 1,1,1,1,1, + }; + + Category.MUSICWEAPON.classes = new Class[] { + Triangolo.class, Flute.class, Wardurm.class, Trumpet.class, Harp.class}; + Category.MUSICWEAPON.probs = new float[] { + 1,1,1,1,1, + }; + + Category.ARMOR.classes = new Class[] { + ClothArmor.class, WoodenArmor.class, VestArmor.class, + LeatherArmor.class, CeramicsArmor.class, RubberArmor.class, + DiscArmor.class, StoneArmor.class, CDArmor.class, + MailArmor.class, MultiplelayerArmor.class, StyrofoamArmor.class, + ScaleArmor.class, BulletArmor.class, ProtectiveclothingArmor.class, + PlateArmor.class, MachineArmor.class, PhantomArmor.class, + ErrorArmor.class }; + Category.ARMOR.probs = new float[] { + 1, 1, 1, + 1, 1, 1, + 1, 1, 1, + 1, 1, 1, + 1, 1, 1, + 1, 1, 1, + 0 }; + + Category.FOOD.classes = new Class[] { NormalRation.class, Pasty.class, OverpricedRation.class}; + Category.FOOD.probs = new float[] { 8, 2, 5 }; + + Category.RING.classes = new Class[] { RingOfAccuracy.class, + RingOfEvasion.class, RingOfElements.class, RingOfForce.class, + RingOfFuror.class, RingOfHaste.class, RingOfMagic.class, + RingOfMight.class, RingOfSharpshooting.class, + RingOfTenacity.class, RingOfEnergy.class }; + Category.RING.probs = new float[] { 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10 }; + + Category.ARTIFACT.classes = new Class[] { CapeOfThorns.class, + ChaliceOfBlood.class, CloakOfShadows.class, HornOfPlenty.class, + MasterThievesArmband.class, SandalsOfNature.class, + TalismanOfForesight.class, TimekeepersHourglass.class, + UnstableSpellbook.class, AlchemistsToolkit.class, RobotDMT.class, + EyeOfSkadi.class, EtherealChains.class, + DriedRose.class, GlassTotem.class, AlienBag.class + }; + Category.ARTIFACT.probs = new float[]{ 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; + + Category.SEED.classes = new Class[] { + Firebloom.Seed.class, Icecap.Seed.class, Sorrowmoss.Seed.class, Blindweed.Seed.class, Sungrass.Seed.class, + Earthroot.Seed.class, Fadeleaf.Seed.class, Rotberry.Seed.class, BlandfruitBush.Seed.class, Dreamfoil.Seed.class, + Stormvine.Seed.class, /*Nut.class, Vegetable.class,Blackberry.class, Blueberry.class, Cloudberry.class, + Moonberry.class,*/ Starflower.Seed.class, Phaseshift.Seed.class, Flytrap.Seed.class, Dewcatcher.Seed.class, Seedpod.Seed.class}; + + Category.SEED.probs = new float[] { 12, 12, 12, 12, 12, + 12, 12, 0, 4, 12, + 12,/* 48, 36, 20, 4, 16, + 4,*/ 3, 3, 4, 8, 2}; + + + Category.SEED2.classes = new Class[] { Firebloom.Seed.class, + Icecap.Seed.class, Sorrowmoss.Seed.class, Blindweed.Seed.class, + Stormvine.Seed.class, Starflower.Seed.class}; + + Category.SEED2.probs = new float[] { 8, 4, 6, 4, 3, 1 }; + + Category.SEED3.classes = new Class[] {Sungrass.Seed.class, Earthroot.Seed.class, BlandfruitBush.Seed.class, Dreamfoil.Seed.class, + Starflower.Seed.class, Dewcatcher.Seed.class, Seedpod.Seed.class}; + + Category.SEED3.probs = new float[] { 8, 4, 3, 4, 3, 1 , 1 }; + + + Category.BERRY.classes = new Class[] {Blackberry.class, Blueberry.class, Cloudberry.class, Moonberry.class}; + Category.BERRY.probs = new float[] {6,3,2,1}; + + Category.MUSHROOM.classes = new Class[] {BlueMilk.class, DeathCap.class, Earthstar.class, JackOLantern.class, PixieParasol.class, GoldenJelly.class, GreenSpore.class}; + Category.MUSHROOM.probs = new float[] {4,3,3,3,3,3,2}; + + Category.NORNSTONE.classes = new Class[] {BlueNornStone.class, GreenNornStone.class, OrangeNornStone.class, PurpleNornStone.class, YellowNornStone.class}; + Category.NORNSTONE.probs = new float[] {2,2,2,2,2}; + + Category.EGGS.classes = new Class[] { BlueDragonEgg.class, CocoCatEgg.class, EasterEgg.class,Egg.class, + LightDragonEgg.class, GreenDragonEgg.class, LeryFireEgg.class, RedDragonEgg.class, ScorpionEgg.class, + ShadowDragonEgg.class, SpiderEgg.class, VelociroosterEgg.class, VioletDragonEgg.class, + GoldDragonEgg.class, RandomEgg.class }; + Category.EGGS.probs = new float[] {1,0,1,1,1,1,1,1,1,1,1,1,1,1,1}; + + Category.HIGHFOOD.classes = new Class[] { Chickennugget.class,Foamedbeverage.class,Fruitsalad.class, + Hamburger.class,Herbmeat.class,Honeymeat.class,Honeyrice.class, + Icecream.class,Kebab.class,PerfectFood.class,Porksoup.class, + Ricefood.class,Vegetablekebab.class,Vegetablesoup.class, + Meatroll.class,Vegetableroll.class,HoneyGel.class,Gel.class,HoneyWater.class, + Chocolate.class, FoodFans.class,Frenchfries.class}; + Category.HIGHFOOD.probs = new float[] { 1,1,1,1, + 1,1,1,1, + 1,1,1,1, + 1,1,1, + 1,1,1,1,1, + 1,1,1}; + Category.BOMBS.classes = new Class[] { BuildBomb.class,DungeonBomb.class, + HugeBomb.class,MiniBomb.class, + FireBomb.class,IceBomb.class,EarthBomb.class,StormBomb.class, + LightBomb.class,DarkBomb.class,FishingBomb.class + }; + Category.BOMBS.probs = new float[] { 0,3, + 0,1, + 1,1,1,1, + 1,1,1}; + Category.SUMMONED.classes = new Class[] {ActiveMrDestructo.class,Mobile.class,FairyCard.class + + }; + Category.SUMMONED.probs = new float[] { 1,1,1}; + + Category.PILL.classes = new Class[] {Hardpill.class, Magicpill.class,Musicpill.class, + Powerpill.class, Shootpill.class, Smashpill.class + }; + Category.PILL.probs = new float[] { 1,1,1,1,1,1}; + + Category.LINKDROP.classes = new Class[] { + BuildBomb.class,DungeonBomb.class, + HugeBomb.class,MiniBomb.class, FireBomb.class,IceBomb.class,EarthBomb.class,StormBomb.class, + LightBomb.class,DarkBomb.class,FishingBomb.class, + EmpBola.class ,EscapeKnive.class,PoisonDart.class,Smoke.class,IncendiaryDart.class,Tamahawk.class, + Skull.class, RiceBall.class, Wave.class, ShatteredAmmo.class, HugeShuriken.class, NormalBomb.class, + }; + Category.LINKDROP.probs = new float[] { 3,1, + 1,1,1,1,1,1, + 1,1,1, + 2,2,2,2,2,2, + 2,2,2,2,2,2}; + } + + public static void reset() { + for (Category cat : Category.values()) { + categoryProbs.put(cat, cat.prob); + } + } + + public static Item random() { + return random(Random.chances(categoryProbs)); + } + + public static Item random(Category cat) { + try { + + categoryProbs.put(cat, categoryProbs.get(cat) / 2); + + switch (cat) { + case ARMOR: + return randomArmor(); + case WEAPON: + return randomWeapon(); + case ARTIFACT: + return randomArtifact(); + case RING: + return randomRing(); + default: + return ((Item) cat.classes[Random.chances(cat.probs)] + .newInstance()).random(); + } + + } catch (Exception e) { + + return null; + + } + } + + public static Item random(Class cl) { + try { + + return ((Item) cl.newInstance()).random(); + + } catch (Exception e) { + + return null; + + } + } + + public static Armor randomArmor() { + int curStr = Hero.STARTING_STR + + Dungeon.limitedDrops.strengthPotions.count; + + return randomArmor(curStr); + } + + public static Armor randomArmor(int targetStr) { + + Category cat = Category.ARMOR; + + try { + Armor a1 = (Armor) cat.classes[Random.chances(cat.probs)] + .newInstance(); + Armor a2 = (Armor) cat.classes[Random.chances(cat.probs)] + .newInstance(); + + a1.random(); + a2.random(); + + return Math.abs(targetStr - a1.STR) < Math.abs(targetStr - a2.STR) ? a1 + : a2; + } catch (Exception e) { + return null; + } + } + + public static Weapon randomWeapon() { + int curStr = Hero.STARTING_STR + + Dungeon.limitedDrops.strengthPotions.count; + + return randomWeapon(curStr); + } + + public static Weapon randomWeapon(int targetStr) { + + try { + Category cat = Category.WEAPON; + + Weapon w1 = (Weapon) cat.classes[Random.chances(cat.probs)] + .newInstance(); + Weapon w2 = (Weapon) cat.classes[Random.chances(cat.probs)] + .newInstance(); + + w1.random(); + w2.random(); + + return Math.abs(targetStr - w1.STR) < Math.abs(targetStr - w2.STR) ? w1 + : w2; + } catch (Exception e) { + return null; + } + } + + // enforces uniqueness of artifacts throughout a run. + public static Artifact randomArtifact() { + + try { + Category cat = Category.ARTIFACT; + + Artifact t1 = (Artifact) cat.classes[Random.chances(cat.probs)] + .newInstance(); + Artifact t2 = (Artifact) cat.classes[Random.chances(cat.probs)] + .newInstance(); + + t1.random(); + t2.random(); + + return Random.Int(6) > 2 ? t1 : t2; + + } catch (Exception e) { + //Log.e("PD", Log.getStackTraceString(e)); + return null; + } + } + + public static Ring randomRing() { + + try { + Category cat = Category.RING; + + Ring r1 = (Ring) cat.classes[Random.chances(cat.probs)] + .newInstance(); + Ring r2 = (Ring) cat.classes[Random.chances(cat.probs)] + .newInstance(); + + r1.random(); + r2.random(); + + return Random.Int(6) > 2 ? r1 : r2; + + } catch (Exception e) { + //Log.e("PD", Log.getStackTraceString(e)); + return null; + } + } + + /*public static boolean removeArtifact(Artifact artifact) { + if (spawnedArtifacts.contains(artifact.getClass().getSimpleName())) + return false; + + Category cat = Category.ARTIFACT; + for (int i = 0; i < cat.classes.length; i++) + if (cat.classes[i].equals(artifact.getClass())) { + if (cat.probs[i] > 0) { + cat.probs[i] = 0; + spawnedArtifacts.add(artifact.getClass().getSimpleName()); + return true; + } else + return false; + } + + return false; + }*/ + + // resets artifact probabilities, for new dungeons + /*public static void initArtifacts() { + spawnedArtifacts.clear(); + Category.ARTIFACT.probs = INITIAL_ARTIFACT_PROBS; + //checks for dried rose quest completion, adds the rose in accordingly. + if (Ghost.Quest.processed) Category.ARTIFACT.probs[12] = 1; + }*/ + + //private static ArrayList spawnedArtifacts = new ArrayList(); + + //private static final String ARTIFACTS = "artifacts"; + + // used to store information on which artifacts have been spawned. +/* public static void storeInBundle(Bundle bundle) { + bundle.put(ARTIFACTS, + spawnedArtifacts.toArray(new String[spawnedArtifacts.size()])); + }*/ + + /*public static void restoreFromBundle(Bundle bundle) { + initArtifacts(); + + if (bundle.contains(ARTIFACTS)) { + Category cat = Category.ARTIFACT; + + for (String artifact : spawnedArtifacts) + for (int i = 0; i < cat.classes.length; i++) + if ((cat.classes[i].getSimpleName().equals(artifact)) && (cat.probs[i] > 0)) { + cat.probs[i] = 0; + spawnedArtifacts.add(artifact); + } + } + }*/ +} diff --git a/java/com/hmdzl/spspd/items/Gold.java b/java/com/hmdzl/spspd/items/Gold.java new file mode 100644 index 00000000..7debbc1d --- /dev/null +++ b/java/com/hmdzl/spspd/items/Gold.java @@ -0,0 +1,116 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.Statistics; +import com.hmdzl.spspd.actors.buffs.GoldTouch; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.items.artifacts.MasterThievesArmband; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.CharSprite; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public class Gold extends Item { + + private static final String TXT_COLLECT = "Collect gold coins to spend them later in a shop."; + private static final String TXT_INFO = "A pile of %d gold coins. " + + TXT_COLLECT; + private static final String TXT_INFO_1 = "One gold coin. " + TXT_COLLECT; + private static final String TXT_VALUE = "%+d"; + + { + //name = "gold"; + image = ItemSpriteSheet.GOLD; + stackable = true; + } + + public Gold() { + this(1); + } + + public Gold(int value) { + this.quantity = value; + } + + @Override + public ArrayList actions(Hero hero) { + return new ArrayList(); + } + + @Override + public boolean doPickUp(Hero hero) { + + Dungeon.gold += quantity; + Statistics.goldCollected += quantity; + Badges.validateGoldCollected(); + + MasterThievesArmband.Thievery thievery = hero + .buff(MasterThievesArmband.Thievery.class); + GoldTouch goldtouch = hero + .buff(GoldTouch.class); + if (thievery != null && goldtouch == null) + thievery.collect(quantity); + + GameScene.pickUp(this); + hero.sprite.showStatus(CharSprite.NEUTRAL, TXT_VALUE, quantity); + hero.spendAndNext(TIME_TO_PICK_UP); + + Sample.INSTANCE.play(Assets.SND_GOLD, 1, 1, Random.Float(0.9f, 1.1f)); + + return true; + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + @Override + public Item random() { + quantity = Random.Int(30 + Dungeon.depth * 10, 60 + Dungeon.depth * 20); + return this; + } + + private static final String VALUE = "value"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(VALUE, quantity); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + quantity = bundle.getInt(VALUE); + } +} diff --git a/java/com/hmdzl/spspd/items/GreaterStylus.java b/java/com/hmdzl/spspd/items/GreaterStylus.java new file mode 100644 index 00000000..0cf970f2 --- /dev/null +++ b/java/com/hmdzl/spspd/items/GreaterStylus.java @@ -0,0 +1,118 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.particles.PurpleParticle; +import com.hmdzl.spspd.items.armor.Armor; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; +import com.hmdzl.spspd.windows.WndBag; +import com.watabou.noosa.audio.Sample; + +public class GreaterStylus extends Item { + + private static final String TXT_SELECT_ARMOR = "Select an armor to inscribe on"; + private static final String TXT_INSCRIBED = "you inscribed your %s with the stylus"; + + private static final float TIME_TO_INSCRIBE = 2; + + private static final String AC_INSCRIBE = "INSCRIBE"; + + { + name = "greater arcane stylus"; + image = ItemSpriteSheet.STYLUS; + + stackable = true; + + + } + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + actions.add(AC_INSCRIBE); + return actions; + } + + @Override + public void execute(Hero hero, String action) { + if (action == AC_INSCRIBE) { + + curUser = hero; + GameScene.selectItem(itemSelector, WndBag.Mode.ARMOR, + TXT_SELECT_ARMOR); + + } else { + + super.execute(hero, action); + + } + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + private void inscribe(Armor armor) { + + detach(curUser.belongings.backpack); + + GLog.w(TXT_INSCRIBED, armor.name()); + + armor.hasglyph(); + + curUser.sprite.operate(curUser.pos); + curUser.sprite.centerEmitter().start(PurpleParticle.BURST, 0.05f, 10); + Sample.INSTANCE.play(Assets.SND_BURNING); + + curUser.spend(TIME_TO_INSCRIBE); + curUser.busy(); + } + + @Override + public int price() { + return 30 * quantity; + } + + @Override + public String info() { + return "This arcane stylus is made of some dark, very hard stone. Using it you can inscribe " + + "a magical glyph on your armor, but you have no power over choosing what glyph it will be, " + + "the stylus will decide it for you."; + } + + private final WndBag.Listener itemSelector = new WndBag.Listener() { + @Override + public void onSelect(Item item) { + if (item != null) { + GreaterStylus.this.inscribe((Armor) item); + } + } + }; +} diff --git a/java/com/hmdzl/spspd/items/Heap.java b/java/com/hmdzl/spspd/items/Heap.java new file mode 100644 index 00000000..df4f951f --- /dev/null +++ b/java/com/hmdzl/spspd/items/Heap.java @@ -0,0 +1,592 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items; + +import java.util.Collection; +import java.util.Collections; +import java.util.LinkedList; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Burning; +import com.hmdzl.spspd.actors.buffs.Frost; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.mobs.Mimic; +import com.hmdzl.spspd.actors.mobs.RedWraith; +import com.hmdzl.spspd.actors.mobs.Wraith; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.effects.Splash; +import com.hmdzl.spspd.effects.particles.ElmoParticle; +import com.hmdzl.spspd.effects.particles.FlameParticle; +import com.hmdzl.spspd.effects.particles.ShadowParticle; +import com.hmdzl.spspd.items.bombs.Bomb; +import com.hmdzl.spspd.items.eggs.Egg; +import com.hmdzl.spspd.items.food.meatfood.ChargrilledMeat; +import com.hmdzl.spspd.items.food.meatfood.FrozenCarpaccio; +import com.hmdzl.spspd.items.food.meatfood.Meat; +import com.hmdzl.spspd.items.food.meatfood.MysteryMeat; +import com.hmdzl.spspd.items.nornstone.NornStone; +import com.hmdzl.spspd.items.potions.Potion; +import com.hmdzl.spspd.items.potions.PotionOfMight; +import com.hmdzl.spspd.items.potions.PotionOfStrength; +import com.hmdzl.spspd.items.scrolls.Scroll; +import com.hmdzl.spspd.items.scrolls.ScrollOfUpgrade; +import com.hmdzl.spspd.items.scrolls.ScrollOfMagicalInfusion; +import com.hmdzl.spspd.items.weapon.Weapon; +import com.hmdzl.spspd.items.weapon.melee.relic.AresSword; +import com.hmdzl.spspd.items.weapon.melee.relic.CromCruachAxe; +import com.hmdzl.spspd.items.weapon.melee.relic.LokisFlail; +import com.hmdzl.spspd.items.weapon.melee.relic.NeptunusTrident; +import com.hmdzl.spspd.items.weapon.melee.relic.JupitersWraith; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Bundlable; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public class Heap implements Bundlable { + + private static final int SEEDS_TO_POTION = 3; + + public enum Type { + HEAP, FOR_SALE, CHEST, LOCKED_CHEST, CRYSTAL_CHEST, TOMB, SKELETON, REMAINS, MIMIC //,MONSTERBOX + } + + public Type type = Type.HEAP; + + public int pos = 0; + + public ItemSprite sprite; + public boolean seen = false; + + public LinkedList items = new LinkedList(); + + public int image() { + switch (type) { + case HEAP: + case FOR_SALE: + return size() > 0 ? items.peek().image() : 0; + case CHEST: + case MIMIC: + return ItemSpriteSheet.CHEST; + case LOCKED_CHEST: + return ItemSpriteSheet.LOCKED_CHEST; + case CRYSTAL_CHEST: + return ItemSpriteSheet.CRYSTAL_CHEST; + case TOMB: + return ItemSpriteSheet.TOMB; + case SKELETON: + return ItemSpriteSheet.BONES; + case REMAINS: + return ItemSpriteSheet.REMAINS; + //case MONSTERBOX: + // return ItemSpriteSheet.LOCKED_CHEST; + default: + return 0; + } + } + + + public boolean chestCheck() { + switch (type) { + case HEAP: + case FOR_SALE: + case TOMB: + case SKELETON: + case REMAINS: + return false; + case CRYSTAL_CHEST: + case LOCKED_CHEST: + case MIMIC: + case CHEST: + return true; + default: + return false; + } + } + + + public ItemSprite.Glowing glowing() { + return (type == Type.HEAP || type == Type.FOR_SALE) && items.size() > 0 ? items + .peek().glowing() : null; + } + + public void open(Hero hero) { + switch (type) { + //case MONSTERBOX: + // if (MonsterBox.spawnAt(pos, items) != null) { + // GLog.n(TXT_MONSTERBOX); + // destroy(); + // } else { + // type = Type.CHEST; + // } + case MIMIC: + if (Mimic.spawnAt(pos, items) != null) { + GLog.n(Messages.get(this,"mimic")); + destroy(); + } else { + type = Type.CHEST; + } + break; + case TOMB: + Wraith.spawnAround(hero.pos); + break; + case SKELETON: + case REMAINS: + CellEmitter.center(pos).start(Speck.factory(Speck.RATTLE), 0.1f, 3); + for (Item item : items) { + + if (RedWraith.spawnAt(pos) == null) { + hero.sprite.emitter().burst(ShadowParticle.CURSE, 6); + hero.damage(hero.HP / 2, this); + } + Sample.INSTANCE.play(Assets.SND_CURSED); + break; + } + + break; + default: + } + + //if (type != Type.MIMIC && type != Type.MONSTERBOX) { + if (type != Type.MIMIC) { + type = Type.HEAP; + sprite.link(); + sprite.drop(); + } + } + + public int size() { + return items.size(); + } + + public Item pickUp() { + + Item item = items.removeFirst(); + if (items.isEmpty()) { + destroy(); + } else if (sprite != null) { + sprite.view(image(), glowing()); + } + + return item; + } + + public Item peek() { + return items.peek(); + } + + public void drop(Item item) { + + if (item.stackable && type != Type.FOR_SALE) { + + for (Item i : items) { + if (i.isSimilar(item)) { + i.quantity += item.quantity; + item = i; + break; + } + } + items.remove(item); + + } + + if ((item instanceof Dewdrop || item instanceof YellowDewdrop || item instanceof RedDewdrop || item instanceof VioletDewdrop) && type != Type.FOR_SALE ) { + items.add(item); + } else { + items.addFirst(item); + } + + if (sprite != null) { + sprite.view(image(), glowing()); + } + } + + public void spdrop(Item item) { + + items.add(item); + + if (sprite != null) { + sprite.view(image(), glowing()); + } + } + + + + public void replace(Item a, Item b) { + int index = items.indexOf(a); + if (index != -1) { + items.remove(index); + items.add(index, b); + } + } + + public void burn() { + + if (type == Type.MIMIC) { + Mimic m = Mimic.spawnAt(pos, items); + if (m != null) { + Buff.affect(m, Burning.class).reignite(m); + m.sprite.emitter().burst(FlameParticle.FACTORY, 5); + destroy(); + } + } + + if (type != Type.HEAP) { + return; + } + + boolean burnt = false; + boolean evaporated = false; + + for (Item item : items.toArray(new Item[0])) { + if (item instanceof Scroll + && !(item instanceof ScrollOfUpgrade || item instanceof ScrollOfMagicalInfusion)) { + items.remove(item); + burnt = true; + } else if (item instanceof Egg) { + ((Egg) item).burns++; + burnt = true; + } else if (item instanceof MysteryMeat) { + replace(item, ChargrilledMeat.cook((MysteryMeat) item)); + burnt = true; + } else if (item instanceof Meat) { + replace(item, ChargrilledMeat.cook((Meat) item)); + burnt = true; + //} else if (item instanceof Nut) { + //replace(item, ToastedNut.cook((Nut) item)); + //burnt = true; + //} else if (item instanceof Bomb) { + //items.remove(item); + //((Bomb) item).explode(pos); + // stop processing the burning, it will be replaced by the + // explosion. + //return; + } + } + + if (burnt || evaporated) { + + if (Dungeon.visible[pos]) { + if (burnt) { + burnFX(pos); + } else { + evaporateFX(pos); + } + } + + if (isEmpty()) { + destroy(); + } else if (sprite != null) { + sprite.view(image(), glowing()); + } + + } + } + + // Note: should not be called to initiate an explosion, but rather by an + // explosion that is happening. + public void explode() { + + // breaks open most standard containers, mimics die. + if (type == Type.MIMIC || type == Type.CHEST || type == Type.SKELETON) { + type = Type.HEAP; + sprite.link(); + sprite.drop(); + return; + } + + if (type != Type.HEAP) { + + return; + + } else { + + for (Item item : items.toArray(new Item[0])) { + + if (item instanceof Bomb) { + + items.remove(item); + ((Bomb) item).explode(pos); + + if (((Bomb) item).explodesDestructively()) { + //stop processing current explosion, it will be replaced by the new one. + return; + } + // unique and upgraded items can endure the blast + } else if (!(item.level > 0 || item.unique)) + items.remove(item); + + } + + if (items.isEmpty()) + destroy(); + } + + } + + /* + public void dewcollect() { + + + for (Item item : items.toArray(new Item[0])) { + + if (item instanceof Dewdrop || + item instanceof YellowDewdrop || + item instanceof RedDewdrop) { + + item.doPickUp(Dungeon.hero); + } + } + } + */ + public int dewdrops(){ + + if (type != Type.HEAP) { + return 0; + } + + int drops=0; + + for (Item item : items.toArray(new Item[0])) { + if (item instanceof Dewdrop) { + drops++; + } else if (item instanceof VioletDewdrop) { + drops++; + } else if (item instanceof RedDewdrop) { + drops++; + } else if (item instanceof YellowDewdrop) { + drops++; + } + } + + return drops; + } + + + public void lit() { + if (type != Type.HEAP) { + return; + } + for (Item item : items.toArray(new Item[0])) { + if (item instanceof Egg) { + ((Egg) item).lits++; + } + } + } + + + public void summon() { + if (type != Type.HEAP) { + return; + } + for (Item item : items.toArray(new Item[0])) { + if (item instanceof Egg) { + ((Egg) item).summons++; + } + } + } + + public void poison() { + if (type != Type.HEAP) { + return; + } + for (Item item : items.toArray(new Item[0])) { + if (item instanceof Egg) { + ((Egg) item).poisons++; + } + } + } + + public void light() { + if (type != Type.HEAP) { + return; + } + for (Item item : items.toArray(new Item[0])) { + if (item instanceof Egg) { + ((Egg) item).light++; + } + } + } + + public void freeze() { + + if (type == Type.MIMIC) { + Mimic m = Mimic.spawnAt(pos, items); + if (m != null) { + Buff.prolong(m, Frost.class, + Frost.duration(m) * Random.Float(1.0f, 1.5f)); + destroy(); + } + } + + + if (type != Type.HEAP) { + return; + } + + boolean frozen = false; + for (Item item : items.toArray(new Item[0])) { + if (item instanceof MysteryMeat) { + replace(item, FrozenCarpaccio.cook((MysteryMeat) item)); + frozen = true; + } else if (item instanceof Potion + && !(item instanceof PotionOfStrength || item instanceof PotionOfMight)) { + items.remove(item); + ((Potion) item).shatter(pos); + frozen = true; + }else if (item instanceof Egg) { + ((Egg) item).freezes++; + frozen = true; + } else if (item instanceof Bomb) { + ((Bomb) item).fuse = null; + frozen = true; + } else if (item instanceof Meat) { + replace(item, FrozenCarpaccio.cook((Meat) item)); + frozen = true; + } + } + + if (frozen) { + if (isEmpty()) { + destroy(); + } else if (sprite != null) { + sprite.view(image(), glowing()); + } + } + } + + public Item transmute() { + + CellEmitter.get(pos).burst(Speck.factory(Speck.BUBBLE), 3); + Splash.at(pos, 0xFFFFFF, 3); + + float chances[] = new float[items.size()]; + int count = 0; + + + return null; + + } + + public Weapon consecrate() { + + CellEmitter.get(pos).burst(Speck.factory(Speck.FORGE), 3); + Splash.at(pos, 0xFFFFFF, 3); + + int count=0; + int type=0; + + for (Item item : items) { + if (item instanceof NornStone) { + count += item.quantity; + if(type==0){ + type=((NornStone) item).type; + } else if (Random.Int(3)= 2) { + + CellEmitter.get(pos).burst(Speck.factory(Speck.WOOL), 6); + Sample.INSTANCE.play(Assets.SND_PUFF); + + destroy(); + + switch (type) { + case 1: weapon = new LokisFlail().enchantLoki(); + break; + case 2: weapon = new NeptunusTrident(); weapon.enchantNeptune(); + break; + case 3: weapon = new CromCruachAxe(); weapon.enchantLuck(); + break; + case 4: weapon = new AresSword(); weapon.enchantAres(); + break; + case 5: weapon = new JupitersWraith(); weapon.enchantJupiter(); + break; + default: weapon = new AresSword(); weapon.enchantAres(); + break; + } + + return weapon; + + } else { + return null; + } + } + + + public static void burnFX(int pos) { + CellEmitter.get(pos).burst(ElmoParticle.FACTORY, 6); + Sample.INSTANCE.play(Assets.SND_BURNING); + } + + public static void evaporateFX(int pos) { + CellEmitter.get(pos).burst(Speck.factory(Speck.STEAM), 5); + } + + public boolean isEmpty() { + return items == null || items.size() == 0; + } + + public void destroy() { + Dungeon.level.heaps.remove(this.pos); + if (sprite != null) { + sprite.kill(); + } + items.clear(); + items = null; + } + + private static final String POS = "pos"; + private static final String SEEN = "seen"; + private static final String TYPE = "type"; + private static final String ITEMS = "items"; + + @SuppressWarnings("unchecked") + @Override + public void restoreFromBundle(Bundle bundle) { + pos = bundle.getInt(POS); + seen = bundle.getBoolean( SEEN ); + type = Type.valueOf(bundle.getString(TYPE)); + items = new LinkedList( + (Collection) ((Collection) bundle.getCollection(ITEMS))); + items.removeAll(Collections.singleton(null)); + } + + @Override + public void storeInBundle(Bundle bundle) { + bundle.put(POS, pos); + bundle.put( SEEN, seen ); + bundle.put(TYPE, type.toString()); + bundle.put(ITEMS, items); + } + +} diff --git a/java/com/hmdzl/spspd/items/Item.java b/java/com/hmdzl/spspd/items/Item.java new file mode 100644 index 00000000..a15407d4 --- /dev/null +++ b/java/com/hmdzl/spspd/items/Item.java @@ -0,0 +1,600 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.SnipersMark; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.hero.HeroClass; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.bags.Bag; +import com.hmdzl.spspd.items.weapon.missiles.Boomerang; +import com.hmdzl.spspd.items.weapon.missiles.MissileWeapon; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.scenes.CellSelector; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.sprites.MissileSprite; +import com.hmdzl.spspd.ui.QuickSlotButton; +import com.hmdzl.spspd.utils.GLog; + +import com.watabou.noosa.audio.Sample; +import com.watabou.noosa.particles.Emitter; +import com.watabou.utils.Bundlable; +import com.watabou.utils.Bundle; +import com.watabou.utils.Callback; + +public class Item implements Bundlable { + + private static final String TXT_PACK_FULL = "Your pack is too full for the %s"; + + private static final String TXT_TO_STRING = "%s"; + private static final String TXT_TO_STRING_X = "%s x%d"; + private static final String TXT_TO_STRING_LVL = "%s%+d"; + private static final String TXT_TO_STRING_LVL_X = "%s%+d x%d"; + + protected static final float TIME_TO_THROW = 1.0f; + protected static final float TIME_TO_PICK_UP = 1.0f; + protected static final float TIME_TO_DROP = 0.5f; + + public static final String AC_DROP = "DROP"; + public static final String AC_THROW = "THROW"; + + public String defaultAction; + public boolean usesTargeting; + + protected String name = Messages.get(this, "name"); + public int image = 0; + + public boolean stackable = false; + public boolean breakable = true; + protected int quantity = 1; + + public int level = 0; + public int consumedValue = 0; + public boolean levelKnown = false; + + public boolean cursed; + public boolean cursedKnown; + public boolean reinforced; + + // Unique items persist through revival + public boolean unique = false; + + private static Comparator itemComparator = new Comparator() { + @Override + public int compare(Item lhs, Item rhs) { + return Generator.Category.order(lhs) + - Generator.Category.order(rhs); + } + }; + + public ArrayList actions(Hero hero) { + ArrayList actions = new ArrayList(); + actions.add(AC_DROP); + actions.add(AC_THROW); + return actions; + } + + public boolean doPickUp(Hero hero) { + if (collect(hero.belongings.backpack)) { + + GameScene.pickUp(this); + Sample.INSTANCE.play(Assets.SND_ITEM); + if (hero.heroClass == HeroClass.SOLDIER){ + hero.belongings.observeS(); + } + hero.spendAndNext(TIME_TO_PICK_UP); + + return true; + + } else { + return false; + } + } + + public void doDrop(Hero hero) { + hero.spendAndNext(TIME_TO_DROP); + Dungeon.level.drop(detachAll(hero.belongings.backpack), hero.pos).sprite + .drop(hero.pos); + } + + public void sync() { + name = Messages.get(this, "name"); + } + + + public void doThrow(Hero hero) { + GameScene.selectCell(thrower); + } + + public void execute(Hero hero, String action) { + + curUser = hero; + curItem = this; + + if (action.equals(AC_DROP)) { + + doDrop(hero); + + } else if (action.equals(AC_THROW)) { + + doThrow(hero); + + } + } + + public void execute(Hero hero) { + execute(hero, defaultAction); + } + + protected void onThrow(int cell) { + Heap heap = Dungeon.level.drop(this, cell); + if (!heap.isEmpty()) { + heap.sprite.drop(cell); + } + } + + public boolean collect(Bag container) { + + ArrayList items = container.items; + + if (items.contains(this)) { + return true; + } + + for (Item item : items) { + if (item instanceof Bag && ((Bag) item).grab(this)) { + return collect((Bag) item); + } + } + + if (stackable) { + for (Item item : items) { + if (isSimilar(item)) { + item.quantity += quantity; + item.updateQuickslot(); + return true; + } + } + } + + if (items.size() < container.size) { + + if (Dungeon.hero != null && Dungeon.hero.isAlive()) { + Badges.validateItemLevelAquired(this); + } + + items.add(this); + if (stackable || this instanceof Boomerang) + Dungeon.quickslot.replaceSimilar(this); + updateQuickslot(); + Collections.sort(items, itemComparator); + return true; + + } else { + + GLog.n(Messages.get(Item.class, "pack_full", name())); + return false; + + } + } + + public boolean collect() { + return collect(Dungeon.hero.belongings.backpack); + } + + public final Item detach(Bag container) { + + if (quantity <= 0) { + + return null; + + } else if (quantity == 1) { + + if (stackable || this instanceof Boomerang ) { + Dungeon.quickslot.convertToPlaceholder(this); + } + + return detachAll(container); + + } else { + + quantity--; + updateQuickslot(); + + try { + + // pssh, who needs copy constructors? + Item detached = getClass().newInstance(); + Bundle copy = new Bundle(); + this.storeInBundle(copy); + detached.restoreFromBundle(copy); + detached.quantity(1); + + detached.onDetach(); + return detached; + } catch (Exception e) { + return null; + } + } + } + + /*public final Item detachAll( Bag container ) { + Dungeon.quickslot.clearItem( this ); + updateQuickslot(); + + for (Item item : container.items) { + if (item == this) { + container.items.remove(this); + item.onDetach(); + return this; + } else if (item instanceof Bag) { + Bag bag = (Bag)item; + if (bag.contains( this )) { + return detachAll( bag ); + } + } + } + + return this; + }*/ + + public final Item detach(Bag container, Integer quant) { + + if (quantity <= 0) { + + return null; + + } else if (quantity == 1) { + + if (stackable || this instanceof Boomerang) { + Dungeon.quickslot.convertToPlaceholder(this); + } + + return detachAll(container); + + } else { + + quantity-=quant; + updateQuickslot(); + + try { + + // pssh, who needs copy constructors? + Item detached = getClass().newInstance(); + Bundle copy = new Bundle(); + this.storeInBundle(copy); + detached.restoreFromBundle(copy); + detached.quantity(quant); + + detached.onDetach(); + return detached; + } catch (Exception e) { + return null; + } + } + } + + public final Item detachAll(Bag container) { + Dungeon.quickslot.clearItem(this); + updateQuickslot(); + + for (Item item : container.items) { + if (item == this) { + container.items.remove(this); + item.onDetach(); + return this; + } else if (item instanceof Bag) { + Bag bag = (Bag) item; + if (bag.contains(this)) { + return detachAll(bag); + } + } + } + + return this; + } + + public boolean isSimilar(Item item) { + return getClass() == item.getClass(); + } + + protected void onDetach() { + } + + public Item uncurse(){ + cursed=false; + return this; + } + + public Item reinforce(){ + reinforced=true; + return this; + } + + + public Item upgrade() { + + cursedKnown = true; + this.level++; + + updateQuickslot(); + + return this; + } + + final public Item upgrade(int n) { + for (int i = 0; i < n; i++) { + upgrade(); + } + + return this; + } + + public Item degrade() { + + this.level--; + + return this; + } + + final public Item degrade(int n) { + for (int i = 0; i < n; i++) { + degrade(); + } + + return this; + } + + public int visiblyUpgraded() { + return levelKnown ? level : 0; + } + + public boolean visiblyCursed() { + return cursed && cursedKnown; + } + + public boolean isUpgradable() { + return true; + } + + public boolean isReinforced() { + return reinforced; + } + + public boolean isIdentified() { + return levelKnown && cursedKnown; + } + + public boolean isEquipped(Hero hero) { + return false; + } + + public Item identify() { + + levelKnown = true; + cursedKnown = true; + + return this; + } + + public static void evoke(Hero hero) { + hero.sprite.emitter().burst(Speck.factory(Speck.EVOKE), 5); + } + + @Override + public String toString() { + + if (levelKnown && level != 0) { + if (quantity > 1) { + return Messages.format( TXT_TO_STRING_LVL_X, name(), level, quantity ); + } else { + return Messages.format( TXT_TO_STRING_LVL, name(), level ); + } + } else { + if (quantity > 1) { + return Messages.format( TXT_TO_STRING_X, name(), quantity ); + } else { + return Messages.format( TXT_TO_STRING, name() ); + } + } + } + + public String name() { + return name; + } + + public final String trueName() { + return name; + } + + public int image() { + return image; + } + + public ItemSprite.Glowing glowing() { + return null; + } + + public Emitter emitter() { return null; } + + public String info() { + return desc(); + } + + public String desc() { + return Messages.get(this, "desc"); + } + + public int quantity() { + return quantity; + } + + public Item quantity(int value) { + quantity = value; + return this; + } + + public int price() { + return 0; + } + + public static Item virtual(Class cl) { + try { + + Item item = cl.newInstance(); + item.quantity = 0; + return item; + + } catch (Exception e) { + return null; + } + } + + public Item random() { + return this; + } + + public String status() { + return quantity != 1 ? Integer.toString(quantity) : null; + } + + public void updateQuickslot() { + QuickSlotButton.refresh(); + } + + private static final String QUANTITY = "quantity"; + private static final String LEVEL = "level"; + private static final String LEVEL_KNOWN = "levelKnown"; + private static final String CURSED = "cursed"; + private static final String REINFORCED = "reinforced"; + private static final String CURSED_KNOWN = "cursedKnown"; + private static final String OLDSLOT = "quickslot"; + private static final String QUICKSLOT = "quickslotpos"; + + @Override + public void storeInBundle(Bundle bundle) { + bundle.put(QUANTITY, quantity); + bundle.put(LEVEL, level); + bundle.put(LEVEL_KNOWN, levelKnown); + bundle.put(CURSED, cursed); + bundle.put(REINFORCED, reinforced); + bundle.put(CURSED_KNOWN, cursedKnown); + if (Dungeon.quickslot.contains(this)) { + bundle.put(QUICKSLOT, Dungeon.quickslot.getSlot(this)); + } + } + + @Override + public void restoreFromBundle(Bundle bundle) { + quantity = bundle.getInt(QUANTITY); + levelKnown = bundle.getBoolean(LEVEL_KNOWN); + cursedKnown = bundle.getBoolean(CURSED_KNOWN); + + int level = bundle.getInt(LEVEL); + if (level > 0) { + upgrade(level); + } else if (level < 0) { + degrade(-level); + } + + cursed = bundle.getBoolean(CURSED); + reinforced = bundle.getBoolean(REINFORCED); + + // only want to populate slot on first load. + if (Dungeon.hero == null) { + // support for pre-0.2.3 saves and rankings + if (bundle.contains(OLDSLOT)) { + Dungeon.quickslot.setSlot(0, this); + } else if (bundle.contains(QUICKSLOT)) { + Dungeon.quickslot.setSlot(bundle.getInt(QUICKSLOT), this); + } + } + } + + public int throwPos( Hero user, int dst){ + return new Ballistica( user.pos, dst, Ballistica.PROJECTILE ).collisionPos; + } + + public void cast(final Hero user, int dst) { + + final int cell = throwPos( user, dst ); + //final int cell = new Ballistica( user.pos, dst, Ballistica.PROJECTILE ).collisionPos; + user.sprite.zap(cell); + user.busy(); + + Sample.INSTANCE.play(Assets.SND_MISS, 0.6f, 0.6f, 1.5f); + + Char enemy = Actor.findChar(cell); + QuickSlotButton.target(enemy); + + // FIXME!!! + float delay = TIME_TO_THROW; + if (this instanceof MissileWeapon) { + delay *= ((MissileWeapon) this).speedFactor(user); + if (enemy != null) { + SnipersMark mark = user.buff(SnipersMark.class); + if (mark != null) { + if (mark.object == enemy.id()) { + delay *= 0.5f; + } + user.remove(mark); + } + } + } + final float finalDelay = delay; + + ((MissileSprite) user.sprite.parent.recycle(MissileSprite.class)) + .reset(user.pos, cell, this, new Callback() { + @Override + public void call() { + Item.this.detach(user.belongings.backpack) + .onThrow(cell); + user.spendAndNext(finalDelay); + } + }); + } + + protected static Hero curUser = null; + protected static Item curItem = null; + protected static CellSelector.Listener thrower = new CellSelector.Listener() { + @Override + public void onSelect(Integer target) { + if (target != null) { + curItem.cast(curUser, target); + } + } + + @Override + public String prompt() { + return Messages.get(Item.class, "prompt"); + } + }; + + +} diff --git a/java/com/hmdzl/spspd/items/ItemStatusHandler.java b/java/com/hmdzl/spspd/items/ItemStatusHandler.java new file mode 100644 index 00000000..bec9a502 --- /dev/null +++ b/java/com/hmdzl/spspd/items/ItemStatusHandler.java @@ -0,0 +1,176 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; + +import com.hmdzl.spspd.Dungeon; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public class ItemStatusHandler { + + private Class[] items; + + private HashMap, Integer> images; + private HashMap, String> labels; + private HashSet> known; + + public ItemStatusHandler(Class[] items, String[] allLabels, + Integer[] allImages) { + + this.items = items; + + this.images = new HashMap, Integer>(); + this.labels = new HashMap, String>(); + known = new HashSet>(); + + ArrayList labelsLeft = new ArrayList( + Arrays.asList(allLabels)); + ArrayList imagesLeft = new ArrayList( + Arrays.asList(allImages)); + + for (int i = 0; i < items.length; i++) { + + Class item = (items[i]); + + int index = Random.Int(labelsLeft.size()); + + labels.put(item, labelsLeft.get(index)); + labelsLeft.remove(index); + + images.put(item, imagesLeft.get(index)); + imagesLeft.remove(index); + } + } + + public ItemStatusHandler(Class[] items, String[] labels, + Integer[] images, Bundle bundle) { + + this.items = items; + + this.images = new HashMap, Integer>(); + this.labels = new HashMap, String>(); + known = new HashSet>(); + + restore(bundle, labels, images); + } + + private static final String PFX_IMAGE = "_image"; + private static final String PFX_LABEL = "_label"; + private static final String PFX_KNOWN = "_known"; + + public void save(Bundle bundle) { + for (int i = 0; i < items.length; i++) { + String itemName = items[i].toString(); + bundle.put(itemName + PFX_IMAGE, images.get(items[i])); + bundle.put(itemName + PFX_LABEL, labels.get(items[i])); + bundle.put(itemName + PFX_KNOWN, known.contains(items[i])); + } + } + + private void restore(Bundle bundle, String[] allLabels, Integer[] allImages) { + + ArrayList labelsLeft = new ArrayList( + Arrays.asList(allLabels)); + ArrayList imagesLeft = new ArrayList( + Arrays.asList(allImages)); + + for (int i = 0; i < items.length; i++) { + + Class item = (items[i]); + String itemName = item.toString(); + + if (bundle.contains(itemName + PFX_LABEL) && Dungeon.version > 4) { + + String label = bundle.getString(itemName + PFX_LABEL); + labels.put(item, label); + labelsLeft.remove(label); + + Integer image = bundle.getInt(itemName + PFX_IMAGE); + images.put(item, image); + imagesLeft.remove(image); + + if (bundle.getBoolean(itemName + PFX_KNOWN)) { + known.add(item); + } + + // if there's a new item, give it a random image + // or.. if we're loading from an untrusted version, randomize + // the image to be safe. + } else { + + int index = Random.Int(labelsLeft.size()); + + labels.put(item, labelsLeft.get(index)); + labelsLeft.remove(index); + + images.put(item, imagesLeft.get(index)); + imagesLeft.remove(index); + + if (bundle.contains(itemName + PFX_KNOWN) + && bundle.getBoolean(itemName + PFX_KNOWN)) { + known.add(item); + } + } + } + } + + public int image(T item) { + return images.get(item.getClass()); + } + + public String label(T item) { + return labels.get(item.getClass()); + } + + public boolean isKnown(T item) { + return known.contains(item.getClass()); + } + + @SuppressWarnings("unchecked") + public void know(T item) { + known.add((Class) item.getClass()); + + if (known.size() == items.length - 1) { + for (int i = 0; i < items.length; i++) { + if (!known.contains(items[i])) { + known.add(items[i]); + break; + } + } + } + } + + public HashSet> known() { + return known; + } + + public HashSet> unknown() { + HashSet> result = new HashSet>(); + for (Class i : items) { + if (!known.contains(i)) { + result.add(i); + } + } + return result; + } +} diff --git a/java/com/hmdzl/spspd/items/KindOfArmor.java b/java/com/hmdzl/spspd/items/KindOfArmor.java new file mode 100644 index 00000000..0f05732e --- /dev/null +++ b/java/com/hmdzl/spspd/items/KindOfArmor.java @@ -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 + */ +package com.hmdzl.spspd.items; + +import java.util.ArrayList; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.HeroSprite; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Random; + +public class KindOfArmor extends EquipableItem { + + protected static final float TIME_TO_EQUIP = 1f; + + public int MIN = 0; + public int MAX = 1; + public int tier; + + //public KindOfArmor( int tier ) { + //this.tier = tier; + //} + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + actions.add(isEquipped(hero) ? AC_UNEQUIP : AC_EQUIP); + return actions; + } + + @Override + public boolean isEquipped(Hero hero) { + return hero.belongings.armor == this; + } + + //@Override + public boolean doEquip(Hero hero) { + + detachAll(hero.belongings.backpack); + + if (hero.belongings.armor == null + || hero.belongings.armor.doUnequip(hero, true)) { + + hero.belongings.armor = this; + activate(hero); + + cursedKnown = true; + if (cursed) { + equipCursed(hero); + GLog.n(Messages.get(KindOfArmor.class, "cursed", name())); + + } + + ((HeroSprite) hero.sprite).updateArmor(); + + hero.spendAndNext(TIME_TO_EQUIP); + return true; + + } else { + + collect(hero.belongings.backpack); + return false; + } + } + + //@Override + //public void activate(Char ch) { + //buff = buff(); + //buff.attachTo(ch); +// } + + @Override + public boolean doUnequip(Hero hero, boolean collect, boolean single) { + if (super.doUnequip(hero, collect, single)) { + + hero.belongings.armor = null; + ((HeroSprite) hero.sprite).updateArmor(); + + //hero.remove(buff); + //buff = null; + + return true; + + } else { + + return false; + + } + } + + public void activate(Hero hero) { + } + + public int drRoll(Hero owner) { + return Random.NormalIntRange(MIN, MAX); + } + + public float dexterityFactor(Hero hero) { + return 1f; + } + + public float stealthFactor(Hero hero) { + return 1f; + } + + public int energyFactor( Hero hero ){ + return 1; + } + + public void proc(Char attacker, Char defender, int damage) { + } +} diff --git a/java/com/hmdzl/spspd/items/KindOfWeapon.java b/java/com/hmdzl/spspd/items/KindOfWeapon.java new file mode 100644 index 00000000..445aefa2 --- /dev/null +++ b/java/com/hmdzl/spspd/items/KindOfWeapon.java @@ -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 + */ +package com.hmdzl.spspd.items; + +import java.util.ArrayList; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Random; + +public class KindOfWeapon extends EquipableItem { + + protected static final float TIME_TO_EQUIP = 1f; + + public int MIN = 0; + public int MAX = 1; + // public int durable = 10; + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + actions.add(isEquipped(hero) ? AC_UNEQUIP : AC_EQUIP); + return actions; + } + + @Override + public boolean isEquipped(Hero hero) { + return hero.belongings.weapon == this; + } + + @Override + public boolean doEquip(Hero hero) { + + detachAll(hero.belongings.backpack); + + if (hero.belongings.weapon == null + || hero.belongings.weapon.doUnequip(hero, true)) { + + hero.belongings.weapon = this; + activate(hero); + + updateQuickslot(); + + cursedKnown = true; + if (cursed) { + equipCursed(hero); + GLog.n(Messages.get(KindOfWeapon.class, "cursed", name())); + } + + hero.spendAndNext(TIME_TO_EQUIP); + return true; + + } else { + + collect(hero.belongings.backpack); + return false; + } + } + + @Override + public boolean doUnequip(Hero hero, boolean collect, boolean single) { + if (super.doUnequip(hero, collect, single)) { + + hero.belongings.weapon = null; + return true; + + } else { + + return false; + + } + } + + public void activate(Hero hero) { + } + + public int damageRoll(Hero owner) { + return Random.NormalIntRange(MIN, MAX); + } + + public float acuracyFactor(Hero hero) { + return 1f; + } + + public float speedFactor(Hero hero) { + return 1f; + } + + public int reachFactor( Hero hero ){ + return 1; + } + + //public int durableFactor( Hero hero ){ + //return durable; + //} + + public void proc(Char attacker, Char defender, int damage) { + } + +} diff --git a/java/com/hmdzl/spspd/items/KindofMisc.java b/java/com/hmdzl/spspd/items/KindofMisc.java new file mode 100644 index 00000000..5a244633 --- /dev/null +++ b/java/com/hmdzl/spspd/items/KindofMisc.java @@ -0,0 +1,11 @@ +package com.hmdzl.spspd.items; + +import com.hmdzl.spspd.actors.Char; + +/** + * Created by Evan on 24/08/2014. + */ +public abstract class KindofMisc extends EquipableItem { + + public abstract void activate(Char ch); +} diff --git a/java/com/hmdzl/spspd/items/LloydsBeacon.java b/java/com/hmdzl/spspd/items/LloydsBeacon.java new file mode 100644 index 00000000..0d5aa7c6 --- /dev/null +++ b/java/com/hmdzl/spspd/items/LloydsBeacon.java @@ -0,0 +1,180 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.items.artifacts.TimekeepersHourglass; +import com.hmdzl.spspd.items.scrolls.ScrollOfTeleportation; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.scenes.InterlevelScene; +import com.hmdzl.spspd.sprites.ItemSprite.Glowing; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; +import com.hmdzl.spspd.messages.Messages; + +import com.watabou.noosa.Game; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Bundle; + +public class LloydsBeacon extends Item { + + private static final String TXT_PREVENTING = "Strong magic aura of this place prevents you from using the lloyd's beacon!"; + + private static final String TXT_CREATURES = "Psychic aura of neighbouring creatures doesn't allow you to use the lloyd's beacon at this moment."; + + private static final String TXT_RETURN = "The lloyd's beacon is successfully set at your current location, now you can return here anytime."; + + private static final String TXT_INFO = "Lloyd's beacon is an intricate magic device, that allows you to return to a place you have already been."; + + private static final String TXT_SET = "\n\nThis beacon was set somewhere on the level %d of Pixel Dungeon."; + + public static final float TIME_TO_USE = 1; + + public static final String AC_SET = "SET"; + public static final String AC_RETURN = "RETURN"; + + private int returnDepth = -1; + private int returnPos; + + { + name = "lloyd's beacon"; + image = ItemSpriteSheet.BEACON; + + unique = true; + } + + private static final String DEPTH = "depth"; + private static final String POS = "pos"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(DEPTH, returnDepth); + if (returnDepth != -1) { + bundle.put(POS, returnPos); + } + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + returnDepth = bundle.getInt(DEPTH); + returnPos = bundle.getInt(POS); + } + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + actions.add(AC_SET); + if (returnDepth != -1) { + actions.add(AC_RETURN); + } + return actions; + } + + @Override + public void execute(Hero hero, String action) { + + if (action == AC_SET || action == AC_RETURN) { + + if (Dungeon.bossLevel() || Dungeon.depth>24) { + hero.spend(LloydsBeacon.TIME_TO_USE); + GLog.w(TXT_PREVENTING); + return; + } + + for (int i = 0; i < Level.NEIGHBOURS8.length; i++) { + if (Actor.findChar(hero.pos + Level.NEIGHBOURS8[i]) != null) { + GLog.w(TXT_CREATURES); + return; + } + } + } + + if (action == AC_SET) { + + returnDepth = Dungeon.depth; + returnPos = hero.pos; + + hero.spend(LloydsBeacon.TIME_TO_USE); + hero.busy(); + + hero.sprite.operate(hero.pos); + Sample.INSTANCE.play(Assets.SND_BEACON); + + GLog.i(TXT_RETURN); + + } else if (action == AC_RETURN) { + + if (returnDepth == Dungeon.depth) { + ScrollOfTeleportation.appear(hero, returnPos); + Dungeon.level.press(returnPos, hero); + Dungeon.observe(); + } else { + + Buff buff = Dungeon.hero + .buff(TimekeepersHourglass.timeFreeze.class); + if (buff != null) + buff.detach(); + + InterlevelScene.mode = InterlevelScene.Mode.RETURN; + InterlevelScene.returnDepth = returnDepth; + InterlevelScene.returnPos = returnPos; + Game.switchScene(InterlevelScene.class); + } + + } else { + + super.execute(hero, action); + + } + } + + public void reset() { + returnDepth = -1; + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + private static final Glowing WHITE = new Glowing(0xFFFFFF); + + @Override + public Glowing glowing() { + return returnDepth != -1 ? WHITE : null; + } + + @Override + public String info() { + return TXT_INFO + + (returnDepth == -1 ? "" : Messages.format(TXT_SET, returnDepth)); + } +} diff --git a/java/com/hmdzl/spspd/items/OrbOfZot.java b/java/com/hmdzl/spspd/items/OrbOfZot.java new file mode 100644 index 00000000..577673a5 --- /dev/null +++ b/java/com/hmdzl/spspd/items/OrbOfZot.java @@ -0,0 +1,162 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.Statistics; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.mobs.OrbOfZotMob; +import com.hmdzl.spspd.effects.particles.ElmoParticle; +import com.hmdzl.spspd.items.journalpages.EnergyCore; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; +import com.hmdzl.spspd.messages.Messages; + +public class OrbOfZot extends Item { + + //private static final String AC_END = "END THE GAME"; + + { + //name = "Orb Of Zot"; + image = ItemSpriteSheet.ORBOFZOT; + defaultAction = AC_ACTIVATETHROW; + unique = true; + } + + private static boolean activate = false; + public final int fullCharge = 500; + public int charge = 0; + private static final String CHARGE = "charge"; + + private static final String AC_ACTIVATETHROW = "ACTIVATETHROW"; + private static final String AC_BREAK = "BREAK"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(CHARGE, charge); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + charge = bundle.getInt(CHARGE); + } + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + if (charge >= 500){ + actions.add(AC_ACTIVATETHROW); + } + actions.add(AC_BREAK); + return actions; + } + + @Override + public void execute(Hero hero, String action) { + + if (action.equals(AC_ACTIVATETHROW)) { + if (charge < 500) + GLog.i(Messages.get(this, "rest")); + else { + activate = true; + action = AC_THROW; + } + } else { + activate = false; + } + + if (action.equals(AC_BREAK)){ + Dungeon.level.drop(new EnergyCore(), Dungeon.hero.pos).sprite.drop(Dungeon.hero.pos); + this.detachAll(Dungeon.hero.belongings.backpack); + Sample.INSTANCE.play(Assets.SND_BLAST); + hero.sprite.emitter().burst(ElmoParticle.FACTORY, 12); + } + + super.execute(hero, action); + } + + @Override + protected void onThrow(int cell) { + + if (Actor.findChar(cell) != null) { + ArrayList candidates = new ArrayList<>(); + for (int i : Level.NEIGHBOURS8) + if (Level.passable[cell + i]) + candidates.add(cell + i); + int newCell = candidates.isEmpty() ? cell : Random + .element(candidates); + + if (!Level.pit[newCell] && activate) { + OrbOfZotMob.spawnAt(newCell); + } else { + Dungeon.level.drop(this, newCell).sprite.drop(cell); + } + + } else if (!Level.pit[cell] && activate) { + OrbOfZotMob.spawnAt(cell); + } else { + + super.onThrow(cell); + } + + } + + @Override + public boolean doPickUp(Hero hero) { + if (super.doPickUp(hero)) { + + if (!Statistics.orbObtained) { + Statistics.orbObtained = true; + Badges.validateOrbObtained(); + //showAmuletScene(true); + } + + return true; + } else { + return false; + } + } + + @Override + public boolean isIdentified() { + return true; + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public String info() { + String info = desc(); + info += "\n\n" + Messages.get(this,"charge",charge,fullCharge); + return info; + } +} diff --git a/java/com/hmdzl/spspd/items/Palantir.java b/java/com/hmdzl/spspd/items/Palantir.java new file mode 100644 index 00000000..1fdb540d --- /dev/null +++ b/java/com/hmdzl/spspd/items/Palantir.java @@ -0,0 +1,140 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.items.artifacts.TimekeepersHourglass; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.InterlevelScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.noosa.Game; +import com.watabou.utils.Bundle; + +public class Palantir extends Item { + + public static final float TIME_TO_USE = 1; + + public static final String AC_PORT = "PORT"; + + private int specialLevel = 99; + private int returnDepth = 1; + private int returnPos; + private boolean used = false; + + { + //name = "palantir"; + image = ItemSpriteSheet.PALANTIR; + + stackable = false; + unique = true; + } + + private static final String DEPTH = "depth"; + private static final String POS = "pos"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(DEPTH, returnDepth); + if (returnDepth != -1) { + bundle.put(POS, returnPos); + } + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + returnDepth = bundle.getInt(DEPTH); + returnPos = bundle.getInt(POS); + } + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + actions.add(AC_PORT); + + return actions; + } + + @Override + public void execute(Hero hero, String action) { + + if (action == AC_PORT) { + + if ((Dungeon.bossLevel() || Dungeon.depth==1 || Dungeon.depth>25 || hero.petfollow) && Dungeon.depth!=specialLevel) { + hero.spend(TIME_TO_USE); + GLog.w(Messages.get(Item.class, "not_here")); + return; + } + + if (Dungeon.depth>26 && !Dungeon.zotkilled) { + hero.spend(TIME_TO_USE); + GLog.w(Messages.get(Item.class, "boss_first")); + return; + } + + + } + + if (action == AC_PORT) { + + hero.spend(TIME_TO_USE); + + Buff buff = Dungeon.hero + .buff(TimekeepersHourglass.timeFreeze.class); + if (buff != null) + buff.detach(); + + if (Dungeon.depth<25 && !Dungeon.bossLevel()){ + returnDepth = Dungeon.depth; + returnPos = hero.pos; + InterlevelScene.mode = InterlevelScene.Mode.PALANTIR; + } else { + InterlevelScene.mode = InterlevelScene.Mode.RETURN; + detach(hero.belongings.backpack); + } + InterlevelScene.returnDepth = returnDepth; + InterlevelScene.returnPos = returnPos; + Game.switchScene(InterlevelScene.class); + } else { + + super.execute(hero, action); + + } + } + + public void reset() { + returnDepth = -1; + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + +} diff --git a/java/com/hmdzl/spspd/items/Playericon.java b/java/com/hmdzl/spspd/items/Playericon.java new file mode 100644 index 00000000..7b62b8eb --- /dev/null +++ b/java/com/hmdzl/spspd/items/Playericon.java @@ -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 + */ +package com.hmdzl.spspd.items; + + +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; + +public class Playericon extends Item { + + + { + //name = "Player Icon"; + image = ItemSpriteSheet.PLAYERICON; + + stackable = true; + } + + @Override + public boolean doPickUp(Hero hero) { + + GLog.p(Messages.get(this,"thank4play")); + + return super.doPickUp(hero); + } + + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } +} diff --git a/java/com/hmdzl/spspd/items/PocketBallFull.java b/java/com/hmdzl/spspd/items/PocketBallFull.java new file mode 100644 index 00000000..fbb09551 --- /dev/null +++ b/java/com/hmdzl/spspd/items/PocketBallFull.java @@ -0,0 +1,323 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 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 + */ +package com.hmdzl.spspd.items; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.mobs.pets.BlueDragon; +import com.hmdzl.spspd.actors.mobs.pets.BugDragon; +import com.hmdzl.spspd.actors.mobs.pets.Bunny; +import com.hmdzl.spspd.actors.mobs.pets.CocoCat; + +import com.hmdzl.spspd.actors.mobs.pets.Fly; +import com.hmdzl.spspd.actors.mobs.pets.GentleCrab; +import com.hmdzl.spspd.actors.mobs.pets.GoldDragon; +import com.hmdzl.spspd.actors.mobs.pets.GreenDragon; +import com.hmdzl.spspd.actors.mobs.pets.LeryFire; +import com.hmdzl.spspd.actors.mobs.pets.LightDragon; +import com.hmdzl.spspd.actors.mobs.pets.Monkey; +import com.hmdzl.spspd.actors.mobs.pets.RedDragon; +import com.hmdzl.spspd.actors.mobs.pets.RibbonRat; +import com.hmdzl.spspd.actors.mobs.pets.Scorpion; +import com.hmdzl.spspd.actors.mobs.pets.ShadowDragon; +import com.hmdzl.spspd.actors.mobs.pets.Snake; +import com.hmdzl.spspd.actors.mobs.pets.Spider; +import com.hmdzl.spspd.actors.mobs.pets.Stone; + +import com.hmdzl.spspd.actors.mobs.pets.Velocirooster; +import com.hmdzl.spspd.actors.mobs.pets.VioletDragon; + +import com.hmdzl.spspd.actors.mobs.pets.YearPet; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.utils.Bundle; +import com.watabou.utils.PathFinder; +import com.watabou.utils.Random; + +import java.util.ArrayList; + +public class PocketBallFull extends Item { + + { + //name = "pocket ball"; + image = ItemSpriteSheet.PALANTIR; + unique = true; + stackable = false; + } + + public static final String AC_USE = "USE"; + + public int pet_type = 0; + public int pet_ht = 0; + public int pet_level = 0; + public int pet_exp = 0; + + private static final String PET_TYPE = "pet_type"; + private static final String PET_HT = "pet_ht"; + private static final String PET_LEVEL = "pet_level"; + private static final String PET_EXP = "pet_exp"; + + public PocketBallFull() { + this( 1, 5, 1, 0 ); + } + + public PocketBallFull(int type,int ht ,int level, int exp) { + super(); + this.pet_type = type; + this.pet_ht = ht; + this.pet_level = level; + this.pet_exp = exp; + } + + @Override + public void storeInBundle( Bundle bundle ) { + super.storeInBundle( bundle ); + bundle.put( PET_TYPE,pet_type ); + bundle.put( PET_HT ,pet_ht ); + bundle.put( PET_LEVEL, pet_level ); + bundle.put( PET_EXP,pet_exp ); + } + + @Override + public void restoreFromBundle( Bundle bundle ) { + //super.restoreFromBundle( bundle ); + //pet_type = bundle.getInt(PET_TYPE); + pet_ht = bundle.getInt(PET_HT); + pet_level = bundle.getInt(PET_LEVEL); + pet_exp = bundle.getInt(PET_EXP); + try { + pet_type = bundle.getInt(PET_TYPE); + } + catch (Exception ex) + { + pet_type = 1; + } + } + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + if (Dungeon.hero.haspet == false & Dungeon.depth < 26){ + actions.add(AC_USE);} + return actions; + } + + + @Override + public void execute(Hero hero, String action) { + + if (action.equals(AC_USE)) { + ArrayList spawnPoints = new ArrayList(); + for (int i = 0; i < PathFinder.NEIGHBOURS8.length; i++) { + int p = hero.pos + PathFinder.NEIGHBOURS8[i]; + if (Actor.findChar(p) == null && (Level.passable[p] || Level.avoid[p])) { + spawnPoints.add(p); + } + } + if (spawnPoints.size() > 0) { + Dungeon.hero.petType = pet_type; + if (Dungeon.hero.petType==1){ + Spider pet = new Spider(); + pet.pos = Random.element(spawnPoints);GameScene.add(pet); + pet.HP = pet.HT = pet_ht; + pet.level = pet_level; + pet.experience = pet_exp; + } + if (Dungeon.hero.petType==2){ + CocoCat pet = new CocoCat(); + pet.pos = Random.element(spawnPoints);GameScene.add(pet); + pet.HP = pet.HT = pet_ht; + pet.level = pet_level; + pet.experience = pet_exp; + } + if (Dungeon.hero.petType==4){ + RedDragon pet = new RedDragon(); + pet.pos = Random.element(spawnPoints);GameScene.add(pet); + pet.HP = pet.HT = pet_ht; + pet.level = pet_level; + pet.experience = pet_exp; + } + if (Dungeon.hero.petType==3){ + Velocirooster pet = new Velocirooster(); + pet.pos = Random.element(spawnPoints);GameScene.add(pet); + pet.level = pet_level; + pet.experience = pet_exp; + } + if (Dungeon.hero.petType==5){ + GreenDragon pet = new GreenDragon(); + pet.pos = Random.element(spawnPoints);GameScene.add(pet); + pet.HP = pet.HT = pet_ht; + pet.level = pet_level; + pet.experience = pet_exp; + } + if (Dungeon.hero.petType==6){ + VioletDragon pet = new VioletDragon(); + pet.pos = Random.element(spawnPoints);GameScene.add(pet); + pet.HP = pet.HT = pet_ht; + pet.level = pet_level; + pet.experience = pet_exp; + } + if (Dungeon.hero.petType==7){ + BlueDragon pet = new BlueDragon(); + pet.pos = Random.element(spawnPoints);GameScene.add(pet); + pet.HP = pet.HT = pet_ht; + pet.level = pet_level; + pet.experience = pet_exp; + } + if (Dungeon.hero.petType==8){ + Scorpion pet = new Scorpion(); + pet.pos = Random.element(spawnPoints);GameScene.add(pet); + pet.HP = pet.HT = pet_ht; + pet.level = pet_level; + pet.experience = pet_exp; + } + if (Dungeon.hero.petType==9){ + Bunny pet = new Bunny(); + pet.pos = Random.element(spawnPoints);GameScene.add(pet); + pet.HP = pet.HT = pet_ht; + pet.level = pet_level; + pet.experience = pet_exp; + } + if (Dungeon.hero.petType==10){ + LightDragon pet = new LightDragon(); + pet.pos = Random.element(spawnPoints);GameScene.add(pet); + pet.HP = pet.HT = pet_ht; + pet.level = pet_level; + pet.experience = pet_exp; + } + if (Dungeon.hero.petType==11){ + BugDragon pet = new BugDragon(); + pet.pos = Random.element(spawnPoints);GameScene.add(pet); + pet.HP = pet.HT = pet_ht; + pet.level = pet_level; + pet.experience = pet_exp; + } + if (Dungeon.hero.petType==12){ + ShadowDragon pet = new ShadowDragon(); + pet.pos = Random.element(spawnPoints);GameScene.add(pet); + pet.HP = pet.HT = pet_ht; + pet.level = pet_level; + pet.experience = pet_exp; + } + if (Dungeon.hero.petType==13){ + CocoCat pet = new CocoCat(); + pet.pos = Random.element(spawnPoints);GameScene.add(pet); + pet.HP = pet.HT = pet_ht; + pet.level = pet_level; + pet.experience = pet_exp; + } + if (Dungeon.hero.petType==14){ + LeryFire pet = new LeryFire(); + pet.pos = Random.element(spawnPoints);GameScene.add(pet); + pet.HP = pet.HT = pet_ht; + pet.level = pet_level; + pet.experience = pet_exp; + } + if (Dungeon.hero.petType==15){ + GoldDragon pet = new GoldDragon(); + pet.pos = Random.element(spawnPoints);GameScene.add(pet); + pet.HP = pet.HT = pet_ht; + pet.level = pet_level; + pet.experience = pet_exp; + } + if (Dungeon.hero.petType==16){ + Snake pet = new Snake(); + pet.pos = Random.element(spawnPoints);GameScene.add(pet); + pet.HP = pet.HT = pet_ht; + pet.level = pet_level; + pet.experience = pet_exp; + } + if (Dungeon.hero.petType==17){ + Fly pet = new Fly(); + pet.pos = Random.element(spawnPoints);GameScene.add(pet); + pet.HP = pet.HT = pet_ht; + pet.level = pet_level; + pet.experience = pet_exp; + } + if (Dungeon.hero.petType==18){ + Stone pet = new Stone(); + pet.pos = Random.element(spawnPoints);GameScene.add(pet); + pet.HP = pet.HT = pet_ht; + pet.level = pet_level; + pet.experience = pet_exp; + } + if (Dungeon.hero.petType==19){ + Monkey pet = new Monkey(); + pet.pos = Random.element(spawnPoints);GameScene.add(pet); + pet.HP = pet.HT = pet_ht; + pet.level = pet_level; + pet.experience = pet_exp; + } + if (Dungeon.hero.petType==20){ + GentleCrab pet = new GentleCrab(); + pet.pos = Random.element(spawnPoints);GameScene.add(pet); + pet.HP = pet.HT = pet_ht; + pet.level = pet_level; + pet.experience = pet_exp; + } + if (Dungeon.hero.petType==21){ + RibbonRat pet = new RibbonRat(); + pet.pos = Random.element(spawnPoints);GameScene.add(pet); + pet.HP = pet.HT = pet_ht; + pet.level = pet_level; + pet.experience = pet_exp; + } + if (Dungeon.hero.petType==22){ + YearPet pet = new YearPet(); + pet.pos = Random.element(spawnPoints);GameScene.add(pet); + pet.HP = pet.HT = pet_ht; + pet.level = pet_level; + pet.experience = pet_exp; + } + //pet.pos = Random.element(spawnPoints); + // GameScene.add(pet); + + hero.spend(1f); + hero.busy(); + hero.sprite.operate(hero.pos); + hero.next(); + + Dungeon.hero.haspet=true; + detach(hero.belongings.backpack); + + } else { + + super.execute(hero, action); + + } + } + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + @Override + public int price() { + return 1000 * quantity; + } + +} diff --git a/java/com/hmdzl/spspd/items/PotKey.java b/java/com/hmdzl/spspd/items/PotKey.java new file mode 100644 index 00000000..43fe322e --- /dev/null +++ b/java/com/hmdzl/spspd/items/PotKey.java @@ -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 + */ +package com.hmdzl.spspd.items; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.items.artifacts.TimekeepersHourglass; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.InterlevelScene; +import com.hmdzl.spspd.sprites.ItemSprite.Glowing; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.noosa.Game; +import com.watabou.utils.Bundle; + +public class PotKey extends Item { + + public static final float TIME_TO_USE = 1; + + public static final String AC_PORT = "PORT"; + + private int specialLevel = 45; + private int returnDepth = -1; + private int returnPos; + + { + //name = "pot key"; + image = ItemSpriteSheet.POTKEY; + + stackable = false; + unique = true; + } + + private static final String DEPTH = "depth"; + private static final String POS = "pos"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(DEPTH, returnDepth); + if (returnDepth != -1) { + bundle.put(POS, returnPos); + } + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + returnDepth = bundle.getInt(DEPTH); + returnPos = bundle.getInt(POS); + } + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + actions.add(AC_PORT); + + return actions; + } + + @Override + public void execute(Hero hero, String action) { + + if (action == AC_PORT) { + + if ((Dungeon.bossLevel() || Dungeon.depth==1 || Dungeon.depth>25 || hero.petfollow) && Dungeon.depth!=specialLevel) { + hero.spend(TIME_TO_USE); + GLog.w(Messages.get(Item.class, "not_here")); + return; + } + + } + + if (action == AC_PORT) { + + hero.spend(TIME_TO_USE); + + Buff buff = Dungeon.hero + .buff(TimekeepersHourglass.timeFreeze.class); + if (buff != null) + buff.detach(); + + if (Dungeon.depth<25 && !Dungeon.bossLevel()){ + + returnDepth = Dungeon.depth; + returnPos = hero.pos; + InterlevelScene.mode = InterlevelScene.Mode.PORTPOT; + } else { + EmptyBody berry1 = new EmptyBody(); + berry1.doPickUp(Dungeon.hero); + InterlevelScene.mode = InterlevelScene.Mode.RETURN; + detach(hero.belongings.backpack); + } + InterlevelScene.returnDepth = returnDepth; + InterlevelScene.returnPos = returnPos; + Game.switchScene(InterlevelScene.class); + + } else { + + super.execute(hero, action); + + } + } + + public void reset() { + returnDepth = -1; + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + + private static final Glowing BLACK = new Glowing(0x00000); + + @Override + public Glowing glowing() { + return BLACK; + } +} diff --git a/java/com/hmdzl/spspd/items/PowerHand.java b/java/com/hmdzl/spspd/items/PowerHand.java new file mode 100644 index 00000000..679b42fe --- /dev/null +++ b/java/com/hmdzl/spspd/items/PowerHand.java @@ -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 + */ +package com.hmdzl.spspd.items; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.items.bags.Bag; +import com.hmdzl.spspd.items.nornstone.NornStone; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.scenes.PowerHandScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; +import com.hmdzl.spspd.windows.WndBag; +import com.watabou.noosa.Game; +import com.watabou.noosa.audio.Sample; + +import java.io.IOException; +import java.util.ArrayList; + +public class PowerHand extends Item { + + public static final String AC_ADD = "ADD"; + + public static final String AC_USE = "USE"; + protected HandCharger handcharger; + + { + //name = "PowerHand"; + image = ItemSpriteSheet.POWER_HAND; + + } + + protected WndBag.Mode mode = WndBag.Mode.STONE; + + public ArrayList stones = new ArrayList(); + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + actions.add(AC_ADD); + actions.add(AC_USE); + return actions; + } + + @Override + public boolean collect( Bag container ) { + if (super.collect( container )) { + if (container.owner != null) { + charge( container.owner ); + } + return true; + } else { + return false; + } + } + + public void charge( Char owner ) { + if (handcharger == null) handcharger = new HandCharger(); + handcharger.attachTo( owner ); + } + + @Override + public void onDetach( ) { + stopCharging(); + } + + public void stopCharging() { + if (handcharger != null) { + handcharger.detach(); + handcharger = null; + } + } + + @Override + public void execute(Hero hero, String action) { + if (action.equals( AC_USE )) { + if (stones.size() >= 5){ + showPowerHandScene(); + } else { + GLog.i(Messages.get(PowerHand.class, "nothing")); + } + } else if (action.equals( AC_ADD )) { + GameScene.selectItem(itemSelector, mode, Messages.get(this, "prompt")); + } else { + super.execute(hero, action); + + } + } + + @Override + public String desc() { + String desc = super.desc(); + + + if (stones.size() > 0) { + + desc += "\n\n" + Messages.get(this, "desc_stones", stones.size()); + } + + return desc; + } + + private void showPowerHandScene() { + try { + stones.clear(); + Dungeon.saveAll(); + Game.switchScene(PowerHandScene.class); + } catch (IOException e) { + } + } + + private static final String STONES = "stones"; + + //@Override + //public void storeInBundle( Bundle bundle ) { + // super.storeInBundle(bundle); + // bundle.put( STONES, stones.toArray(new Class[stones.size()]) ); + //} + + //@Override + //public void restoreFromBundle( Bundle bundle ) { + // super.restoreFromBundle(bundle); + // if (bundle.contains(STONES)) + // Collections.addAll(stones, bundle.getStringArray(STONES)); + //} + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + protected WndBag.Listener itemSelector = new WndBag.Listener() { + @Override + public void onSelect(Item item) { + if (item != null && item instanceof NornStone) { + if (stones.contains(item.name()) || item instanceof StoneOre) { + GLog.w(Messages.get(PowerHand.class, "already_fed")); + } else { + stones.add(item.name()); + + Hero hero = Dungeon.hero; + hero.sprite.operate(hero.pos); + Sample.INSTANCE.play(Assets.SND_PLANT); + hero.busy(); + hero.spend(2f); + GLog.i(Messages.get(PowerHand.class, "absorb_stone")); + item.detach(hero.belongings.backpack); + } + + } + } + }; + + protected class HandCharger extends Buff { + + @Override + public boolean attachTo( Char target ) { + super.attachTo( target ); + + return true; + } + + @Override + public boolean act() { + spend( TICK ); + return true; + } + } +} diff --git a/java/com/hmdzl/spspd/items/PuddingCup.java b/java/com/hmdzl/spspd/items/PuddingCup.java new file mode 100644 index 00000000..acc998ed --- /dev/null +++ b/java/com/hmdzl/spspd/items/PuddingCup.java @@ -0,0 +1,104 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items; + +import java.io.IOException; +import java.util.ArrayList; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.scenes.LoadSaveScene; +import com.hmdzl.spspd.scenes.Pudding_CupScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.noosa.Game; + +public class PuddingCup extends Item { + + private static final String AC_SAVE = "SAVE" ; + + { + //name = "pudding cup"; + image = ItemSpriteSheet.PUDDING_CUP; + + unique = true; + } + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + actions.add(AC_SAVE); + return actions; + } + + @Override + public void execute(Hero hero, String action) { + if (action == AC_SAVE) { + //showPudding_cupScene(); + curUser = hero; + detach(curUser.belongings.backpack); + try { + Dungeon.saveAll(); + } catch (IOException e) { + // + } + Dungeon.canSave=true; + Game.switchScene(LoadSaveScene.class); + + } else { + + super.execute(hero, action); + + } + } + + + @Override + public boolean doPickUp(Hero hero) { + if (super.doPickUp(hero)) { + + //if (!Statistics.amuletObtained) { + // Statistics.amuletObtained = true; + //Badges.validateVictory(); + + showPudding_cupScene(); + + //} + + return true; + } else { + return false; + } + } + + private void showPudding_cupScene() { + try { + Dungeon.saveAll(); + Game.switchScene(Pudding_CupScene.class); + } catch (IOException e) { + } + } + + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } +} diff --git a/java/com/hmdzl/spspd/items/RedDewdrop.java b/java/com/hmdzl/spspd/items/RedDewdrop.java new file mode 100644 index 00000000..818b6e65 --- /dev/null +++ b/java/com/hmdzl/spspd/items/RedDewdrop.java @@ -0,0 +1,71 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2014 Oleg Dolya + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.items; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.hero.HeroClass; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.CharSprite; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.noosa.audio.Sample; + +public class RedDewdrop extends Item { + + private static final String TXT_VALUE = "%+dHP"; + + { + //name = "red dewdrop"; + image = ItemSpriteSheet.REDDEWDROP; + + stackable = true; + } + + @Override + public boolean doPickUp(Hero hero) { + + DewVial vial = hero.belongings.getItem(DewVial.class); + + if (vial == null || vial.isFull()) { + + int value = 5 + (Dungeon.depth - 1) / 5; + if (hero.heroClass == HeroClass.HUNTRESS) { + value++; + } + + int effect = Math.min(hero.HT - hero.HP, value * quantity); + if (effect > 0) { + hero.HP += effect; + hero.sprite.emitter().burst(Speck.factory(Speck.HEALING), 1); + hero.sprite.showStatus(CharSprite.POSITIVE, Messages.get(this, "value", effect)); + } + + } else if (vial != null) { + + vial.collectDew(this); + + } + + Sample.INSTANCE.play(Assets.SND_DEWDROP); + hero.spendAndNext(TIME_TO_PICK_UP); + + return true; + } +} diff --git a/java/com/hmdzl/spspd/items/ReturnBeacon.java b/java/com/hmdzl/spspd/items/ReturnBeacon.java new file mode 100644 index 00000000..0ff7baac --- /dev/null +++ b/java/com/hmdzl/spspd/items/ReturnBeacon.java @@ -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 + */ +package com.hmdzl.spspd.items; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.items.artifacts.TimekeepersHourglass; +import com.hmdzl.spspd.scenes.InterlevelScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.noosa.Game; + +public class ReturnBeacon extends Item { + + + private static final String TXT_INFO = "Return beacon is an intricate magic device, that allows you to return to a place you have already been."; + + public static final float TIME_TO_USE = 1; + + //public static final String AC_SET = "SET"; + public static final String AC_RETURN = "RETURN"; + + //private int returnDepth = -1; + //private int returnPos; + + { + name = "return beacon"; + image = ItemSpriteSheet.BEACON; + + unique = true; + } + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + actions.add(AC_RETURN); + return actions; + } + + @Override + public void execute(Hero hero, String action) { + + if (action == AC_RETURN) { + + + Buff buff = Dungeon.hero + .buff(TimekeepersHourglass.timeFreeze.class); + if (buff != null) + buff.detach(); + + InterlevelScene.mode = InterlevelScene.Mode.RETURNSAVE; + InterlevelScene.returnDepth = 1; + InterlevelScene.returnPos = 1; + Game.switchScene(InterlevelScene.class); + + + } else { + + super.execute(hero, action); + + } + } + + + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + + @Override + public String info() { + return TXT_INFO; + } +} diff --git a/java/com/hmdzl/spspd/items/SaveYourLife.java b/java/com/hmdzl/spspd/items/SaveYourLife.java new file mode 100644 index 00000000..d4a0d979 --- /dev/null +++ b/java/com/hmdzl/spspd/items/SaveYourLife.java @@ -0,0 +1,80 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items; + +import java.io.IOException; +import java.util.ArrayList; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.scenes.LoadSaveScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.noosa.Game; + +public class SaveYourLife extends Item { + + private static final String AC_SAVE = "SAVE" ; + + { + //name = "pudding cup"、 + + + + + + image = ItemSpriteSheet.TPTRAP; + + unique = true; + } + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + actions.add(AC_SAVE); + return actions; + } + + @Override + public void execute(Hero hero, String action) { + if (action == AC_SAVE) { + curUser = hero; + try { + Dungeon.saveAll(); + } catch (IOException e) { + // + } + Dungeon.canSave=true; + Game.switchScene(LoadSaveScene.class); + + } else { + + super.execute(hero, action); + + } + } + + + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } +} diff --git a/java/com/hmdzl/spspd/items/ShadowEaterKey.java b/java/com/hmdzl/spspd/items/ShadowEaterKey.java new file mode 100644 index 00000000..45bfc8c8 --- /dev/null +++ b/java/com/hmdzl/spspd/items/ShadowEaterKey.java @@ -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 + */ +package com.hmdzl.spspd.items; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.items.artifacts.TimekeepersHourglass; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.InterlevelScene; +import com.hmdzl.spspd.sprites.ItemSprite.Glowing; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.noosa.Game; +import com.watabou.utils.Bundle; + +public class ShadowEaterKey extends Item { + + public static final float TIME_TO_USE = 1; + + public static final String AC_PORT = "PORT"; + + private int specialLevel = 47; + private int returnDepth = -1; + private int returnPos; + + { + //name = "shadoweater"; + image = ItemSpriteSheet.SHADOW_EATER; + + stackable = false; + unique = true; + } + + private static final String DEPTH = "depth"; + private static final String POS = "pos"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(DEPTH, returnDepth); + if (returnDepth != -1) { + bundle.put(POS, returnPos); + } + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + returnDepth = bundle.getInt(DEPTH); + returnPos = bundle.getInt(POS); + } + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + actions.add(AC_PORT); + + return actions; + } + + @Override + public void execute(Hero hero, String action) { + + if (action == AC_PORT) { + + if ((Dungeon.bossLevel() || Dungeon.depth==1 || Dungeon.depth>25 || hero.petfollow) && Dungeon.depth!=specialLevel) { + hero.spend(TIME_TO_USE); + GLog.w(Messages.get(Item.class, "not_here")); + return; + } + + } + + if (action == AC_PORT) { + + hero.spend(TIME_TO_USE); + + Buff buff = Dungeon.hero + .buff(TimekeepersHourglass.timeFreeze.class); + if (buff != null) + buff.detach(); + + if (Dungeon.depth<25 && !Dungeon.bossLevel()){ + + returnDepth = Dungeon.depth; + returnPos = hero.pos; + InterlevelScene.mode = InterlevelScene.Mode.PORTSHADOWEATER; + } else { + InterlevelScene.mode = InterlevelScene.Mode.RETURN; + detach(hero.belongings.backpack); + } + InterlevelScene.returnDepth = returnDepth; + InterlevelScene.returnPos = returnPos; + Game.switchScene(InterlevelScene.class); + + } else { + + super.execute(hero, action); + + } + } + + public void reset() { + returnDepth = -1; + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return false; + } + + + private static final Glowing BLACK = new Glowing(0x00000); + + @Override + public Glowing glowing() { + return BLACK; + } +} diff --git a/java/com/hmdzl/spspd/items/ShoesKit.java b/java/com/hmdzl/spspd/items/ShoesKit.java new file mode 100644 index 00000000..12456c33 --- /dev/null +++ b/java/com/hmdzl/spspd/items/ShoesKit.java @@ -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 + */ +package com.hmdzl.spspd.items; + +import java.util.ArrayList; + +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class ShoesKit extends Item { + + private static final String TXT_SELECT_SHOES = "Select an shoes to upgrade"; + private static final String TXT_UPGRADED = "you applied the armor kit to upgrade your %s"; + + private static final float TIME_TO_UPGRADE = 2; + + private static final String AC_APPLY = "APPLY"; + + { + //name = "armor kit"; + image = ItemSpriteSheet.SHOESKIT; + + unique = true; + } + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + actions.add(AC_APPLY); + return actions; + } + + @Override + public void execute(Hero hero, String action) { + if (action == AC_APPLY) { + + curUser = hero; + //GameScene.selectItem(itemSelector, WndBag.Mode.SHOES, + //TXT_SELECT_SHOES); + + } else { + + super.execute(hero, action); + + } + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + /*private void upgrade(Shoes shoes) { + + detach(curUser.belongings.backpack); + + curUser.sprite.centerEmitter().start(Speck.factory(Speck.KIT), 0.05f, + 10); + curUser.spend(TIME_TO_UPGRADE); + curUser.busy(); + + GLog.w(TXT_UPGRADED, shoes.name()); + + switch (owner.heroClass) { + case WARRIOR: + classShoes = new JumpW(); + break; + case ROGUE: + classShoes = new JumpR(); + break; + case MAGE: + classShoes = new JumpM(); + break; + case HUNTRESS: + classShoes = new JumpH(); + break; + } + + shoes.detach(curUser.belongings.backpack); + classShoes.collect(curUser.belongings.backpack); + + + curUser.sprite.operate(curUser.pos); + Sample.INSTANCE.play(Assets.SND_EVOKE); + }*/ + + /*private final WndBag.Listener itemSelector = new WndBag.Listener() { + @Override + public void onSelect(Item item) { + if (item != null) { + ShoesKit.this.upgrade((Shoes) item); + } + } + };*/ + + @Override + public int price() { + return 200 * quantity; + } +} diff --git a/java/com/hmdzl/spspd/items/SoulCollect.java b/java/com/hmdzl/spspd/items/SoulCollect.java new file mode 100644 index 00000000..c72b2b80 --- /dev/null +++ b/java/com/hmdzl/spspd/items/SoulCollect.java @@ -0,0 +1,80 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.hero.Hero; + +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; + +public class SoulCollect extends Item { + + { + //name = "Soul collect"; + image = ItemSpriteSheet.SOUL_COLLECT; + stackable = false; + } + + + public static final String AC_BREAK = "BREAK"; + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + if (Dungeon.depth<26) { + actions.add(AC_BREAK); + } + return actions; + } + + @Override + public void execute(Hero hero, String action) { + + if (action.equals(AC_BREAK)) { + curUser = hero; + GLog.w(Messages.get(this, "win")); + //Statistics.archersKilled += 51; + //Statistics.skeletonsKilled += 51; + //Statistics.piranhasKilled += 51; + //Statistics.goldThievesKilled += 51; + Badges.validateOtilukeRescued(); + curUser.sprite.operate(curUser.pos); + detach(hero.belongings.backpack); + curUser.spendAndNext(1f); + curUser.busy(); + + } else { + super.execute(hero, action); + + } + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } +} diff --git a/java/com/hmdzl/spspd/items/StoneOre.java b/java/com/hmdzl/spspd/items/StoneOre.java new file mode 100644 index 00000000..0285ea43 --- /dev/null +++ b/java/com/hmdzl/spspd/items/StoneOre.java @@ -0,0 +1,51 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items; + +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class StoneOre extends Item { + + + { + //name = "stone ore"; + image = ItemSpriteSheet.STONE; + + stackable=true; + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + + @Override + public int price() { + return 100 * quantity; + } + + public StoneOre() { this(1); } + public StoneOre(int value) { this.quantity = value; } + +} diff --git a/java/com/hmdzl/spspd/items/Stylus.java b/java/com/hmdzl/spspd/items/Stylus.java new file mode 100644 index 00000000..2a6341d7 --- /dev/null +++ b/java/com/hmdzl/spspd/items/Stylus.java @@ -0,0 +1,112 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.hero.HeroClass; +import com.hmdzl.spspd.effects.particles.PurpleParticle; +import com.hmdzl.spspd.items.armor.Armor; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; +import com.hmdzl.spspd.windows.WndBag; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Random; + +public class Stylus extends Item { + + private static final float TIME_TO_INSCRIBE = 2; + + private static final String AC_INSCRIBE = "INSCRIBE"; + + { + //name = "arcane stylus"; + image = ItemSpriteSheet.STYLUS; + + stackable = true; + + + } + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + actions.add(AC_INSCRIBE); + return actions; + } + + @Override + public void execute(Hero hero, String action) { + if (action == AC_INSCRIBE) { + + curUser = hero; + GameScene.selectItem(itemSelector, WndBag.Mode.ARMOR, + Messages.get(this,"prompt")); + + } else { + + super.execute(hero, action); + + } + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + private void inscribe(Armor armor) { + if (!(Dungeon.hero.heroClass == HeroClass.FOLLOWER ) || (Dungeon.hero.heroClass == HeroClass.FOLLOWER && Random.Int(10)>=1 )) + detach(curUser.belongings.backpack); + + GLog.w(Messages.get(this,"inscribed")); + + armor.hasglyph(); + + curUser.sprite.operate(curUser.pos); + curUser.sprite.centerEmitter().start(PurpleParticle.BURST, 0.05f, 10); + Sample.INSTANCE.play(Assets.SND_BURNING); + + curUser.spend(TIME_TO_INSCRIBE); + curUser.busy(); + } + + @Override + public int price() { + return 30 * quantity; + } + + private final WndBag.Listener itemSelector = new WndBag.Listener() { + @Override + public void onSelect(Item item) { + if (item != null) { + Stylus.this.inscribe((Armor) item); + } + } + }; +} diff --git a/java/com/hmdzl/spspd/items/TenguKey.java b/java/com/hmdzl/spspd/items/TenguKey.java new file mode 100644 index 00000000..b0eb955a --- /dev/null +++ b/java/com/hmdzl/spspd/items/TenguKey.java @@ -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 + */ +package com.hmdzl.spspd.items; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.items.artifacts.TimekeepersHourglass; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.InterlevelScene; +import com.hmdzl.spspd.sprites.ItemSprite.Glowing; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.noosa.Game; +import com.watabou.utils.Bundle; + +public class TenguKey extends Item { + + public static final float TIME_TO_USE = 1; + + public static final String AC_PORT = "PORT"; + + private int specialLevel = 36; + private int returnDepth = -1; + private int returnPos; + + { + //name = "hideout key"; + image = ItemSpriteSheet.TENGUKEY; + + stackable = false; + unique = true; + } + + private static final String DEPTH = "depth"; + private static final String POS = "pos"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(DEPTH, returnDepth); + if (returnDepth != -1) { + bundle.put(POS, returnPos); + } + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + returnDepth = bundle.getInt(DEPTH); + returnPos = bundle.getInt(POS); + } + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + actions.add(AC_PORT); + + return actions; + } + + @Override + public void execute(Hero hero, String action) { + + if (action == AC_PORT) { + + if ((Dungeon.bossLevel() || Dungeon.depth==1 || Dungeon.depth>25 || hero.petfollow) && Dungeon.depth!=specialLevel) { + hero.spend(TIME_TO_USE); + GLog.w(Messages.get(Item.class, "not_here")); + return; + } + + if (Dungeon.depth==specialLevel && !Dungeon.tengudenkilled && !Dungeon.level.reset) { + hero.spend(TIME_TO_USE); + GLog.w(Messages.get(Item.class, "boss_first")); + return; + } + } + + if (action == AC_PORT) { + + hero.spend(TIME_TO_USE); + + Buff buff = Dungeon.hero + .buff(TimekeepersHourglass.timeFreeze.class); + if (buff != null) + buff.detach(); + + if (Dungeon.depth<25 && !Dungeon.bossLevel()){ + + returnDepth = Dungeon.depth; + returnPos = hero.pos; + InterlevelScene.mode = InterlevelScene.Mode.PORTTENGU; + } else { + InterlevelScene.mode = InterlevelScene.Mode.RETURN; + detach(hero.belongings.backpack); + } + InterlevelScene.returnDepth = returnDepth; + InterlevelScene.returnPos = returnPos; + Game.switchScene(InterlevelScene.class); + + } else { + + super.execute(hero, action); + + } + } + + public void reset() { + returnDepth = -1; + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + + private static final Glowing BLACK = new Glowing(0x00000); + + @Override + public Glowing glowing() { + return BLACK; + } +} diff --git a/java/com/hmdzl/spspd/items/TomeOfMastery.java b/java/com/hmdzl/spspd/items/TomeOfMastery.java new file mode 100644 index 00000000..29b84e69 --- /dev/null +++ b/java/com/hmdzl/spspd/items/TomeOfMastery.java @@ -0,0 +1,149 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.actors.buffs.Blindness; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Fury; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.hero.HeroSubClass; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.effects.SpellSprite; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.utils.GLog; + +import com.hmdzl.spspd.windows.WndChooseWay; +import com.watabou.noosa.audio.Sample; + +public class TomeOfMastery extends Item { + + public static final float TIME_TO_READ = 10; + + public static final String AC_READ = "READ"; + + { + stackable = false; + //name = "Tome of Mastery"; + image = ItemSpriteSheet.MASTERY; + + unique = true; + } + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + actions.add(AC_READ); + return actions; + } + + @Override + public void execute(Hero hero, String action) { + if (action.equals(AC_READ)) { + + if (hero.buff(Blindness.class) != null) { + GLog.w(Messages.get(this,"blind")); + return; + } + + curUser = hero; + + HeroSubClass way1 = null; + HeroSubClass way2 = null; + switch (hero.heroClass) { + case WARRIOR: + way1 = HeroSubClass.GLADIATOR; + way2 = HeroSubClass.BERSERKER; + break; + case MAGE: + way1 = HeroSubClass.BATTLEMAGE; + way2 = HeroSubClass.WARLOCK; + break; + case ROGUE: + way1 = HeroSubClass.FREERUNNER; + way2 = HeroSubClass.ASSASSIN; + break; + case HUNTRESS: + way1 = HeroSubClass.SNIPER; + way2 = HeroSubClass.WARDEN; + break; + case PERFORMER: + way1 = HeroSubClass.SUPERSTAR; + way2 = HeroSubClass.JOKER; + break; + case SOLDIER: + way1 = HeroSubClass.AGENT; + way2 = HeroSubClass.LEADER; + break; + case FOLLOWER: + way1 = HeroSubClass.PASTOR; + way2 = HeroSubClass.ARTISAN; + break; + } + GameScene.show(new WndChooseWay(this, way1, way2)); + + } else { + + super.execute(hero, action); + + } + } + + @Override + public boolean doPickUp(Hero hero) { + Badges.validateMastery(); + return super.doPickUp(hero); + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + public void choose(HeroSubClass way) { + + detach(curUser.belongings.backpack); + + curUser.spend(TomeOfMastery.TIME_TO_READ); + curUser.busy(); + + curUser.subClass = way; + + curUser.sprite.operate(curUser.pos); + Sample.INSTANCE.play(Assets.SND_MASTERY); + + SpellSprite.show(curUser, SpellSprite.MASTERY); + curUser.sprite.emitter().burst(Speck.factory(Speck.MASTERY), 12); + GLog.w(Messages.get(this, "way", way.title()) ); + + if (way == HeroSubClass.BERSERKER + && curUser.HP <= curUser.HT * Fury.LEVEL) { + Buff.affect(curUser, Fury.class); + } + } +} diff --git a/java/com/hmdzl/spspd/items/Torch.java b/java/com/hmdzl/spspd/items/Torch.java new file mode 100644 index 00000000..a81768ed --- /dev/null +++ b/java/com/hmdzl/spspd/items/Torch.java @@ -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 + */ +package com.hmdzl.spspd.items; + +import java.util.ArrayList; + +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.HighLight; +import com.hmdzl.spspd.actors.buffs.Light; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.particles.FlameParticle; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.noosa.particles.Emitter; + +public class Torch extends Item { + + public static final String AC_LIGHT = "LIGHT"; + + public static final float TIME_TO_LIGHT = 1; + + { + //name = "torch"; + image = ItemSpriteSheet.TORCH; + + stackable = true; + + defaultAction = AC_LIGHT; + } + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + actions.add(AC_LIGHT); + return actions; + } + + @Override + public void execute(Hero hero, String action) { + + if (action.equals(AC_LIGHT)) { + + hero.spend(TIME_TO_LIGHT); + hero.busy(); + + hero.sprite.operate(hero.pos); + + detach(hero.belongings.backpack); + Buff.affect(hero, HighLight.class, 300); + + Emitter emitter = hero.sprite.centerEmitter(); + emitter.start(FlameParticle.FACTORY, 0.2f, 3); + + } else { + + super.execute(hero, action); + + } + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + @Override + public int price() { + return 10 * quantity; + } +} diff --git a/java/com/hmdzl/spspd/items/Towel.java b/java/com/hmdzl/spspd/items/Towel.java new file mode 100644 index 00000000..aa615fd4 --- /dev/null +++ b/java/com/hmdzl/spspd/items/Towel.java @@ -0,0 +1,152 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.buffs.Bleeding; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Cold; +import com.hmdzl.spspd.actors.buffs.CountDown; +import com.hmdzl.spspd.actors.buffs.Dry; +import com.hmdzl.spspd.actors.buffs.Hot; +import com.hmdzl.spspd.actors.buffs.Ooze; +import com.hmdzl.spspd.actors.buffs.Wet; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.actors.mobs.pets.PET; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; + +public class Towel extends Item { + + public static final float TIME_TO_USE = 1; + + public static final String AC_TOWEL = "TOWEL"; + public static final String AC_TOWEL_PET = "TOWEL_PET"; + + { + //name = "towel"; + image = ItemSpriteSheet.TOWEL; + unique = true; + level = 20; + + } + + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + + actions.add(AC_TOWEL); + + if(checkpet()!=null && checkpetNear()){ + actions.add(AC_TOWEL_PET); + } + + return actions; + } + + private PET checkpet(){ + for (Mob mob : Dungeon.level.mobs) { + if(mob instanceof PET) { + return (PET) mob; + } + } + return null; + } + + private boolean checkpetNear(){ + Hero hero = Dungeon.hero; + for (int n : Level.NEIGHBOURS8) { + int c = hero.pos + n; + if (Actor.findChar(c) instanceof PET) { + return true; + } + } + return false; + } + + + @Override + public void execute(Hero hero, String action) { + + + if (action == AC_TOWEL) { + + Buff.detach(hero, Bleeding.class); + Buff.detach(hero, Ooze.class); + Buff.detach(hero,Hot.class); + Buff.detach(hero,Cold.class); + Buff.detach(hero,Wet.class); + Buff.detach(hero,Dry.class); + Buff.detach(hero,CountDown.class); + + Dungeon.observe(); + + GLog.w(Messages.get(this,"apply")); + + level -= 1; + if (level==0){ + detach(Dungeon.hero.belongings.backpack); + GLog.w(Messages.get(this,"end")); + } + + + } else if (action == AC_TOWEL_PET) { + + PET pet = checkpet(); + pet.HP=pet.HT; + Dungeon.observe(); + + GLog.w(Messages.get(this,"apply")); + + level -= 1; + if (level==0){ + detach(Dungeon.hero.belongings.backpack); + GLog.w(Messages.get(this,"end")); + } + + + } else { + + super.execute(hero, action); + } + } + + @Override + public int price() { + return 500 * quantity; + } + + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + +} diff --git a/java/com/hmdzl/spspd/items/TownReturnBeacon.java b/java/com/hmdzl/spspd/items/TownReturnBeacon.java new file mode 100644 index 00000000..10215058 --- /dev/null +++ b/java/com/hmdzl/spspd/items/TownReturnBeacon.java @@ -0,0 +1,165 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.items.artifacts.TimekeepersHourglass; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.scenes.InterlevelScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.noosa.Game; +import com.watabou.utils.Bundle; + +public class TownReturnBeacon extends Item { + + + private static final String TXT_INFO = "Return beacon is an intricate magic device, that allows you to return to a place you have already been."; + private static final String TXT_CREATURES = "Psychic aura of neighbouring creatures doesn't allow you to use the lloyd's beacon at this moment."; + + public static final float TIME_TO_USE = 1; + + //public static final String AC_SET = "SET"; + public static final String AC_RETURN = "RETURN"; + public static final String AC_RETURNTOWN = "RETURNTOWN"; + public static final String FAIL = "Strong magic aura of this place prevents you from using the beacon!"; + + private int returnDepth = -1; + private int returnPos; + + { + name = "dolyahaven return beacon"; + image = ItemSpriteSheet.BEACON; + + unique = true; + } + + private static final String DEPTH = "depth"; + private static final String POS = "pos"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(DEPTH, returnDepth); + if (returnDepth != -1) { + bundle.put(POS, returnPos); + } + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + returnDepth = bundle.getInt(DEPTH); + returnPos = bundle.getInt(POS); + } + + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + if (Dungeon.depth==55 && returnDepth>55 && !Badges.checkOtilukeRescued()){ + actions.add(AC_RETURN); + } + if(Dungeon.depth>55){ + actions.add(AC_RETURNTOWN); + } + return actions; + } + + @Override + public void execute(Hero hero, String action) { + + if (action == AC_RETURNTOWN) { + + if (Dungeon.bossLevel() || Dungeon.level.locked || hero.petfollow) { + hero.spend(TIME_TO_USE); + GLog.w(FAIL); + return; + } + + for (int i = 0; i < Level.NEIGHBOURS8.length; i++) { + if (Actor.findChar(hero.pos + Level.NEIGHBOURS8[i]) != null) { + GLog.w(TXT_CREATURES); + return; + } + } + + } + + if (action == AC_RETURNTOWN) { + + hero.spend(TIME_TO_USE); + + returnDepth = Dungeon.depth; + returnPos = hero.pos; + + Buff buff = Dungeon.hero + .buff(TimekeepersHourglass.timeFreeze.class); + if (buff != null) + buff.detach(); + + InterlevelScene.mode = InterlevelScene.Mode.RETURN; + InterlevelScene.returnDepth = 55; + InterlevelScene.returnPos = 1925; + Game.switchScene(InterlevelScene.class); + + } else if (action == AC_RETURN) { + + hero.spend(TIME_TO_USE); + + Buff buff = Dungeon.hero + .buff(TimekeepersHourglass.timeFreeze.class); + if (buff != null) + buff.detach(); + + InterlevelScene.mode = InterlevelScene.Mode.RETURN; + InterlevelScene.returnDepth = returnDepth; + InterlevelScene.returnPos = returnPos; + Game.switchScene(InterlevelScene.class); + + } else { + + super.execute(hero, action); + + } + } + + + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + + @Override + public String info() { + return TXT_INFO; + } +} diff --git a/java/com/hmdzl/spspd/items/TransmutationBall.java b/java/com/hmdzl/spspd/items/TransmutationBall.java new file mode 100644 index 00000000..85156a11 --- /dev/null +++ b/java/com/hmdzl/spspd/items/TransmutationBall.java @@ -0,0 +1,236 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2019 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ + +package com.hmdzl.spspd.items; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.hero.HeroClass; +import com.hmdzl.spspd.items.armor.Armor; +import com.hmdzl.spspd.items.artifacts.Artifact; + +import com.hmdzl.spspd.items.rings.Ring; +import com.hmdzl.spspd.items.wands.Wand; +import com.hmdzl.spspd.items.weapon.melee.MeleeWeapon; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.windows.WndBag; +import com.watabou.utils.Random; + +import java.util.ArrayList; + +public class TransmutationBall extends Item { + + private static final String AC_USE = "USE"; + + { + image = ItemSpriteSheet.TRAN_BALL; + + stackable = true; + } + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + actions.add(AC_USE); + return actions; + } + + @Override + public void execute(Hero hero, String action) { + if (action == AC_USE) { + + curUser = hero; + GameScene.selectItem(itemSelector, + WndBag.Mode.TRANMSUTABLE, + Messages.get(TransmutationBall.class, "prompt")); + + } else { + + super.execute(hero, action); + + } + } + + private void use(Item item) { + if (!(Dungeon.hero.heroClass == HeroClass.FOLLOWER ) || (Dungeon.hero.heroClass == HeroClass.FOLLOWER && Random.Int(10)>=1 )) + detach(curUser.belongings.backpack); + + curUser.sprite.operate(curUser.pos); + //curUser.sprite.emitter().start(Speck.factory(Speck.CHANGE), 0.2f, 0); + + curUser.spend(1f); + curUser.busy(); + + } + + + private final WndBag.Listener itemSelector = new WndBag.Listener() { + @Override + public void onSelect(Item item) { + curUser = Dungeon.hero; + Item result; + if (item != null) { + if (item instanceof MeleeWeapon) { + result = changeWeapon((MeleeWeapon) item); + } else if (item instanceof Armor) { + result = changeArmor((Armor) item); + } else if (item instanceof Ring) { + result = changeRing((Ring) item); + } else if (item instanceof Wand) { + result = changeWand((Wand) item); + } else if (item instanceof Artifact) { + result = changeArtifact((Artifact) item); + } else { + result = null; + } + item.detach(Dungeon.hero.belongings.backpack); + Dungeon.level.drop(result, Dungeon.hero.pos).sprite.drop(); + TransmutationBall.this.use(item); + } + } + }; + + + private MeleeWeapon changeWeapon(MeleeWeapon w) { + + MeleeWeapon n; + do { + n = (MeleeWeapon) Generator.random(Generator.Category.MELEEWEAPON); + } while (n.getClass() == w.getClass()); + + n.level = 0; + + int level = w.level; + if (level > 0) { + n.upgrade(level); + } else if (level < 0) { + n.degrade(-level); + } + + n.enchantment = w.enchantment; + n.reinforced = w.reinforced; + n.levelKnown = w.levelKnown; + n.cursedKnown = w.cursedKnown; + n.cursed = w.cursed; + + return n; + + } + + private Armor changeArmor(Armor r) { + Armor n; + do { + n = (Armor) Generator.random(Generator.Category.ARMOR); + } 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.glyph = r.glyph; + n.reinforced = r.reinforced; + n.levelKnown = r.levelKnown; + n.cursedKnown = r.cursedKnown; + n.cursed = r.cursed; + + return n; + } + + + private Ring changeRing(Ring r) { + Ring n; + do { + n = (Ring) Generator.random(Generator.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.reinforced = r.reinforced; + n.levelKnown = r.levelKnown; + n.cursedKnown = r.cursedKnown; + n.cursed = r.cursed; + + return n; + } + + private Artifact changeArtifact(Artifact a) { + Artifact n; + do { + n = (Artifact) Generator.random(Generator.Category.ARTIFACT); + } while (n.getClass() == a.getClass()); + + if (n != null) { + n.cursedKnown = a.cursedKnown; + n.cursed = a.cursed; + n.levelKnown = a.levelKnown; + n.transferUpgrade(a.visiblyUpgraded()); + } + + return n; + } + + private Wand changeWand(Wand w) { + + Wand n; + do { + n = (Wand) Generator.random(Generator.Category.WAND); + } while (n.getClass() == w.getClass()); + + n.level = 0; + n.updateLevel(); + n.upgrade(w.level); + + n.reinforced = w.reinforced; + n.levelKnown = w.levelKnown; + n.cursedKnown = w.cursedKnown; + n.cursed = w.cursed; + + return n; + } + + + @Override + public int price() { + return 50; + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } +} diff --git a/java/com/hmdzl/spspd/items/TreasureMap.java b/java/com/hmdzl/spspd/items/TreasureMap.java new file mode 100644 index 00000000..88c6ba05 --- /dev/null +++ b/java/com/hmdzl/spspd/items/TreasureMap.java @@ -0,0 +1,171 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.actors.mobs.pets.PET; +import com.hmdzl.spspd.items.artifacts.TimekeepersHourglass; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.InterlevelScene; +import com.hmdzl.spspd.sprites.ItemSprite.Glowing; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.noosa.Game; +import com.watabou.utils.Bundle; + +public class TreasureMap extends Item { + + public static final float TIME_TO_USE = 1; + + public static final String AC_PORT = "PORT"; + + private int specialLevel = 43; + private int returnDepth = -1; + private int returnPos; + + { + //name = "treasure map"; + image = ItemSpriteSheet.MAP; + + stackable = false; + unique = true; + } + + private static final String DEPTH = "depth"; + private static final String POS = "pos"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(DEPTH, returnDepth); + if (returnDepth != -1) { + bundle.put(POS, returnPos); + } + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + returnDepth = bundle.getInt(DEPTH); + returnPos = bundle.getInt(POS); + } + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + actions.add(AC_PORT); + + return actions; + } + + @Override + public void execute(Hero hero, String action) { + + if (action == AC_PORT) { + + if ((Dungeon.bossLevel() || Dungeon.depth==1 || Dungeon.depth>25 || hero.petfollow) && Dungeon.depth!=specialLevel) { + hero.spend(TIME_TO_USE); + GLog.w(Messages.get(Item.class, "not_here")); + return; + } + + if (Dungeon.depth==specialLevel && !Dungeon.gnollkingkilled && !Dungeon.level.reset) { + hero.spend(TIME_TO_USE); + GLog.w(Messages.get(Item.class, "boss_first")); + return; + } + } + + if (action == AC_PORT) { + + Buff buff = Dungeon.hero + .buff(TimekeepersHourglass.timeFreeze.class); + if (buff != null) + buff.detach(); + + if (Dungeon.depth<25 && !Dungeon.bossLevel()){ + + returnDepth = Dungeon.depth; + returnPos = hero.pos; + InterlevelScene.mode = InterlevelScene.Mode.PORTMAP; + } else { + InterlevelScene.mode = InterlevelScene.Mode.RETURN; + detach(hero.belongings.backpack); + } + InterlevelScene.returnDepth = returnDepth; + InterlevelScene.returnPos = returnPos; + Game.switchScene(InterlevelScene.class); + + } else { + + super.execute(hero, action); + + } + } + + + private PET checkpet(){ + for (Mob mob : Dungeon.level.mobs) { + if(mob instanceof PET) { + return (PET) mob; + } + } + return null; + } + + private boolean checkpetNear(){ + for (int n : Level.NEIGHBOURS8) { + int c = Dungeon.hero.pos + n; + if (Actor.findChar(c) instanceof PET) { + return true; + } + } + return false; + } + + public void reset() { + returnDepth = -1; + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + + private static final Glowing WHITE = new Glowing(0xFFFFCC); + + + @Override + public Glowing glowing() { + return WHITE; + } + +} diff --git a/java/com/hmdzl/spspd/items/TriForce.java b/java/com/hmdzl/spspd/items/TriForce.java new file mode 100644 index 00000000..086f7f28 --- /dev/null +++ b/java/com/hmdzl/spspd/items/TriForce.java @@ -0,0 +1,149 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.items.artifacts.TimekeepersHourglass; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.InterlevelScene; +import com.hmdzl.spspd.sprites.ItemSprite.Glowing; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.noosa.Game; +import com.watabou.utils.Bundle; + +public class TriForce extends Item { + + public static final float TIME_TO_USE = 1; + + public static final String AC_PORT = "PORT"; + + private int returnDepth = -1; + private int returnPos; + + { + //name = "Triforce"; + image = ItemSpriteSheet.TRIFORCE; + + stackable = false; + unique = true; + } + + private static final String DEPTH = "depth"; + private static final String POS = "pos"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(DEPTH, returnDepth); + if (returnDepth != -1) { + bundle.put(POS, returnPos); + } + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + returnDepth = bundle.getInt(DEPTH); + returnPos = bundle.getInt(POS); + } + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + actions.add(AC_PORT); + + return actions; + } + + @Override + public void execute(Hero hero, String action) { + + if (action == AC_PORT) { + + if (Dungeon.bossLevel()) { + hero.spend(TIME_TO_USE); + GLog.w(Messages.get(Item.class, "not_here")); + return; + } + + if (Dungeon.depth>26 && !Dungeon.shadowyogkilled) { + hero.spend(TIME_TO_USE); + GLog.w(Messages.get(Item.class, "boss_first")); + return; + } + + + } + + if (action == AC_PORT) { + + hero.spend(TIME_TO_USE); + + Buff buff = Dungeon.hero + .buff(TimekeepersHourglass.timeFreeze.class); + if (buff != null) + buff.detach(); + + if (Dungeon.depth<25 && !Dungeon.bossLevel()){ + returnDepth = Dungeon.depth; + returnPos = hero.pos; + InterlevelScene.mode = InterlevelScene.Mode.PORT4; + } else { + InterlevelScene.mode = InterlevelScene.Mode.RETURN; + detach(hero.belongings.backpack); + } + + + InterlevelScene.returnDepth = returnDepth; + InterlevelScene.returnPos = returnPos; + Game.switchScene(InterlevelScene.class); + + } else { + + super.execute(hero, action); + + } + } + + public void reset() { + returnDepth = -1; + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + + private static final Glowing WHITE = new Glowing(0xFFFFCC); + + @Override + public Glowing glowing() { + return WHITE; + } +} diff --git a/java/com/hmdzl/spspd/items/TriforceOfCourage.java b/java/com/hmdzl/spspd/items/TriforceOfCourage.java new file mode 100644 index 00000000..4b5bef58 --- /dev/null +++ b/java/com/hmdzl/spspd/items/TriforceOfCourage.java @@ -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 + */ +package com.hmdzl.spspd.items; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class TriforceOfCourage extends Item { + + { + //name = "Triforce of Courage"; + image = ItemSpriteSheet.ATRIFORCE; + + stackable = false; + unique = true; + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + @Override + public boolean doPickUp(Hero hero) { + if (super.doPickUp(hero)) { + + if (Dungeon.level != null && Dungeon.depth==31) { + Dungeon.triforceofcourage = true; + } + + return true; + } else { + return false; + } + } + + @Override + public int price() { + return 10 * quantity; + } +} diff --git a/java/com/hmdzl/spspd/items/TriforceOfPower.java b/java/com/hmdzl/spspd/items/TriforceOfPower.java new file mode 100644 index 00000000..b63d7ed6 --- /dev/null +++ b/java/com/hmdzl/spspd/items/TriforceOfPower.java @@ -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 + */ +package com.hmdzl.spspd.items; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class TriforceOfPower extends Item { + + { + //name = "Triforce of Power"; + image = ItemSpriteSheet.ATRIFORCE; + + stackable = false; + unique = true; + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + + @Override + public boolean doPickUp(Hero hero) { + if (super.doPickUp(hero)) { + + if (Dungeon.level != null && Dungeon.depth==32) { + Dungeon.triforceofpower= true; + } + + return true; + } else { + return false; + } + } + + @Override + public int price() { + return 10 * quantity; + } +} diff --git a/java/com/hmdzl/spspd/items/TriforceOfWisdom.java b/java/com/hmdzl/spspd/items/TriforceOfWisdom.java new file mode 100644 index 00000000..f922af90 --- /dev/null +++ b/java/com/hmdzl/spspd/items/TriforceOfWisdom.java @@ -0,0 +1,73 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class TriforceOfWisdom extends Item { + + { + //name = "Triforce of Wisdom"; + image = ItemSpriteSheet.ATRIFORCE; + + stackable = false; + unique = true; + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + + @Override + public boolean doPickUp(Hero hero) { + if (super.doPickUp(hero)) { + + if (Dungeon.level != null && Dungeon.depth==33) { + Dungeon.triforceofwisdom= true; + } + + return true; + } else { + return false; + } + } + + @Override + public void doDrop(Hero hero) { + + if (Dungeon.level != null && Dungeon.depth==33) { + Dungeon.triforceofwisdom= false; + } + + super.doDrop(hero); + } + + @Override + public int price() { + return 10 * quantity; + } +} diff --git a/java/com/hmdzl/spspd/items/UpgradeBlobRed.java b/java/com/hmdzl/spspd/items/UpgradeBlobRed.java new file mode 100644 index 00000000..0bb24731 --- /dev/null +++ b/java/com/hmdzl/spspd/items/UpgradeBlobRed.java @@ -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 + */ +package com.hmdzl.spspd.items; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.hero.HeroClass; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.scrolls.ScrollOfUpgrade; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; +import com.hmdzl.spspd.windows.WndBag; +import com.watabou.utils.Random; + +public class UpgradeBlobRed extends Item { + + private static final String TXT_SELECT = "Select an item to upgrade"; + private static final String TXT_UPGRADED = "your %s certainly looks better"; + + private static final float TIME_TO_INSCRIBE = 2; + + private static final int upgrades = 3; + + + private static final String AC_INSCRIBE = "INSCRIBE"; + + { + //name = "red upgrade goo"; + image = ItemSpriteSheet.UPGRADEGOO_RED; + + stackable = true; + + + } + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + actions.add(AC_INSCRIBE); + return actions; + } + + @Override + public void execute(Hero hero, String action) { + if (action == AC_INSCRIBE) { + + curUser = hero; + GameScene.selectItem(itemSelector, WndBag.Mode.UPGRADEABLE, + Messages.get(ScrollOfUpgrade.class,"prompt")); + + } else { + + super.execute(hero, action); + + } + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + private void upgrade(Item item) { + if (!(Dungeon.hero.heroClass == HeroClass.FOLLOWER ) || (Dungeon.hero.heroClass == HeroClass.FOLLOWER && Random.Int(10)>=1 )) + detach(curUser.belongings.backpack); + + GLog.w(Messages.get(ScrollOfUpgrade.class,"looks_better", item.name())); + + if (item.reinforced){ + item.upgrade(upgrades); + } else { + item.upgrade(Math.min(upgrades, 15-item.level)); + } + + curUser.sprite.operate(curUser.pos); + curUser.sprite.emitter().start(Speck.factory(Speck.UP), 0.2f, 3); + Badges.validateItemLevelAquired(item); + + curUser.spend(TIME_TO_INSCRIBE); + curUser.busy(); + + } + + @Override + public int price() { + return 30 * quantity; + } + + private final WndBag.Listener itemSelector = new WndBag.Listener() { + @Override + public void onSelect(Item item) { + if (item != null) { + UpgradeBlobRed.this.upgrade(item); + } + } + }; +} diff --git a/java/com/hmdzl/spspd/items/UpgradeBlobViolet.java b/java/com/hmdzl/spspd/items/UpgradeBlobViolet.java new file mode 100644 index 00000000..3d567f46 --- /dev/null +++ b/java/com/hmdzl/spspd/items/UpgradeBlobViolet.java @@ -0,0 +1,118 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.hero.HeroClass; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.scrolls.ScrollOfUpgrade; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; +import com.hmdzl.spspd.windows.WndBag; +import com.watabou.utils.Random; + +public class UpgradeBlobViolet extends Item { + + private static final float TIME_TO_INSCRIBE = 2; + + private static final String AC_INSCRIBE = "INSCRIBE"; + + private static final int upgrades = 5; + + { + //name = "violet upgrade goo"; + image = ItemSpriteSheet.UPGRADEGOO_VIOLET; + + stackable = true; + + + } + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + actions.add(AC_INSCRIBE); + return actions; + } + + @Override + public void execute(Hero hero, String action) { + if (action == AC_INSCRIBE) { + + curUser = hero; + GameScene.selectItem(itemSelector, WndBag.Mode.UPGRADEABLE, + Messages.get(ScrollOfUpgrade.class,"prompt")); + + } else { + + super.execute(hero, action); + + } + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + private void upgrade(Item item) { +if (!(Dungeon.hero.heroClass == HeroClass.FOLLOWER ) || (Dungeon.hero.heroClass == HeroClass.FOLLOWER && Random.Int(10)>=1 )) + detach(curUser.belongings.backpack); + + GLog.w(Messages.get(ScrollOfUpgrade.class,"looks_better", item.name())); + + if (item.reinforced){ + item.upgrade(upgrades); + } else { + item.upgrade(Math.min(upgrades, 15-item.level)); + } + + curUser.sprite.operate(curUser.pos); + curUser.sprite.emitter().start(Speck.factory(Speck.UP), 0.2f, 3); + Badges.validateItemLevelAquired(item); + + curUser.spend(TIME_TO_INSCRIBE); + curUser.busy(); + + } + + @Override + public int price() { + return 30 * quantity; + } + + private final WndBag.Listener itemSelector = new WndBag.Listener() { + @Override + public void onSelect(Item item) { + if (item != null) { + UpgradeBlobViolet.this.upgrade(item); + } + } + }; +} diff --git a/java/com/hmdzl/spspd/items/UpgradeBlobYellow.java b/java/com/hmdzl/spspd/items/UpgradeBlobYellow.java new file mode 100644 index 00000000..cb6e8b54 --- /dev/null +++ b/java/com/hmdzl/spspd/items/UpgradeBlobYellow.java @@ -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 + */ +package com.hmdzl.spspd.items; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.hero.HeroClass; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.scrolls.ScrollOfUpgrade; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; +import com.hmdzl.spspd.windows.WndBag; +import com.watabou.utils.Random; + +public class UpgradeBlobYellow extends Item { + + private static final String TXT_SELECT = "Select an item to upgrade"; + private static final String TXT_UPGRADED = "your %s certainly looks better"; + + private static final float TIME_TO_INSCRIBE = 2; + + private static final String AC_INSCRIBE = "INSCRIBE"; + + private static final int upgrades = 1; + + { + //name = "yellow upgrade goo"; + image = ItemSpriteSheet.UPGRADEGOO_YELLOW; + + stackable = true; + + + } + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + actions.add(AC_INSCRIBE); + return actions; + } + + @Override + public void execute(Hero hero, String action) { + if (action == AC_INSCRIBE) { + + curUser = hero; + GameScene.selectItem(itemSelector, WndBag.Mode.UPGRADEABLE, + Messages.get(ScrollOfUpgrade.class,"prompt")); + + } else { + + super.execute(hero, action); + + } + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + private void upgrade(Item item) { +if (!(Dungeon.hero.heroClass == HeroClass.FOLLOWER ) || (Dungeon.hero.heroClass == HeroClass.FOLLOWER && Random.Int(10)>=1 )) + detach(curUser.belongings.backpack); + + GLog.w(Messages.get(ScrollOfUpgrade.class,"looks_better", item.name())); + + if (item.reinforced){ + item.upgrade(upgrades); + } else { + item.upgrade(Math.min(upgrades, 15-item.level)); + } + + curUser.sprite.operate(curUser.pos); + curUser.sprite.emitter().start(Speck.factory(Speck.UP), 0.2f, 3); + Badges.validateItemLevelAquired(item); + + curUser.spend(TIME_TO_INSCRIBE); + curUser.busy(); + } + + @Override + public int price() { + return 30 * quantity; + } + + private final WndBag.Listener itemSelector = new WndBag.Listener() { + @Override + public void onSelect(Item item) { + if (item != null) { + UpgradeBlobYellow.this.upgrade(item); + } + } + }; +} diff --git a/java/com/hmdzl/spspd/items/UpgradeEatBall.java b/java/com/hmdzl/spspd/items/UpgradeEatBall.java new file mode 100644 index 00000000..c75d3931 --- /dev/null +++ b/java/com/hmdzl/spspd/items/UpgradeEatBall.java @@ -0,0 +1,160 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2019 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ + +package com.hmdzl.spspd.items; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.hero.HeroClass; +import com.hmdzl.spspd.items.potions.Potion; + +import com.hmdzl.spspd.items.scrolls.Scroll; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.plants.Seedpod; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.windows.WndBag; +import com.watabou.utils.Random; + +import java.util.ArrayList; + +public class UpgradeEatBall extends Item { + + private static final String AC_USE = "USE"; + + { + image = ItemSpriteSheet.UP_EATER; + + stackable = true; + } + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + actions.add(AC_USE); + return actions; + } + + @Override + public void execute(Hero hero, String action) { + if (action == AC_USE) { + curUser = hero; + GameScene.selectItem(itemSelector, + WndBag.Mode.EATABLE, + Messages.get(UpgradeEatBall.class, "prompt")); + + } else { + + super.execute(hero, action); + + } + } + + private void use(Item item) { +if (!(Dungeon.hero.heroClass == HeroClass.FOLLOWER ) || (Dungeon.hero.heroClass == HeroClass.FOLLOWER && Random.Int(10)>=1 )) + detach(curUser.belongings.backpack); + + curUser.sprite.operate(curUser.pos); + //curUser.sprite.emitter().start(Speck.factory(Speck.CHANGE), 0.2f, 0); + + curUser.spend(1f); + curUser.busy(); + + } + + + private final WndBag.Listener itemSelector = new WndBag.Listener() { + @Override + public void onSelect(Item item) { + curUser = Dungeon.hero; + Item result; + if (item != null) { + if (item.isUpgradable()) { + result = eatUpgradable((Item) item); + } else if (item instanceof Scroll + || item instanceof Potion + || item instanceof Stylus) { + result = eatStandard((Item) item); + } else { + result = null; + } + item.detach(Dungeon.hero.belongings.backpack); + Dungeon.level.drop(result, Dungeon.hero.pos).sprite.drop(); + UpgradeEatBall.this.use(item); + } + } + }; + + private Item eatUpgradable(Item w) { + + int ups = w.level; + + Item n = null; + + if (Random.Float()<(ups/10)){ + + n = new UpgradeBlobViolet(); + + } else if (Random.Float()<(ups/5)) { + + n = new UpgradeBlobRed(); + + } else if (Random.Float()<(ups/3)) { + + n = new UpgradeBlobYellow(); + + } else { + + n =new Seedpod.Seed() ; + } + + return n; + } + + private Item eatStandard(Item w) { + + Item n = null; + + if (Random.Float()<0.1f){ + n = new UpgradeBlobYellow(); + } else { + n = new Seedpod.Seed() ; + } + + return n; + } + + + @Override + public int price() { + return 50; + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } +} diff --git a/java/com/hmdzl/spspd/items/VioletDewdrop.java b/java/com/hmdzl/spspd/items/VioletDewdrop.java new file mode 100644 index 00000000..3b03b8ba --- /dev/null +++ b/java/com/hmdzl/spspd/items/VioletDewdrop.java @@ -0,0 +1,72 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.hero.HeroClass; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.CharSprite; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.noosa.audio.Sample; + +public class VioletDewdrop extends Item { + + private static final String TXT_VALUE = "%+dHP"; + + { + //name = "violet dewdrop"; + image = ItemSpriteSheet.VIOLETDEWDROP; + + stackable = true; + } + + @Override + public boolean doPickUp(Hero hero) { + + DewVial vial = hero.belongings.getItem(DewVial.class); + + if (vial == null || vial.isFull()) { + + int value = 2 + (Dungeon.depth - 1) / 5; + if (hero.heroClass == HeroClass.HUNTRESS) { + value++; + } + + int effect = Math.min(hero.HT - hero.HP, value * quantity); + if (effect > 0) { + hero.HP += effect; + hero.sprite.emitter().burst(Speck.factory(Speck.HEALING), 1); + hero.sprite.showStatus(CharSprite.POSITIVE, Messages.get(this, "value", effect)); + } + + } else if (vial != null) { + + vial.collectDew(this); + + } + + Sample.INSTANCE.play(Assets.SND_DEWDROP); + hero.spendAndNext(TIME_TO_PICK_UP); + + return true; + } + +} diff --git a/java/com/hmdzl/spspd/items/WaterItem2.java b/java/com/hmdzl/spspd/items/WaterItem2.java new file mode 100644 index 00000000..3c818b9d --- /dev/null +++ b/java/com/hmdzl/spspd/items/WaterItem2.java @@ -0,0 +1,82 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2014 Oleg Dolya + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.items; + +import java.util.ArrayList; + +import com.hmdzl.spspd.actors.hero.Hero; + +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.Terrain; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class WaterItem2 extends Item { + + public static final String AC_POUR = "POUR"; + + { + //name = "water"; + image = ItemSpriteSheet.DEWDROP; + + stackable = true; + } + + @Override + public ArrayList actions( Hero hero ) { + ArrayList actions = super.actions( hero ); + + actions.add( AC_POUR ); + + return actions; + } + + @Override + public void execute( final Hero hero, String action ) { + if( action.equals( AC_POUR ) ){ + + curUser = hero; + curItem = this; + + Level.set(curUser.pos, Terrain.WATER); + GameScene.updateMap(curUser.pos); + + detach(curUser.belongings.backpack); + + } else { + super.execute(hero, action); + } + } + + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + @Override + public int price() { + return 10 * quantity; + } + +} diff --git a/java/com/hmdzl/spspd/items/Weightstone.java b/java/com/hmdzl/spspd/items/Weightstone.java new file mode 100644 index 00000000..bb9b5075 --- /dev/null +++ b/java/com/hmdzl/spspd/items/Weightstone.java @@ -0,0 +1,181 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.hero.HeroClass; +import com.hmdzl.spspd.effects.particles.PurpleParticle; +import com.hmdzl.spspd.items.weapon.Weapon; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; +import com.hmdzl.spspd.windows.WndBag; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Random; + +public class Weightstone extends Item { + + private static final float TIME_TO_APPLY = 2; + + private static final String AC_APPLY = "APPLY"; + + { + + image = ItemSpriteSheet.WEIGHT; + + stackable = true; + + + } + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + actions.add(AC_APPLY); + return actions; + } + + @Override + public void execute(Hero hero, String action) { + if (action == AC_APPLY) { + + curUser = hero; + GameScene.selectItem(itemSelector, WndBag.Mode.WEAPON, + Messages.get(this, "select")); + + } else { + + super.execute(hero, action); + + } + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + private void apply(Weapon weapon) { + + if (!(Dungeon.hero.heroClass == HeroClass.FOLLOWER ) || (Dungeon.hero.heroClass == HeroClass.FOLLOWER && Random.Int(10)>=1 )) + detach(curUser.belongings.backpack); + + GLog.w(Messages.get(this,"apply")); + + weapon.enchant(); + + curUser.sprite.operate(curUser.pos); + curUser.sprite.centerEmitter().start(PurpleParticle.BURST, 0.05f, 10); + Sample.INSTANCE.play(Assets.SND_MISS); + + curUser.spend(TIME_TO_APPLY); + curUser.busy(); + } + + @Override + public int price() { + return 40 * quantity; + } + + private final WndBag.Listener itemSelector = new WndBag.Listener() { + @Override + public void onSelect(Item item) { + if (item != null) { + Weightstone.this.apply((Weapon) item);; + } + } + }; + + /*public class WndBalance extends Window { + + private static final int WIDTH = 120; + private static final int MARGIN = 2; + private static final int BUTTON_WIDTH = WIDTH - MARGIN * 2; + private static final int BUTTON_HEIGHT = 20; + + public WndBalance(final Weapon weapon) { + super(); + + IconTitle titlebar = new IconTitle(weapon); + titlebar.setRect(0, 0, WIDTH, 0); + add(titlebar); + + RenderedTextMultiline tfMesage = PixelScene.renderMultiline( Messages.get(this, "choice"), 8 ); + tfMesage.maxWidth(WIDTH - MARGIN * 2); + tfMesage.setPos(MARGIN, titlebar.bottom() + MARGIN); + add( tfMesage ); + + float pos = tfMesage.top() + tfMesage.height(); + + if (weapon.imbue != Weapon.Imbue.LIGHT) { + RedButton btnSpeed = new RedButton(Messages.get(this, "light")) { + @Override + protected void onClick() { + hide(); + Weightstone.this.apply(weapon, true); + } + }; + btnSpeed.setRect(MARGIN, pos + MARGIN, BUTTON_WIDTH, + BUTTON_HEIGHT); + add(btnSpeed); + + pos = btnSpeed.bottom(); + } + + if (weapon.imbue != Weapon.Imbue.HEAVY) { + RedButton btnAccuracy = new RedButton(Messages.get(this, "heavy")) { + @Override + protected void onClick() { + hide(); + Weightstone.this.apply(weapon, false); + } + }; + btnAccuracy.setRect(MARGIN, pos + MARGIN, BUTTON_WIDTH, + BUTTON_HEIGHT); + add(btnAccuracy); + + pos = btnAccuracy.bottom(); + } + + RedButton btnCancel = new RedButton(Messages.get(this, "cancel")) { + @Override + protected void onClick() { + hide(); + } + }; + btnCancel + .setRect(MARGIN, pos + MARGIN, BUTTON_WIDTH, BUTTON_HEIGHT); + add(btnCancel); + + resize(WIDTH, (int) btnCancel.bottom() + MARGIN); + } + + protected void onSelect(int index) { + } + }*/ +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/Whistle.java b/java/com/hmdzl/spspd/items/Whistle.java new file mode 100644 index 00000000..694ab154 --- /dev/null +++ b/java/com/hmdzl/spspd/items/Whistle.java @@ -0,0 +1,106 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.hero.Hero; + +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.scenes.PixelScene; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.ui.RenderedTextMultiline; +import com.hmdzl.spspd.ui.Window; +import com.hmdzl.spspd.windows.IconTitle; + +public class Whistle extends Item { + + + public static final float TIME_TO_USE = 1; + + public static final String AC_CALL = "CALL"; + + { + //name = "whistle"; + image = ItemSpriteSheet.POCKET_BALL; + unique = true; + stackable = false; + } + + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + if (Dungeon.depth < 26) actions.add(AC_CALL); + return actions; + } + + @Override + public void execute(Hero hero, String action) { + + + if (action == AC_CALL) { + GameScene.show( new WndWhistle(this) ); + } else { + + super.execute(hero, action); + + } + + } + + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + private static class WndWhistle extends Window { + + private static final int BTN_SIZE = 32; + private static final float GAP = 2; + private static final float BTN_GAP = 12; + private static final int WIDTH = 116; + + WndWhistle(final Whistle whis){ + + IconTitle titlebar = new IconTitle(); + titlebar.icon( new ItemSprite(whis) ); + titlebar.label( Messages.get(this, "title") ); + titlebar.setRect( 0, 0, WIDTH, 0 ); + add( titlebar ); + + RenderedTextMultiline message = + PixelScene.renderMultiline(Messages.get(this, "desc"),6); + message.maxWidth( WIDTH ); + message.setPos(0, titlebar.bottom() + GAP); + add( message ); + + + resize(WIDTH, (int)(message.bottom() + GAP)); + } + + } +} diff --git a/java/com/hmdzl/spspd/items/YellowDewdrop.java b/java/com/hmdzl/spspd/items/YellowDewdrop.java new file mode 100644 index 00000000..9439316e --- /dev/null +++ b/java/com/hmdzl/spspd/items/YellowDewdrop.java @@ -0,0 +1,71 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2014 Oleg Dolya + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.items; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.hero.HeroClass; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.CharSprite; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.noosa.audio.Sample; + +public class YellowDewdrop extends Item { + + private static final String TXT_VALUE = "%+dHP"; + + { + //name = "yellow dewdrop"; + image = ItemSpriteSheet.YELLOWDEWDROP; + + stackable = true; + } + + @Override + public boolean doPickUp(Hero hero) { + + DewVial vial = hero.belongings.getItem(DewVial.class); + + if (vial == null || vial.isFull()) { + + int value = 2 + (Dungeon.depth - 1) / 5; + if (hero.heroClass == HeroClass.HUNTRESS) { + value++; + } + + int effect = Math.min(hero.HT - hero.HP, value * quantity); + if (effect > 0) { + hero.HP += effect; + hero.sprite.emitter().burst(Speck.factory(Speck.HEALING), 1); + hero.sprite.showStatus(CharSprite.POSITIVE, Messages.get(this, "value", effect)); + } + + } else if (vial != null) { + + vial.collectDew(this); + + } + + Sample.INSTANCE.play(Assets.SND_DEWDROP); + hero.spendAndNext(TIME_TO_PICK_UP); + + return true; + } +} diff --git a/java/com/hmdzl/spspd/items/armor/Armor.java b/java/com/hmdzl/spspd/items/armor/Armor.java new file mode 100644 index 00000000..81bd16d0 --- /dev/null +++ b/java/com/hmdzl/spspd/items/armor/Armor.java @@ -0,0 +1,335 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.armor; + +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.hero.HeroClass; +import com.hmdzl.spspd.actors.hero.HeroSubClass; +import com.hmdzl.spspd.items.KindOfArmor; +import com.hmdzl.spspd.items.armor.glyphs.AdaptGlyph; +import com.hmdzl.spspd.items.armor.glyphs.Changeglyph; +import com.hmdzl.spspd.items.armor.glyphs.Crystalglyph; +import com.hmdzl.spspd.items.armor.glyphs.Darkglyph; +import com.hmdzl.spspd.items.armor.glyphs.Earthglyph; +import com.hmdzl.spspd.items.armor.glyphs.Electricityglyph; +import com.hmdzl.spspd.items.armor.glyphs.Fireglyph; +import com.hmdzl.spspd.items.armor.glyphs.Iceglyph; +import com.hmdzl.spspd.items.armor.glyphs.Lightglyph; +import com.hmdzl.spspd.items.armor.glyphs.RecoilGlyph; +import com.hmdzl.spspd.items.armor.glyphs.Revivalglyph; +import com.hmdzl.spspd.items.armor.glyphs.Testglyph; +import com.hmdzl.spspd.items.rings.RingOfEvasion; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.sprites.HeroSprite; +import com.hmdzl.spspd.sprites.ItemSprite; + +import com.watabou.utils.Bundlable; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public class Armor extends KindOfArmor { + + private static final String TXT_TO_STRING = "%s :%d"; + + public int tier; + + public int STR = 10; + public float DEX = 1f; // dexterity modifier + public float STE = 1f; // stealth modifier + public int ENG = 1; // energy modifier + + public Glyph glyph; + + @Override + public boolean doEquip(Hero hero) { + + detachAll(hero.belongings.backpack); + if (hero.belongings.armor == null + || hero.belongings.armor.doUnequip(hero, true)) { + + hero.belongings.armor = this; + activate(hero); + ((HeroSprite) hero.sprite).updateArmor(); + hero.spendAndNext(TIME_TO_EQUIP); + return true; + + } else { + + collect(hero.belongings.backpack); + return false; + } + + } + + @Override + public boolean doUnequip(Hero hero, boolean collect, boolean single) { + if (super.doUnequip(hero, collect, single)) { + hero.belongings.armor = null; + ((HeroSprite) hero.sprite).updateArmor(); + return true; + } else { + return false; + } + } + + @Override + public void proc(Char attacker, Char defender, int damage) { + + if (glyph != null) { + glyph.proc(this, attacker, defender, damage); + } + + } + + private static final String GLYPH = "glyph"; + + public int STR() + { + if(Dungeon.hero != null && Dungeon.hero.belongings.armor == this && STR > 2 && + ( Dungeon.hero.heroClass == HeroClass.WARRIOR || Dungeon.hero.subClass == HeroSubClass.ARTISAN )) + return STR - 2; + else return STR; + } + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(GLYPH, glyph); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + //glyph = (Glyph) bundle.get(GLYPH); + glyph = ((Glyph) bundle.get(GLYPH)); + } + + @Override + public float dexterityFactor(Hero hero) { + + int encumbrance = STR() - hero.STR(); + + float DEX = this.DEX; + + int bonus = 0; + for (Buff buff : hero.buffs(RingOfEvasion.Evasion.class)) { + bonus += ((RingOfEvasion.Evasion) buff).level; + } + + DEX+= (float) (Math.min(2,bonus/15)); + + return encumbrance > 0 ? (float) (DEX / Math.pow(1.5, encumbrance)) : DEX; + } + + + @Override + public float stealthFactor(Hero hero) { + + int encumbrance = STR() - hero.STR(); + + float STE = this.STE; + + int bonus = 0; + for (Buff buff : hero.buffs(RingOfEvasion.Evasion.class)) { + bonus += ((RingOfEvasion.Evasion) buff).level; + } + + STE+= (float) (Math.min(6,bonus/5)); + + return encumbrance > 0 ? (float) (STE / Math.pow(1.5, encumbrance)) : STE; + } + + + @Override + public int energyFactor(Hero hero) { + int ENG = this.ENG; + return ENG; + } + + /*public int tier() { + int tier = this.tier(); + return tier; + }*/ + + @Override + public int drRoll(Hero hero) { + int encumbrance = STR() - hero.STR(); + int dr = super.drRoll(hero); + return encumbrance > 0 ? Math.max((int)(Math.round(dr)*(1-encumbrance/3)),0) :Math.round(dr); + } + + + public Item upgrade(boolean hasglyph) { + + if (hasglyph) { + if (glyph != null) { + hasglyphAdv(); + } else { + hasglyph(); + } + + } + + return super.upgrade(); + } + + @Override + public String toString() { + return levelKnown ? Messages.format(TXT_TO_STRING, super.toString(), STR()) + : super.toString(); + } + + @Override + public String name() { + return glyph == null ? super.name() : glyph.name(super.name()); + } + + @Override + public Item random() { + if (Random.Float() < 0.4) { + int n = 1; + if (Random.Int(3) == 0) { + n++; + if (Random.Int(3) == 0) { + n++; + } + } + if (Random.Int(2) == 0) { + upgrade(n); + } else { + degrade(n); + cursed = true; + } + } + + return this; + } + + public Armor hasglyph( Glyph gph ) { + glyph = gph; + return this; + } + + public Armor hasglyph() { + + Class oldGlyphClass = glyph != null ? glyph.getClass() + : null; + Glyph gph = Glyph.random(); + while (gph.getClass() == oldGlyphClass) { + gph = Glyph.random(); + } + + return hasglyph(gph); + } + + public Armor hasglyphAdv() { + + Class oldGlyphClass = glyph != null ? glyph.getClass() + : null; + Glyph gph = Glyph.randomAdv(); + while (gph.getClass() == oldGlyphClass) { + gph = Glyph.randomAdv(); + } + + return hasglyph(gph); + } + + public boolean isGlyphed() { + return glyph != null; + } + + @Override + public ItemSprite.Glowing glowing() { + return glyph != null ? glyph.glowing() : null; + } + + public static abstract class Glyph implements Bundlable { + + private static final Class[] glyphs = new Class[] { Changeglyph.class, + Crystalglyph.class, Darkglyph.class, Earthglyph.class, + Electricityglyph.class, Fireglyph.class, Iceglyph.class, + Lightglyph.class, Revivalglyph.class, Testglyph.class, + AdaptGlyph.class, RecoilGlyph.class}; + + private static final float[] chances = new float[] { 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1,1,1 }; + + private static final float[] chancesAdv = new float[] { 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1,1,1 }; + + public abstract int proc(Armor armor, Char attacker, Char defender, + int damage); + + public String name(String armorName) { + return Messages.get(this, "name", armorName); + } + + public String desc() { + return Messages.get(this, "desc"); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + } + + @Override + public void storeInBundle(Bundle bundle) { + } + + public ItemSprite.Glowing glowing() { + return ItemSprite.Glowing.WHITE; + } + + public boolean checkOwner(Char owner) { + if (!owner.isAlive() && owner instanceof Hero) { + + Badges.validateDeathFromGlyph(); + return true; + + } else { + return false; + } + } + + @SuppressWarnings("unchecked") + public static Glyph random() { + try { + return ((Class) glyphs[Random.chances(chances)]) + .newInstance(); + } catch (Exception e) { + return null; + } + } + + @SuppressWarnings("unchecked") + public static Glyph randomAdv() { + try { + return ((Class) glyphs[Random.chances(chancesAdv)]) + .newInstance(); + } catch (Exception e) { + return null; + } + } + + } +} diff --git a/java/com/hmdzl/spspd/items/armor/glyphs/AdaptGlyph.java b/java/com/hmdzl/spspd/items/armor/glyphs/AdaptGlyph.java new file mode 100644 index 00000000..e1add4e8 --- /dev/null +++ b/java/com/hmdzl/spspd/items/armor/glyphs/AdaptGlyph.java @@ -0,0 +1,104 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.armor.glyphs; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.EarthImbue; +import com.hmdzl.spspd.actors.buffs.FireImbue; +import com.hmdzl.spspd.actors.buffs.Haste; +import com.hmdzl.spspd.actors.buffs.Invisibility; +import com.hmdzl.spspd.actors.buffs.Levitation; +import com.hmdzl.spspd.actors.buffs.Recharging; +import com.hmdzl.spspd.items.armor.Armor; +import com.hmdzl.spspd.items.armor.Armor.Glyph; +import com.hmdzl.spspd.items.misc.FourClover; +import com.hmdzl.spspd.levels.Terrain; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.sprites.ItemSprite.Glowing; +import com.hmdzl.spspd.actors.buffs.armorbuff.GlyphDark; +import com.hmdzl.spspd.actors.buffs.armorbuff.GlyphEarth; +import com.hmdzl.spspd.actors.buffs.armorbuff.GlyphElectricity; +import com.hmdzl.spspd.actors.buffs.armorbuff.GlyphFire; +import com.hmdzl.spspd.actors.buffs.armorbuff.GlyphIce; +import com.hmdzl.spspd.actors.buffs.armorbuff.GlyphLight; +import com.watabou.utils.Random; + +public class AdaptGlyph extends Glyph { + + private static ItemSprite.Glowing DEEPGREEN = new ItemSprite.Glowing(0x006633); + + @Override + public int proc(Armor armor, Char attacker, Char defender, int damage) { + + GlyphDark gdark = defender.buff(GlyphDark.class); + GlyphIce gice = defender.buff(GlyphIce.class); + GlyphLight glight = defender.buff(GlyphLight.class); + GlyphFire gfire = defender.buff(GlyphFire.class); + GlyphEarth gearth = defender.buff(GlyphEarth.class); + GlyphElectricity gelect = defender.buff(GlyphElectricity.class); + FourClover.FourCloverBless fcb = defender.buff(FourClover.FourCloverBless.class); + + if (defender.isAlive() && (gdark != null || gice != null || glight != null || gfire != null || gearth != null || gelect != null )) + { + Buff.detach(defender,GlyphIce.class); + Buff.detach(defender,GlyphLight.class); + Buff.detach(defender,GlyphFire.class); + Buff.detach(defender,GlyphEarth.class); + Buff.detach(defender,GlyphElectricity.class); + Buff.detach(defender,GlyphDark.class); + } + + int level = Math.max(0, armor.level); + + if (Random.Int(level + 5) >= 4 || (fcb != null && Random.Int(level + 5) >= 2)) { + + if (Dungeon.level.map[defender.pos] == Terrain.GRASS) { + Buff.prolong(defender, EarthImbue.class,5f); + } + + if (Dungeon.level.map[defender.pos] == Terrain.WATER) { + Buff.prolong(defender, Haste.class,5f); + } + + if (Dungeon.level.map[defender.pos] == Terrain.HIGH_GRASS) { + Buff.prolong(defender, Invisibility.class,5f); + } + + if (Dungeon.level.map[defender.pos] == Terrain.CHASM) { + Buff.affect(defender, Levitation.class,10f); + } + + if (Dungeon.level.map[defender.pos] == Terrain.INACTIVE_TRAP) { + Buff.prolong(defender, Recharging.class,5f); + } + + if (Dungeon.level.map[defender.pos] == Terrain.EMBERS) { + Buff.affect(defender, FireImbue.class).set(5f); + } + } + return damage; + } + + @Override + public Glowing glowing() { + return DEEPGREEN; + } + +} diff --git a/java/com/hmdzl/spspd/items/armor/glyphs/Changeglyph.java b/java/com/hmdzl/spspd/items/armor/glyphs/Changeglyph.java new file mode 100644 index 00000000..5bf1ef24 --- /dev/null +++ b/java/com/hmdzl/spspd/items/armor/glyphs/Changeglyph.java @@ -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 + */ +package com.hmdzl.spspd.items.armor.glyphs; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Invisibility; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.mobs.npcs.MirrorImage; +import com.hmdzl.spspd.items.armor.Armor; +import com.hmdzl.spspd.items.armor.Armor.Glyph; +import com.hmdzl.spspd.items.misc.FourClover; +import com.hmdzl.spspd.items.scrolls.ScrollOfTeleportation; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.sprites.ItemSprite.Glowing; +import com.hmdzl.spspd.actors.buffs.armorbuff.GlyphDark; +import com.hmdzl.spspd.actors.buffs.armorbuff.GlyphEarth; +import com.hmdzl.spspd.actors.buffs.armorbuff.GlyphElectricity; +import com.hmdzl.spspd.actors.buffs.armorbuff.GlyphFire; +import com.hmdzl.spspd.actors.buffs.armorbuff.GlyphIce; +import com.hmdzl.spspd.actors.buffs.armorbuff.GlyphLight; + +import com.watabou.utils.Random; + +import java.util.ArrayList; + +public class Changeglyph extends Glyph { + + private static ItemSprite.Glowing PURPLE = new ItemSprite.Glowing(0x8844CC); + + @Override + public int proc(Armor armor, Char attacker, Char defender, int damage) { + GlyphDark gdark = defender.buff(GlyphDark.class); + GlyphIce gice = defender.buff(GlyphIce.class); + GlyphLight glight = defender.buff(GlyphLight.class); + GlyphFire gfire = defender.buff(GlyphFire.class); + GlyphEarth gearth = defender.buff(GlyphEarth.class); + GlyphElectricity gelect = defender.buff(GlyphElectricity.class); + FourClover.FourCloverBless fcb = defender.buff(FourClover.FourCloverBless.class); + if (defender.isAlive() && (gdark != null || gice != null || glight != null || gfire != null || gearth != null || gelect != null )) + { + Buff.detach(defender,GlyphIce.class); + Buff.detach(defender,GlyphLight.class); + Buff.detach(defender,GlyphFire.class); + Buff.detach(defender,GlyphEarth.class); + Buff.detach(defender,GlyphElectricity.class); + Buff.detach(defender,GlyphDark.class); + } + + int level = Math.max(0, armor.level); + + if (Random.Int(level / 2 + 6) >= 5 || (fcb != null && Random.Int(level / 2 + 6) >= 3)) { + + ArrayList respawnPoints = new ArrayList(); + + for (int i = 0; i < Level.NEIGHBOURS8.length; i++) { + int p = defender.pos + Level.NEIGHBOURS8[i]; + if (Actor.findChar(p) == null + && (Level.passable[p] || Level.avoid[p])) { + respawnPoints.add(p); + } + } + + if (respawnPoints.size() > 0) { + MirrorImage mob = new MirrorImage(); + mob.duplicate((Hero) defender); + GameScene.add(mob); + ScrollOfTeleportation.appear(mob, Random.element(respawnPoints)); + checkOwner(defender); + } + + } + + if (Dungeon.bossLevel()) { + return damage; + } + + int nTries = (armor.level < 0 ? 1 : armor.level + 1) * 5; + for (int i=0; i < nTries; i++) { + int pos = Random.Int( Level.LENGTH ); + if (Dungeon.visible[pos] && Level.passable[pos] && Actor.findChar( pos ) == null) { + + ScrollOfTeleportation.appear( defender, pos ); + Dungeon.level.press( pos, defender ); + Buff.affect(defender, Invisibility.class, 5f); + Dungeon.observe(); + break; + } + } + + return damage; + } + + @Override + public Glowing glowing() { + return PURPLE; + } +} diff --git a/java/com/hmdzl/spspd/items/armor/glyphs/Crystalglyph.java b/java/com/hmdzl/spspd/items/armor/glyphs/Crystalglyph.java new file mode 100644 index 00000000..0838008e --- /dev/null +++ b/java/com/hmdzl/spspd/items/armor/glyphs/Crystalglyph.java @@ -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 + */ +package com.hmdzl.spspd.items.armor.glyphs; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.GlassShield; +import com.hmdzl.spspd.items.armor.Armor; +import com.hmdzl.spspd.items.armor.Armor.Glyph; +import com.hmdzl.spspd.items.misc.FourClover; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.sprites.ItemSprite.Glowing; +import com.hmdzl.spspd.actors.buffs.armorbuff.GlyphDark; +import com.hmdzl.spspd.actors.buffs.armorbuff.GlyphEarth; +import com.hmdzl.spspd.actors.buffs.armorbuff.GlyphElectricity; +import com.hmdzl.spspd.actors.buffs.armorbuff.GlyphFire; +import com.hmdzl.spspd.actors.buffs.armorbuff.GlyphIce; +import com.hmdzl.spspd.actors.buffs.armorbuff.GlyphLight; + +import com.watabou.utils.Random; + +public class Crystalglyph extends Glyph { + + private static ItemSprite.Glowing PINK = new ItemSprite.Glowing(0xCCAA88); + + @Override + public int proc(Armor armor, Char attacker, Char defender, int damage) { + GlyphDark gdark = defender.buff(GlyphDark.class); + GlyphIce gice = defender.buff(GlyphIce.class); + GlyphLight glight = defender.buff(GlyphLight.class); + GlyphFire gfire = defender.buff(GlyphFire.class); + GlyphEarth gearth = defender.buff(GlyphEarth.class); + GlyphElectricity gelect = defender.buff(GlyphElectricity.class); + FourClover.FourCloverBless fcb = defender.buff(FourClover.FourCloverBless.class); + if (defender.isAlive() && (gdark != null || gice != null || glight != null || gfire != null || gearth != null || gelect != null )) + { + Buff.detach(defender,GlyphIce.class); + Buff.detach(defender,GlyphLight.class); + Buff.detach(defender,GlyphFire.class); + Buff.detach(defender,GlyphEarth.class); + Buff.detach(defender,GlyphElectricity.class); + Buff.detach(defender,GlyphDark.class); + } + + int level = Math.max(0, armor.level); + if (Random.Int(level / 2 + 6) >= 5 && (damage > 30 || (fcb != null && damage > 15))) { + Buff.affect(defender, GlassShield.class).turns(1); + } + return damage; + } + @Override + public Glowing glowing() { + return PINK; + } +} diff --git a/java/com/hmdzl/spspd/items/armor/glyphs/Darkglyph.java b/java/com/hmdzl/spspd/items/armor/glyphs/Darkglyph.java new file mode 100644 index 00000000..4794bc90 --- /dev/null +++ b/java/com/hmdzl/spspd/items/armor/glyphs/Darkglyph.java @@ -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 + */ +package com.hmdzl.spspd.items.armor.glyphs; + +import android.icu.util.Calendar; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Hunger; +import com.hmdzl.spspd.actors.buffs.Weakness; +import com.hmdzl.spspd.actors.buffs.armorbuff.GlyphDark; +import com.hmdzl.spspd.actors.buffs.armorbuff.GlyphEarth; +import com.hmdzl.spspd.actors.buffs.armorbuff.GlyphElectricity; +import com.hmdzl.spspd.actors.buffs.armorbuff.GlyphFire; +import com.hmdzl.spspd.actors.buffs.armorbuff.GlyphIce; +import com.hmdzl.spspd.actors.buffs.armorbuff.GlyphLight; +import com.hmdzl.spspd.actors.mobs.DwarfLich; +import com.hmdzl.spspd.actors.mobs.Fiend; +import com.hmdzl.spspd.actors.mobs.Warlock; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.armor.Armor; +import com.hmdzl.spspd.items.armor.Armor.Glyph; +import com.hmdzl.spspd.items.misc.FourClover; +import com.hmdzl.spspd.sprites.CharSprite; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.sprites.ItemSprite.Glowing; +import com.hmdzl.spspd.ui.BuffIndicator; +import com.watabou.utils.Random; + +import java.util.HashSet; + +public class Darkglyph extends Glyph { + + private static ItemSprite.Glowing BLACK = new ItemSprite.Glowing( 0x000000 ); + + @Override + public int proc(Armor armor, Char attacker, Char defender, int damage) { + + GlyphDark gdark = defender.buff(GlyphDark.class); + GlyphIce gice = defender.buff(GlyphIce.class); + GlyphLight glight = defender.buff(GlyphLight.class); + GlyphFire gfire = defender.buff(GlyphFire.class); + GlyphEarth gearth = defender.buff(GlyphEarth.class); + GlyphElectricity gelect = defender.buff(GlyphElectricity.class); + FourClover.FourCloverBless fcb = defender.buff(FourClover.FourCloverBless.class); + + if (defender.isAlive() && gdark == null) + { + Buff.detach(defender,GlyphIce.class); + Buff.detach(defender,GlyphLight.class); + Buff.detach(defender,GlyphFire.class); + Buff.detach(defender,GlyphEarth.class); + Buff.detach(defender,GlyphElectricity.class); + Buff.affect(defender,GlyphDark.class); + } + + int level = Math.max(0, armor.level); + if (Random.Int(level / 2 + 5) >= 8 || (fcb != null && Random.Int(level/2 + 5) >= 6)) { + + int healing = Random.Int(attacker.HP/10); + + if (healing > 0) { + defender.HP += Random.Int(Math.min(healing, defender.HT - defender.HP)/2); + defender.sprite.emitter().burst(Speck.factory(Speck.HEALING), 1); + //defender.sprite.showStatus(CharSprite.POSITIVE,Integer.toString(healing)); + attacker.damage(healing, this); + } + } + + return damage; + } + + @Override + public Glowing glowing() { + return BLACK; + } + +} diff --git a/java/com/hmdzl/spspd/items/armor/glyphs/Earthglyph.java b/java/com/hmdzl/spspd/items/armor/glyphs/Earthglyph.java new file mode 100644 index 00000000..252a9f24 --- /dev/null +++ b/java/com/hmdzl/spspd/items/armor/glyphs/Earthglyph.java @@ -0,0 +1,92 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.armor.glyphs; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.DefenceUp; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.particles.EarthParticle; +import com.hmdzl.spspd.items.armor.Armor; +import com.hmdzl.spspd.items.armor.Armor.Glyph; +import com.hmdzl.spspd.items.misc.FourClover; +import com.hmdzl.spspd.plants.Earthroot; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.sprites.ItemSprite.Glowing; + +import com.hmdzl.spspd.actors.buffs.armorbuff.GlyphDark; +import com.hmdzl.spspd.actors.buffs.armorbuff.GlyphEarth; +import com.hmdzl.spspd.actors.buffs.armorbuff.GlyphElectricity; +import com.hmdzl.spspd.actors.buffs.armorbuff.GlyphFire; +import com.hmdzl.spspd.actors.buffs.armorbuff.GlyphIce; +import com.hmdzl.spspd.actors.buffs.armorbuff.GlyphLight; + +import com.watabou.noosa.Camera; +import com.watabou.utils.Random; + +public class Earthglyph extends Glyph { + + private static ItemSprite.Glowing GERY = new ItemSprite.Glowing( 0xCCCCCC); + + @Override + public int proc(Armor armor, Char attacker, Char defender, int damage) { + + GlyphDark gdark = defender.buff(GlyphDark.class); + GlyphIce gice = defender.buff(GlyphIce.class); + GlyphLight glight = defender.buff(GlyphLight.class); + GlyphFire gfire = defender.buff(GlyphFire.class); + GlyphEarth gearth = defender.buff(GlyphEarth.class); + GlyphElectricity gelect = defender.buff(GlyphElectricity.class); + FourClover.FourCloverBless fcb = defender.buff(FourClover.FourCloverBless.class); + + if (defender.isAlive() && gearth == null) + { + Buff.detach(defender,GlyphIce.class); + Buff.detach(defender,GlyphLight.class); + Buff.detach(defender,GlyphFire.class); + Buff.detach(defender,GlyphDark.class); + Buff.detach(defender,GlyphElectricity.class); + Buff.affect(defender,GlyphEarth.class); + } + + int level = Math.max(0, armor.level); + int levelRoots = Math.min(4, armor.level); + + if (Random.Int(4) == 0 ) { + + Buff.affect(defender, Earthroot.Armor.class).level(5 * (level + 1)); + CellEmitter.bottom(defender.pos).start(EarthParticle.FACTORY, + 0.05f, 8); + Camera.main.shake(1, 0.4f); + + } + + if (Random.Int(level + 6) >= 5 || (fcb != null && Random.Int(level + 6) >= 3)) { + Buff.prolong(defender, DefenceUp.class,5f).level(20); + } + + return damage; + + } + + @Override + public Glowing glowing() { + return GERY; + } + +} diff --git a/java/com/hmdzl/spspd/items/armor/glyphs/Electricityglyph.java b/java/com/hmdzl/spspd/items/armor/glyphs/Electricityglyph.java new file mode 100644 index 00000000..2a3edd0d --- /dev/null +++ b/java/com/hmdzl/spspd/items/armor/glyphs/Electricityglyph.java @@ -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 + */ +package com.hmdzl.spspd.items.armor.glyphs; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Paralysis; +import com.hmdzl.spspd.actors.buffs.Recharging; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.particles.EnergyParticle; +import com.hmdzl.spspd.items.armor.Armor; +import com.hmdzl.spspd.items.armor.Armor.Glyph; +import com.hmdzl.spspd.items.misc.FourClover; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.sprites.ItemSprite.Glowing; + +import com.hmdzl.spspd.actors.buffs.armorbuff.GlyphDark; +import com.hmdzl.spspd.actors.buffs.armorbuff.GlyphEarth; +import com.hmdzl.spspd.actors.buffs.armorbuff.GlyphElectricity; +import com.hmdzl.spspd.actors.buffs.armorbuff.GlyphFire; +import com.hmdzl.spspd.actors.buffs.armorbuff.GlyphIce; +import com.hmdzl.spspd.actors.buffs.armorbuff.GlyphLight; + +import com.watabou.utils.Random; + +public class Electricityglyph extends Glyph { + + private static ItemSprite.Glowing WHITE = new ItemSprite.Glowing( 0xFFFFFF); + + @Override + public int proc(Armor armor, Char attacker, Char defender, int damage) { + + GlyphDark gdark = defender.buff(GlyphDark.class); + GlyphIce gice = defender.buff(GlyphIce.class); + GlyphLight glight = defender.buff(GlyphLight.class); + GlyphFire gfire = defender.buff(GlyphFire.class); + GlyphEarth gearth = defender.buff(GlyphEarth.class); + GlyphElectricity gelect = defender.buff(GlyphElectricity.class); + FourClover.FourCloverBless fcb = defender.buff(FourClover.FourCloverBless.class); + + if (defender.isAlive() && gelect == null) + { + Buff.detach(defender,GlyphIce.class); + Buff.detach(defender,GlyphLight.class); + Buff.detach(defender,GlyphFire.class); + Buff.detach(defender,GlyphEarth.class); + Buff.detach(defender,GlyphDark.class); + Buff.affect(defender,GlyphElectricity.class); + } + + int level = Math.max(0, armor.level); + + + if (Random.Int(level) >= 5) { + if (defender instanceof Hero) { + Buff.prolong(defender, Recharging.class, Math.min(level,30)); + } + } + + if (Random.Int(level + 6) >= 5 || (fcb != null && Random.Int(level + 6) >= 3)) { + Buff.prolong(attacker, Paralysis.class, 2f); + CellEmitter.get(attacker.pos).start(EnergyParticle.FACTORY, 0.2f, 6); + } + + return damage; + } + + @Override + public Glowing glowing() { + return WHITE; + } + +} diff --git a/java/com/hmdzl/spspd/items/armor/glyphs/Fireglyph.java b/java/com/hmdzl/spspd/items/armor/glyphs/Fireglyph.java new file mode 100644 index 00000000..aac520e2 --- /dev/null +++ b/java/com/hmdzl/spspd/items/armor/glyphs/Fireglyph.java @@ -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 + */ +package com.hmdzl.spspd.items.armor.glyphs; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.Fire; +import com.hmdzl.spspd.actors.blobs.TarGas; +import com.hmdzl.spspd.actors.buffs.AttackUp; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Burning; +import com.hmdzl.spspd.actors.buffs.Charm; +import com.hmdzl.spspd.actors.buffs.Hot; +import com.hmdzl.spspd.actors.buffs.Tar; +import com.hmdzl.spspd.actors.mobs.FireElemental; +import com.hmdzl.spspd.actors.mobs.Yog; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.effects.particles.FlameParticle; +import com.hmdzl.spspd.items.armor.Armor; +import com.hmdzl.spspd.items.armor.Armor.Glyph; +import com.hmdzl.spspd.items.misc.FourClover; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.sprites.ItemSprite.Glowing; +import com.hmdzl.spspd.actors.buffs.armorbuff.GlyphDark; +import com.hmdzl.spspd.actors.buffs.armorbuff.GlyphEarth; +import com.hmdzl.spspd.actors.buffs.armorbuff.GlyphElectricity; +import com.hmdzl.spspd.actors.buffs.armorbuff.GlyphFire; +import com.hmdzl.spspd.actors.buffs.armorbuff.GlyphIce; +import com.hmdzl.spspd.actors.buffs.armorbuff.GlyphLight; + +import com.watabou.utils.GameMath; +import com.watabou.utils.Random; + +import java.util.HashSet; + +public class Fireglyph extends Glyph { + + private static ItemSprite.Glowing ORANGE = new ItemSprite.Glowing( 0xFF4400 ); + + @Override + public int proc(Armor armor, Char attacker, Char defender, int damage) { + + GlyphDark gdark = defender.buff(GlyphDark.class); + GlyphIce gice = defender.buff(GlyphIce.class); + GlyphLight glight = defender.buff(GlyphLight.class); + GlyphFire gfire = defender.buff(GlyphFire.class); + GlyphEarth gearth = defender.buff(GlyphEarth.class); + GlyphElectricity gelect = defender.buff(GlyphElectricity.class); + FourClover.FourCloverBless fcb = defender.buff(FourClover.FourCloverBless.class); + + if (defender.isAlive() && gfire == null) + { + Buff.detach(defender,GlyphIce.class); + Buff.detach(defender,GlyphLight.class); + Buff.detach(defender,GlyphDark.class); + Buff.detach(defender,GlyphEarth.class); + Buff.detach(defender,GlyphElectricity.class); + Buff.affect(defender,GlyphFire.class); + } + + int level = Math.max(0, armor.level); + + if (Random.Int(level + 6) >= 5 || (fcb != null && Random.Int(level + 6) >= 3)) { + Buff.affect(attacker, Burning.class).reignite( attacker ); + defender.sprite.emitter().burst(FlameParticle.FACTORY, 5); + } + + if (Random.Int(level + 7) >= 6) { + Buff.prolong(defender, AttackUp.class,5f).level(25); + } + + return damage; + } + + @Override + public Glowing glowing() { + return ORANGE; + } + +} diff --git a/java/com/hmdzl/spspd/items/armor/glyphs/Iceglyph.java b/java/com/hmdzl/spspd/items/armor/glyphs/Iceglyph.java new file mode 100644 index 00000000..87ef1e84 --- /dev/null +++ b/java/com/hmdzl/spspd/items/armor/glyphs/Iceglyph.java @@ -0,0 +1,201 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.armor.glyphs; + +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.ResultDescriptions; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Frost; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.particles.SnowParticle; +import com.hmdzl.spspd.items.armor.Armor; +import com.hmdzl.spspd.items.armor.Armor.Glyph; +import com.hmdzl.spspd.items.misc.FourClover; +import com.hmdzl.spspd.sprites.CharSprite; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.sprites.ItemSprite.Glowing; +import com.hmdzl.spspd.ui.BuffIndicator; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.actors.buffs.armorbuff.GlyphDark; +import com.hmdzl.spspd.actors.buffs.armorbuff.GlyphEarth; +import com.hmdzl.spspd.actors.buffs.armorbuff.GlyphElectricity; +import com.hmdzl.spspd.actors.buffs.armorbuff.GlyphFire; +import com.hmdzl.spspd.actors.buffs.armorbuff.GlyphIce; +import com.hmdzl.spspd.actors.buffs.armorbuff.GlyphLight; + +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public class Iceglyph extends Glyph { + + private static ItemSprite.Glowing BLUE = new ItemSprite.Glowing(0x0000FF); + + @Override + public int proc(Armor armor, Char attacker, Char defender, int damage) { + + GlyphDark gdark = defender.buff(GlyphDark.class); + GlyphIce gice = defender.buff(GlyphIce.class); + GlyphLight glight = defender.buff(GlyphLight.class); + GlyphFire gfire = defender.buff(GlyphFire.class); + GlyphEarth gearth = defender.buff(GlyphEarth.class); + GlyphElectricity gelect = defender.buff(GlyphElectricity.class); + FourClover.FourCloverBless fcb = defender.buff(FourClover.FourCloverBless.class); + + if (defender.isAlive() && gice == null) + { + Buff.detach(defender,GlyphDark.class); + Buff.detach(defender,GlyphLight.class); + Buff.detach(defender,GlyphFire.class); + Buff.detach(defender,GlyphEarth.class); + Buff.detach(defender,GlyphElectricity.class); + Buff.affect(defender,GlyphIce.class); + } + + if (damage == 0) { + return 0; + } + + int level = Math.max(0, armor.level); + + if (Random.Int(level + 6) >= 5 || (fcb != null && Random.Int(level + 6) >= 3)) { + Buff.prolong(attacker, Frost.class, Frost.duration(attacker)* Random.Float(1f, 1.5f)); + CellEmitter.get(attacker.pos).start(SnowParticle.FACTORY, 0.2f, 6); + } + + if (Random.Int(level + 7) >= 6) { + DeferedDamage debuff = defender.buff(DeferedDamage.class); + if (debuff == null) { + debuff = new DeferedDamage(); + debuff.attachTo(defender); + } + debuff.prolong(damage); + + defender.sprite.showStatus(CharSprite.WARNING, Messages.get(this, "deferred", damage)); + + return 0; + + } else { + return damage; + } + + } + + //private static final HashSet> RESISTANCES = new HashSet>(); + //private static final HashSet> IMMUNITIES = new HashSet>(); + //static { + //RESISTANCES.add( Frost.class ); + //RESISTANCES.add( Cold.class ); + //RESISTANCES.add( Chill.class ); + //IMMUNITIES.add(WeatherOfSnow.class ); + + //RESISTS.add( DisintegrationTrap.class ); + //RESISTS.add( GrimTrap.class ); + + //RESISTS.add( Shaman.class ); + //RESISTS.add( Warlock.class ); + //RESISTS.add( Eye.class ); + //RESISTS.add( Yog.BurningFist.class ); + //} + + + @Override + public Glowing glowing() { + return BLUE; + } + + public static class DeferedDamage extends Buff { + + protected int damage = 0; + + private static final String DAMAGE = "damage"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(DAMAGE, damage); + + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + damage = bundle.getInt(DAMAGE); + } + + @Override + public boolean attachTo(Char target) { + if (super.attachTo(target)) { + postpone(TICK); + return true; + } else { + return false; + } + } + + public void prolong(int damage) { + this.damage += damage; + }; + + @Override + public int icon() { + return BuffIndicator.DEFERRED; + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public boolean act() { + if (target.isAlive()) { + + int damageThisTick = Math.max(1, (int)(damage*0.1f)); + target.damage( damageThisTick, this ); + if (target == Dungeon.hero && !target.isAlive()) { + + Glyph glyph = new Iceglyph(); + Dungeon.fail(Messages.format(ResultDescriptions.GLYPH)); + //GLog.n("%s killed you...", glyph.name()); + + Badges.validateDeathFromGlyph(); + } + spend(TICK); + + damage -= damageThisTick; + if (--damage <= 0) { + detach(); + } + + } else { + + detach(); + + } + + return true; + } + @Override + public String desc() { + return Messages.get(this, "desc", damage); + } + + } +} diff --git a/java/com/hmdzl/spspd/items/armor/glyphs/Lightglyph.java b/java/com/hmdzl/spspd/items/armor/glyphs/Lightglyph.java new file mode 100644 index 00000000..854debf7 --- /dev/null +++ b/java/com/hmdzl/spspd/items/armor/glyphs/Lightglyph.java @@ -0,0 +1,95 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.armor.glyphs; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Amok; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Charm; +import com.hmdzl.spspd.actors.buffs.Frost; +import com.hmdzl.spspd.actors.buffs.Terror; +import com.hmdzl.spspd.actors.mobs.SewerHeart; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.effects.particles.SnowParticle; +import com.hmdzl.spspd.items.armor.Armor; +import com.hmdzl.spspd.items.armor.Armor.Glyph; +import com.hmdzl.spspd.items.misc.FourClover; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.sprites.ItemSprite.Glowing; +import com.hmdzl.spspd.actors.buffs.armorbuff.GlyphDark; +import com.hmdzl.spspd.actors.buffs.armorbuff.GlyphEarth; +import com.hmdzl.spspd.actors.buffs.armorbuff.GlyphElectricity; +import com.hmdzl.spspd.actors.buffs.armorbuff.GlyphFire; +import com.hmdzl.spspd.actors.buffs.armorbuff.GlyphIce; +import com.hmdzl.spspd.actors.buffs.armorbuff.GlyphLight; +import com.watabou.utils.GameMath; +import com.watabou.utils.Random; + +import java.util.HashSet; + +public class Lightglyph extends Glyph { + + private static ItemSprite.Glowing YELLOW = new ItemSprite.Glowing( 0xFFFF44 ); + + @Override + public int proc(Armor armor, Char attacker, Char defender, int damage) { + + GlyphDark gdark = defender.buff(GlyphDark.class); + GlyphIce gice = defender.buff(GlyphIce.class); + GlyphLight glight = defender.buff(GlyphLight.class); + GlyphFire gfire = defender.buff(GlyphFire.class); + GlyphEarth gearth = defender.buff(GlyphEarth.class); + GlyphElectricity gelect = defender.buff(GlyphElectricity.class); + FourClover.FourCloverBless fcb = defender.buff(FourClover.FourCloverBless.class); + + if (defender.isAlive() && glight == null) + { + Buff.detach(defender,GlyphIce.class); + Buff.detach(defender,GlyphDark.class); + Buff.detach(defender,GlyphFire.class); + Buff.detach(defender,GlyphEarth.class); + Buff.detach(defender,GlyphElectricity.class); + Buff.affect(defender,GlyphLight.class); + } + + int level = (int) GameMath.gate(0, armor.level, 6); + + if (Random.Int(level / 2 + 5) >= 4) { + + int duration = Random.IntRange(4, 7); + Buff.affect(attacker, Charm.class, Charm.durationFactor(attacker) + * duration).object = defender.id(); + Buff.affect(attacker, Amok.class,10f); + attacker.sprite.centerEmitter().start(Speck.factory(Speck.HEART),0.2f, 5); + } + + else if (Random.Int(level / 2 + 5) >= 3 || (fcb != null && Random.Int(level/2 + 5) >= 1)) { + Buff.affect(attacker, Terror.class, 10f).object = defender.id(); + } + + return damage; + } + + @Override + public Glowing glowing() { + return YELLOW; + } + +} diff --git a/java/com/hmdzl/spspd/items/armor/glyphs/RecoilGlyph.java b/java/com/hmdzl/spspd/items/armor/glyphs/RecoilGlyph.java new file mode 100644 index 00000000..b3875c1f --- /dev/null +++ b/java/com/hmdzl/spspd/items/armor/glyphs/RecoilGlyph.java @@ -0,0 +1,85 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.armor.glyphs; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Bleeding; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.items.armor.Armor; +import com.hmdzl.spspd.items.armor.Armor.Glyph; +import com.hmdzl.spspd.items.misc.FourClover; +import com.hmdzl.spspd.items.wands.WandOfFlow; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.sprites.ItemSprite.Glowing; +import com.hmdzl.spspd.actors.buffs.armorbuff.GlyphDark; +import com.hmdzl.spspd.actors.buffs.armorbuff.GlyphEarth; +import com.hmdzl.spspd.actors.buffs.armorbuff.GlyphElectricity; +import com.hmdzl.spspd.actors.buffs.armorbuff.GlyphFire; +import com.hmdzl.spspd.actors.buffs.armorbuff.GlyphIce; +import com.hmdzl.spspd.actors.buffs.armorbuff.GlyphLight; +import com.watabou.utils.Random; + +public class RecoilGlyph extends Glyph { + + private static ItemSprite.Glowing BROWN = new ItemSprite.Glowing(0xCC6600); + + @Override + public int proc(Armor armor, Char attacker, Char defender, int damage) { + + GlyphDark gdark = defender.buff(GlyphDark.class); + GlyphIce gice = defender.buff(GlyphIce.class); + GlyphLight glight = defender.buff(GlyphLight.class); + GlyphFire gfire = defender.buff(GlyphFire.class); + GlyphEarth gearth = defender.buff(GlyphEarth.class); + GlyphElectricity gelect = defender.buff(GlyphElectricity.class); + FourClover.FourCloverBless fcb = defender.buff(FourClover.FourCloverBless.class); + + if (defender.isAlive() && (gdark != null || gice != null || glight != null || gfire != null || gearth != null || gelect != null )) + { + Buff.detach(defender,GlyphIce.class); + Buff.detach(defender,GlyphLight.class); + Buff.detach(defender,GlyphFire.class); + Buff.detach(defender,GlyphEarth.class); + Buff.detach(defender,GlyphElectricity.class); + Buff.detach(defender,GlyphDark.class); + } + + int level = Math.max(0, armor.level); + + if (Random.Int( level + 5 ) >= 4 || (fcb != null && Random.Int(level + 5) >= 2)){ + int oppositeHero = attacker.pos + (attacker.pos - defender.pos); + Ballistica trajectory = new Ballistica(attacker.pos, oppositeHero, Ballistica.MAGIC_BOLT); + WandOfFlow.throwChar(attacker, trajectory, 2); + } + + if ( Random.Int( level/2 + 5) >= 4) { + + Buff.affect( attacker, Bleeding.class).set( Math.max( level/2, damage)); + + } + + return damage; + } + + @Override + public Glowing glowing() { + return BROWN; + } + +} diff --git a/java/com/hmdzl/spspd/items/armor/glyphs/Revivalglyph.java b/java/com/hmdzl/spspd/items/armor/glyphs/Revivalglyph.java new file mode 100644 index 00000000..cb6a6cc4 --- /dev/null +++ b/java/com/hmdzl/spspd/items/armor/glyphs/Revivalglyph.java @@ -0,0 +1,78 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.armor.glyphs; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.armor.Armor; +import com.hmdzl.spspd.items.armor.Armor.Glyph; +import com.hmdzl.spspd.items.misc.FourClover; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.sprites.ItemSprite.Glowing; +import com.hmdzl.spspd.utils.GLog; +import com.hmdzl.spspd.actors.buffs.armorbuff.GlyphDark; +import com.hmdzl.spspd.actors.buffs.armorbuff.GlyphEarth; +import com.hmdzl.spspd.actors.buffs.armorbuff.GlyphElectricity; +import com.hmdzl.spspd.actors.buffs.armorbuff.GlyphFire; +import com.hmdzl.spspd.actors.buffs.armorbuff.GlyphIce; +import com.hmdzl.spspd.actors.buffs.armorbuff.GlyphLight; +import com.watabou.utils.Random; + +public class Revivalglyph extends Glyph { + + private static ItemSprite.Glowing RED = new ItemSprite.Glowing(0xCC0000); + + @Override + public int proc(Armor armor, Char attacker, Char defender, int damage) { + + GlyphDark gdark = defender.buff(GlyphDark.class); + GlyphIce gice = defender.buff(GlyphIce.class); + GlyphLight glight = defender.buff(GlyphLight.class); + GlyphFire gfire = defender.buff(GlyphFire.class); + GlyphEarth gearth = defender.buff(GlyphEarth.class); + GlyphElectricity gelect = defender.buff(GlyphElectricity.class); + FourClover.FourCloverBless fcb = defender.buff(FourClover.FourCloverBless.class); + + if (defender.isAlive() && (gdark != null || gice != null || glight != null || gfire != null || gearth != null || gelect != null )) + { + Buff.detach(defender,GlyphIce.class); + Buff.detach(defender,GlyphLight.class); + Buff.detach(defender,GlyphFire.class); + Buff.detach(defender,GlyphEarth.class); + Buff.detach(defender,GlyphElectricity.class); + Buff.detach(defender,GlyphDark.class); + } + + int level = Math.max(0, armor.level); + if (damage > defender.HP && (Math.min(level*1.5,45) > Random.Int(100) || (fcb != null && Math.min(level*1.5,45) > Random.Int(90)))){ + defender.HP = defender.HT; + CellEmitter.get(defender.pos).start(Speck.factory(Speck.LIGHT), 0.2f, 3); + GLog.w(Messages.get(this, "revive")); + return 0; + } + return damage; + } + + @Override + public Glowing glowing() { + return RED; + } +} diff --git a/java/com/hmdzl/spspd/items/armor/glyphs/Testglyph.java b/java/com/hmdzl/spspd/items/armor/glyphs/Testglyph.java new file mode 100644 index 00000000..e32f3c99 --- /dev/null +++ b/java/com/hmdzl/spspd/items/armor/glyphs/Testglyph.java @@ -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 + */ +package com.hmdzl.spspd.items.armor.glyphs; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.Blob; +import com.hmdzl.spspd.actors.blobs.ConfusionGas; +import com.hmdzl.spspd.actors.blobs.DarkGas; +import com.hmdzl.spspd.actors.blobs.ParalyticGas; +import com.hmdzl.spspd.actors.blobs.StenchGas; +import com.hmdzl.spspd.actors.blobs.TarGas; +import com.hmdzl.spspd.actors.blobs.ToxicGas; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.GasesImmunity; +import com.hmdzl.spspd.items.armor.Armor; +import com.hmdzl.spspd.items.armor.Armor.Glyph; +import com.hmdzl.spspd.items.misc.FourClover; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.sprites.ItemSprite.Glowing; +import com.hmdzl.spspd.actors.buffs.armorbuff.GlyphDark; +import com.hmdzl.spspd.actors.buffs.armorbuff.GlyphEarth; +import com.hmdzl.spspd.actors.buffs.armorbuff.GlyphElectricity; +import com.hmdzl.spspd.actors.buffs.armorbuff.GlyphFire; +import com.hmdzl.spspd.actors.buffs.armorbuff.GlyphIce; +import com.hmdzl.spspd.actors.buffs.armorbuff.GlyphLight; +import com.watabou.utils.Random; + +public class Testglyph extends Glyph { + + private static ItemSprite.Glowing GREEN = new ItemSprite.Glowing(0x22CC44); + + @Override + public int proc(Armor armor, Char attacker, Char defender, int damage) { + + GlyphDark gdark = defender.buff(GlyphDark.class); + GlyphIce gice = defender.buff(GlyphIce.class); + GlyphLight glight = defender.buff(GlyphLight.class); + GlyphFire gfire = defender.buff(GlyphFire.class); + GlyphEarth gearth = defender.buff(GlyphEarth.class); + GlyphElectricity gelect = defender.buff(GlyphElectricity.class); + FourClover.FourCloverBless fcb = defender.buff(FourClover.FourCloverBless.class); + + if (defender.isAlive() && (gdark != null || gice != null || glight != null || gfire != null || gearth != null || gelect != null )) + { + Buff.detach(defender,GlyphIce.class); + Buff.detach(defender,GlyphLight.class); + Buff.detach(defender,GlyphFire.class); + Buff.detach(defender,GlyphEarth.class); + Buff.detach(defender,GlyphElectricity.class); + Buff.detach(defender,GlyphDark.class); + } + + int level = Math.max(0, armor.level); + + if (Random.Int(level + 5) >= 4 || (fcb != null && Random.Int(level + 5) >= 2)) { + Buff.prolong(defender, GasesImmunity.class, GasesImmunity.DURATION); + + switch (Random.Int (6)) { + case 0: + GameScene.add(Blob.seed(attacker.pos, 25, ToxicGas.class)); + break; + case 1: + GameScene.add(Blob.seed(attacker.pos, 25, ConfusionGas.class)); + break; + case 2: + GameScene.add(Blob.seed(attacker.pos, 25, ParalyticGas.class)); + break; + case 3: + GameScene.add(Blob.seed(attacker.pos, 25, DarkGas.class)); + break; + case 4: + GameScene.add(Blob.seed(attacker.pos, 25, TarGas.class)); + break; + case 5: + GameScene.add(Blob.seed(attacker.pos, 25, StenchGas.class)); + break; + default: + break; + } + } + return damage; + } + + @Override + public Glowing glowing() { + return GREEN; + } + +} diff --git a/java/com/hmdzl/spspd/items/armor/normalarmor/BaseArmor.java b/java/com/hmdzl/spspd/items/armor/normalarmor/BaseArmor.java new file mode 100644 index 00000000..0000e24f --- /dev/null +++ b/java/com/hmdzl/spspd/items/armor/normalarmor/BaseArmor.java @@ -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 + */ +package com.hmdzl.spspd.items.armor.normalarmor; + +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class BaseArmor extends NormalArmor { + + { + //name = "base armor"; + image = ItemSpriteSheet.ERROR_ARMOR; + MAX = 0; + MIN = 0; + } + + public BaseArmor() { + super(0,1f,1f,4); + } + + @Override + public Item upgrade(boolean hasglyph) { + MIN --; + MAX-=3; + + return super.upgrade(hasglyph); + } + + /*@Override + public int proc(Char attacker, Char defender, int damage) { + + if (glyph != null) { + glyph.proc(this, attacker, defender, damage); + } ; + return damage; + };*/ +} diff --git a/java/com/hmdzl/spspd/items/armor/normalarmor/BulletArmor.java b/java/com/hmdzl/spspd/items/armor/normalarmor/BulletArmor.java new file mode 100644 index 00000000..4bb0e660 --- /dev/null +++ b/java/com/hmdzl/spspd/items/armor/normalarmor/BulletArmor.java @@ -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 + */ +package com.hmdzl.spspd.items.armor.normalarmor; + +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class BulletArmor extends NormalArmor { + + { + //name = "bulletproof armor"; + image = ItemSpriteSheet.BULLET_ARMOR; + STR += 1; + MAX = 46; + MIN = 10; + } + + public BulletArmor() { + super(5,0.2f,-1f,2); + } + + @Override + public Item upgrade(boolean hasglyph) { + MIN += 1; + MAX += 2; + return super.upgrade(hasglyph); + } +} diff --git a/java/com/hmdzl/spspd/items/armor/normalarmor/CDArmor.java b/java/com/hmdzl/spspd/items/armor/normalarmor/CDArmor.java new file mode 100644 index 00000000..211b248f --- /dev/null +++ b/java/com/hmdzl/spspd/items/armor/normalarmor/CDArmor.java @@ -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 + */ +package com.hmdzl.spspd.items.armor.normalarmor; + +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class CDArmor extends NormalArmor { + + { + //name = "cd armor"; + image = ItemSpriteSheet.CD_ARMOR; + STR -= 1; + MAX = 15; + MIN = 0; + } + + public CDArmor() { + super(3,3.2f,8f,3); + } + + @Override + public Item upgrade(boolean hasglyph) { + MIN -= 1; + MAX -= 1; + return super.upgrade(hasglyph); + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/armor/normalarmor/CeramicsArmor.java b/java/com/hmdzl/spspd/items/armor/normalarmor/CeramicsArmor.java new file mode 100644 index 00000000..f8fa4129 --- /dev/null +++ b/java/com/hmdzl/spspd/items/armor/normalarmor/CeramicsArmor.java @@ -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 + */ +package com.hmdzl.spspd.items.armor.normalarmor; + +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class CeramicsArmor extends NormalArmor { + + { + //name = "ceramics armor"; + image = ItemSpriteSheet.CERAMICS_ARMOR; + STR += 1; + MAX = 18; + MIN = 4; + } + + public CeramicsArmor() { + super(2,0.8f,0.5f,3); + } + + @Override + public Item upgrade(boolean hasglyph) { + MIN += 1; + //MAX += 0; + return super.upgrade(hasglyph); + } +} diff --git a/java/com/hmdzl/spspd/items/armor/normalarmor/ClothArmor.java b/java/com/hmdzl/spspd/items/armor/normalarmor/ClothArmor.java new file mode 100644 index 00000000..8424a46f --- /dev/null +++ b/java/com/hmdzl/spspd/items/armor/normalarmor/ClothArmor.java @@ -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 + */ +package com.hmdzl.spspd.items.armor.normalarmor; + +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class ClothArmor extends NormalArmor { + + { + //name = "cloth armor"; + image = ItemSpriteSheet.ARMOR_CLOTH; + } + + public ClothArmor() { + super(1,2f,6f,3); + } + /*@Override + public int proc(Char attacker, Char defender, int damage) { + + if (glyph != null) { + glyph.proc(this, attacker, defender, damage); + } ; + return damage; + };*/ +} diff --git a/java/com/hmdzl/spspd/items/armor/normalarmor/DiscArmor.java b/java/com/hmdzl/spspd/items/armor/normalarmor/DiscArmor.java new file mode 100644 index 00000000..083cf03b --- /dev/null +++ b/java/com/hmdzl/spspd/items/armor/normalarmor/DiscArmor.java @@ -0,0 +1,34 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.armor.normalarmor; + +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.messages.Messages; + +public class DiscArmor extends NormalArmor { + + { + //name = "disc armor"; + image = ItemSpriteSheet.ARMOR_DISC; + } + + public DiscArmor() { + super(3,1.6f,4f,4); + } + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/armor/normalarmor/ErrorArmor.java b/java/com/hmdzl/spspd/items/armor/normalarmor/ErrorArmor.java new file mode 100644 index 00000000..52c94b0c --- /dev/null +++ b/java/com/hmdzl/spspd/items/armor/normalarmor/ErrorArmor.java @@ -0,0 +1,107 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.armor.normalarmor; + +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.ArmorBreak; +import com.hmdzl.spspd.actors.buffs.AttackDown; +import com.hmdzl.spspd.actors.buffs.Bleeding; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.GrowSeed; +import com.hmdzl.spspd.actors.buffs.Ooze; +import com.hmdzl.spspd.actors.buffs.Shocked; +import com.hmdzl.spspd.actors.buffs.Terror; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.effects.particles.ShadowParticle; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.utils.Random; + +public class ErrorArmor extends NormalArmor { + + { + //name = "error armor"; + image = ItemSpriteSheet.ERROR_ARMOR; + STR = 0; + MAX = 0; + MIN = 0; + } + + public ErrorArmor() { + super(0,1f,1f,10); + } + + @Override + public Item upgrade(boolean hasglyph) { + MIN --; + MAX-=3; + + return super.upgrade(hasglyph); + } + + + @Override + public void proc(Char attacker, Char defender, int damage) { + + switch (Random.Int (10)) { + case 0 : + if (attacker.properties().contains(Char.Property.BOSS) || attacker.properties().contains(Char.Property.MINIBOSS)){ + attacker.damage(Random.Int(attacker.HT/8, attacker.HT/4), this);} + else attacker.damage(Random.Int(attacker.HT, attacker.HT * 2), this); + attacker.sprite.emitter().burst(ShadowParticle.UP, 5); + if (!defender.isAlive() && attacker instanceof Hero) { + Badges.validateGrimWeapon(); + } + break; + case 1 : + Buff.affect(attacker, Bleeding.class).set(5); + break; + case 2 : + Buff.affect(attacker, Ooze.class); + break; + case 3 : + Buff.affect(attacker, Terror.class, Terror.DURATION).object = defender.id(); + break; + case 4 : + if (defender.HP < defender.HT){ + defender.HP += (int)((defender.HT)/10); + defender.sprite.emitter().start(Speck.factory(Speck.HEALING), 0.4f,1);} + break; + case 5 : + Buff.prolong(attacker, AttackDown.class, 5f).level(35); + break; + case 6 : + Buff.prolong(attacker, ArmorBreak.class, 5f).level(35); + break; + case 7 : + Buff.affect(attacker, GrowSeed.class).reignite(attacker); + break; + case 8 : + Buff.affect(attacker, Shocked.class); + break; + default: + break; + } + + if (glyph != null) { + glyph.proc(this, attacker, defender, damage); + } ; + }; +} diff --git a/java/com/hmdzl/spspd/items/armor/normalarmor/LeatherArmor.java b/java/com/hmdzl/spspd/items/armor/normalarmor/LeatherArmor.java new file mode 100644 index 00000000..32e6238a --- /dev/null +++ b/java/com/hmdzl/spspd/items/armor/normalarmor/LeatherArmor.java @@ -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 + */ +package com.hmdzl.spspd.items.armor.normalarmor; + +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.messages.Messages; + +public class LeatherArmor extends NormalArmor { + + { + //name = "leather armor"; + image = ItemSpriteSheet.ARMOR_LEATHER; + } + + public LeatherArmor() { + super(2,1.8f,5f,3); + } +} diff --git a/java/com/hmdzl/spspd/items/armor/normalarmor/LifeArmor.java b/java/com/hmdzl/spspd/items/armor/normalarmor/LifeArmor.java new file mode 100644 index 00000000..46f8f620 --- /dev/null +++ b/java/com/hmdzl/spspd/items/armor/normalarmor/LifeArmor.java @@ -0,0 +1,153 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.armor.normalarmor; + +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.ArmorBreak; +import com.hmdzl.spspd.actors.buffs.AttackDown; +import com.hmdzl.spspd.actors.buffs.Bleeding; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.GrowSeed; +import com.hmdzl.spspd.actors.buffs.Ooze; +import com.hmdzl.spspd.actors.buffs.Shocked; +import com.hmdzl.spspd.actors.buffs.Terror; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.effects.particles.ShadowParticle; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public class LifeArmor extends NormalArmor { + + public Buff passiveBuff; + { + //name = "life armor"; + image = ItemSpriteSheet.LIVE_ARMOR; + MAX = 0; + MIN = 0; + } + + public LifeArmor() { + super(1,2,5,3); + } + + public int charge = 0; + public int time = 0; + private static final String CHARGE = "charge"; + private static final String TIME = "time"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(CHARGE, charge); + bundle.put(TIME, time); + } + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + time = bundle.getInt(TIME); + } + + protected LifeBuff passiveBuff() { + return new LifeCharge(); + } + public class LifeBuff extends Buff { + public int level() { + return level; + } + public boolean isCursed() { + return cursed; + } + } + @Override + public boolean doEquip(Hero hero) { + activate(hero); + return super.doEquip(hero); + } + @Override + public void activate(Hero hero) { + passiveBuff = passiveBuff(); + passiveBuff.attachTo(hero); + } + + @Override + public boolean doUnequip(Hero hero, boolean collect, boolean single) { + if (super.doUnequip(hero, collect, single)) { + if (passiveBuff != null){ + passiveBuff.detach(); + passiveBuff = null; + } + hero.belongings.armor = null; + return true; + } else { + return false; + } + } + + public class LifeCharge extends LifeBuff { + @Override + public boolean act() { + if (time > 1) { + time--; + } else { + Dungeon.hero.HP += charge; + charge = 0; + } + + if (charge>=LifeArmor.this.MAX){ + LifeArmor.this.MAX = charge; + } else LifeArmor.this.MAX = 0; + spend(TICK); + return true; + } + @Override + public String toString() { + return "LifeCharge"; + } + @Override + public void detach() { + charge = 0; + time = 0; + super.detach(); + } + } + + @Override + public Item upgrade(boolean hasglyph) { + + MAX-=2; + + return super.upgrade(hasglyph); + } + + + @Override + public void proc(Char attacker, Char defender, int damage) { + + charge += damage; + time = 20; + + if (glyph != null) { + glyph.proc(this, attacker, defender, damage); + } ; + }; +} diff --git a/java/com/hmdzl/spspd/items/armor/normalarmor/MachineArmor.java b/java/com/hmdzl/spspd/items/armor/normalarmor/MachineArmor.java new file mode 100644 index 00000000..1ae64f8c --- /dev/null +++ b/java/com/hmdzl/spspd/items/armor/normalarmor/MachineArmor.java @@ -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 + */ +package com.hmdzl.spspd.items.armor.normalarmor; + +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class MachineArmor extends NormalArmor { + + { + //name = "machine armor"; + image = ItemSpriteSheet.MECH_ARMOR; + STR += 1; + MAX = 60; + MIN = 15; + } + + public MachineArmor() { + super(6,0,-2,1); + } + + @Override + public Item upgrade(boolean hasglyph) { + MIN += 2; + MAX += 2; + return super.upgrade(hasglyph); + } +} diff --git a/java/com/hmdzl/spspd/items/armor/normalarmor/MailArmor.java b/java/com/hmdzl/spspd/items/armor/normalarmor/MailArmor.java new file mode 100644 index 00000000..bb76094a --- /dev/null +++ b/java/com/hmdzl/spspd/items/armor/normalarmor/MailArmor.java @@ -0,0 +1,34 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.armor.normalarmor; + +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.messages.Messages; + +public class MailArmor extends NormalArmor { + + { + //name = "mail armor"; + image = ItemSpriteSheet.ARMOR_MAIL; + } + + public MailArmor() { + super(4,1.4f,3f,4); + } + +} diff --git a/java/com/hmdzl/spspd/items/armor/normalarmor/MultiplelayerArmor.java b/java/com/hmdzl/spspd/items/armor/normalarmor/MultiplelayerArmor.java new file mode 100644 index 00000000..6bdfc882 --- /dev/null +++ b/java/com/hmdzl/spspd/items/armor/normalarmor/MultiplelayerArmor.java @@ -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 + */ +package com.hmdzl.spspd.items.armor.normalarmor; + +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class MultiplelayerArmor extends NormalArmor { + + { + //name = "Multiplelayer Armor"; + image = ItemSpriteSheet.MUL_ARMOR; + STR += 1; + MAX = 36; + MIN = 8; + } + + public MultiplelayerArmor() { + super(4,0.4f,-0.5f,3); + } + + @Override + public Item upgrade(boolean hasglyph) { + MIN += 1; + MAX += 1; + return super.upgrade(hasglyph); + } +} diff --git a/java/com/hmdzl/spspd/items/armor/normalarmor/NormalArmor.java b/java/com/hmdzl/spspd/items/armor/normalarmor/NormalArmor.java new file mode 100644 index 00000000..4590aaf3 --- /dev/null +++ b/java/com/hmdzl/spspd/items/armor/normalarmor/NormalArmor.java @@ -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 + */ +package com.hmdzl.spspd.items.armor.normalarmor; + +import java.text.DecimalFormat; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.items.armor.Armor; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.items.Item; + + +public class NormalArmor extends Armor { + + private int tier; + public NormalArmor(int tier, float dex, float ste, int eng) { + super(); + + this.tier = tier; + + DEX = dex; + STE = ste; + ENG = eng; + + STR = typicalSTR(); + + MIN = min(); + MAX = max(); + } + + private int min() { + return 0; + } + + private int max() { + return (int) ( 8*tier - 4 ); + } + + + + @Override + public Item upgrade() { + return upgrade(false); + } + + @Override + public Item upgrade(boolean hasglyph) { + MIN +=1; + MAX +=3; + return super.upgrade(hasglyph); + } + + public Item safeUpgrade() { + return upgrade(glyph != null); + } + + + @Override + public Item degrade() { + return super.degrade(); + } + + public int typicalSTR() { + return 8 + tier * 2; + } + + @Override + public String info() { + String name = name(); + + String info = desc(); + + if (levelKnown) { + info += "\n\n" + Messages.get(NormalArmor.class, "stats_known", tier, MIN, MAX, STR); + info += "\n\n" + Messages.get(NormalArmor.class, "stats_known2",new DecimalFormat("#.##").format(DEX), new DecimalFormat("#.##").format(STE), ENG); + } else { + info += "\n\n" + Messages.get(NormalArmor.class, "stats_unknown", tier, min(), max(), typicalSTR()); + } + + String stats_desc = Messages.get(this, "stats_desc"); + if (!stats_desc.equals("")) info+= "\n\n" + stats_desc; + + if (glyph != null) { + info += "\n\n" + Messages.get(NormalArmor.class, "inscribed",glyph.desc()); + } + + if (reinforced) { + info += "\n\n" + Messages.get(Item.class, "reinforced"); + } + + if (levelKnown && STR() > Dungeon.hero.STR()) { + info += "\n\n" + Messages.get(NormalArmor.class, "too_heavy"); + } + + if (cursed && isEquipped( Dungeon.hero )) { + info += "\n\n" + Messages.get(NormalArmor.class, "cursed_worn"); + } else if (cursedKnown && cursed) { + info += "\n\n" + Messages.get(NormalArmor.class, "cursed"); + } + + return info; + } + + @Override + public int price() { + int price = 100; + if (glyph != null) { + price *= 1.5; + } + if (cursed && cursedKnown) { + price /= 2; + } + if (levelKnown) { + if (level > 0) { + price *= (level + 1); + } else if (level < 0) { + price /= (1 - level); + } + } + if (price < 1) { + price = 1; + } + return price; + + } + + } \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/armor/normalarmor/PhantomArmor.java b/java/com/hmdzl/spspd/items/armor/normalarmor/PhantomArmor.java new file mode 100644 index 00000000..704ce1fc --- /dev/null +++ b/java/com/hmdzl/spspd/items/armor/normalarmor/PhantomArmor.java @@ -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 + */ +package com.hmdzl.spspd.items.armor.normalarmor; + +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class PhantomArmor extends NormalArmor { + + { + //name = "phantom armor"; + image = ItemSpriteSheet.PHANTOM_ARMOR; + STR -= 1; + MAX = 35; + MIN = 0; + } + + public PhantomArmor() { + super(6,2f,2f,2); + } + + @Override + public Item upgrade(boolean hasglyph) { + MIN -= 1; + return super.upgrade(hasglyph); + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/armor/normalarmor/PlateArmor.java b/java/com/hmdzl/spspd/items/armor/normalarmor/PlateArmor.java new file mode 100644 index 00000000..67d88bff --- /dev/null +++ b/java/com/hmdzl/spspd/items/armor/normalarmor/PlateArmor.java @@ -0,0 +1,34 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.armor.normalarmor; + +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.messages.Messages; + +public class PlateArmor extends NormalArmor { + + { + //name = "plate armor"; + image = ItemSpriteSheet.ARMOR_PLATE; + } + + public PlateArmor() { + super(6,1.2f,1f,3); + } + +} diff --git a/java/com/hmdzl/spspd/items/armor/normalarmor/ProtectiveclothingArmor.java b/java/com/hmdzl/spspd/items/armor/normalarmor/ProtectiveclothingArmor.java new file mode 100644 index 00000000..34e3d66b --- /dev/null +++ b/java/com/hmdzl/spspd/items/armor/normalarmor/ProtectiveclothingArmor.java @@ -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 + */ +package com.hmdzl.spspd.items.armor.normalarmor; + +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class ProtectiveclothingArmor extends NormalArmor { + + { + //name = "protectiveclothing armor"; + image = ItemSpriteSheet.PRO_ARMOR; + STR -= 1; + MAX = 30; + MIN = 0; + } + + public ProtectiveclothingArmor() { + super(5,2.4f,4f,3); + } + + @Override + public Item upgrade(boolean hasglyph) { + MIN -= 1; + return super.upgrade(hasglyph); + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/armor/normalarmor/RubberArmor.java b/java/com/hmdzl/spspd/items/armor/normalarmor/RubberArmor.java new file mode 100644 index 00000000..75781ec6 --- /dev/null +++ b/java/com/hmdzl/spspd/items/armor/normalarmor/RubberArmor.java @@ -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 + */ +package com.hmdzl.spspd.items.armor.normalarmor; + +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class RubberArmor extends NormalArmor { + + { + //name = "rubber armor"; + image = ItemSpriteSheet.RUBBER_ARMOR; + STR -= 1; + MAX = 8; + MIN = 0; + } + + public RubberArmor() { + super(2,3.6f,10f,2); + } + + @Override + public Item upgrade(boolean hasglyph) { + MIN -= 1; + MAX -= 2; + return super.upgrade(hasglyph); + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/armor/normalarmor/ScaleArmor.java b/java/com/hmdzl/spspd/items/armor/normalarmor/ScaleArmor.java new file mode 100644 index 00000000..100f9422 --- /dev/null +++ b/java/com/hmdzl/spspd/items/armor/normalarmor/ScaleArmor.java @@ -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 + */ +package com.hmdzl.spspd.items.armor.normalarmor; + +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.messages.Messages; + +public class ScaleArmor extends NormalArmor { + + { + //name = "scale armor"; + image = ItemSpriteSheet.ARMOR_SCALE; + } + + public ScaleArmor() { + super(5,1f,2f,3); + } +} diff --git a/java/com/hmdzl/spspd/items/armor/normalarmor/StoneArmor.java b/java/com/hmdzl/spspd/items/armor/normalarmor/StoneArmor.java new file mode 100644 index 00000000..af6f12e8 --- /dev/null +++ b/java/com/hmdzl/spspd/items/armor/normalarmor/StoneArmor.java @@ -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 + */ +package com.hmdzl.spspd.items.armor.normalarmor; + +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class StoneArmor extends NormalArmor { + + { + //name = "Stone Armor"; + image = ItemSpriteSheet.STONE_ARMOR; + STR += 1; + MAX = 26; + MIN = 6; + } + + public StoneArmor() { + super(3,0.6f,0,4); + } + + @Override + public Item upgrade(boolean hasglyph) { + MIN += 1; + MAX += 1; + return super.upgrade(hasglyph); + } +} diff --git a/java/com/hmdzl/spspd/items/armor/normalarmor/StyrofoamArmor.java b/java/com/hmdzl/spspd/items/armor/normalarmor/StyrofoamArmor.java new file mode 100644 index 00000000..a1c28c75 --- /dev/null +++ b/java/com/hmdzl/spspd/items/armor/normalarmor/StyrofoamArmor.java @@ -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 + */ +package com.hmdzl.spspd.items.armor.normalarmor; + +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class StyrofoamArmor extends NormalArmor { + + { + //name = "styrofoam armor"; + image = ItemSpriteSheet.STY_ARMOR; + STR -= 1; + MAX = 22; + MIN = 0; + } + + public StyrofoamArmor() { + super(4,2.8f,6f,4); + } + + @Override + public Item upgrade(boolean hasglyph) { + MIN -= 1; + MAX -= 1; + return super.upgrade(hasglyph); + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/armor/normalarmor/VestArmor.java b/java/com/hmdzl/spspd/items/armor/normalarmor/VestArmor.java new file mode 100644 index 00000000..c49976e6 --- /dev/null +++ b/java/com/hmdzl/spspd/items/armor/normalarmor/VestArmor.java @@ -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 + */ +package com.hmdzl.spspd.items.armor.normalarmor; + +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class VestArmor extends NormalArmor { + + { + //name = "vest armor"; + image = ItemSpriteSheet.VEST_ARMOR; + STR -= 1; + MAX = 2; + MIN = 0; + } + + public VestArmor() { + super(1,4f,12f,1); + } + + @Override + public Item upgrade(boolean hasglyph) { + MIN -= 1; + MAX -= 2; + return super.upgrade(hasglyph); + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/armor/normalarmor/WoodenArmor.java b/java/com/hmdzl/spspd/items/armor/normalarmor/WoodenArmor.java new file mode 100644 index 00000000..8795045c --- /dev/null +++ b/java/com/hmdzl/spspd/items/armor/normalarmor/WoodenArmor.java @@ -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 + */ +package com.hmdzl.spspd.items.armor.normalarmor; + +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class WoodenArmor extends NormalArmor { + + { + //name = "wooden armor"; + image = ItemSpriteSheet.WOODEN_ARMOR; + STR += 1; + MAX = 6; + MIN = 2; + } + + public WoodenArmor() { + super(1,1f,1f,2); + } + + @Override + public Item upgrade(boolean hasglyph) { + MIN += 1; + //MAX += 0; + return super.upgrade(hasglyph); + } +} diff --git a/java/com/hmdzl/spspd/items/artifacts/AlchemistsToolkit.java b/java/com/hmdzl/spspd/items/artifacts/AlchemistsToolkit.java new file mode 100644 index 00000000..6555d6d5 --- /dev/null +++ b/java/com/hmdzl/spspd/items/artifacts/AlchemistsToolkit.java @@ -0,0 +1,287 @@ +package com.hmdzl.spspd.items.artifacts; + +import java.util.ArrayList; +import java.util.Collections; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.particles.ElmoParticle; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.potions.Potion; +import com.hmdzl.spspd.items.potions.PotionOfExperience; +import com.hmdzl.spspd.items.potions.PotionOfMight; +import com.hmdzl.spspd.items.potions.PotionOfOverHealing; +import com.hmdzl.spspd.items.potions.PotionOfStrength; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; +import com.hmdzl.spspd.windows.WndBag; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +/** + * Created by debenhame on 24/11/2014. + */ +public class AlchemistsToolkit extends Artifact { + + { + //name = "Alchemists Toolkit"; + image = ItemSpriteSheet.ARTIFACT_TOOLKIT; + + level = 0; + levelCap = 10; + defaultAction = AC_BREW; + } + + public static final String AC_BREW = "BREW"; + public static final String AC_CREATE = "CREATE"; + + // arrays used in containing potion collections for mix logic. + public final ArrayList combination = new ArrayList<>(); + public ArrayList curGuess = new ArrayList<>(); + public ArrayList bstGuess = new ArrayList<>(); + + public int numWrongPlace = 0; + public int numRight = 0; + + private int seedsToPotion = 0; + + //protected String inventoryTitle = "Select a potion"; + protected WndBag.Mode mode = WndBag.Mode.POTION; + + public AlchemistsToolkit() { + super(); + + Generator.Category cat = Generator.Category.POTION; + for (int i = 1; i <= 3; i++) { + Class potion; + do { + potion = cat.classes[Random.chances(cat.probs)]; + // forcing the player to use experience potions would be + // completely unfair. + } while (combination.contains(potion) + || potion == PotionOfExperience.class || potion == PotionOfOverHealing.class + || potion == PotionOfStrength.class || potion == PotionOfMight.class + ); + combination.add(potion); + } + } + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + if (isEquipped(hero) && level < levelCap && !cursed) + actions.add(AC_BREW); + if (level > 0 && !isEquipped(hero) ) + actions.add(AC_CREATE); + return actions; + } + + @Override + public void execute(Hero hero, String action) { + if (action.equals(AC_BREW)) { + GameScene.selectItem(itemSelector, mode, Messages.get(this, "prompt")); + } else if (action.equals(AC_CREATE)) { + curUser = hero; + Sample.INSTANCE.play(Assets.SND_BURNING); + curUser.sprite.emitter().burst(ElmoParticle.FACTORY, 12); + curUser.spendAndNext(1f); + for(int i=0; i level) { + + level = score; + seedsToPotion = 0; + bstGuess = curGuess; + this.numRight = numRight; + this.numWrongPlace = numWrongPlace; + + if (level == 10) { + bstGuess = new ArrayList<>(); + GLog.p(Messages.get(this,"prefect")); + } else { + GLog.w(brewDesc(numWrongPlace, numRight) + + Messages.get(this, "bestbrew")); + } + + } else { + + GLog.w(brewDesc(numWrongPlace, numRight) + + Messages.get(this, "waste")); + } + curGuess = new ArrayList<>(); + + } + + private String brewDesc(int numWrongPlace, int numRight) { + String result = ""; + if (numWrongPlace > 0) { + result += numWrongPlace + Messages.get(this, "bdorder"); + } if (numRight > 0) { + result += numRight + Messages.get(this, "right"); + } + return result; + } + + @Override + protected ArtifactBuff passiveBuff() { + return new alchemy(); + } + + @Override + public String desc() { + String result = Messages.get(this, "desc"); + if (isEquipped(Dungeon.hero)) + if (cursed) + result += "\n\n" + Messages.get(this, "desc_cursed"); + if (level == 0) { + result += "\n\n" + Messages.get(this, "level_zero"); + } else if (level == 10) { + result += "\n\n" + Messages.get(this, "level_ten"); + } else if (!bstGuess.isEmpty()) { + result += "\n\n" + Messages.get(this, "make_from") + + Messages.get(bstGuess.get(0), "name") + ", " + Messages.get(bstGuess.get(1), "name") + ", " + + Messages.get(bstGuess.get(2), "name") + ", " + + brewDesc(numWrongPlace, numRight); + + // would only trigger if an upgraded toolkit was gained through + // transmutation or bones. + } else { + result += Messages.get(this, "need_fix");; + } + return result; + } + + private static final String COMBINATION = "combination"; + private static final String CURGUESS = "curguess"; + private static final String BSTGUESS = "bstguess"; + + private static final String NUMWRONGPLACE = "numwrongplace"; + private static final String NUMRIGHT = "numright"; + + private static final String SEEDSTOPOTION = "seedstopotion"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(NUMWRONGPLACE, numWrongPlace); + bundle.put(NUMRIGHT, numRight); + + bundle.put(SEEDSTOPOTION, seedsToPotion); + + bundle.put(COMBINATION, + combination.toArray(new Class[combination.size()])); + bundle.put(CURGUESS, curGuess.toArray(new Class[curGuess.size()])); + bundle.put(BSTGUESS, bstGuess.toArray(new Class[bstGuess.size()])); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + numWrongPlace = bundle.getInt(NUMWRONGPLACE); + numRight = bundle.getInt(NUMRIGHT); + + seedsToPotion = bundle.getInt(SEEDSTOPOTION); + + combination.clear(); + Collections.addAll(combination, bundle.getClassArray(COMBINATION)); + Collections.addAll(curGuess, bundle.getClassArray(CURGUESS)); + Collections.addAll(bstGuess, bundle.getClassArray(BSTGUESS)); + } + + public class alchemy extends ArtifactBuff { + + public boolean tryCook(int count) { + + // this logic is handled inside the class with a variable so that it + // may be stored. + // to prevent manipulation where a player could keep throwing in 1-2 + // seeds until they get lucky. + if (seedsToPotion == 0) { + if (Random.Int(20) < 10 + level) { + if (Random.Int(20) < level) { + seedsToPotion = 1; + } else + seedsToPotion = 2; + } else + seedsToPotion = 3; + } + + if (count >= seedsToPotion) { + seedsToPotion = 0; + return true; + } else + return false; + + } + + } + + protected WndBag.Listener itemSelector = new WndBag.Listener() { + @Override + public void onSelect(Item item) { + if (item != null && item instanceof Potion && item.isIdentified()) { + if (!curGuess.contains(item.getClass())) { + + Hero hero = Dungeon.hero; + hero.sprite.operate(hero.pos); + hero.busy(); + hero.spend(1f); + Sample.INSTANCE.play(Assets.SND_DRINK); + + //item.detach(hero.belongings.backpack); + + curGuess.add(item.getClass()); + if (curGuess.size() == 3) { + guessBrew(); + } else { + GLog.i(Messages.get(AlchemistsToolkit.class, "addpotion")); + } + } else { + GLog.w(Messages.get(AlchemistsToolkit.class, "have_add")); + } + } else if (item != null) { + GLog.w(Messages.get(AlchemistsToolkit.class, "know_first")); + } + } + }; + +} + diff --git a/java/com/hmdzl/spspd/items/artifacts/AlienBag.java b/java/com/hmdzl/spspd/items/artifacts/AlienBag.java new file mode 100644 index 00000000..374eb7fb --- /dev/null +++ b/java/com/hmdzl/spspd/items/artifacts/AlienBag.java @@ -0,0 +1,164 @@ +package com.hmdzl.spspd.items.artifacts; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.DefenceUp; +import com.hmdzl.spspd.actors.buffs.Invisibility; +import com.hmdzl.spspd.actors.buffs.Levitation; +import com.hmdzl.spspd.actors.buffs.ShieldArmor; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Bundle; + +/** + * Created by dachhack on 10/15/2015. + */ +public class AlienBag extends Artifact { + + { + //name = "AlienBag"; + image = ItemSpriteSheet.ALIEN_BAG; + + level = 0; + exp = 0; + levelCap = 10; + + charge = 0; + partialCharge = 0; + chargeCap = 100; + + + defaultAction = AC_SHIELD; + } + + public static final String AC_SHIELD = "SHIELD"; + public static final String AC_BOMB = "BOMB"; + public static final String AC_FLY = "FLY"; + public static final String AC_ETC = "ETC"; + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + if (isEquipped(hero) && charge == 100 && !cursed) { + actions.add(AC_SHIELD); + actions.add(AC_FLY); + } + if (level > 1) actions.add(AC_BOMB); + //if (level > 2 && !isEquipped(hero) ) + //actions.add(AC_ETC); + return actions; + } + + @Override + public void execute(Hero hero, String action) { + super.execute(hero, action); + if (action.equals(AC_SHIELD)) { + + if (!isEquipped(hero)) + GLog.i(Messages.get(Artifact.class, "need_to_equip") ); + else if (charge != chargeCap) + GLog.i(Messages.get(this, "no_charge")); + else { + charge = 0; + Buff.affect(hero,ShieldArmor.class).level(level * 20); + hero.spend(1f); + updateQuickslot(); + } + + } else if (action.equals(AC_BOMB)) { + level--; + for(int i=0; i<2; i++) { + Dungeon.level.drop(Generator.random(Generator.Category.BOMBS), hero.pos).sprite.drop(); + } + hero.spend(1f); + updateQuickslot(); + + } else if (action.equals(AC_FLY)) { + charge = 0; + Buff.affect(hero, Invisibility.class, level * 5f); + Buff.affect(hero, Levitation.class, level * 5f); + Buff.affect(hero, DefenceUp.class, level * 5f).level(level * 5); + hero.spend(1f); + updateQuickslot(); + } else if (action.equals(AC_ETC)) { + hero.spend(1f); + } + } + + public int level(){ + return level; + } + + + @Override + protected ArtifactBuff passiveBuff() { + return new bagRecharge(); + } + + @Override + public String desc() { + String desc = super.desc(); + if (isEquipped(Dungeon.hero)) { + if (charge == 100) + desc += "\n\n" + Messages.get(this,"full_charge"); + } + return desc; + } + + public class bagRecharge extends ArtifactBuff { + @Override + public boolean act() { + if (charge < chargeCap) { + partialCharge += 1f + level * 1f; + if (partialCharge >= 10) { + charge++; + partialCharge = 0; + if (charge == chargeCap) { + partialCharge = 0; + } + + } + } else + partialCharge = 0; + + + updateQuickslot(); + + spend(TICK); + + return true; + } + public void gainExp( float levelPortion ) { + if (cursed) return; + exp += Math.round(levelPortion*100); + if (exp > 100+level()*50 && level() < levelCap){ + exp -= 100+level()*50; + GLog.p( Messages.get(this, "levelup") ); + upgrade(); + } + + } + } + + private static final String PARTIALCHARGE = "partialCharge"; + private static final String CHARGE = "charge"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(PARTIALCHARGE, partialCharge); + bundle.put(CHARGE, charge); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + partialCharge = bundle.getInt(PARTIALCHARGE); + charge = bundle.getInt(CHARGE); + } +} diff --git a/java/com/hmdzl/spspd/items/artifacts/Artifact.java b/java/com/hmdzl/spspd/items/artifacts/Artifact.java new file mode 100644 index 00000000..c90c956f --- /dev/null +++ b/java/com/hmdzl/spspd/items/artifacts/Artifact.java @@ -0,0 +1,306 @@ +package com.hmdzl.spspd.items.artifacts; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.KindofMisc; +import com.hmdzl.spspd.utils.GLog; +import com.hmdzl.spspd.messages.Messages; + +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +/** + * Created by Evan on 24/08/2014. + */ +public class Artifact extends KindofMisc { + + private static final float TIME_TO_EQUIP = 1f; + + private static final String TXT_TO_STRING = "%s"; + private static final String TXT_TO_STRING_CHARGE = "%s (%d/%d)"; + private static final String TXT_TO_STRING_LVL = "%s%+d"; + private static final String TXT_TO_STRING_LVL_CHARGE = "%s%+d (%d/%d)"; + + protected Buff passiveBuff; + protected Buff activeBuff; + + // level is used internally to track upgrades to artifacts, size/logic + // varies per artifact. + // already inherited from item superclass + // exp is used to count progress towards levels for some artifacts + protected int exp = 0; + // levelCap is the artifact's maximum level + protected int levelCap = 0; + + // the current artifact charge + protected int charge = 0; + // the build towards next charge, usually rolls over at 1. + // better to keep charge as an int and use a separate float than casting. + protected float partialCharge = 0; + // the maximum charge, varies per artifact, not all artifacts use this. + protected int chargeCap = 0; + + // used by some artifacts to keep track of duration of effects or cooldowns + // to use. + protected int cooldown = 0; + + public Artifact() { + super(); + } + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + actions.add(isEquipped(hero) ? AC_UNEQUIP : AC_EQUIP); + return actions; + } + + @Override + public boolean doEquip(Hero hero) { + + if (hero.belongings.misc1 != null && hero.belongings.misc2 != null && hero.belongings.misc3 != null) { + + GLog.w(Messages.get(Artifact.class, "onlythree")); + return false; + + } else if ((hero.belongings.misc1 != null && hero.belongings.misc1.getClass() == this.getClass()) + || (hero.belongings.misc2 != null && hero.belongings.misc2.getClass() == this.getClass()) + || (hero.belongings.misc3 != null && hero.belongings.misc3.getClass() == this.getClass())) { + + GLog.w( Messages.get(Artifact.class, "cannot_wear_two")); + return false; + + } else { + + if (hero.belongings.misc1 == null) { + hero.belongings.misc1 = this; + } else if (hero.belongings.misc2 == null){ + hero.belongings.misc2 = this; + } else { + hero.belongings.misc3 = this; + } + + detach(hero.belongings.backpack); + + activate(hero); + + cursedKnown = true; + identify(); + if (cursed) { + equipCursed(hero); + GLog.n(Messages.get(Artifact.class, "cursed_worn") ); + } + + hero.spendAndNext(TIME_TO_EQUIP); + return true; + + } + + } + + @Override + public void activate(Char ch) { + passiveBuff = passiveBuff(); + passiveBuff.attachTo(ch); + } + + @Override + public boolean doUnequip(Hero hero, boolean collect, boolean single) { + if (super.doUnequip(hero, collect, single)) { + + if (hero.belongings.misc1 == this) { + hero.belongings.misc1 = null; + } else if (hero.belongings.misc2 == this) { + hero.belongings.misc2 = null; + } else { + hero.belongings.misc3 = null; + } + + passiveBuff.detach(); + passiveBuff = null; + + if (activeBuff != null) { + activeBuff.detach(); + activeBuff = null; + } + + return true; + + } else { + + return false; + + } + } + + @Override + public boolean isEquipped(Hero hero) { + return hero.belongings.misc1 == this || hero.belongings.misc2 == this || hero.belongings.misc3 == this; + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public int visiblyUpgraded() { + return ((level * 10) / levelCap); + } + + // transfers upgrades from another artifact, transfer level will equal the + // displayed level + public void transferUpgrade(int transferLvl) { + upgrade(Math.round((float) (transferLvl * levelCap) / 10)); + if (level > levelCap) { + level = levelCap; + } + updateArtifact(); + } + + @Override + public String info() { + if (cursed && cursedKnown && !isEquipped(Dungeon.hero)) { + + return desc() + "\n\n" + Messages.get(Artifact.class, "curse_known"); + + } else { + + return desc(); + + } + } + + @Override + public String toString() { + + if (levelKnown && level / levelCap != 0) { + if (chargeCap > 0) { + return Messages.format(TXT_TO_STRING_LVL_CHARGE, name(), + visiblyUpgraded(), charge, chargeCap); + } else { + return Messages.format(TXT_TO_STRING_LVL, name(), + visiblyUpgraded()); + } + } else { + if (chargeCap > 0) { + return Messages.format(TXT_TO_STRING_CHARGE, name(), charge, + chargeCap); + } else { + return Messages.format(TXT_TO_STRING, name()); + } + } + } + + @Override + public String status() { + + // display the current cooldown + if (cooldown != 0) + return Messages.format("%d", cooldown); + + // display as percent + if (chargeCap == 100) + return Messages.format("%d%%", charge); + + // display as #/# + if (chargeCap > 0) + return Messages.format("%d/%d", charge, chargeCap); + + // if there's no cap - + // - but there is charge anyway, display that charge + if (charge != 0) + return Messages.format("%d", charge); + + // otherwise, if there's no charge, return null. + return null; + } + + // converts class names to be more concise and readable. + protected String convertName(String className) { + // removes known redundant parts of names. + className = className.replaceFirst("ScrollOf|PotionOf", ""); + + // inserts a space infront of every uppercase character + className = className.replaceAll("(\\p{Ll})(\\p{Lu})", "$1 $2"); + + return className; + }; + + @Override + public Item random() { + if (Random.Float() < 0.3f) { + cursed = true; + } + return this; + } + + @Override + public int price() { + int price = 100; + if (level > 0) + price += 50 * ((level * 10) / levelCap); + if (cursed && cursedKnown) { + price /= 2; + } + if (price < 1) { + price = 1; + } + return price; + } + + protected ArtifactBuff passiveBuff() { + return null; + } + + protected ArtifactBuff activeBuff() { + return null; + } + + public class ArtifactBuff extends Buff { + + public int level() { + return level; + } + + public boolean isCursed() { + return cursed; + } + + } + + private static final String IMAGE = "image"; + private static final String EXP = "exp"; + private static final String CHARGE = "charge"; + private static final String PARTIALCHARGE = "partialcharge"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(IMAGE, image); + bundle.put(EXP, exp); + bundle.put(CHARGE, charge); + bundle.put(PARTIALCHARGE, partialCharge); + + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + image = bundle.getInt(IMAGE); + exp = bundle.getInt(EXP); + charge = bundle.getInt(CHARGE); + partialCharge = bundle.getFloat(PARTIALCHARGE); + updateArtifact(); + } + + public void updateArtifact() { + // in case any artifacts have special computations between levels + // to be overriden and used when we restore from saves or transfer upgrades + } +} diff --git a/java/com/hmdzl/spspd/items/artifacts/CapeOfThorns.java b/java/com/hmdzl/spspd/items/artifacts/CapeOfThorns.java new file mode 100644 index 00000000..d6ff8926 --- /dev/null +++ b/java/com/hmdzl/spspd/items/artifacts/CapeOfThorns.java @@ -0,0 +1,160 @@ +package com.hmdzl.spspd.items.artifacts; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Needling; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.particles.ElmoParticle; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.ui.BuffIndicator; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Random; + +import java.util.ArrayList; + +/** + * Created by debenhame on 03/09/2014. + */ +public class CapeOfThorns extends Artifact { + + { + //name = "Cape of Thorns"; + image = ItemSpriteSheet.ARTIFACT_CAPE; + + level = 0; + levelCap = 10; + + charge = 0; + chargeCap = 100; + cooldown = 0; + + defaultAction = AC_NEEDLING; + } + + public static final String AC_NEEDLING = "NEEDLING"; + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + if (isEquipped(hero) && level > 1 && !cursed) + actions.add(AC_NEEDLING); + return actions; + } + + @Override + public void execute(Hero hero, String action) { + super.execute(hero, action); + if (action.equals(AC_NEEDLING)) { + if (!isEquipped(hero)) + GLog.i(Messages.get(Artifact.class, "need_to_equip")); + else if (cursed) + GLog.i(Messages.get(Artifact.class, "cursed")); + else { + if (level > 1) level--; + Sample.INSTANCE.play(Assets.SND_BURNING); + hero.sprite.emitter().burst(ElmoParticle.FACTORY, 12); + Buff.affect(hero, Needling.class, (level + 1) * 10f); + hero.spend(1f); + hero.busy(); + hero.sprite.operate(hero.pos); + updateQuickslot(); + } + } + } + @Override + protected ArtifactBuff passiveBuff() { + return new Thorns(); + } + + @Override + public String desc() { + String desc = Messages.get(this, "desc"); + if (isEquipped( Dungeon.hero )) { + desc += "\n\n"; + if (cooldown == 0) + desc += Messages.get(this, "desc_inactive"); + else + desc += Messages.get(this, "desc_active"); + } + + return desc; + } + + public class Thorns extends ArtifactBuff { + + @Override + public boolean act() { + if (cooldown > 0) { + cooldown--; + if (cooldown == 0) { + BuffIndicator.refreshHero(); + GLog.w(Messages.get(this, "inert") ); + } + updateQuickslot(); + } + spend(TICK); + return true; + } + + public int proc(int damage, Char attacker) { + if (cooldown == 0) { + charge += damage * (0.7 + level * 0.1); + if (charge >= chargeCap) { + charge = 0; + cooldown = 10 + level; + GLog.p(Messages.get(this, "radiating")); + BuffIndicator.refreshHero(); + } + } + + if (cooldown != 0) { + int deflected = Random.NormalIntRange(0, damage); + damage -= deflected; + + attacker.damage(deflected, this); + + exp += deflected; + + if (exp >= (level + 1) * 5 && level < levelCap) { + exp -= (level + 1) * 5; + upgrade(); + GLog.p(Messages.get(this, "levelup") ); + } + + } + updateQuickslot(); + return damage; + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public String desc() { + return Messages.get(this, "desc", dispTurns(cooldown)); + } + + @Override + public int icon() { + if (cooldown == 0) + return BuffIndicator.NONE; + else + return BuffIndicator.THORNS; + } + + @Override + public void detach() { + cooldown = 0; + charge = 0; + super.detach(); + } + + } + +} diff --git a/java/com/hmdzl/spspd/items/artifacts/ChaliceOfBlood.java b/java/com/hmdzl/spspd/items/artifacts/ChaliceOfBlood.java new file mode 100644 index 00000000..76f57271 --- /dev/null +++ b/java/com/hmdzl/spspd/items/artifacts/ChaliceOfBlood.java @@ -0,0 +1,166 @@ +package com.hmdzl.spspd.items.artifacts; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.ResultDescriptions; +import com.hmdzl.spspd.actors.buffs.BloodAngry; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.particles.ElmoParticle; +import com.hmdzl.spspd.effects.particles.ShadowParticle; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.plants.Earthroot; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.utils.GLog; + +import com.hmdzl.spspd.windows.WndOptions; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Random; + +/** + * Created by debenhame on 27/08/2014. + */ +public class ChaliceOfBlood extends Artifact { + + private static final String TXT_CHALICE = "Chalice of Blood"; + private static final String TXT_YES = "Yes, I know what I'm doing"; + private static final String TXT_NO = "No, I changed my mind"; + private static final String TXT_PRICK = "Each time you use the chalice it will drain more life energy, " + + "if you are not careful this draining effect can easily kill you.\n\n" + + "Are you sure you want to offer it more life energy?"; + + { + //name = "Chalice of Blood"; + image = ItemSpriteSheet.ARTIFACT_CHALICE1; + + level = 0; + levelCap = 10; + + defaultAction = AC_BLOODANGRY; + } + + public static final String AC_PRICK = "PRICK"; + public static final String AC_BLOODANGRY = "BLOODANGRY"; + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + if (isEquipped(hero) && level < levelCap && !cursed) + actions.add(AC_PRICK); + if (isEquipped(hero) && level > 3 && !cursed) + actions.add(AC_BLOODANGRY); + return actions; + } + + @Override + public void execute(Hero hero, String action) { + super.execute(hero, action); + if (action.equals(AC_PRICK)) { + + int damage = 3 * (level * level); + + if (damage > hero.HP * 0.75) { + + GameScene.show(new WndOptions(Messages.get(this, "name"), + Messages.get(this, "prick_warn"), + Messages.get(this, "yes"), + Messages.get(this, "no")) { + @Override + protected void onSelect(int index) { + if (index == 0) + prick(Dungeon.hero); + }; + }); + + } else { + prick(hero); + } + } else if (action.equals(AC_BLOODANGRY)) { + if (!isEquipped(hero) || level < 4) + GLog.i(Messages.get(Artifact.class, "need_to_equip") ); + else { + if (level > 3 )level-=3; + Sample.INSTANCE.play(Assets.SND_BURNING); + hero.sprite.emitter().burst(ElmoParticle.FACTORY, 12); + Buff.affect(hero, BloodAngry.class).set(100); + hero.spend(1f); + hero.busy(); + hero.sprite.operate(hero.pos); + updateQuickslot(); + } + } + } + + private void prick(Hero hero) { + int damage = 3 * (level * level); + + Earthroot.Armor armor = hero.buff(Earthroot.Armor.class); + if (armor != null) { + damage = armor.absorb(damage); + } + + damage -= Random.IntRange(0, hero.drRoll()); + + hero.sprite.operate(hero.pos); + hero.busy(); + hero.spend(3f); + GLog.w( Messages.get(this, "onprick") ); + if (damage <= 0){ + damage = 1; + } else { + Sample.INSTANCE.play(Assets.SND_CURSED); + hero.sprite.emitter().burst( ShadowParticle.CURSE, 4+(damage/10) ); + } + + hero.damage(damage, this); + + if (!hero.isAlive()) { + Dungeon.fail(Messages.format(ResultDescriptions.ITEM)); + //GLog.n("The Chalice sucks your life essence dry..."); + } else { + upgrade(); + } + } + + @Override + public Item upgrade() { + if (level >= 6) + image = ItemSpriteSheet.ARTIFACT_CHALICE3; + else if (level >= 2) + image = ItemSpriteSheet.ARTIFACT_CHALICE2; + return super.upgrade(); + } + + @Override + protected ArtifactBuff passiveBuff() { + return new chaliceRegen(); + } + + @Override + public String desc() { + String desc = super.desc(); + + if (isEquipped (Dungeon.hero)){ + desc += "\n\n"; + if (cursed) + desc += Messages.get(this, "desc_cursed"); + else if (level == 0) + desc += Messages.get(this, "desc_1"); + else if (level < levelCap) + desc += Messages.get(this, "desc_2"); + else + desc += Messages.get(this, "desc_3"); + } + + return desc; + } + + public class chaliceRegen extends ArtifactBuff { + + } + +} diff --git a/java/com/hmdzl/spspd/items/artifacts/CloakOfShadows.java b/java/com/hmdzl/spspd/items/artifacts/CloakOfShadows.java new file mode 100644 index 00000000..bd3a2527 --- /dev/null +++ b/java/com/hmdzl/spspd/items/artifacts/CloakOfShadows.java @@ -0,0 +1,283 @@ +package com.hmdzl.spspd.items.artifacts; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.ForeverShadow; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.particles.ElmoParticle; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.CharSprite; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.ui.BuffIndicator; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.noosa.audio.Sample; +import com.watabou.noosa.tweeners.AlphaTweener; +import com.watabou.utils.Bundle; + +/** + * Created by debenhame on 25/08/2014. + */ +public class CloakOfShadows extends Artifact { + + { + //name = "Cloak of Shadows"; + image = ItemSpriteSheet.ARTIFACT_CLOAK; + + level = 0; + exp = 0; + levelCap = 10; + + charge = Math.min(level+3, 10); + partialCharge = 0; + chargeCap = Math.min(level+3, 10); + + defaultAction = AC_STEALTH; + + + } + + private boolean stealthed = false; + + public static final String AC_STEALTH = "STEALTH"; + public static final String AC_SHADOW = "SHADOW"; + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + if (isEquipped(hero) && charge > 1) + actions.add(AC_STEALTH); + if (isEquipped(hero) && level > 3 && !cursed) + actions.add(AC_SHADOW); + return actions; + } + + @Override + public void execute(Hero hero, String action) { + if (action.equals(AC_STEALTH)) { + + if (!stealthed) { + if (!isEquipped(hero)) + GLog.i(Messages.get(Artifact.class, "need_to_equip")); + else if (cooldown > 0) + GLog.i(Messages.get(this, "cooldown", cooldown) ); + else if (charge <= 1) + GLog.i( Messages.get(this, "no_charge") ); + else { + stealthed = true; + hero.spend(1f); + hero.busy(); + Sample.INSTANCE.play(Assets.SND_MELD); + activeBuff = activeBuff(); + activeBuff.attachTo(hero); + if (hero.sprite.parent != null) { + hero.sprite.parent.add(new AlphaTweener(hero.sprite, + 0.4f, 0.4f)); + } else { + hero.sprite.alpha(0.4f); + } + hero.sprite.operate(hero.pos); + } + } else { + stealthed = false; + activeBuff.detach(); + activeBuff = null; + hero.spend( 1f ); + hero.sprite.operate(hero.pos); + } + } else if (action.equals(AC_SHADOW)) { + if (!isEquipped(hero)) + GLog.i(Messages.get(Artifact.class, "need_to_equip") ); + else { + if (level > 3 )level-=3; + Sample.INSTANCE.play(Assets.SND_BURNING); + hero.sprite.emitter().burst(ElmoParticle.FACTORY, 12); + Buff.affect(hero, ForeverShadow.class,(level+3)*10f); + hero.spend(1f); + hero.busy(); + hero.sprite.operate(hero.pos); + updateQuickslot(); + } + } else + super.execute(hero, action); + } + + @Override + public void activate(Char ch) { + super.activate(ch); + if (stealthed) { + activeBuff = activeBuff(); + activeBuff.attachTo(ch); + } + } + + @Override + public boolean doUnequip(Hero hero, boolean collect, boolean single) { + if (super.doUnequip(hero, collect, single)) { + stealthed = false; + return true; + } else + return false; + } + + @Override + protected ArtifactBuff passiveBuff() { + return new cloakRecharge(); + } + + @Override + protected ArtifactBuff activeBuff() { + return new cloakStealth(); + } + + @Override + public Item upgrade() { + chargeCap = Math.min(chargeCap + 1, 10); + return super.upgrade(); + } + + private static final String STEALTHED = "stealthed"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(STEALTHED, stealthed); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + stealthed = bundle.getBoolean(STEALTHED); + if (bundle.contains("cooldown")){ + exp = 0; + level=(int)Math.ceil(level*0.7f); + charge = chargeCap = Math.min(3 + level, 10); + } + } + + public class cloakRecharge extends ArtifactBuff { + @Override + public boolean act() { + if (charge < chargeCap) { + if (!stealthed ) { + float turnsToCharge = (50 - (chargeCap - charge)); + if (level() > 7) turnsToCharge -= 10*(level() - 7)/3f; + partialCharge += (1f / turnsToCharge); + } + + if (partialCharge >= 1) { + charge++; + partialCharge -= 1; + if (charge == chargeCap){ + partialCharge = 0; + } + + } + } else + partialCharge = 0; + + if (cooldown > 0) + cooldown --; + + updateQuickslot(); + + spend( TICK ); + + return true; + } + + + } + + + public class cloakStealth extends ArtifactBuff { + int turnsToCost = 0; + @Override + public int icon() { + return BuffIndicator.INVISIBLE; + } + + @Override + public boolean attachTo( Char target ) { + if (super.attachTo( target )) { + target.invisible++; + return true; + } else { + return false; + } + } + + @Override + public boolean act(){ + turnsToCost--; + + if (turnsToCost <= 0){ + charge--; + if (charge < 0) { + charge = 0; + detach(); + GLog.w(Messages.get(this, "no_charge")); + ((Hero) target).interrupt(); + } else { + //target hero level is 1 + 2*cloak level + int lvlDiffFromTarget = ((Hero) target).lvl - (1+level()*2); + //plus an extra one for each level after 6 + if (level() >= 7){ + lvlDiffFromTarget -= level()-6; + } + if (lvlDiffFromTarget >= 0){ + exp += Math.round(10f * Math.pow(1.1f, lvlDiffFromTarget)); + } else { + exp += Math.round(10f * Math.pow(0.75f, -lvlDiffFromTarget)); + } + + if (exp >= (level() + 1) * 50 && level() < levelCap) { + upgrade(); + exp -= level() * 50; + GLog.p(Messages.get(this, "levelup")); + + } + turnsToCost = 5; + } + updateQuickslot(); + } + + spend( TICK ); + + return true; + } + + public void dispel(){ + updateQuickslot(); + detach(); + } + + @Override + public void fx(boolean on) { + if (on) target.sprite.add( CharSprite.State.INVISIBLE ); + else if (target.invisible == 0) target.sprite.remove( CharSprite.State.INVISIBLE ); + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public String desc() { + return Messages.get(this, "desc"); + } + + @Override + public void detach() { + if (target.invisible > 0) + target.invisible--; + stealthed = false; + updateQuickslot(); + super.detach(); + } + } +} diff --git a/java/com/hmdzl/spspd/items/artifacts/DriedRose.java b/java/com/hmdzl/spspd/items/artifacts/DriedRose.java new file mode 100644 index 00000000..0ad12c9d --- /dev/null +++ b/java/com/hmdzl/spspd/items/artifacts/DriedRose.java @@ -0,0 +1,855 @@ +package com.hmdzl.spspd.items.artifacts; + +import java.util.ArrayList; +import java.util.HashSet; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.ToxicGas; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Burning; +import com.hmdzl.spspd.actors.buffs.Dewcharge; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.actors.mobs.RedWraith; +import com.hmdzl.spspd.actors.mobs.npcs.Ghost; +import com.hmdzl.spspd.actors.mobs.npcs.NPC; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.effects.particles.ElmoParticle; +import com.hmdzl.spspd.effects.particles.ShaftParticle; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.armor.Armor; +import com.hmdzl.spspd.items.scrolls.ScrollOfPsionicBlast; +import com.hmdzl.spspd.items.weapon.melee.MeleeWeapon; +import com.hmdzl.spspd.items.weapon.melee.special.WraithBreath; +import com.hmdzl.spspd.items.weapon.missiles.Boomerang; +import com.hmdzl.spspd.items.weapon.missiles.ManyKnive; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.messages.Languages; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.scenes.PixelScene; +import com.hmdzl.spspd.sprites.GhostSprite; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.ui.RenderedTextMultiline; +import com.hmdzl.spspd.ui.Window; +import com.hmdzl.spspd.utils.GLog; +import com.hmdzl.spspd.windows.IconTitle; +import com.hmdzl.spspd.windows.WndBag; +import com.hmdzl.spspd.windows.WndBlacksmith; +import com.hmdzl.spspd.windows.WndQuest; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Bundle; +import com.watabou.utils.PathFinder; +import com.watabou.utils.Random; + +/** + * Created by debenhame on 21/11/2014. + */ +public class DriedRose extends Artifact { + + { + //name = "Dried Rose"; + image = ItemSpriteSheet.ARTIFACT_ROSE1; + + level = 0; + levelCap = 10; + + charge = 100; + chargeCap = 100; + + defaultAction = AC_SUMMON; + } + + protected static boolean talkedTo = false; + protected static boolean firstSummon = false; + + private GhostHero ghost = null; + private int ghostID = 0; + + private MeleeWeapon weapon = null; + private Armor armor = null; + + public int droppedPetals = 0; + + public static final String AC_SUMMON = "SUMMON"; + public static final String AC_OUTFIT = "OUTFIT"; + public static final String AC_SOULBLESS = "SOULBLESS"; + + public DriedRose() { + super(); + talkedTo = firstSummon = false; + } + + @Override + public ArrayList actions( Hero hero ) { + ArrayList actions = super.actions( hero ); + if (!Ghost.Quest.completed()){ + actions.remove(AC_EQUIP); + return actions; + } + if (isEquipped( hero ) && charge == chargeCap && !cursed) { + actions.add(AC_SUMMON); + } + if (isIdentified() && !cursed){ + actions.add(AC_OUTFIT); + } + if (level > 0 && !isEquipped(hero) ) + actions.add(AC_SOULBLESS); + + return actions; + } + + @Override + public void execute( Hero hero, String action ) { + + super.execute(hero, action); + + if (action.equals(AC_SUMMON)) { + + if (ghost != null) GLog.i( Messages.get(this, "spawned") ); + else if (!isEquipped( hero )) GLog.i( Messages.get(Artifact.class, "need_to_equip") ); + else if (charge != chargeCap) GLog.i( Messages.get(this, "no_charge") ); + else if (cursed) GLog.i( Messages.get(this, "cursed") ); + else { + ArrayList spawnPoints = new ArrayList(); + for (int i = 0; i < PathFinder.NEIGHBOURS8.length; i++) { + int p = hero.pos + PathFinder.NEIGHBOURS8[i]; + if (Actor.findChar(p) == null && (Level.passable[p] || Level.avoid[p])) { + spawnPoints.add(p); + } + } + + if (spawnPoints.size() > 0) { + ghost = new GhostHero( this ); + ghostID = ghost.id(); + ghost.pos = Random.element(spawnPoints); + + GameScene.add(ghost, 1f); + CellEmitter.get(ghost.pos).start( ShaftParticle.FACTORY, 0.3f, 4 ); + CellEmitter.get(ghost.pos).start( Speck.factory(Speck.LIGHT), 0.2f, 3 ); + + hero.spend(1f); + hero.busy(); + hero.sprite.operate(hero.pos); + + if (!firstSummon) { + ghost.yell( Messages.get(GhostHero.class, "hello", Dungeon.hero.givenName()) ); + Sample.INSTANCE.play( Assets.SND_GHOST ); + firstSummon = true; + } else + ghost.saySpawned(); + + charge = 0; + updateQuickslot(); + + } else + GLog.i( Messages.get(this, "no_space") ); + } + + } else if (action.equals(AC_OUTFIT)){ + GameScene.show( new WndGhostHero(this) ); + } else if (action.equals(AC_SOULBLESS)) { + curUser = hero; + Sample.INSTANCE.play(Assets.SND_BURNING); + curUser.sprite.emitter().burst(ElmoParticle.FACTORY, 12); + Buff.affect(curUser, Dewcharge.class,level*100f); + curUser.spendAndNext(1f); + detach(curUser.belongings.backpack); + } + + } + + public int ghostStrength(){ + return 13 + level/2; + } + + @Override + public String desc() { + if (!Ghost.Quest.completed() && !isIdentified()){ + return Messages.get(this, "desc_no_quest"); + } + + String desc = super.desc(); + + if (isEquipped( Dungeon.hero )){ + if (!cursed){ + + if (level < levelCap) + desc+= "\n\n" + Messages.get(this, "desc_hint"); + + } else + desc += "\n\n" + Messages.get(this, "desc_cursed"); + } + + return desc; + } + + @Override + protected ArtifactBuff passiveBuff() { + return new roseRecharge(); + } + + @Override + public Item upgrade() { + if (level >= 9) + image = ItemSpriteSheet.ARTIFACT_ROSE3; + else if (level >= 4) + image = ItemSpriteSheet.ARTIFACT_ROSE2; + + // For upgrade transferring via well of transmutation + droppedPetals = Math.max(level, droppedPetals); + + return super.upgrade(); + } + + private static final String TALKEDTO = "talkedto"; + private static final String FIRSTSUMMON = "firstsummon"; + private static final String GHOSTID = "ghostID"; + private static final String PETALS = "petals"; + + private static final String WEAPON = "weapon"; + private static final String ARMOR = "armor"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + + bundle.put(TALKEDTO, talkedTo); + bundle.put(FIRSTSUMMON, firstSummon); + bundle.put( GHOSTID, ghostID ); + bundle.put( PETALS, droppedPetals ); + + if (weapon != null) bundle.put( WEAPON, weapon ); + if (armor != null) bundle.put( ARMOR, armor ); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + + talkedTo = bundle.getBoolean(TALKEDTO); + firstSummon = bundle.getBoolean(FIRSTSUMMON); + ghostID = bundle.getInt( GHOSTID ); + droppedPetals = bundle.getInt( PETALS ); + + if (bundle.contains(WEAPON)) weapon = (MeleeWeapon)bundle.get( WEAPON ); + if (bundle.contains(ARMOR)) armor = (Armor)bundle.get( ARMOR ); + } + + private static GhostHero heldGhost; + + public static void holdGhostHero( Level level ){ + for (Mob mob : level.mobs.toArray( new Mob[0] )) { + if (mob instanceof DriedRose.GhostHero) { + level.mobs.remove( mob ); + heldGhost = (GhostHero) mob; + break; + } + } + } + + public static void restoreGhostHero( Level level, int pos ){ + if (heldGhost != null){ + level.mobs.add( heldGhost ); + + int ghostPos; + do { + ghostPos = pos + PathFinder.NEIGHBOURS8[Random.Int(8)]; + } while (Level.solid[ghostPos] || level.findMob(ghostPos) != null); + + heldGhost.pos = ghostPos; + heldGhost = null; + } + } + + public static void clearHeldGhostHero(){ + heldGhost = null; + } + + public class roseRecharge extends ArtifactBuff { + + @Override + public boolean act() { + + spend( TICK ); + + if (ghost == null && ghostID != 0){ + Actor a = Actor.findById(ghostID); + if (a != null){ + ghost = (GhostHero)a; + } else { + ghostID = 0; + } + } + + //rose does not charge while ghost hero is alive + if (ghost != null){ + return true; + } + + if (charge < chargeCap && !cursed ) { + partialCharge += 2/5f; //250 turns to a full charge + if (partialCharge > 1){ + charge++; + partialCharge--; + if (charge == chargeCap){ + partialCharge = 0f; + GLog.p( Messages.get(DriedRose.class, "charged") ); + } + } + } else if (cursed && Random.Int(100) == 0) { + + ArrayList spawnPoints = new ArrayList(); + + for (int i = 0; i < PathFinder.NEIGHBOURS8.length; i++) { + int p = target.pos + PathFinder.NEIGHBOURS8[i]; + if (Actor.findChar(p) == null && (Level.passable[p] || Level.avoid[p])) { + spawnPoints.add(p); + } + } + + if (spawnPoints.size() > 0) { + RedWraith.spawnAt(Random.element(spawnPoints)); + Sample.INSTANCE.play(Assets.SND_CURSED); + } + + } + + updateQuickslot(); + + return true; + } + } + public static class Petal extends Item { + + { + //name = "dried petal"; + stackable = true; + image = ItemSpriteSheet.PETAL; + } + + @Override + public boolean doPickUp(Hero hero) { + DriedRose rose = hero.belongings.getItem(DriedRose.class); + + if (rose == null) { + GLog.w( Messages.get(this, "no_rose")); + return false; + } + if (rose.level >= rose.levelCap) { + GLog.i(Messages.get(this, "no_room")); + hero.spendAndNext(TIME_TO_PICK_UP); + return true; + } else { + + rose.upgrade(); + if (rose.level == rose.levelCap) { + GLog.p(Messages.get(this, "maxlevel")); + } else + GLog.i(Messages.get(this, "levelup")); + + Sample.INSTANCE.play(Assets.SND_DEWDROP); + hero.spendAndNext(TIME_TO_PICK_UP); + return true; + + } + } + } + + public static class GhostHero extends NPC { + + { + //name = "sad ghost"; + spriteClass = GhostSprite.class; + + flying = true; + + state = WANDERING; + enemy = null; + + ally = true; + + loot = new WraithBreath(); + lootChance = 0.3f; + } + + private DriedRose rose = null; + + public GhostHero() { + super(); + } + + public GhostHero(DriedRose rose) { + this(); + this.rose = rose; + updateRose(); + HP = HT; + } + + private void updateRose(){ + if (rose == null) { + rose = Dungeon.hero.belongings.getItem(DriedRose.class); + } + + evadeSkill = (Dungeon.hero.lvl+4)*2; + if (rose == null) return; + HT = 50 + 20*rose.level; + } + + public void saySpawned(){ + if (Messages.lang() != Languages.ENGLISH) return; //don't say anything if not on english + int i = (Dungeon.depth - 1) / 5; + if (chooseEnemy() == null) + yell( Random.element( VOICE_AMBIENT[i] ) ); + else + yell( Random.element( VOICE_ENEMIES[i][ Dungeon.bossLevel() ? 1 : 0 ] ) ); + Sample.INSTANCE.play( Assets.SND_GHOST ); + } + + public void sayAnhk(){ + yell( Random.element( VOICE_BLESSEDANKH ) ); + Sample.INSTANCE.play( Assets.SND_GHOST ); + } + + public void sayDefeated(){ + if (Messages.lang() != Languages.ENGLISH) return; //don't say anything if not on english + yell( Random.element( VOICE_DEFEATED[ Dungeon.bossLevel() ? 1 : 0 ] ) ); + Sample.INSTANCE.play( Assets.SND_GHOST ); + } + + public void sayHeroKilled(){ + if (Messages.lang() != Languages.ENGLISH) return; //don't say anything if not on english + yell(Random.element(VOICE_HEROKILLED)); + Sample.INSTANCE.play( Assets.SND_GHOST ); + } + + public void sayBossBeaten(){ + yell( Random.element( VOICE_BOSSBEATEN[ Dungeon.depth==25 ? 1 : 0 ] ) ); + Sample.INSTANCE.play( Assets.SND_GHOST ); + } + + @Override + protected boolean act() { + updateRose(); + if (rose == null || !rose.isEquipped(Dungeon.hero)){ + damage(1, this); + } + if (!isAlive()) + return true; + if (!Dungeon.hero.isAlive()) { + sayHeroKilled(); + sprite.die(); + destroy(); + return true; + } + return super.act(); + } + + @Override + public int hitSkill(Char target) { + //same accuracy as the hero. + int acc = Dungeon.hero.lvl + 9; + + if (rose != null && rose.weapon != null){ + acc *= rose.weapon.ACU; + } + + return acc; + } + + @Override + protected float attackDelay() { + if (rose != null && rose.weapon != null){ + return rose.weapon.DLY; + } else { + return super.attackDelay(); + } + } + + @Override + protected boolean canAttack(Char enemy) { + if (rose != null && rose.weapon != null) { + return Dungeon.level.distance(pos, enemy.pos) <= rose.weapon.RCH; + } else { + return super.canAttack(enemy); + } + } + + @Override + public int damageRoll() { + int dmg = 0; + if (rose != null && rose.weapon != null){ + dmg += Random.NormalIntRange(rose.weapon.MIN, rose.weapon.MAX); + } else { + dmg += Random.NormalIntRange(0, 5); + } + + return dmg; + } + + @Override + public int attackProc(Char enemy, int damage) { + if (rose != null && rose.weapon != null) { + rose.weapon.proc(this, enemy, damage); + return damage; + } else { + return super.attackProc(enemy, damage); + } + } + + @Override + public int defenseProc(Char enemy, int damage) { + return super.defenseProc(enemy, damage); + } + + @Override + public void damage(int dmg, Object src) { + //TODO improve this when I have proper damage source logic + super.damage( dmg, src ); + } + + @Override + public float speed() { + float speed = super.speed(); + return speed; + } + + @Override + public int evadeSkill(Char enemy) { + + int eva = Dungeon.hero.lvl + 4; + + if (rose != null && rose.armor != null){ + eva *= rose.armor.DEX; + } + //int defense = super.evadeSkill(enemy); + return eva; + } + + @Override + public int drRoll() { + int block = 0; + if (rose != null && rose.armor != null){ + block += Random.NormalIntRange( rose.armor.MIN, rose.armor.MAX); + } + return block; + } + + @Override + protected boolean getCloser(int target) { + if (state == WANDERING + || Level.distance(target, Dungeon.hero.pos) > 6) + this.target = target = Dungeon.hero.pos; + return super.getCloser(target); + } + + @Override + protected Char chooseEnemy() { + if (enemy == null || !enemy.isAlive() || state == WANDERING) { + + HashSet enemies = new HashSet(); + for (Mob mob : Dungeon.level.mobs) { + if (mob.hostile && Level.fieldOfView[mob.pos] + && mob.state != mob.PASSIVE) { + enemies.add(mob); + } + } + enemy = enemies.size() > 0 ? Random.element(enemies) : null; + } + return enemy; + } + + @Override + public void add(Buff buff) { + // in other words, can't be directly affected by buffs/debuffs. + } + + @Override + public boolean interact() { + if (!DriedRose.talkedTo){ + DriedRose.talkedTo = true; + GameScene.show(new WndQuest(this, Messages.get(this, "introduce") )); + return false; + } else if (Dungeon.level.passable[pos] || Dungeon.hero.flying) { + int curPos = pos; + + moveSprite( pos, Dungeon.hero.pos ); + move( Dungeon.hero.pos ); + + Dungeon.hero.sprite.move( Dungeon.hero.pos, curPos ); + Dungeon.hero.move( curPos ); + + Dungeon.hero.spend( 1 / Dungeon.hero.speed() ); + Dungeon.hero.busy(); + return true; + } else { + return false; + } + } + + @Override + public void die(Object cause) { + sayDefeated(); + super.die(cause); + } + + @Override + public void destroy() { + updateRose(); + if (rose != null) { + rose.ghost = null; + rose.ghostID = -1; + } + super.destroy(); + } + + private static final HashSet> IMMUNITIES = new HashSet>(); + static { + IMMUNITIES.add(ToxicGas.class); + IMMUNITIES.add( Burning.class ); + IMMUNITIES.add(ScrollOfPsionicBlast.class); + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } + + // ************************************************************************************ + // This is a bunch strings & string arrays, used in all of the sad + // ghost's voice lines. + // ************************************************************************************ + + public static final String VOICE_HELLO = "Hello again "; + + private static final String VOICE_INTRODUCE = "My spirit is bound to this rose, it was very precious to me, a " + + "gift from my love whom I left on the surface.\n\nI cannot return to him, but thanks to you I have a " + + "second chance to complete my journey. When I am able I will respond to your call and fight with you.\n\n" + + "hopefully you may succeed where I failed..."; + + // 1st index - depth type, 2nd index - specific line. + public static final String[][] VOICE_AMBIENT = { + { + "These sewers were once safe, some even lived here in the winter...", + "I wonder what happened to the guard patrols, did they give up?...", + "I had family on the surface, I hope they are safe..." }, + { + "I've heard stories about this place, nothing good...", + "This place was always more of a dungeon than a prison...", + "I can't imagine what went on when this place was abandoned..." }, + { + "No human or dwarf has been here for a very long time...", + "Something must have gone very wrong, for the dwarves to abandon a gold mine...", + "I feel great evil lurking below..." }, + { "The dwarves were industrious, but greedy...", + "I hope the surface never ends up like this place...", + "So the dwarvern metropolis really has fallen..." }, + { + "What is this place?...", + "So the stories are true, we have to fight a demon god...", + "I feel a great evil in this place..." }, + { "... I don't like this place... We should leave as soon as possible..." } }; + + // 1st index - depth type, 2nd index - boss or not, 3rd index - specific + // line. + public static final String[][][] VOICE_ENEMIES = { + { + { + "Let's make the sewers safe again...", + "If the guards couldn't defeat them, perhaps we can...", + "These crabs are extremely annoying..." }, + { + "Beware Goo!...", + "Many of my friends died to this thing, time for vengeance...", + "Such an abomination cannot be allowed to live..." } }, + { + { + "What dark magic happened here?...", + "To think the captives of this place are now its guardians...", + "They were criminals before, now they are monsters..." }, + { + "If only he would see reason, he doesn't seem insane...", + "He assumes we are hostile, if only he would stop to talk...", + "The one prisoner left sane is a deadly assassin. Of course..." } }, + { + { + "The creatures here are twisted, just like the sewers... ", + "more gnolls, I hate gnolls...", + "Even the bats are bloodthirsty here..." }, + { + "Only dwarves would build a mining machine that kills looters...", + "That thing is huge...", + "How has it survived here for so long?..." } }, + { + { + "Dwarves aren't supposed to look that pale...", + "I don't know what's worse, the dwarves, or their creations...", + "They all obey their master without question, even now..." }, + { + "When people say power corrupts, this is what they mean...", + "He's more a Lich than a King now...", + "Looks like he's more demon than dwarf now..." } }, + { + { "What the heck is that thing?...", + "This place is terrifying...", + "What were the dwarves thinking, toying with power like this?..." }, + { "Oh.... this doesn't look good...", + "So that's what a god looks like?...", + "This is going to hurt..." } }, + { + { "I don't like this place... we should leave as soon as we can..." }, + { "Hello source viewer, I'm writing this here as this line should never trigger. Have a nice day!" } } }; + + // 1st index - Yog or not, 2nd index - specific line. + public static final String[][] VOICE_BOSSBEATEN = { + { "Yes!", "Victory!" }, + { "It's over... we won...", + "I can't believe it... We just killed a god..." } }; + + // 1st index - boss or not, 2nd index - specific line. + public static final String[][] VOICE_DEFEATED = { + { "Good luck...", "I will return...", "Tired... for now..." }, + { "No... I can't....", "I'm sorry.. good luck..", + "Finish it off... without me..." } }; + + public static final String[] VOICE_HEROKILLED = { "nooo...", "no...", + "I couldn't help them..." }; + + public static final String[] VOICE_BLESSEDANKH = { "Incredible!...", + "Wish I had one of those...", "How did you survive that?..." }; + } + private static class WndGhostHero extends Window { + + private static final int BTN_SIZE = 32; + private static final float GAP = 2; + private static final float BTN_GAP = 12; + private static final int WIDTH = 116; + + private WndBlacksmith.ItemButton btnWeapon; + private WndBlacksmith.ItemButton btnArmor; + + WndGhostHero(final DriedRose rose){ + + IconTitle titlebar = new IconTitle(); + titlebar.icon( new ItemSprite(rose) ); + titlebar.label( Messages.get(this, "title") ); + titlebar.setRect( 0, 0, WIDTH, 0 ); + add( titlebar ); + + RenderedTextMultiline message = + PixelScene.renderMultiline(Messages.get(this, "desc", rose.ghostStrength()), 6); + message.maxWidth( WIDTH ); + message.setPos(0, titlebar.bottom() + GAP); + add( message ); + + btnWeapon = new WndBlacksmith.ItemButton(){ + @Override + protected void onClick() { + if (rose.weapon != null){ + item(new WndBag.Placeholder(ItemSpriteSheet.WEAPON_HOLDER)); + if (!rose.weapon.doPickUp(Dungeon.hero)){ + Dungeon.level.drop( rose.weapon, Dungeon.hero.pos); + } + rose.weapon = null; + } else { + GameScene.selectItem(new WndBag.Listener() { + @Override + public void onSelect(Item item) { + if (!(item instanceof MeleeWeapon || item instanceof Boomerang || item instanceof ManyKnive)) { + //do nothing, should only happen when window is cancelled + } else if (item.unique || item instanceof Boomerang) { + GLog.w( Messages.get(WndGhostHero.class, "cant_unique")); + hide(); + } else if (!item.isIdentified()) { + GLog.w( Messages.get(WndGhostHero.class, "cant_unidentified")); + hide(); + } else if (item.cursed) { + GLog.w( Messages.get(WndGhostHero.class, "cant_cursed")); + hide(); + } else if (((MeleeWeapon)item).STR > rose.ghostStrength()) { + GLog.w( Messages.get(WndGhostHero.class, "cant_strength")); + hide(); + } else { + if (item.isEquipped(Dungeon.hero)){ + ((MeleeWeapon) item).doUnequip(Dungeon.hero, false, false); + } else { + item.detach(Dungeon.hero.belongings.backpack); + } + rose.weapon = (MeleeWeapon) item; + item(rose.weapon); + } + + } + }, WndBag.Mode.WEAPON, Messages.get(WndGhostHero.class, "weapon_prompt")); + } + } + }; + btnWeapon.setRect( (WIDTH - BTN_GAP) / 2 - BTN_SIZE, message.top() + message.height() + GAP, BTN_SIZE, BTN_SIZE ); + if (rose.weapon != null) { + btnWeapon.item(rose.weapon); + } else { + btnWeapon.item(new WndBag.Placeholder(ItemSpriteSheet.WEAPON_HOLDER)); + } + add( btnWeapon ); + + btnArmor = new WndBlacksmith.ItemButton(){ + @Override + protected void onClick() { + if (rose.armor != null){ + item(new WndBag.Placeholder(ItemSpriteSheet.ARMOR_HOLDER)); + if (!rose.armor.doPickUp(Dungeon.hero)){ + Dungeon.level.drop( rose.armor, Dungeon.hero.pos); + } + rose.armor = null; + } else { + GameScene.selectItem(new WndBag.Listener() { + @Override + public void onSelect(Item item) { + if (!(item instanceof Armor)) { + //do nothing, should only happen when window is cancelled + } else if (item.unique ) { + GLog.w( Messages.get(WndGhostHero.class, "cant_unique")); + hide(); + } else if (!item.isIdentified()) { + GLog.w( Messages.get(WndGhostHero.class, "cant_unidentified")); + hide(); + } else if (item.cursed) { + GLog.w( Messages.get(WndGhostHero.class, "cant_cursed")); + hide(); + } else if (((Armor)item).STR > rose.ghostStrength()) { + GLog.w( Messages.get(WndGhostHero.class, "cant_strength")); + hide(); + } else { + if (item.isEquipped(Dungeon.hero)){ + ((Armor) item).doUnequip(Dungeon.hero, false, false); + } else { + item.detach(Dungeon.hero.belongings.backpack); + } + rose.armor = (Armor) item; + item(rose.armor); + } + + } + }, WndBag.Mode.ARMOR, Messages.get(WndGhostHero.class, "armor_prompt")); + } + } + }; + btnArmor.setRect( btnWeapon.right() + BTN_GAP, btnWeapon.top(), BTN_SIZE, BTN_SIZE ); + if (rose.armor != null) { + btnArmor.item(rose.armor); + } else { + btnArmor.item(new WndBag.Placeholder(ItemSpriteSheet.ARMOR_HOLDER)); + } + add( btnArmor ); + + resize(WIDTH, (int)(btnArmor.bottom() + GAP)); + } + + } + +} diff --git a/java/com/hmdzl/spspd/items/artifacts/EtherealChains.java b/java/com/hmdzl/spspd/items/artifacts/EtherealChains.java new file mode 100644 index 00000000..73434375 --- /dev/null +++ b/java/com/hmdzl/spspd/items/artifacts/EtherealChains.java @@ -0,0 +1,300 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2015 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.items.artifacts; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.AttackDown; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Cripple; +import com.hmdzl.spspd.actors.buffs.Locked; +import com.hmdzl.spspd.actors.buffs.Silent; +import com.hmdzl.spspd.actors.buffs.Slow; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.Chains; +import com.hmdzl.spspd.effects.Pushing; +import com.hmdzl.spspd.effects.particles.ElmoParticle; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.CellSelector; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Callback; +import com.watabou.utils.Random; + +import java.util.ArrayList; + +public class EtherealChains extends Artifact { + + public static final String AC_CAST = "CAST"; + public static final String AC_LOCKED = "LOCKED"; + + { + image = ItemSpriteSheet.ARTIFACT_CHAINS; + + levelCap = 5; + exp = 0; + + charge = 5; + + defaultAction = AC_CAST; + usesTargeting = true; + } + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions( hero ); + if (isEquipped(hero) && charge > 0 && !cursed) + actions.add(AC_CAST); + if (isEquipped(hero) && level > 1 && !cursed) + actions.add(AC_LOCKED); + return actions; + } + + @Override + public void execute(Hero hero, String action) { + if (action.equals(AC_CAST)){ + + curUser = hero; + + if (!isEquipped( hero )) GLog.i( Messages.get(Artifact.class, "need_to_equip") ); + else if (charge < 1) GLog.i( Messages.get(this, "no_charge") ); + else if (cursed) GLog.w( Messages.get(this, "cursed") ); + else { + GameScene.selectCell(caster); + } + + } else if (action.equals(AC_LOCKED)){ + + curUser = hero; + + if (!isEquipped( hero )) GLog.i( Messages.get(Artifact.class, "need_to_equip") ); + else if (charge < 1) GLog.i( Messages.get(this, "no_charge") ); + else if (cursed) GLog.w( Messages.get(this, "cursed") ); + else { + GameScene.selectCell(locker); + } + + } else + super.execute(hero, action); + } + + private CellSelector.Listener caster = new CellSelector.Listener(){ + + @Override + public void onSelect(Integer target) { + if (target != null && (Dungeon.level.visited[target] || Dungeon.level.mapped[target])){ + + //ballistica does not go through walls on pre-rework boss arenas + int missileProperties = (Dungeon.depth == 10 || Dungeon.depth == 15 || Dungeon.depth == 20 || Dungeon.depth == 25) ? + Ballistica.PROJECTILE : Ballistica.STOP_CHARS | Ballistica.STOP_TARGET; + + final Ballistica chain = new Ballistica(curUser.pos, target, missileProperties); + + //determine if we're grabbing an enemy, pulling to a location, or doing nothing. + if (Actor.findChar( chain.collisionPos ) != null){ + int newPos = -1; + for (int i : chain.subPath(1, chain.dist)){ + if (!Level.solid[i] && Actor.findChar(i) == null){ + newPos = i; + break; + } + } + if (newPos == -1){ + GLog.w( Messages.get(EtherealChains.class, "does_nothing") ); + } else { + final int newMobPos = newPos; + final Char affected = Actor.findChar( chain.collisionPos ); + int chargeUse = Level.distance(affected.pos, newMobPos); + if (chargeUse > charge) { + GLog.w( Messages.get(EtherealChains.class, "no_charge") ); + return; + } else if (affected.properties().contains(Char.Property.IMMOVABLE)) { + GLog.w( Messages.get(EtherealChains.class, "cant_pull") ); + return; + } else { + charge -= chargeUse; + updateQuickslot(); + } + curUser.busy(); + curUser.sprite.parent.add(new Chains(curUser.pos, affected.pos, new Callback() { + public void call() { + Actor.add(new Pushing(affected, affected.pos, newMobPos, new Callback() { + public void call() { + Dungeon.level.press(newMobPos, affected); + } + })); + affected.pos = newMobPos; + Dungeon.observe(); + curUser.spendAndNext(1f); + } + })); + } + + } else if (Level.solid[chain.path.get(chain.dist)] + || (chain.dist > 0 && Level.solid[chain.path.get(chain.dist-1)]) + || (chain.path.size() > chain.dist+1 && Level.solid[chain.path.get(chain.dist+1)]) + //if the player is trying to grapple the edge of the map, let them. + || (chain.path.size() == chain.dist+1)) { + int newPos = -1; + for (int i : chain.subPath(1, chain.dist)){ + if (!Level.solid[i] && Actor.findChar(i) == null) newPos = i; + } + if (newPos == -1) { + GLog.w( Messages.get(EtherealChains.class, "does_nothing") ); + } else { + final int newHeroPos = newPos; + int chargeUse = Level.distance(curUser.pos, newHeroPos); + if (chargeUse > charge){ + GLog.w( Messages.get(EtherealChains.class, "no_charge") ); + return; + } else { + charge -= chargeUse; + updateQuickslot(); + } + curUser.busy(); + curUser.sprite.parent.add(new Chains(curUser.pos, target, new Callback() { + public void call() { + Actor.add(new Pushing(curUser, curUser.pos, newHeroPos, new Callback() { + public void call() { + Dungeon.level.press(newHeroPos, curUser); + } + })); + curUser.spendAndNext(1f); + curUser.pos = newHeroPos; + Dungeon.observe(); + } + })); + } + + } else { + GLog.i( Messages.get(EtherealChains.class, "nothing_to_grab") ); + } + + } + + } + + @Override + public String prompt() { + return Messages.get(EtherealChains.class, "prompt"); + } + }; + + private CellSelector.Listener locker = new CellSelector.Listener(){ + + @Override + public void onSelect(Integer target) { + if (target != null && (Dungeon.level.visited[target] || Dungeon.level.mapped[target])){ + + if (Actor.findChar( target ) != null){ + Char mob = Actor.findChar(target); + Buff.affect(mob,Locked.class,level*4f); + Buff.affect(mob,Silent.class,level*4f); + Buff.affect(mob,AttackDown.class,level*4f).level(90); + Buff.affect(mob,Slow.class,level*4f); + level--; + Sample.INSTANCE.play(Assets.SND_BURNING); + curUser.sprite.emitter().burst(ElmoParticle.FACTORY, 12); + curUser.spendAndNext(1f); + updateQuickslot(); + + } else { + GLog.i( Messages.get(EtherealChains.class, "nothing_to_grab") ); + } + + } + + } + + @Override + public String prompt() { + return Messages.get(EtherealChains.class, "prompt"); + } + }; + + @Override + protected ArtifactBuff passiveBuff() { + return new chainsRecharge(); + } + + @Override + public String desc() { + String desc = super.desc(); + + if (isEquipped( Dungeon.hero )){ + desc += "\n\n"; + if (cursed) + desc += Messages.get(this, "desc_cursed"); + else + desc += Messages.get(this, "desc_equipped"); + } + return desc; + } + + public class chainsRecharge extends ArtifactBuff{ + + @Override + public boolean act() { + int chargeTarget = 5+(level()*2); + if (charge < chargeTarget && !cursed ) { + partialCharge += 1 / (40f - (chargeTarget - charge)*2f); + } else if (cursed && Random.Int(100) == 0){ + Buff.prolong( target, Cripple.class, 10f); + } + + if (partialCharge >= 1) { + partialCharge --; + charge ++; + } + + updateQuickslot(); + + spend( TICK ); + + return true; + } + + public void gainExp( float levelPortion ) { + if (cursed) return; + + exp += Math.round(levelPortion*100); + + //past the soft charge cap, gaining charge from leveling is slowed. + if (charge > 5+(level()*2)){ + levelPortion *= (5+((float)level()*2))/charge; + } + partialCharge += levelPortion*10f; + + if (exp > 100+level()*50 && level() < levelCap){ + exp -= 100+level()*50; + GLog.p( Messages.get(this, "levelup") ); + upgrade(); + } + + } + } +} diff --git a/java/com/hmdzl/spspd/items/artifacts/EyeOfSkadi.java b/java/com/hmdzl/spspd/items/artifacts/EyeOfSkadi.java new file mode 100644 index 00000000..bed8423a --- /dev/null +++ b/java/com/hmdzl/spspd/items/artifacts/EyeOfSkadi.java @@ -0,0 +1,270 @@ +package com.hmdzl.spspd.items.artifacts; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.ArmorBreak; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Chill; +import com.hmdzl.spspd.actors.buffs.Frost; +import com.hmdzl.spspd.actors.buffs.Poison; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.particles.ElmoParticle; +import com.hmdzl.spspd.effects.particles.SnowParticle; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.StoneOre; +import com.hmdzl.spspd.items.nornstone.NornStone; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.CellSelector; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; +import com.hmdzl.spspd.windows.WndBag; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +/** + * Created by dachhack on 10/15/2015. + */ +public class EyeOfSkadi extends Artifact { + + { + //name = "Eye of Skadi"; + image = ItemSpriteSheet.RING_FROST; + + level = 0; + exp = 0; + levelCap = 10; + + charge = 0; + partialCharge = 0; + chargeCap = 100; + + + defaultAction = AC_CURSE; + } + + protected WndBag.Mode mode = WndBag.Mode.STONE; + + public static int consumedpts = 0; + + public static final String AC_BLAST = "BLAST"; + public static final String AC_ADD = "ADD"; + public static final String AC_CURSE = "CURSE"; + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + if (isEquipped(hero) && charge == 100 && !cursed) + actions.add(AC_CURSE); + if (isEquipped(hero) && level < levelCap && !cursed) + actions.add(AC_ADD); + if (isEquipped(hero) && level > 1 && !cursed) + actions.add(AC_BLAST); + return actions; + } + + @Override + public void execute(Hero hero, String action) { + super.execute(hero, action); + if (action.equals(AC_BLAST)) { + curUser = hero; + if (!isEquipped(hero)) + GLog.i(Messages.get(Artifact.class, "need_to_equip") ); + else { + + blast(hero.pos); + level--; + exp -=level; + Sample.INSTANCE.play(Assets.SND_BURNING); + updateQuickslot(); + //GLog.p("Blast!"); + CellEmitter.get(hero.pos).start(SnowParticle.FACTORY, 0.2f, 6); + + } + + } else if (action.equals(AC_ADD)) { + GameScene.selectItem(itemSelector, mode,Messages.get(this, "prompt")); + } else if (action.equals(AC_CURSE)) { + curUser = hero; + if (charge != chargeCap) {GLog.i(Messages.get(this, "no_charge"));} + else GameScene.selectCell(curser); + } + } + + private CellSelector.Listener curser = new CellSelector.Listener(){ + + @Override + public void onSelect(Integer target) { + if (target != null && (Dungeon.level.visited[target] || Dungeon.level.mapped[target])){ + + if (Actor.findChar( target ) != null){ + Char mob = Actor.findChar(target); + Buff.affect(mob,Poison.class).set(level*2f); + Buff.affect(mob,Frost.class,level*4f); + Buff.affect(mob,ArmorBreak.class,level*4f).level(80); + Buff.affect(mob,Chill.class,level*4f); + charge = 0; + curUser.sprite.emitter().burst(ElmoParticle.FACTORY, 12); + curUser.spendAndNext(1f); + updateQuickslot(); + + } else { + GLog.i( Messages.get(EtherealChains.class, "nothing_to_grab") ); + } + + } + + } + + @Override + public String prompt() { + return Messages.get(EtherealChains.class, "prompt"); + } + }; + + public int level(){ + return level; + } + + public void blast(int cell) { + for (Mob mob : Dungeon.level.mobs.toArray(new Mob[0])) { + + mob.damage(Random.Int(mob.HP/4,mob.HP/2 ), this); + Buff.prolong(mob, Frost.class, Frost.duration(mob)* Random.Float(1f*level(), 1.5f*level())); + CellEmitter.get(mob.pos).start(SnowParticle.FACTORY, 0.2f, 6); + + } + eyeUsed(); + } + + + + protected void eyeUsed() { + + updateQuickslot(); + + } + + + + + @Override + protected ArtifactBuff passiveBuff() { + return new eyeRecharge(); + } + + @Override + public String desc() { + String desc = super.desc(); + if (isEquipped(Dungeon.hero)) { + if (charge < 100) + desc += "\n\n" + Messages.get(this,"need_charge"); + else + desc += "\n\n" + Messages.get(this,"full_charge"); + } + + return desc; + } + + public class eyeRecharge extends ArtifactBuff { + @Override + public boolean act() { + if (charge < chargeCap && !cursed ) { + + partialCharge += 1+level; + + if (partialCharge >= 10) { + charge++; + partialCharge = 0; + if (charge == chargeCap) { + partialCharge = 0; + } + + } + } else if (cursed && Random.Int(100) == 0){ + Buff.prolong( target, Frost.class, 5f); + } else + partialCharge = 0; + + + updateQuickslot(); + + spend(TICK); + + return true; + } + + } + + private static final String PARTIALCHARGE = "partialCharge"; + private static final String CHARGE = "charge"; + private static final String CONSUMED = "consumedpts"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(PARTIALCHARGE, partialCharge); + bundle.put(CHARGE, charge); + bundle.put(CONSUMED, consumedpts); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + partialCharge = bundle.getInt(PARTIALCHARGE); + charge = bundle.getInt(CHARGE); + consumedpts = bundle.getInt(CONSUMED); + } + + protected static WndBag.Listener itemSelector = new WndBag.Listener() { + @Override + public void onSelect(Item item) { + if (item != null && item instanceof StoneOre) { + Hero hero = Dungeon.hero; + consumedpts += 1; + + hero.sprite.operate(hero.pos); + hero.busy(); + hero.spend(2f); + Sample.INSTANCE.play(Assets.SND_BURNING); + hero.sprite.emitter().burst(ElmoParticle.FACTORY, 12); + item.detach(hero.belongings.backpack); + GLog.h(Messages.get(EyeOfSkadi.class, "exp",consumedpts)); + + int levelChk = curItem.level*2 + 1 ; + + if (consumedpts > levelChk && curItem.level<10) { + curItem.upgrade(); + GLog.p(Messages.get(EyeOfSkadi.class, "infuse_ore")); + } + + } else if (item != null && item instanceof NornStone) { + Hero hero = Dungeon.hero; + consumedpts += 5; + + hero.sprite.operate(hero.pos); + hero.busy(); + hero.spend(2f); + Sample.INSTANCE.play(Assets.SND_BURNING); + hero.sprite.emitter().burst(ElmoParticle.FACTORY, 12); + item.detach(hero.belongings.backpack); + GLog.h(Messages.get(EyeOfSkadi.class, "exp", consumedpts)); + + int levelChk = curItem.level * 2 + 1; + + if (consumedpts > levelChk && curItem.level < 10) { + curItem.upgrade(); + GLog.p(Messages.get(EyeOfSkadi.class, "infuse_ore")); + } + } + } + }; + +} diff --git a/java/com/hmdzl/spspd/items/artifacts/GlassTotem.java b/java/com/hmdzl/spspd/items/artifacts/GlassTotem.java new file mode 100644 index 00000000..49df67b8 --- /dev/null +++ b/java/com/hmdzl/spspd/items/artifacts/GlassTotem.java @@ -0,0 +1,128 @@ +package com.hmdzl.spspd.items.artifacts; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.actors.buffs.ArmorBreak; +import com.hmdzl.spspd.actors.buffs.AttackUp; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.DefenceUp; +import com.hmdzl.spspd.actors.buffs.GlassShield; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.particles.ElmoParticle; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Random; + +/** + * Created by dachhack on 10/15/2015. + */ +public class GlassTotem extends Artifact { + + { + //name = "Glass Totem"; + image = ItemSpriteSheet.GLASSTOTEM; + + level = 0; + levelCap = 10; + + defaultAction = AC_ATK; + } + + public static final String AC_ATK = "ATK"; + public static final String AC_DEF = "DEF"; + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + if (isEquipped(hero)&& !cursed){ + actions.add(AC_ATK);} + if (isEquipped(hero) && level > 1 && !cursed) + actions.add(AC_DEF); + return actions; + } + + @Override + public void execute(Hero hero, String action) { + super.execute(hero, action); + if (action.equals(AC_ATK)) { + if (!isEquipped(hero)) + GLog.i(Messages.get(Artifact.class, "need_to_equip") ); + else if (cursed) + GLog.i( Messages.get(Artifact.class, "cursed") ); + else { + if (level<10)level++; + Buff.affect(hero, AttackUp.class,200).level(75); + Buff.affect(hero, ArmorBreak.class,200).level(75); + hero.spend(1f); + hero.busy(); + hero.sprite.operate(hero.pos); + updateQuickslot(); + } + + } else if (action.equals(AC_DEF)) { + if (!isEquipped(hero)) + GLog.i(Messages.get(Artifact.class, "need_to_equip") ); + else { + if (level > 1 )level--; + Sample.INSTANCE.play(Assets.SND_BURNING); + hero.sprite.emitter().burst(ElmoParticle.FACTORY, 12); + Buff.detach(hero, AttackUp.class); + Buff.affect(hero, GlassShield.class).turns(2); + hero.spend(3f); + hero.busy(); + hero.sprite.operate(hero.pos); + updateQuickslot(); + } + } + } + + //public int level(){ + //return level; + //} + + + @Override + protected ArtifactBuff passiveBuff() { + return new glassRecharge(); + } + + @Override + public String desc() { + String desc = super.desc(); + return desc; + } + + public class glassRecharge extends ArtifactBuff { + @Override + public boolean act() { + if (cursed && Random.Int(100) == 0){ + Buff.affect( target, ArmorBreak.class, 10f).level(100); + } else if (Random.Int(1000/(level+1)) == 0){ + Buff.affect( target, AttackUp.class, 5f).level(20); + Buff.affect( target, DefenceUp.class, 5f).level(20); + } + spend( TICK ); + return true; + } + } + + /*private static final String PARTIALCHARGE = "partialCharge"; + private static final String CHARGE = "charge"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(PARTIALCHARGE, partialCharge); + bundle.put(CHARGE, charge); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + partialCharge = bundle.getInt(PARTIALCHARGE); + charge = bundle.getInt(CHARGE); + }*/ +} diff --git a/java/com/hmdzl/spspd/items/artifacts/HornOfPlenty.java b/java/com/hmdzl/spspd/items/artifacts/HornOfPlenty.java new file mode 100644 index 00000000..ff6b526f --- /dev/null +++ b/java/com/hmdzl/spspd/items/artifacts/HornOfPlenty.java @@ -0,0 +1,231 @@ +package com.hmdzl.spspd.items.artifacts; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.Statistics; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Feed; +import com.hmdzl.spspd.actors.buffs.Recharging; +import com.hmdzl.spspd.actors.buffs.Hunger; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.effects.SpellSprite; +import com.hmdzl.spspd.effects.particles.ElmoParticle; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.food.fruit.Blandfruit; +import com.hmdzl.spspd.items.food.Food; +import com.hmdzl.spspd.items.scrolls.ScrollOfRecharging; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; +import com.hmdzl.spspd.windows.WndBag; +import com.watabou.noosa.audio.Sample; + +/** + * Created by debenhame on 26/08/2014. + */ +public class HornOfPlenty extends Artifact { + + { + //name = "Horn of Plenty"; + image = ItemSpriteSheet.ARTIFACT_HORN1; + + level = 0; + levelCap = 30; + + charge = 0; + partialCharge = 0; + chargeCap = 10; + + defaultAction = AC_EAT; + } + + private static final float TIME_TO_EAT = 3f; + + private float energy = 36f; + + public static final String AC_EAT = "EAT"; + public static final String AC_STORE = "STORE"; + public static final String AC_FEED = "FEED"; + + protected String inventoryTitle = "Select a piece of food"; + protected WndBag.Mode mode = WndBag.Mode.FOOD; + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + if (isEquipped(hero) && charge > 0) + actions.add(AC_EAT); + if (isEquipped(hero) && level < 30 && !cursed) + actions.add(AC_STORE); + if (isEquipped(hero) && level > 0 && !cursed) + actions.add(AC_FEED); + return actions; + } + + @Override + public void execute(Hero hero, String action) { + super.execute(hero, action); + + if (action.equals(AC_EAT)) { + + if (!isEquipped(hero)) + GLog.i( Messages.get(Artifact.class, "need_to_equip")); + else if (charge == 0) + GLog.i( Messages.get(this, "no_food") ); + else { + hero.buff(Hunger.class).satisfy(energy * charge); + + // if you get at least 100 food energy from the horn + if (charge >= 3) { + switch (hero.heroClass) { + case WARRIOR: + if (hero.HP < hero.HT) { + hero.HP = Math.min(hero.HP + 5, hero.HT); + hero.sprite.emitter().burst( + Speck.factory(Speck.HEALING), 1); + } + break; + case MAGE: + Buff.affect( hero, Recharging.class, 4f ); + ScrollOfRecharging.charge(hero); + break; + case ROGUE: + case HUNTRESS: + case PERFORMER: + case SOLDIER: + case FOLLOWER: + break; + } + + Statistics.foodEaten++; + } + charge = 0; + + hero.sprite.operate(hero.pos); + hero.busy(); + SpellSprite.show(hero, SpellSprite.FOOD); + Sample.INSTANCE.play(Assets.SND_EAT); + GLog.i( Messages.get(this, "eat")); + + hero.spend(TIME_TO_EAT); + + Badges.validateFoodEaten(); + + image = ItemSpriteSheet.ARTIFACT_HORN1; + + updateQuickslot(); + } + + } else if (action.equals(AC_STORE)) { + + GameScene.selectItem(itemSelector, mode,Messages.get(this, "prompt")); + } else if (action.equals(AC_FEED)) { + if (!isEquipped(hero)) + GLog.i(Messages.get(Artifact.class, "need_to_equip") ); + else { + Buff.affect(hero, Feed.class,level*3f); + hero.spend(1f); + hero.busy(); + hero.sprite.operate(hero.pos); + Sample.INSTANCE.play(Assets.SND_BURNING); + hero.sprite.emitter().burst(ElmoParticle.FACTORY, 12); + level = 0; + updateQuickslot(); + } + } + } + + @Override + protected ArtifactBuff passiveBuff() { + return new hornRecharge(); + } + + @Override + public String desc() { + String desc = super.desc(); + + if ( isEquipped( Dungeon.hero ) ){ + if (!cursed) { + if (level < levelCap) + desc += "\n\n" +Messages.get(this, "desc_hint"); + } else { + desc += "\n\n" +Messages.get(this, "desc_cursed"); + } + } + + return desc; + } + + public class hornRecharge extends ArtifactBuff { + + @Override + public boolean act() { + if (charge < chargeCap && !cursed) { + + // generates 0.25 food value every round, +0.015 value per level + // to a max of 0.70 food value per round (0.25+0.5, at level 30) + partialCharge += 0.25f + (0.015f * level); + + // charge is in increments of 36 food value. + if (partialCharge >= 80) { + charge++; + partialCharge -= 80; + + if (charge == chargeCap) + image = ItemSpriteSheet.ARTIFACT_HORN4; + else if (charge >= 7) + image = ItemSpriteSheet.ARTIFACT_HORN3; + else if (charge >= 3) + image = ItemSpriteSheet.ARTIFACT_HORN2; + else + image = ItemSpriteSheet.ARTIFACT_HORN1; + + if (charge == chargeCap) { + GLog.p(Messages.get(HornOfPlenty.class, "full")); + partialCharge = 0; + } + + updateQuickslot(); + } + } else + partialCharge = 0; + + spend(TICK); + + return true; + } + + } + + protected static WndBag.Listener itemSelector = new WndBag.Listener() { + @Override + public void onSelect(Item item) { + if (item != null && item instanceof Food) { + if (item instanceof Blandfruit + && ((Blandfruit) item).potionAttrib == null) { + GLog.w(Messages.get(HornOfPlenty.class, "reject") ); + } else { + Hero hero = Dungeon.hero; + hero.sprite.operate(hero.pos); + hero.busy(); + hero.spend(TIME_TO_EAT); + + curItem.upgrade(((Food) item).hornValue); + if (curItem.level >= 30) { + curItem.level = 30; + GLog.p( Messages.get(HornOfPlenty.class, "maxlevel") ); + } else + GLog.p(Messages.get(HornOfPlenty.class, "levelup")); + item.detach(hero.belongings.backpack); + } + + } + } + }; + +} diff --git a/java/com/hmdzl/spspd/items/artifacts/MasterThievesArmband.java b/java/com/hmdzl/spspd/items/artifacts/MasterThievesArmband.java new file mode 100644 index 00000000..bab4035a --- /dev/null +++ b/java/com/hmdzl/spspd/items/artifacts/MasterThievesArmband.java @@ -0,0 +1,135 @@ +package com.hmdzl.spspd.items.artifacts; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.GoldTouch; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.particles.ElmoParticle; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Random; + +import java.util.ArrayList; + +/** + * Created by debenhame on 03/09/2014. + */ +public class MasterThievesArmband extends Artifact { + + { + //name = "Master Thieves' Armband"; + image = ItemSpriteSheet.ARTIFACT_ARMBAND; + + level = 0; + levelCap = 10; + + charge = 0; + } + + private int exp = 0; + public static final String AC_GOLDTOUCH = "GOLDTOUCH"; + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + if (!isEquipped(hero) && level > 1 && !cursed ) + actions.add(AC_GOLDTOUCH); + return actions; + } + + @Override + public void execute(Hero hero, String action) { + super.execute(hero, action); + if (action.equals(AC_GOLDTOUCH)) { + + Buff.affect(hero, GoldTouch.class,level*10f); + Sample.INSTANCE.play(Assets.SND_BURNING); + hero.sprite.emitter().burst(ElmoParticle.FACTORY, 12); + hero.spend(1f); + hero.busy(); + hero.sprite.operate(hero.pos); + detach(curUser.belongings.backpack); + Dungeon.level.drop(Generator.random(Generator.Category.ARTIFACT),hero.pos); + + } + } + + @Override + protected ArtifactBuff passiveBuff() { + return new Thievery(); + } + + @Override + public String desc() { + String desc = super.desc(); + + if ( isEquipped (Dungeon.hero) ) + desc += "\n\n" + Messages.get(this, "desc_worn"); + + return desc; + } + + public class Thievery extends ArtifactBuff { + public void collect(int gold) { + if (!cursed) { + charge += gold/2; + } + } + + @Override + public void detach() { + charge *= 0.95; + super.detach(); + } + + @Override + public boolean act() { + if (cursed) { + + if (Dungeon.gold > 0 && Random.Int(6) == 0){ + Dungeon.gold--; + } + + spend(TICK); + return true; + } else { + return super.act(); + } + } + + public boolean steal(int value) { + if (value <= charge) { + charge -= value; + exp += value; + } else { + float chance = stealChance(value); + //if (Random.Float() > chance) + //return false; + //else { + if (chance <= 1) + charge = 0; + else + // removes the charge it took you to reach 100% + charge -= charge / chance; + exp += value; + //} + } + while (exp >= 1000 && level < levelCap) { + exp -= 1000; + upgrade(); + } + return true; + } + + public float stealChance(int value) { + // get lvl*100 gold or lvl*5% item value of free charge, whichever + // is less. + //int chargeBonus = Math.min(level * 100, (value * level) / 20); + int chargeBonus = Math.min(level * 100, (value * level) / 20); + return (((float) charge + chargeBonus) / value); + } + } +} diff --git a/java/com/hmdzl/spspd/items/artifacts/Pylon.java b/java/com/hmdzl/spspd/items/artifacts/Pylon.java new file mode 100644 index 00000000..9dc0f118 --- /dev/null +++ b/java/com/hmdzl/spspd/items/artifacts/Pylon.java @@ -0,0 +1,324 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2015 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.items.artifacts; +//If it weren't super obvious, this is going to become an artifact soon. + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Invisibility; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.effects.MagicMissile; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.scrolls.ScrollOfTeleportation; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.CellSelector; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.scenes.InterlevelScene; +import com.hmdzl.spspd.sprites.CharSprite; +import com.hmdzl.spspd.sprites.ItemSprite.Glowing; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.noosa.Game; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Bundle; +import com.watabou.utils.Callback; + +import java.util.ArrayList; + +public class Pylon extends Artifact { + + public static final float TIME_TO_USE = 1; + + public static final String AC_ZAP = "ZAP"; + public static final String AC_SET = "SET"; + public static final String AC_RETURN = "RETURN"; + public static final String AC_RANKUP = "RANKUP"; + + private int returnDepth = -1; + private int returnPos; + + { + image = ItemSpriteSheet.ARTIFACT_BEACON; + + levelCap = 3; + + charge = 0; + chargeCap = 3; + + defaultAction = AC_ZAP; + usesTargeting = true; + } + + private static final String DEPTH = "depth"; + private static final String POS = "pos"; + + @Override + public void storeInBundle( Bundle bundle ) { + super.storeInBundle( bundle ); + bundle.put( DEPTH, returnDepth ); + if (returnDepth != -1) { + bundle.put( POS, returnPos ); + } + } + + @Override + public void restoreFromBundle( Bundle bundle ) { + super.restoreFromBundle(bundle); + returnDepth = bundle.getInt( DEPTH ); + returnPos = bundle.getInt( POS ); + } + + @Override + public ArrayList actions( Hero hero ) { + ArrayList actions = super.actions( hero ); + actions.add( AC_ZAP ); + actions.add( AC_SET ); + if (returnDepth != -1) { + actions.add( AC_RETURN ); + } + if (level == 3) { + actions.add( AC_RANKUP ); + } + return actions; + } + + @Override + public void execute( Hero hero, String action ) { + + if (action == AC_SET || action == AC_RETURN) { + + if (Dungeon.bossLevel() || Dungeon.depth > 25) { + hero.spend( 1f ); + GLog.w( Messages.get(this, "preventing") ); + return; + } + + for (int i=0; i < Level.NEIGHBOURS8.length; i++) { + if (Actor.findChar( hero.pos + Level.NEIGHBOURS8[i] ) != null) { + GLog.w( Messages.get(this, "creatures") ); + return; + } + } + } + + if (action == AC_ZAP ){ + + curUser = hero; + int chargesToUse = 1; + + if (!isEquipped( hero )) GLog.i( Messages.get(Artifact.class, "need_to_equip") ); + else if (charge < chargesToUse) GLog.i( Messages.get(this, "no_charge") ); + else { + GameScene.selectCell(zapper); + } + + } else if (action == AC_SET) { + + returnDepth = Dungeon.depth; + returnPos = hero.pos; + + hero.spend( 1f ); + hero.busy(); + + hero.sprite.operate( hero.pos ); + Sample.INSTANCE.play( Assets.SND_BEACON ); + + GLog.i( Messages.get(this, "return") ); + + } else if (action == AC_RETURN) { + + if (returnDepth == Dungeon.depth) { + ScrollOfTeleportation.appear( hero, returnPos ); + Dungeon.level.press( returnPos, hero ); + Dungeon.observe(); + } else { + + Buff buff = Dungeon.hero.buff(TimekeepersHourglass.timeFreeze.class); + if (buff != null) buff.detach(); + + for (Mob mob : Dungeon.level.mobs.toArray( new Mob[0] )) + if (mob instanceof DriedRose.GhostHero) mob.destroy(); + + InterlevelScene.mode = InterlevelScene.Mode.RETURN; + InterlevelScene.returnDepth = returnDepth; + InterlevelScene.returnPos = returnPos; + Game.switchScene( InterlevelScene.class ); + } + + + } else if (action == AC_RANKUP) { + hero.HT +=5; + hero.hitSkill++; + hero.evadeSkill++; + hero.magicSkill++; + level = 0; + hero.sprite.showStatus(CharSprite.POSITIVE, Messages.get(this, "rankup")); + }else { + + super.execute( hero, action ); + + } + } + + protected CellSelector.Listener zapper = new CellSelector.Listener() { + + @Override + public void onSelect(Integer target) { + + if (target == null) return; + + Invisibility.dispel(); + charge -= 1; + updateQuickslot(); + + if (Actor.findChar(target) == curUser){ + ScrollOfTeleportation.teleportHero(curUser); + curUser.spendAndNext(1f); + } else { + final Ballistica bolt = new Ballistica( curUser.pos, target, Ballistica.MAGIC_BOLT ); + final Char ch = Actor.findChar(bolt.collisionPos); + + if (ch == curUser){ + ScrollOfTeleportation.teleportHero(curUser); + curUser.spendAndNext( 1f ); + } else { + Sample.INSTANCE.play( Assets.SND_ZAP ); + curUser.sprite.zap(bolt.collisionPos); + curUser.busy(); + + MagicMissile.force(curUser.sprite.parent, bolt.sourcePos, bolt.collisionPos, new Callback() { + @Override + public void call() { + if (ch != null) { + + int count = 10; + int pos; + do { + pos = Dungeon.level.randomRespawnCell(); + if (count-- <= 0) { + break; + } + } while (pos == -1); + + + if (pos == -1 || Dungeon.bossLevel()) { + + GLog.w( Messages.get(ScrollOfTeleportation.class, "no_tele") ); + + } else if (ch.properties().contains(Char.Property.IMMOVABLE)) { + + GLog.w( Messages.get(Pylon.class, "tele_fail") ); + + } else { + + ch.pos = pos; + ch.sprite.place(ch.pos); + ch.sprite.visible = Dungeon.visible[pos]; + + } + } + curUser.spendAndNext(1f); + } + }); + + } + + + } + + } + + @Override + public String prompt() { + return Messages.get(Pylon.class, "prompt"); + } + }; + + @Override + protected ArtifactBuff passiveBuff() { + return new beaconRecharge(); + } + + @Override + public Item upgrade() { + if (level == levelCap) return this; + if (charge < chargeCap) charge ++; + GLog.p( Messages.get(this, "levelup") ); + return super.upgrade(); + } + + @Override + public String desc() { + String desc = super.desc(); + if (returnDepth != -1){ + desc += "\n\n" + Messages.get(this, "desc_set", returnDepth); + } + return desc; + } + + public void reset() { + returnDepth = -1; + } + + private static final Glowing WHITE = new Glowing( 0xFFFFFF ); + + @Override + public Glowing glowing() { + return returnDepth != -1 ? WHITE : null; + } + + public class beaconRecharge extends ArtifactBuff{ + @Override + public boolean act() { + if (charge < chargeCap && !cursed ) { + partialCharge += 1 / (100f - (chargeCap - charge)*10f); + + if (partialCharge >= 1) { + partialCharge --; + charge ++; + + if (charge == chargeCap){ + partialCharge = 0; + } + } + } + + updateQuickslot(); + spend( TICK ); + return true; + } + public void gainExp( float levelPortion ) { + if (cursed) return; + exp += Math.round(levelPortion*100); + if (exp > 300 && level() < levelCap){ + exp -= 300; + upgrade(); + } + + } + } +} diff --git a/java/com/hmdzl/spspd/items/artifacts/RobotDMT.java b/java/com/hmdzl/spspd/items/artifacts/RobotDMT.java new file mode 100644 index 00000000..7b092d19 --- /dev/null +++ b/java/com/hmdzl/spspd/items/artifacts/RobotDMT.java @@ -0,0 +1,227 @@ +package com.hmdzl.spspd.items.artifacts; + +import java.io.IOException; +import java.util.ArrayList; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.buffs.AttackUp; +import com.hmdzl.spspd.actors.buffs.BerryRegeneration; +import com.hmdzl.spspd.actors.buffs.Bless; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.DefenceUp; +import com.hmdzl.spspd.actors.buffs.Dewcharge; +import com.hmdzl.spspd.actors.buffs.Invisibility; +import com.hmdzl.spspd.actors.buffs.MindVision; +import com.hmdzl.spspd.actors.buffs.Strength; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.particles.ElmoParticle; +import com.hmdzl.spspd.items.armor.normalarmor.ErrorArmor; +import com.hmdzl.spspd.items.wands.WandOfError; +import com.hmdzl.spspd.items.weapon.melee.special.ErrorW; +import com.hmdzl.spspd.items.weapon.missiles.ErrorAmmo; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.LoadSaveScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.noosa.Game; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +/** + * Created by dachhack on 10/15/2015. + */ +public class RobotDMT extends Artifact { + + { + //name = "Robot Determination"; + image = ItemSpriteSheet.RING_DISINTEGRATION; + + level = 0; + exp = 0; + levelCap = 10; + + charge = 0; + partialCharge = 0; + chargeCap = 100; + + + defaultAction = AC_HEART; + } + + public static final String AC_HEART = "HEART"; + public static final String AC_MEMORY = "MEMORY"; + public static final String AC_ERROR = "ERROR"; + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + if (isEquipped(hero) && charge == 100 && !cursed) + actions.add(AC_HEART); + if (level > 9 && !isEquipped(hero) ) + actions.add(AC_MEMORY); + if (Dungeon.error == true && !isEquipped(hero)) + actions.add(AC_ERROR); + return actions; + } + + @Override + public void execute(Hero hero, String action) { + super.execute(hero, action); + if (action.equals(AC_HEART)) { + + if (!isEquipped(hero)) + GLog.i(Messages.get(Artifact.class, "need_to_equip") ); + else if (charge != chargeCap) + GLog.i(Messages.get(this, "no_charge")); + else { + charge = 0; + if (level < 10 )level++; + switch (Random.Int(level)){ + case 0: + Buff.affect(hero, Invisibility.class,50); + GLog.w(Messages.get(this,"patience")); + break; + case 1: + Buff.affect(hero, AttackUp.class,100).level(20); + Buff.affect(hero, DefenceUp.class,100).level(20); + GLog.w(Messages.get(this,"bravery")); + break; + case 2: + Buff.affect(hero, MindVision.class,80); + GLog.w(Messages.get(this,"integrity")); + break; + case 3: + Buff.affect(hero, Bless.class,50); + GLog.w(Messages.get(this,"preseverance")); + break; + case 4: + Buff.affect(hero, BerryRegeneration.class).level(20); + GLog.w(Messages.get(this,"kindness")); + break; + case 5: + Buff.affect(hero,Strength.class); + GLog.w(Messages.get(this,"justice")); + break; + case 6: + Buff.affect(hero,Dewcharge.class, 100f); + GLog.w(Messages.get(this,"soul")); + break; + case 7: + //Buff.affect(hero,Dewcharge.class, 100f); + GLog.w(Messages.get(this,"friendship")); + break; + case 8: + // + GLog.w(Messages.get(this,"chaos")); + Dungeon.error = true; + break; + default: + // + GLog.w(Messages.get(this,"determination")); + break; + } + hero.spend(1f); + updateQuickslot(); + } + + } else if (action.equals(AC_MEMORY)) { + //showPudding_cupScene(false); + curUser = hero; + detach(curUser.belongings.backpack); + try { + Dungeon.saveAll(); + } catch (IOException e) { + // + } + Dungeon.canSave=true; + Game.switchScene(LoadSaveScene.class); + } else if (action.equals(AC_ERROR)) { + curUser = hero; + curUser.spendAndNext(1f); + detach(curUser.belongings.backpack); + Dungeon.error = false; + Sample.INSTANCE.play(Assets.SND_BURNING); + hero.sprite.emitter().burst(ElmoParticle.FACTORY, 12); + switch (Random.Int(4)){ + case 0: + Dungeon.level.drop(new ErrorW() ,Dungeon.hero.pos).sprite.drop(); + break; + case 1: + Dungeon.level.drop(new WandOfError(),Dungeon.hero.pos).sprite.drop(); + break; + case 2: + Dungeon.level.drop(new ErrorArmor(),Dungeon.hero.pos).sprite.drop(); + break; + case 3: + Dungeon.level.drop(new ErrorAmmo(3),Dungeon.hero.pos).sprite.drop(); + break; + + } + } + } + + public int level(){ + return level; + } + + + @Override + protected ArtifactBuff passiveBuff() { + return new dmtRecharge(); + } + + @Override + public String desc() { + String desc = super.desc(); + if (isEquipped(Dungeon.hero)) { + if (charge == 100) + desc += "\n\n" + Messages.get(this,"full_charge"); + } + return desc; + } + + public class dmtRecharge extends ArtifactBuff { + @Override + public boolean act() { + if (charge < chargeCap) { + partialCharge += 1f; + if (partialCharge >= 5) { + charge++; + partialCharge = 0; + if (charge == chargeCap) { + partialCharge = 0; + } + + } + } else + partialCharge = 0; + + + updateQuickslot(); + + spend(TICK); + + return true; + } + + } + + private static final String PARTIALCHARGE = "partialCharge"; + private static final String CHARGE = "charge"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(PARTIALCHARGE, partialCharge); + bundle.put(CHARGE, charge); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + partialCharge = bundle.getInt(PARTIALCHARGE); + charge = bundle.getInt(CHARGE); + } +} diff --git a/java/com/hmdzl/spspd/items/artifacts/SandalsOfNature.java b/java/com/hmdzl/spspd/items/artifacts/SandalsOfNature.java new file mode 100644 index 00000000..e13d6fc7 --- /dev/null +++ b/java/com/hmdzl/spspd/items/artifacts/SandalsOfNature.java @@ -0,0 +1,204 @@ +package com.hmdzl.spspd.items.artifacts; + +import java.util.ArrayList; +import java.util.Collections; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.blobs.Blob; +import com.hmdzl.spspd.actors.blobs.Water; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Roots; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.particles.EarthParticle; +import com.hmdzl.spspd.effects.particles.ElmoParticle; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.plants.Earthroot; +import com.hmdzl.spspd.plants.Plant; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; +import com.hmdzl.spspd.windows.WndBag; +import com.watabou.noosa.Camera; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Bundle; + +/** + * Created by debenhame on 08/09/2014. + */ +public class SandalsOfNature extends Artifact { + + { + //name = "Sandals of Nature"; + image = ItemSpriteSheet.ARTIFACT_SANDALS; + + level = 0; + levelCap = 3; + + charge = 0; + + defaultAction = AC_ROOT; + } + + public static final String AC_FEED = "FEED"; + public static final String AC_ROOT = "ROOT"; + public static final String AC_SPROUT = "SPROUT"; + + //protected String inventoryTitle = "Select a seed"; + protected WndBag.Mode mode = WndBag.Mode.SEED; + + public ArrayList seeds = new ArrayList(); + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + if (isEquipped(hero) && level < 3 && !cursed) + actions.add(AC_FEED); + if (isEquipped(hero) && charge > 0) + actions.add(AC_ROOT); + if (level > 0 && !isEquipped(hero) ) + actions.add(AC_SPROUT); + return actions; + } + + @Override + public void execute(Hero hero, String action) { + super.execute(hero, action); + if (action.equals(AC_FEED)) { + GameScene.selectItem(itemSelector, mode, Messages.get(this, "prompt")); + } else if (action.equals(AC_ROOT) && level > 0) { + + if (!isEquipped(hero)) + GLog.i(Messages.get(Artifact.class, "need_to_equip")); + else if (charge == 0) + GLog.i(Messages.get(this, "no_charge")); + else { + Buff.prolong(hero, Roots.class, 5); + Buff.affect(hero, Earthroot.Armor.class).level(charge); + CellEmitter.bottom(hero.pos).start(EarthParticle.FACTORY, + 0.05f, 8); + Camera.main.shake(1, 0.4f); + charge = 0; + updateQuickslot(); + } + } else if (action.equals(AC_SPROUT)) { + curUser = hero; + int length = Level.getLength(); + + for (int i = 0; i < length; i++) { + + GameScene.add(Blob.seed(i, (2) * 20 * level, Water.class)); + + } + detach(curUser.belongings.backpack); + Sample.INSTANCE.play(Assets.SND_BURNING); + curUser.sprite.emitter().burst(ElmoParticle.FACTORY, 12); + curUser.spendAndNext(2f); + } + } + + @Override + protected ArtifactBuff passiveBuff() { + return new Naturalism(); + } + + @Override + public String desc() { + String desc = Messages.get(this, "desc_" + (level+1)); + + if (isEquipped(Dungeon.hero)) { + desc += "\n\n"; + if (!cursed) + desc += Messages.get(this, "desc_hint"); + else + desc += Messages.get(this, "desc_cursed"); + + if (level > 0) + desc += "\n\n" + Messages.get(this, "desc_ability"); + } + + if (!seeds.isEmpty()) { + desc += "\n\n" + Messages.get(this, "desc_seeds", seeds.size()); + } + + return desc; + } + + @Override + public Item upgrade() { + if (level < 0) + image = ItemSpriteSheet.ARTIFACT_SANDALS; + else if (level == 0) + image = ItemSpriteSheet.ARTIFACT_SHOES; + else if (level == 1) + image = ItemSpriteSheet.ARTIFACT_BOOTS; + else if (level >= 2) + image = ItemSpriteSheet.ARTIFACT_GREAVES; + name = Messages.get(this, "name_" + (level+1)); + return super.upgrade(); + } + + private static final String SEEDS = "seeds"; + //private static final String NAME = "name"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + //bundle.put(NAME, name); + bundle.put(SEEDS, seeds.toArray(new String[seeds.size()])); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + if (level > 0) name = Messages.get(this, "name_" + level); + if (bundle.contains(SEEDS)) + Collections.addAll(seeds, bundle.getStringArray(SEEDS)); + } + + public class Naturalism extends ArtifactBuff { + public void charge() { + if (charge < target.HT) { + // gain 1+(1*level)% of the difference between current charge + // and max HP. + charge += (Math.round((target.HT - charge) + * (.01 + level * 0.01))); + updateQuickslot(); + } + } + } + + protected WndBag.Listener itemSelector = new WndBag.Listener() { + @Override + public void onSelect(Item item) { + if (item != null && item instanceof Plant.Seed) { + if (seeds.contains(item.name())) { + GLog.w(Messages.get(SandalsOfNature.class, "already_fed")); + } else { + seeds.add(item.name()); + + Hero hero = Dungeon.hero; + hero.sprite.operate(hero.pos); + Sample.INSTANCE.play(Assets.SND_PLANT); + hero.busy(); + hero.spend(2f); + if (seeds.size() >= 3 + (level * 3)) { + seeds.clear(); + upgrade(); + if (level >= 1 && level <= 3) { + GLog.p(Messages.get(SandalsOfNature.class, "levelup")); + } + + } else { + GLog.i(Messages.get(SandalsOfNature.class, "absorb_seed")); + } + item.detach(hero.belongings.backpack); + } + } + } + }; + +} diff --git a/java/com/hmdzl/spspd/items/artifacts/TalismanOfForesight.java b/java/com/hmdzl/spspd/items/artifacts/TalismanOfForesight.java new file mode 100644 index 00000000..b2eb1a63 --- /dev/null +++ b/java/com/hmdzl/spspd/items/artifacts/TalismanOfForesight.java @@ -0,0 +1,222 @@ +package com.hmdzl.spspd.items.artifacts; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.buffs.Awareness; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Notice; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.particles.ElmoParticle; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.Terrain; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.ui.BuffIndicator; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.noosa.audio.Sample; + +/** + * Created by debenhame on 08/09/2014. + */ +public class TalismanOfForesight extends Artifact { + + { + //name = "Talisman of Foresight"; + image = ItemSpriteSheet.ARTIFACT_TALISMAN; + + level = 0; + exp = 0; + levelCap = 10; + + charge = 0; + partialCharge = 0; + chargeCap = 100; + + defaultAction = AC_SCRY; + } + + public static final String AC_SCRY = "SCRY"; + public static final String AC_NOTICE = "NOTICE"; + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + if (isEquipped(hero) && charge == 100 && !cursed && !Dungeon.sokobanLevel(Dungeon.depth)) + actions.add(AC_SCRY); + if (isEquipped(hero) && level > 2 && !cursed) + actions.add(AC_NOTICE); + return actions; + } + + @Override + public void execute(Hero hero, String action) { + super.execute(hero, action); + if (action.equals(AC_SCRY)) { + + if (!isEquipped(hero)) + GLog.i(Messages.get(Artifact.class, "need_to_equip") ); + else if (charge != chargeCap) + GLog.i(Messages.get(this, "no_charge")); + else { + hero.sprite.operate(hero.pos); + hero.busy(); + Sample.INSTANCE.play(Assets.SND_BEACON); + charge = 0; + for (int i = 0; i < Level.getLength(); i++) { + + int terr = Dungeon.level.map[i]; + if ((Terrain.flags[terr] & Terrain.SECRET) != 0) { + + GameScene.updateMap(i); + + if (Dungeon.visible[i]) { + GameScene.discoverTile(i, terr); + } + } + } + + GLog.p(Messages.get(this, "scry")); + + Buff.affect(hero, Awareness.class, Awareness.DURATION); + Dungeon.observe(); + } + } else if (action.equals(AC_NOTICE)) { + if (!isEquipped(hero)) + GLog.i(Messages.get(Artifact.class, "need_to_equip") ); + else { + if (level > 2 )level-=2; + Sample.INSTANCE.play(Assets.SND_BURNING); + hero.sprite.emitter().burst(ElmoParticle.FACTORY, 12); + Buff.affect(hero, Notice.class,(level+2)*10f); + hero.spend(1f); + hero.busy(); + hero.sprite.operate(hero.pos); + updateQuickslot(); + } + } + } + + @Override + protected ArtifactBuff passiveBuff() { + return new Foresight(); + } + + @Override + public String desc() { + String desc = super.desc(); + + if ( isEquipped( Dungeon.hero ) ){ + if (!cursed) { + desc += "\n\n" + Messages.get(this, "desc_worn"); + + } else { + desc += "\n\n" + Messages.get(this, "desc_cursed"); + } + } + + return desc; + } + + public class Foresight extends ArtifactBuff { + private int warn = 0; + + @Override + public boolean act() { + spend(TICK); + + boolean smthFound = false; + + int distance = 3; + + int cx = target.pos % Level.getWidth(); + int cy = target.pos / Level.getWidth(); + int ax = cx - distance; + if (ax < 0) { + ax = 0; + } + int bx = cx + distance; + if (bx >= Level.getWidth()) { + bx = Level.getWidth() - 1; + } + int ay = cy - distance; + if (ay < 0) { + ay = 0; + } + int by = cy + distance; + if (by >= Level.HEIGHT) { + by = Level.HEIGHT - 1; + } + + for (int y = ay; y <= by; y++) { + for (int x = ax, p = ax + y * Level.getWidth(); x <= bx; x++, p++) { + + if (Dungeon.visible[p] && Level.secret[p] + && Dungeon.level.map[p] != Terrain.SECRET_DOOR) + smthFound = true; + } + } + + if (smthFound == true && !cursed) { + if (warn == 0) { + GLog.w(Messages.get(this, "uneasy")); + if (target instanceof Hero) { + ((Hero) target).interrupt(); + } + } + warn = 3; + } else { + if (warn > 0) { + warn--; + } + } + BuffIndicator.refreshHero(); + + // fully charges in 2500 turns at lvl=0, scaling to 1000 turns at + // lvl = 10. + if (charge < 100 && !cursed) { + partialCharge += 0.04 + (level * 0.006); + + if (partialCharge > 1 && charge < 100) { + partialCharge--; + charge++; + } else if (charge >= 100) { + partialCharge = 0; + GLog.p(Messages.get(this, "full_charge")); + } + } + + return true; + } + + public void charge() { + charge = Math.min(charge + (2 + (level / 3)), chargeCap); + exp++; + if (exp >= 4 && level < levelCap) { + upgrade(); + GLog.p(Messages.get(this, "levelup") ); + exp -= 4; + } + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public String desc() { + return Messages.get(this, "desc"); + } + + @Override + public int icon() { + if (warn == 0) + return BuffIndicator.NONE; + else + return BuffIndicator.FORESIGHT; + } + } +} diff --git a/java/com/hmdzl/spspd/items/artifacts/TimekeepersHourglass.java b/java/com/hmdzl/spspd/items/artifacts/TimekeepersHourglass.java new file mode 100644 index 00000000..e79759be --- /dev/null +++ b/java/com/hmdzl/spspd/items/artifacts/TimekeepersHourglass.java @@ -0,0 +1,390 @@ +package com.hmdzl.spspd.items.artifacts; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.AttackUp; +import com.hmdzl.spspd.actors.buffs.Bless; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.DefenceUp; +import com.hmdzl.spspd.actors.buffs.Hunger; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.effects.particles.ElmoParticle; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.CharSprite; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; +import com.hmdzl.spspd.windows.WndOptions; +import com.watabou.noosa.Group; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +/** + * Created by debenhame on 01/12/2014. + */ +public class TimekeepersHourglass extends Artifact { + + private static final String TXT_HGLASS = "Timekeeper's Hourglass"; + private static final String TXT_STASIS = "Put myself in stasis"; + private static final String TXT_FREEZE = "Freeze time around me"; + private static final String TXT_DESC = "How would you like to use the hourglass's magic?\n\n" + + "While in stasis, time will move normally while you are frozen and completely invulnerable.\n\n" + + "When time is frozen, you can move as if your actions take no time. Note that attacking will break this."; + + { + //name = "Timekeeper's Hourglass"; + image = ItemSpriteSheet.ARTIFACT_HOURGLASS; + + level = 0; + levelCap = 5; + + charge = 10 + level * 2; + partialCharge = 0; + chargeCap = 10 + level * 2; + + defaultAction = AC_ACTIVATE; + } + + public static final String AC_ACTIVATE = "ACTIVATE"; + public static final String AC_RESTART = "RESTART"; + + // keeps track of generated sandbags. + public int sandBags = 0; + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + if (isEquipped(hero) && charge > 0 && !cursed) + actions.add(AC_ACTIVATE); + if (isEquipped(hero) && level > 1 && !cursed) + actions.add(AC_RESTART); + return actions; + } + + @Override + public void execute(Hero hero, String action) { + if (action.equals(AC_ACTIVATE)) { + + if (!isEquipped(hero)) + GLog.i(Messages.get(Artifact.class, "need_to_equip")); + else if (activeBuff != null) + GLog.i(Messages.get(this, "in_use")); + else if (charge <= 1) + GLog.i(Messages.get(this, "no_charge") ); + else if (cursed) + GLog.i(Messages.get(this, "cursed")); + else + GameScene.show(new WndOptions(Messages.get(this, "name"), + Messages.get(this, "prompt"), + Messages.get(this, "stasis"), + Messages.get(this, "freeze")) { + @Override + protected void onSelect(int index) { + if (index == 0) { + GLog.i(Messages.get(TimekeepersHourglass.class, "onstasis")); + GameScene.flash(0xFFFFFF); + Sample.INSTANCE.play(Assets.SND_TELEPORT); + + activeBuff = new timeStasis(); + activeBuff.attachTo(Dungeon.hero); + } else if (index == 1) { + GLog.i(Messages.get(TimekeepersHourglass.class, "onfreeze")); + GameScene.flash(0xFFFFFF); + Sample.INSTANCE.play(Assets.SND_TELEPORT); + + activeBuff = new timeFreeze(); + activeBuff.attachTo(Dungeon.hero); + } + }; + }); + } else if (action.equals(AC_RESTART)){ + + level--; + curUser = hero; + curUser.HP = curUser.HT; + Buff.affect(curUser,AttackUp.class,50f).level(20); + Buff.affect(curUser,DefenceUp.class,50f).level(20); + Buff.affect(curUser,Bless.class,50f); + curUser.belongings.charge( true ); + Sample.INSTANCE.play(Assets.SND_BURNING); + curUser.sprite.emitter().burst(ElmoParticle.FACTORY, 12); + curUser.spendAndNext(1f); + + } else + super.execute(hero, action); + } + + @Override + public void activate(Char ch) { + super.activate(ch); + if (activeBuff != null) + activeBuff.attachTo(ch); + } + + @Override + public boolean doUnequip(Hero hero, boolean collect, boolean single) { + if (super.doUnequip(hero, collect, single)) { + if (activeBuff != null) { + activeBuff.detach(); + activeBuff = null; + } + return true; + } else + return false; + } + + @Override + protected ArtifactBuff passiveBuff() { + return new hourglassRecharge(); + } + + @Override + public Item upgrade() { + chargeCap += 2; + + // for artifact transmutation. + while (level + 1 > sandBags) + sandBags++; + + return super.upgrade(); + } + + @Override + public String desc() { + String desc = super.desc(); + + if (isEquipped( Dungeon.hero )){ + if (!cursed) { + if (level < levelCap ) + desc += "\n\n" + Messages.get(this, "desc_hint"); + + } else + desc += "\n\n" + Messages.get(this, "desc_cursed"); + } + return desc; + } + + @Override + public void updateArtifact() { + chargeCap = 10 + level*2; + } + + private static final String SANDBAGS = "sandbags"; + private static final String BUFF = "buff"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(SANDBAGS, sandBags); + + if (activeBuff != null) + bundle.put(BUFF, activeBuff); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + sandBags = bundle.getInt(SANDBAGS); + + // these buffs belong to hourglass, need to handle unbundling within the + // hourglass class. + if (bundle.contains(BUFF)) { + Bundle buffBundle = bundle.getBundle(BUFF); + + if (buffBundle.contains(timeFreeze.PARTIALTIME)) + activeBuff = new timeFreeze(); + else + activeBuff = new timeStasis(); + + activeBuff.restoreFromBundle(buffBundle); + } + } + + public class hourglassRecharge extends ArtifactBuff { + @Override + public boolean act() { + if (charge < chargeCap && !cursed) { + partialCharge += 1 / (60f - (chargeCap - charge) * 2f); + + if (partialCharge >= 1) { + partialCharge--; + charge++; + + if (charge == chargeCap) { + partialCharge = 0; + } + } + } else if (cursed && Random.Int(10) == 0) + ((Hero) target).spend(TICK); + + updateQuickslot(); + + spend(TICK); + + return true; + } + } + + public class timeStasis extends ArtifactBuff { + + @Override + public boolean attachTo(Char target) { + spend(charge); + ((Hero) target).spendAndNext(charge); + + // shouldn't punish the player for going into stasis frequently + Hunger hunger = target.buff(Hunger.class); + if (hunger != null && !hunger.isStarving()) + hunger.satisfy(charge); + + charge = 0; + + target.invisible++; + + updateQuickslot(); + + Dungeon.observe(); + + return super.attachTo(target); + } + + @Override + public boolean act() { + detach(); + return true; + } + + @Override + public void detach() { + if (target.invisible > 0) + target.invisible--; + super.detach(); + activeBuff = null; + Dungeon.observe(); + } + } + + public class timeFreeze extends ArtifactBuff { + + float partialTime = 0f; + + ArrayList presses = new ArrayList(); + + public boolean processTime(float time) { + partialTime += time; + + while (partialTime >= 1f) { + partialTime--; + charge--; + } + + updateQuickslot(); + + if (charge <= 0) { + detach(); + return false; + } else + return true; + + } + + public void setDelayedPress(int cell) { + if (!presses.contains(cell)) + presses.add(cell); + } + + public void triggerPresses() { + for (int cell : presses) + Dungeon.level.press(cell, null); + + presses = new ArrayList(); + } + + @Override + public boolean attachTo(Char target) { + if (Dungeon.level != null) + for (Mob mob : Dungeon.level.mobs.toArray(new Mob[0])) + mob.sprite.add(CharSprite.State.PARALYSED); + Group.freezeEmitters = true; + return super.attachTo(target); + } + + @Override + public void detach() { + triggerPresses(); + for (Mob mob : Dungeon.level.mobs.toArray(new Mob[0])) + mob.sprite.remove(CharSprite.State.PARALYSED); + Group.freezeEmitters = false; + + charge = 0; + updateQuickslot(); + super.detach(); + activeBuff = null; + } + + private static final String PRESSES = "presses"; + private static final String PARTIALTIME = "partialtime"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + + int[] values = new int[presses.size()]; + for (int i = 0; i < values.length; i++) + values[i] = presses.get(i); + bundle.put(PRESSES, values); + + bundle.put(PARTIALTIME, partialTime); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + + int[] values = bundle.getIntArray(PRESSES); + for (int value : values) + presses.add(value); + + partialTime = bundle.getFloat(PARTIALTIME); + } + } + + public static class sandBag extends Item { + + { + //name = "bag of magic sand"; + image = ItemSpriteSheet.SANDBAG; + } + + @Override + public boolean doPickUp(Hero hero) { + TimekeepersHourglass hourglass = hero.belongings + .getItem(TimekeepersHourglass.class); + if (hourglass != null && !hourglass.cursed) { + hourglass.upgrade(); + Sample.INSTANCE.play(Assets.SND_DEWDROP); + if (hourglass.level == hourglass.levelCap) + GLog.p(Messages.get(this, "maxlevel")); + else + GLog.i(Messages.get(this, "levelup")); + hero.spendAndNext(TIME_TO_PICK_UP); + return true; + } else { + GLog.w( Messages.get(this, "no_hourglass")); + return false; + } + } + + @Override + public int price() { + return 10; + } + } + +} diff --git a/java/com/hmdzl/spspd/items/artifacts/UnstableSpellbook.java b/java/com/hmdzl/spspd/items/artifacts/UnstableSpellbook.java new file mode 100644 index 00000000..13f6e622 --- /dev/null +++ b/java/com/hmdzl/spspd/items/artifacts/UnstableSpellbook.java @@ -0,0 +1,267 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2015 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.items.artifacts; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.buffs.Blindness; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.particles.ElmoParticle; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.misc.SkillOfAtk; +import com.hmdzl.spspd.items.misc.SkillOfDef; +import com.hmdzl.spspd.items.misc.SkillOfMig; +import com.hmdzl.spspd.items.scrolls.Scroll; +import com.hmdzl.spspd.items.scrolls.ScrollOfIdentify; +import com.hmdzl.spspd.items.scrolls.ScrollOfMagicMapping; +import com.hmdzl.spspd.items.scrolls.ScrollOfRemoveCurse; +import com.hmdzl.spspd.items.scrolls.ScrollOfTeleportation; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; +import com.hmdzl.spspd.windows.WndBag; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +import java.util.ArrayList; + +/** + * Created by debenhame on 26/11/2014. + */ +public class UnstableSpellbook extends Artifact { + + { + image = ItemSpriteSheet.ARTIFACT_SPELLBOOK; + + levelCap = 10; + + charge = ((level/2)+2); + partialCharge = 0; + chargeCap = ((level/2)+2); + + defaultAction = AC_READ; + } + + public static final String AC_READ = "READ"; + public static final String AC_ADD = "ADD"; + public static final String AC_SONG = "SONG"; + public static int consumedpts = 0; + + private final ArrayList scrolls = new ArrayList<>(); + + protected WndBag.Mode mode = WndBag.Mode.SCROLL; + + /*public UnstableSpellbook() { + super(); + + Class[] scrollClasses = Generator.Category.SCROLL.classes; + float[] probs = Generator.Category.SCROLL.probs.clone(); //array of primitives, clone gives deep copy. + int i = Random.chances(probs); + + while (i != -1){ + scrolls.add(scrollClasses[i]); + probs[i] = 0; + + i = Random.chances(probs); + }; + }*/ + + @Override + public ArrayList actions( Hero hero ) { + ArrayList actions = super.actions( hero ); + if (isEquipped( hero ) && charge > 0 && !cursed) + actions.add(AC_READ); + if (isEquipped( hero ) && level< levelCap && !cursed) + actions.add(AC_ADD); + if (isEquipped(hero) && level > 3 && !cursed) + actions.add(AC_SONG); + return actions; + } + + @Override + public void execute( Hero hero, String action ) { + if (action.equals( AC_READ )) { + + if (hero.buff( Blindness.class ) != null) GLog.w( Messages.get(this, "blinded") ); + else if (!isEquipped( hero )) GLog.i( Messages.get(Artifact.class, "need_to_equip") ); + else if (charge == 0) GLog.i( Messages.get(this, "no_charge") ); + else if (cursed) GLog.i( Messages.get(this, "cursed") ); + else { + charge--; + + Scroll scroll; + do { + scroll = (Scroll) Generator.random(Generator.Category.SCROLL); + } while (scroll == null || + //gotta reduce the rate on these scrolls or that'll be all the item does. + ((scroll instanceof ScrollOfIdentify || + scroll instanceof ScrollOfRemoveCurse || + scroll instanceof ScrollOfMagicMapping) && Random.Int(2) == 0) + || (scroll instanceof ScrollOfTeleportation && Dungeon.bossLevel())); + + scroll.ownedByBook = true; + curItem = scroll; + curUser = hero; + if (Random.Int(20)> level) { + scroll.doRead(); + } else { + scroll.empoweredRead(); + } + updateQuickslot(); + } + + } else if (action.equals( AC_ADD )) { + GameScene.selectItem(itemSelector, mode, Messages.get(this, "prompt")); + } else if (action.equals( AC_SONG )) { + curUser = hero; + level-=4; + exp-=100; + switch (Random.Int(3)){ + case 0: + Dungeon.hero.hitSkill++; + GLog.w(Messages.get(SkillOfAtk.class, "skillup")); + break; + case 1: + Dungeon.hero.evadeSkill++; + GLog.w(Messages.get(SkillOfDef.class, "skillup")); + break; + case 2: + Dungeon.hero.magicSkill++; + GLog.w(Messages.get(SkillOfMig.class, "skillup")); + break; + } + curUser.spendAndNext(1f); + updateQuickslot(); + Sample.INSTANCE.play(Assets.SND_BURNING); + curUser.sprite.emitter().burst(ElmoParticle.FACTORY, 12); + } else + super.execute( hero, action ); + } + + @Override + protected ArtifactBuff passiveBuff() { + return new bookRecharge(); + } + + @Override + public Item upgrade() { + chargeCap = (((level+1)/2)+3); + return super.upgrade(); + } + + @Override + public String desc() { + String desc = super.desc(); + + if (cursed && isEquipped (Dungeon.hero)){ + desc += "\n\n" + Messages.get(this, "desc_cursed"); + } + + if (level < levelCap) { + desc += "\n\n" + Messages.get(this, "desc_index",consumedpts); + } + + return desc; + } + + private static final String SCROLLS = "scrolls"; + private static final String PARTIALCHARGE = "partialCharge"; + private static final String CHARGE = "charge"; + private static final String CONSUMED = "consumedpts"; + + @Override + public void storeInBundle( Bundle bundle ) { + super.storeInBundle(bundle); + bundle.put( SCROLLS, scrolls.toArray(new Class[scrolls.size()]) ); + bundle.put(PARTIALCHARGE, partialCharge); + bundle.put(CHARGE, charge); + bundle.put(CONSUMED, consumedpts); + } + + @Override + public void restoreFromBundle( Bundle bundle ) { + super.restoreFromBundle(bundle); + partialCharge = bundle.getInt(PARTIALCHARGE); + charge = bundle.getInt(CHARGE); + consumedpts = bundle.getInt(CONSUMED); + + } + + public class bookRecharge extends ArtifactBuff{ + @Override + public boolean act() { + if (charge < chargeCap && !cursed) { + partialCharge += 1 / (150f - (chargeCap - charge)*15f); + + if (partialCharge >= 1) { + partialCharge --; + charge ++; + + if (charge == chargeCap){ + partialCharge = 0; + } + } + } + + updateQuickslot(); + + spend( TICK ); + + return true; + } + } + + protected WndBag.Listener itemSelector = new WndBag.Listener() { + @Override + public void onSelect(Item item) { + if (item != null && item instanceof Scroll && item.isIdentified()) { + Hero hero = Dungeon.hero; + int scrollWorth = item.consumedValue; + consumedpts += scrollWorth; + + hero.sprite.operate(hero.pos); + hero.busy(); + hero.spend(2f); + Sample.INSTANCE.play(Assets.SND_BURNING); + hero.sprite.emitter().burst(ElmoParticle.FACTORY, 12); + + item.detach(hero.belongings.backpack); + GLog.h(Messages.get(UnstableSpellbook.class, "exp",consumedpts)); + + int levelChk = ((level*2)+1)*10; + + if (consumedpts > levelChk && level<10) { + upgrade(); + GLog.p(Messages.get(UnstableSpellbook.class, "infuse_scroll")); + } + + + } else if (item instanceof Scroll && !item.isIdentified()){ + GLog.w(Messages.get(UnstableSpellbook.class, "unknown_scroll")); + } else if (item != null){ + GLog.w(Messages.get(UnstableSpellbook.class, "unable_scroll")); + } + } + }; + } diff --git a/java/com/hmdzl/spspd/items/bags/Bag.java b/java/com/hmdzl/spspd/items/bags/Bag.java new file mode 100644 index 00000000..ba12240c --- /dev/null +++ b/java/com/hmdzl/spspd/items/bags/Bag.java @@ -0,0 +1,199 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.bags; + +import java.util.ArrayList; +import java.util.Iterator; + +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.windows.WndBag; +import com.watabou.utils.Bundlable; +import com.watabou.utils.Bundle; + +public class Bag extends Item implements Iterable { + + public static final String AC_OPEN = "OPEN"; + + { + image = 11; + unique = true; + defaultAction = AC_OPEN; + } + + public Char owner; + + public ArrayList items = new ArrayList(); + + public int size = 1; + + @Override + public void execute(Hero hero, String action) { + super.execute(hero, action); + + if (action.equals(AC_OPEN)) { + + GameScene.show(new WndBag(this, null, WndBag.Mode.ALL, null)); + + } + } + + @Override + public boolean collect(Bag container) { + + for (Item item : container.items.toArray( new Item[0] )) { + if (grab( item )) { + int slot = Dungeon.quickslot.getSlot(item); + item.detachAll(container); + if (!item.collect(this)) { + item.collect(container); + } + if (slot != -1) { + Dungeon.quickslot.setSlot(slot, item); + } + } + } + + if (super.collect(container)) { + + owner = container.owner; + + /*for (Item item : container.items.toArray(new Item[0])) { + if (grab(item)) { + item.detachAll(container); + item.collect(this); + } + }*/ + + Badges.validateAllBagsBought(this); + + return true; + } else { + return false; + } + } + + @Override + public void onDetach() { + this.owner = null; + for (Item item : items) + Dungeon.quickslot.clearItem(item); + updateQuickslot(); + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + public void clear() { + items.clear(); + } + + //private static final String ITEMS = Messages.get(Bag.class,"inventory"); + + private static final String ITEMS = "inventory"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(ITEMS, items); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + for (Bundlable item : bundle.getCollection(ITEMS)) { + if (item != null) + ((Item) item).collect(this); + } + ; + } + + public boolean contains(Item item) { + for (Item i : items) { + if (i == item) { + return true; + } else if (i instanceof Bag && ((Bag) i).contains(item)) { + return true; + } + } + return false; + } + + public boolean grab(Item item) { + return false; + } + + @Override + public Iterator iterator() { + return new ItemIterator(); + } + + private class ItemIterator implements Iterator { + + private int index = 0; + private Iterator nested = null; + + @Override + public boolean hasNext() { + if (nested != null) { + return nested.hasNext() || index < items.size(); + } else { + return index < items.size(); + } + } + + @Override + public Item next() { + if (nested != null && nested.hasNext()) { + + return nested.next(); + + } else { + + nested = null; + + Item item = items.get(index++); + if (item instanceof Bag) { + nested = ((Bag) item).iterator(); + } + + return item; + } + } + + @Override + public void remove() { + if (nested != null) { + nested.remove(); + } else { + items.remove(index); + } + } + } +} diff --git a/java/com/hmdzl/spspd/items/bags/HeartOfScarecrow.java b/java/com/hmdzl/spspd/items/bags/HeartOfScarecrow.java new file mode 100644 index 00000000..ccc53d4c --- /dev/null +++ b/java/com/hmdzl/spspd/items/bags/HeartOfScarecrow.java @@ -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 + */ +package com.hmdzl.spspd.items.bags; + + +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.ShadowEaterKey; +import com.hmdzl.spspd.items.armor.Armor; +import com.hmdzl.spspd.items.weapon.Weapon; +import com.hmdzl.spspd.items.weapon.melee.MeleeWeapon; +import com.hmdzl.spspd.items.weapon.melee.relic.RelicMeleeWeapon; +import com.hmdzl.spspd.items.weapon.missiles.MissileWeapon; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class HeartOfScarecrow extends Bag { + + { + //name = "HeartOfScarecrow"; + image = ItemSpriteSheet.H_O_SCARECROW; + + size = 25; + } + + + @Override + public boolean grab(Item item) { + if (item instanceof MeleeWeapon + ||item instanceof MissileWeapon + ||item instanceof RelicMeleeWeapon + || item instanceof Armor + ||item instanceof ShadowEaterKey){ + return true; + } else { + return false; + } + } + + @Override + public int price() { + return 50 * quantity; + } + + @Override + public boolean doPickUp( Hero hero ) { + + return hero.belongings.getItem( HeartOfScarecrow.class ) == null && super.doPickUp( hero ) ; + + } + +} + diff --git a/java/com/hmdzl/spspd/items/bags/KeyRing.java b/java/com/hmdzl/spspd/items/bags/KeyRing.java new file mode 100644 index 00000000..d5804528 --- /dev/null +++ b/java/com/hmdzl/spspd/items/bags/KeyRing.java @@ -0,0 +1,77 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.bags; + +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.items.ChallengeBook; +import com.hmdzl.spspd.items.DolyaSlate; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.PotKey; +import com.hmdzl.spspd.items.TenguKey; +import com.hmdzl.spspd.items.keys.Key; +import com.hmdzl.spspd.items.AncientCoin; +import com.hmdzl.spspd.items.ConchShell; +import com.hmdzl.spspd.items.Bone; +import com.hmdzl.spspd.items.TriForce; +import com.hmdzl.spspd.items.TreasureMap; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.items.rings.Ring; + +public class KeyRing extends Bag { + + { + //name = "key ring"; + image = ItemSpriteSheet.KEYRING; + + size = 25; + } + + @Override + public boolean grab(Item item) { + if (item instanceof Key + || item instanceof TenguKey + || item instanceof PotKey + || item instanceof AncientCoin + || item instanceof ConchShell + || item instanceof Bone + || item instanceof TriForce + || item instanceof DolyaSlate + || item instanceof Ring + || item instanceof TreasureMap + || item instanceof ChallengeBook + ){ + return true; + } else { + return false; + } + } + + @Override + public int price() { + return 50 * quantity; + } + + @Override + public boolean doPickUp( Hero hero ) { + + return hero.belongings.getItem( KeyRing.class ) == null && super.doPickUp( hero ) ; + + } + +} + diff --git a/java/com/hmdzl/spspd/items/bags/PotionBandolier.java b/java/com/hmdzl/spspd/items/bags/PotionBandolier.java new file mode 100644 index 00000000..a5103d6e --- /dev/null +++ b/java/com/hmdzl/spspd/items/bags/PotionBandolier.java @@ -0,0 +1,46 @@ +package com.hmdzl.spspd.items.bags; + +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.bombs.Bomb; +import com.hmdzl.spspd.items.medicine.Pill; +import com.hmdzl.spspd.items.potions.Potion; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +/** + * Created by debenhame on 05/02/2015. + */ +public class PotionBandolier extends Bag { + + { + //name = "potion bandolier"; + image = ItemSpriteSheet.BANDOLIER; + + size = 25; + } + + @Override + public boolean grab(Item item) { + if (item instanceof Potion || + item instanceof Pill || + item instanceof Bomb + ){ + return true; + } else { + return false; + } + } + + @Override + public int price() { + return 50 * quantity; + } + + @Override + public boolean doPickUp( Hero hero ) { + + return hero.belongings.getItem( PotionBandolier.class ) == null && super.doPickUp( hero ) ; + + } + +} diff --git a/java/com/hmdzl/spspd/items/bags/ScrollHolder.java b/java/com/hmdzl/spspd/items/bags/ScrollHolder.java new file mode 100644 index 00000000..a9bc1469 --- /dev/null +++ b/java/com/hmdzl/spspd/items/bags/ScrollHolder.java @@ -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 + */ +package com.hmdzl.spspd.items.bags; + +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.items.summon.ActiveMrDestructo; +import com.hmdzl.spspd.items.bombs.Bomb; + + +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.OrbOfZot; + + + +import com.hmdzl.spspd.items.challengelists.ChallengeList; +import com.hmdzl.spspd.items.journalpages.JournalPage; +import com.hmdzl.spspd.items.scrolls.Scroll; +import com.hmdzl.spspd.items.summon.CallCoconut; +import com.hmdzl.spspd.items.summon.FairyCard; +import com.hmdzl.spspd.items.summon.Mobile; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class ScrollHolder extends Bag { + + { + //name = "scroll holder"; + image = ItemSpriteSheet.HOLDER; + + size = 25; + } + + @Override + public boolean grab(Item item) { + if (item instanceof Scroll + || item instanceof ActiveMrDestructo + || item instanceof CallCoconut + || item instanceof Mobile + || item instanceof FairyCard + || item instanceof OrbOfZot + || item instanceof JournalPage + || item instanceof ChallengeList + ){ + return true; + } else { + return false; + } + } + + @Override + public int price() { + return 50 * quantity; + } + + @Override + public boolean doPickUp( Hero hero ) { + + return hero.belongings.getItem( ScrollHolder.class ) == null && super.doPickUp( hero ) ; + + } +} diff --git a/java/com/hmdzl/spspd/items/bags/SeedPouch.java b/java/com/hmdzl/spspd/items/bags/SeedPouch.java new file mode 100644 index 00000000..e7df5e3b --- /dev/null +++ b/java/com/hmdzl/spspd/items/bags/SeedPouch.java @@ -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 + */ +package com.hmdzl.spspd.items.bags; + +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.items.Item; + +import com.hmdzl.spspd.items.StoneOre; +import com.hmdzl.spspd.items.nornstone.NornStone; +import com.hmdzl.spspd.plants.Plant; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class SeedPouch extends Bag { + + { + //name = "seed pouch"; + image = ItemSpriteSheet.POUCH; + + size = 25; + } + + @Override + public boolean grab(Item item) { + if (item instanceof Plant.Seed + || item instanceof StoneOre + || item instanceof NornStone){ + return true; + } else { + return false; + } + } + + @Override + public int price() { + + return 50 * quantity; + } + + @Override + public boolean doPickUp( Hero hero ) { + + return hero.belongings.getItem( SeedPouch.class ) == null && super.doPickUp( hero ) ; + + } +} diff --git a/java/com/hmdzl/spspd/items/bags/ShoppingCart.java b/java/com/hmdzl/spspd/items/bags/ShoppingCart.java new file mode 100644 index 00000000..1af047da --- /dev/null +++ b/java/com/hmdzl/spspd/items/bags/ShoppingCart.java @@ -0,0 +1,54 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.bags; + + +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.food.Food; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class ShoppingCart extends Bag { + + { + //name = "shopping cart"; + image = ItemSpriteSheet.SHOPCART; + + size = 25; + } + + + @Override + public boolean grab(Item item) { + return item instanceof Food ; + } + + @Override + public int price() { + return 50 * quantity; + } + + @Override + public boolean doPickUp( Hero hero ) { + + return hero.belongings.getItem( ShoppingCart.class ) == null && super.doPickUp( hero ) ; + + } + +} + diff --git a/java/com/hmdzl/spspd/items/bags/WandHolster.java b/java/com/hmdzl/spspd/items/bags/WandHolster.java new file mode 100644 index 00000000..a48ef7e4 --- /dev/null +++ b/java/com/hmdzl/spspd/items/bags/WandHolster.java @@ -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 + */ +package com.hmdzl.spspd.items.bags; + +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.TriforceOfCourage; +import com.hmdzl.spspd.items.TriforceOfPower; +import com.hmdzl.spspd.items.TriforceOfWisdom; +import com.hmdzl.spspd.items.wands.Wand; +import com.hmdzl.spspd.items.weapon.guns.GunWeapon; +import com.hmdzl.spspd.items.weapon.spammo.SpAmmo; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.messages.Messages; + +public class WandHolster extends Bag { + + { + //name = "wand holster"; + image = ItemSpriteSheet.HOLSTER; + + size = 25; + } + + @Override + public boolean grab(Item item) { + if (item instanceof Wand + || item instanceof TriforceOfCourage + || item instanceof TriforceOfPower + || item instanceof TriforceOfWisdom + || item instanceof SpAmmo + || item instanceof GunWeapon){ + return true; + } else { + return false; + } + + } + + @Override + public boolean collect(Bag container) { + if (super.collect(container)) { + if (owner != null) { + for (Item item : items) { + if (item instanceof Wand){ + ((Wand) item).charge(owner); + } + } + } + return true; + } else { + return false; + } + } + + @Override + public void onDetach() { + super.onDetach(); + for (Item item : items) { + if (item instanceof Wand){ + ((Wand) item).stopCharging(); + } + } + } + + @Override + public int price() { + return 50 * quantity; + } + + @Override + public boolean doPickUp( Hero hero ) { + + return hero.belongings.getItem( WandHolster.class ) == null && super.doPickUp( hero ) ; + + } + +} diff --git a/java/com/hmdzl/spspd/items/bombs/Bomb.java b/java/com/hmdzl/spspd/items/bombs/Bomb.java new file mode 100644 index 00000000..f3a11f79 --- /dev/null +++ b/java/com/hmdzl/spspd/items/bombs/Bomb.java @@ -0,0 +1,252 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 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 + */ +package com.hmdzl.spspd.items.bombs; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.particles.BlastParticle; +import com.hmdzl.spspd.items.Heap; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; + +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Bundle; + +public class Bomb extends Item { + + { + //name = "bomb"; + image = ItemSpriteSheet.BOMB; + + defaultAction = AC_LIGHTTHROW; + usesTargeting = true; + + stackable = true; + } + + public Fuse fuse; + + // FIXME using a static variable for this is kinda gross, should be a better + // way + private static boolean lightingFuse = false; + + private static final String AC_LIGHTTHROW = "LIGHTTHROW"; + + + @Override + public boolean isSimilar(Item item) { + return super.isSimilar(item) && this.fuse == ((Bomb) item).fuse; + } + + public boolean explodesDestructively(){ + return true; + } + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + actions.add(AC_LIGHTTHROW); + return actions; + } + + @Override + public void execute(Hero hero, String action) { + if (action.equals(AC_LIGHTTHROW)) { + lightingFuse = true; + action = AC_THROW; + } else { + lightingFuse = false; + } + + super.execute(hero, action); + } + + @Override + protected void onThrow( int cell ) { + if (!Dungeon.level.pit[ cell ] && lightingFuse) { + Actor.addDelayed(fuse = new Fuse().ignite(this), 2); + } + if (Actor.findChar( cell ) != null && !(Actor.findChar( cell ) instanceof Hero) ){ + ArrayList candidates = new ArrayList<>(); + //for (int i : PathFinder.NEIGHBOURS8) + //if (Dungeon.level.passable[cell + i]) + //candidates.add(cell + i); + //int newCell = candidates.isEmpty() ? cell : Random.element(candidates); + int newCell = cell; + Dungeon.level.drop( this, newCell ).sprite.drop( cell ); + } else + super.onThrow( cell ); + } + + @Override + public boolean doPickUp(Hero hero) { + if (fuse != null) { + GLog.w( Messages.get(this, "snuff_fuse")); + fuse = null; + } + return super.doPickUp(hero); + } + + public void explode(int cell) { + this.fuse = null; + + Sample.INSTANCE.play(Assets.SND_BLAST); + + if (Dungeon.visible[cell]) { + CellEmitter.center(cell).burst(BlastParticle.FACTORY, 30); + } + + // boolean terrainAffected = false; + // for (int n : Level.NEIGHBOURS9) { + // int c = cell + n; + // if (c >= 0 && c < Level.getLength()) { + // if (Dungeon.visible[c]) { + // CellEmitter.get(c).burst(SmokeParticle.FACTORY, 4); + // } + + // if (Level.flamable[c]) { + // Level.set(c, Terrain.EMBERS); + // GameScene.updateMap(c); + // terrainAffected = true; + // } + + // Heap heap = Dungeon.level.heaps.get(c); + // if (heap != null) heap.explode(); + + + // Char ch = Actor.findChar(c); + // if (ch != null) { + // those not at the center of the blast take damage less + // consistently. + // int minDamage = c == cell ? Dungeon.depth + 5 : 1; + // int maxDamage = 10 + Dungeon.depth * 2; + + // int dmg = Random.NormalIntRange(minDamage, maxDamage) + // - Math.max(ch.drRoll(),0); + //if (dmg > 0) { + // ch.damage(dmg, this); + // } + + // if (ch == Dungeon.hero && !ch.isAlive()) + // constant is used here in the rare instance a player + // is killed by a double bomb. + //Dungeon.fail(ResultDescriptions.ITEM); + //} + //} + //} + + //if (terrainAffected) { + //Dungeon.observe(); + // } + + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + @Override + public ItemSprite.Glowing glowing() { + return fuse != null ? new ItemSprite.Glowing(0xFF0000, 0.6f) : null; + } + + @Override + public int price() { + return 20 * quantity; + } + + @Override + public String info() { + if (fuse == null) + return super.desc(); + else + return Messages.get(this, "desc_burning"); + } + + private static final String FUSE = "fuse"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(FUSE, fuse); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + if (bundle.contains(FUSE)) + Actor.add(fuse = ((Fuse) bundle.get(FUSE)).ignite(this)); + } + + public static class Fuse extends Actor { + + private Bomb bomb; + + public Fuse ignite(Bomb bomb) { + this.bomb = bomb; + return this; + } + + @Override + protected boolean act() { + + // something caused our bomb to explode early, or be defused. Do + // nothing. + if (bomb.fuse != this) { + Actor.remove(this); + return true; + } + + // look for our bomb, remove it from its heap, and blow it up. + for (Heap heap : Dungeon.level.heaps.values()) { + if (heap.items.contains(bomb)) { + heap.items.remove(bomb); + + if (heap.items.isEmpty()){ + heap.destroy(); + } + + bomb.explode(heap.pos); + + Actor.remove(this); + return true; + } + } + + // can't find our bomb, this should never happen, throw an + // exception. + bomb.fuse = null; + Actor.remove( this ); + return true; + } + } +} diff --git a/java/com/hmdzl/spspd/items/bombs/BuildBomb.java b/java/com/hmdzl/spspd/items/bombs/BuildBomb.java new file mode 100644 index 00000000..b1f5152e --- /dev/null +++ b/java/com/hmdzl/spspd/items/bombs/BuildBomb.java @@ -0,0 +1,82 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 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 + */ +package com.hmdzl.spspd.items.bombs; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.particles.SmokeParticle; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.Terrain; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +import com.watabou.utils.Random; + +public class BuildBomb extends Bomb { + + { + //name = "bomb"; + image = ItemSpriteSheet.BOMB; + } + + @Override + public void explode(int cell) { + super.explode(cell); + boolean terrainAffected = false; + for (int n : Level.NEIGHBOURS9) { + int c = cell + n; + if (c >= 0 && c < Level.getLength()) { + if (Dungeon.visible[c]) { + CellEmitter.get(c).burst(SmokeParticle.FACTORY, 4); + } + + if (Level.flamable[c]) { + Level.set(c, Terrain.EMBERS); + GameScene.updateMap(c); + terrainAffected = true; + } + + Char ch = Actor.findChar(c); + if (ch != null) { + // those not at the center of the blast take damage less + // consistently. + int minDamage = ch.HT/12; + int maxDamage = ch.HT/5; + + int dmg = Random.NormalIntRange(minDamage, maxDamage) + - Math.max(ch.drRoll(),0); + if (dmg > 0) { + ch.damage(dmg, this); + } + } + } + } + + if (terrainAffected) { + Dungeon.observe(); + } + + } + + @Override + public int price() { + return 10 * quantity; + } +} diff --git a/java/com/hmdzl/spspd/items/bombs/DangerousBomb.java b/java/com/hmdzl/spspd/items/bombs/DangerousBomb.java new file mode 100644 index 00000000..3bfdacc0 --- /dev/null +++ b/java/com/hmdzl/spspd/items/bombs/DangerousBomb.java @@ -0,0 +1,104 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 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 + */ +package com.hmdzl.spspd.items.bombs; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.ResultDescriptions; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.particles.SmokeParticle; +import com.hmdzl.spspd.items.Heap; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.Terrain; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +import com.watabou.utils.Random; + +public class DangerousBomb extends Bomb { + + { + //name = "cluster bomb"; + image = ItemSpriteSheet.HUGE_BOMB; + } + + @Override + public void explode(int cell) { + super.explode(cell); + boolean terrainAffected = false; + for (int n : Level.NEIGHBOURS9DIST2) { + int c = cell + n; + if (c >= 0 && c < Level.getLength()) { + if (Dungeon.visible[c]) { + CellEmitter.get(c).burst(SmokeParticle.FACTORY, 4); + } + + if (Level.flamable[c]) { + Level.set(c, Terrain.EMBERS); + GameScene.updateMap(c); + terrainAffected = true; + } + + if (Dungeon.level.map[c] == Terrain.WALL && Level.insideMap(c)){ + Level.set(c, Terrain.EMPTY); + GameScene.updateMap(c); + terrainAffected = true; + } + + // destroys items / triggers bombs caught in the blast. + Heap heap = Dungeon.level.heaps.get(c); + if (heap != null) + heap.explode(); + + Char ch = Actor.findChar(c); + if (ch != null) { + // those not at the center of the blast take damage less + // consistently. + if ( ch == Dungeon.hero){ + + int minDamage = ch.HT/8; + int maxDamage = ch.HT/4; + + int dmg = Random.NormalIntRange(minDamage, maxDamage) + - Math.max(ch.drRoll(),0); + if (dmg > 0) { + ch.damage(dmg, this); + } + if (ch == Dungeon.hero && !ch.isAlive()) + // constant is used here in the rare instance a player + // is killed by a double bomb. + Dungeon.fail(Messages.format(ResultDescriptions.ITEM)); + } + } + } + } + + if (terrainAffected) { + Dungeon.observe(); + } + + } + + @Override + public int price() { + return 20 * quantity; + } + +} diff --git a/java/com/hmdzl/spspd/items/bombs/DarkBomb.java b/java/com/hmdzl/spspd/items/bombs/DarkBomb.java new file mode 100644 index 00000000..8ea5563b --- /dev/null +++ b/java/com/hmdzl/spspd/items/bombs/DarkBomb.java @@ -0,0 +1,81 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 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 + */ +package com.hmdzl.spspd.items.bombs; + + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Terror; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.particles.SmokeParticle; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.utils.Random; + +public class DarkBomb extends Bomb { + + { + //name = "seeking bomb"; + image = ItemSpriteSheet.DARK_BOMB; + } + + + @Override + public void explode(int cell) { + super.explode(cell); + curUser = Dungeon.hero; + for (int n: Level.NEIGHBOURS9) { + int c = cell + n; + if (c >= 0 && c < Level.getLength()) { + if (Dungeon.visible[c]) { + CellEmitter.get(c).burst(SmokeParticle.FACTORY, 4); + } + Char ch = Actor.findChar(c); + if (ch != null){ + Buff.affect(ch, Terror.class, Terror.DURATION).object = curUser.id(); + if (ch.properties().contains(Char.Property.HUMAN) + || ch.properties().contains(Char.Property.PLANT) + || ch.properties().contains(Char.Property.ORC) + || ch.properties().contains(Char.Property.TROLL) + || ch.properties().contains(Char.Property.DWARF) + || ch.properties().contains(Char.Property.BEAST) + || ch.properties().contains(Char.Property.ELF) + || ch.properties().contains(Char.Property.GOBLIN) + || ch.properties().contains(Char.Property.BOSS) + || ch.properties().contains(Char.Property.MINIBOSS) + ) { + int dmg = Random.NormalIntRange(200, 400); + ch.damage(dmg, this); + + } else { + int dmg = Random.NormalIntRange(50, 100); + ch.damage(dmg, this); + } + }} + } + + Dungeon.observe(); + } + + @Override + public int price() { + return 20 * quantity; + } +} diff --git a/java/com/hmdzl/spspd/items/bombs/DungeonBomb.java b/java/com/hmdzl/spspd/items/bombs/DungeonBomb.java new file mode 100644 index 00000000..36f6d930 --- /dev/null +++ b/java/com/hmdzl/spspd/items/bombs/DungeonBomb.java @@ -0,0 +1,140 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 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 + */ +package com.hmdzl.spspd.items.bombs; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.particles.SmokeParticle; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.Terrain; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.CharSprite; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +import com.watabou.utils.Random; + +public class DungeonBomb extends Bomb { + + { + //name = "bomb"; + image = ItemSpriteSheet.BOMB; + } + + @Override + public void explode(int cell) { + super.explode(cell); + + boolean terrainAffected = false; + for (int n : Level.NEIGHBOURS9) { + int c = cell + n; + if (c >= 0 && c < Level.getLength()) { + if (Dungeon.visible[c]) { + CellEmitter.get(c).burst(SmokeParticle.FACTORY, 4); + } + + if (Level.flamable[c]) { + Level.set(c, Terrain.EMBERS); + GameScene.updateMap(c); + terrainAffected = true; + } + + if (Dungeon.level.map[c] == Terrain.WALL && Level.insideMap(c)){ + Level.set(c, Terrain.EMPTY); + GameScene.updateMap(c); + terrainAffected = true; + } + + Char ch = Actor.findChar(c); + if (ch != null) { + // those not at the center of the blast take damage less + // consistently. + if (ch.properties().contains(Char.Property.BOSS) || ch.properties().contains(Char.Property.MINIBOSS)){ + int minDamage = ch.HT/10; + int maxDamage = ch.HT/5; + + int dmg = Random.NormalIntRange(minDamage, maxDamage) + - Math.max(ch.drRoll(),0); + if (dmg > 0) { + ch.damage(dmg, this); + } + + } else { + + + int minDamage = ch.HT/5; + int maxDamage = ch.HT/4; + + int dmg = Random.NormalIntRange(minDamage, maxDamage); + //- Math.max(ch.drRoll(),0); + if (dmg > 0) { + ch.damage(dmg, this); + } + } + } + } + } + + if (terrainAffected) { + Dungeon.observe(); + } + + } + + + @Override + public Item random() { + switch (Random.Int(2)) { + case 0: + default: + return this; + case 1: + return new DoubleBomb(); + } + } + + + @Override + public int price() { + return 10 * quantity; + } + + public static class DoubleBomb extends DungeonBomb { + + { + //name = "two bombs"; + image = ItemSpriteSheet.DBL_BOMB; + stackable = false; + } + + @Override + public boolean doPickUp(Hero hero) { + DungeonBomb bomb = new DungeonBomb(); + bomb.quantity(2); + if (bomb.doPickUp(hero)) { + // isaaaaac.... + hero.sprite.showStatus(CharSprite.NEUTRAL, "1+1 free!"); + return true; + } + return false; + } + } +} diff --git a/java/com/hmdzl/spspd/items/bombs/EarthBomb.java b/java/com/hmdzl/spspd/items/bombs/EarthBomb.java new file mode 100644 index 00000000..3dd9dc30 --- /dev/null +++ b/java/com/hmdzl/spspd/items/bombs/EarthBomb.java @@ -0,0 +1,65 @@ + +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 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 + */ +package com.hmdzl.spspd.items.bombs; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Ooze; +import com.hmdzl.spspd.actors.buffs.Roots; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.BArray; +import com.watabou.utils.PathFinder; + +public class EarthBomb extends Bomb { + + { + image = ItemSpriteSheet.EARTH_BOMB; + } + + + @Override + public void explode(int cell) { + super.explode(cell); + ArrayList plantCandidates = new ArrayList<>(); + + PathFinder.buildDistanceMap( cell, BArray.not( Dungeon.level.solid, null ), 2 ); + for (int i = 0; i < PathFinder.distance.length; i++) { + if (PathFinder.distance[i] < Integer.MAX_VALUE) { + Char ch = Actor.findChar(i); + if (ch != null){ + Buff.prolong(ch, Roots.class,5f); + Buff.affect(ch, Ooze.class); + } + } + } + } + + + + + @Override + public int price() { + return 20 * quantity; + } + +} diff --git a/java/com/hmdzl/spspd/items/bombs/FireBomb.java b/java/com/hmdzl/spspd/items/bombs/FireBomb.java new file mode 100644 index 00000000..1faeb2cb --- /dev/null +++ b/java/com/hmdzl/spspd/items/bombs/FireBomb.java @@ -0,0 +1,123 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 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 + */ +package com.hmdzl.spspd.items.bombs; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.Blob; +import com.hmdzl.spspd.actors.blobs.Fire; +import com.hmdzl.spspd.actors.blobs.TarGas; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.particles.SmokeParticle; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public class FireBomb extends Bomb { + + { + //name = "smart bomb"; + image = ItemSpriteSheet.FIRE_BOMB; + } + + @Override + public void explode(int cell) { + super.explode(cell); + boolean terrainAffected = false; + for (int n : Level.NEIGHBOURS9) { + int c = cell + n; + if (c >= 0 && c < Level.getLength()) { + if (Dungeon.visible[c]) { + CellEmitter.get(c).burst(SmokeParticle.FACTORY, 4); + } + + GameScene.add(Blob.seed(c,10, Fire.class)); + GameScene.add(Blob.seed(c,10, TarGas.class)); + + // destroys items / triggers bombs caught in the blast. + + Char ch = Actor.findChar(c); + if (ch != null) { + // those not at the center of the blast take damage less + // consistently. + int minDamage = ch.HT/12; + int maxDamage = ch.HT/7; + + int dmg = Random.NormalIntRange(minDamage, maxDamage) + - Math.max(ch.drRoll(),0); + if (dmg > 0) { + ch.damage(dmg, this); + + } + } + } + } + } + + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + + @Override + public ItemSprite.Glowing glowing() { + return fuse != null ? new ItemSprite.Glowing(0xFF0000, 0.6f) : null; + } + + @Override + public int price() { + return 20 * quantity; + } + + @Override + public String desc() { + if (fuse == null) + return super.desc(); + else + return Messages.get(this, "desc_burning"); + } + + private static final String FUSE = "fuse"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(FUSE, fuse); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + if (bundle.contains(FUSE)) + Actor.add(fuse = ((Fuse) bundle.get(FUSE)).ignite(this)); + } + +} diff --git a/java/com/hmdzl/spspd/items/bombs/FishingBomb.java b/java/com/hmdzl/spspd/items/bombs/FishingBomb.java new file mode 100644 index 00000000..90953936 --- /dev/null +++ b/java/com/hmdzl/spspd/items/bombs/FishingBomb.java @@ -0,0 +1,96 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 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 + */ +package com.hmdzl.spspd.items.bombs; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.actors.mobs.npcs.NPC; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.particles.SmokeParticle; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; +import com.hmdzl.spspd.messages.Messages; + +public class FishingBomb extends Bomb { + + { + //name = "Fishing bomb"; + image = ItemSpriteSheet.FISH_BOMB; + } + + @Override + public void explode(int cell) { + super.explode(cell); + + for (int n: Level.NEIGHBOURS9DIST2) { + int c = cell + n; + if (c >= 0 && c < Level.getLength()) { + if (Dungeon.visible[c]) { + CellEmitter.get(c).burst(SmokeParticle.FACTORY, 4); + } + + Char ch = Actor.findChar(c); + if (ch != null) { + if ( ch instanceof Mob && !(ch instanceof Hero || ch instanceof NPC) ) { + + int count = 20; + int pos; + do { + pos = Dungeon.level.randomRespawnCellFish(); + if (count-- <= 0) { + break; + } + } while (pos == -1); + + if (pos == -1) { + + GLog.w(Messages.get(this,"no_tp")); + + } else { + + ch.pos = pos; + ch.sprite.place(ch.pos); + ch.sprite.visible = Dungeon.visible[pos]; + GLog.i(Messages.get(this,"tp")); + + } + + } + } + }} + + } + + + @Override + public int price() { + return 20 * quantity; + } + + public FishingBomb() { + this(1); + } + + public FishingBomb(int value) { + this.quantity = value; + } +} diff --git a/java/com/hmdzl/spspd/items/bombs/HugeBomb.java b/java/com/hmdzl/spspd/items/bombs/HugeBomb.java new file mode 100644 index 00000000..d4655346 --- /dev/null +++ b/java/com/hmdzl/spspd/items/bombs/HugeBomb.java @@ -0,0 +1,95 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 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 + */ +package com.hmdzl.spspd.items.bombs; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.particles.SmokeParticle; +import com.hmdzl.spspd.items.Heap; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.Terrain; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +import com.watabou.utils.Random; + +public class HugeBomb extends Bomb { + + { + //name = "cluster bomb"; + image = ItemSpriteSheet.HUGE_BOMB; + } + + @Override + public void explode(int cell) { + super.explode(cell); + boolean terrainAffected = false; + for (int n : Level.NEIGHBOURS9DIST2) { + int c = cell + n; + if (c >= 0 && c < Level.getLength()) { + if (Dungeon.visible[c]) { + CellEmitter.get(c).burst(SmokeParticle.FACTORY, 4); + } + + if (Level.flamable[c]) { + Level.set(c, Terrain.EMBERS); + GameScene.updateMap(c); + terrainAffected = true; + } + + if (Dungeon.level.map[c] == Terrain.WALL && Level.insideMap(c)){ + Level.set(c, Terrain.EMPTY); + GameScene.updateMap(c); + terrainAffected = true; + } + + // destroys items / triggers bombs caught in the blast. + Heap heap = Dungeon.level.heaps.get(c); + if (heap != null) + heap.explode(); + + Char ch = Actor.findChar(c); + if (ch != null) { + // those not at the center of the blast take damage less + // consistently. + int minDamage = ch.HT/8; + int maxDamage = ch.HT/4; + + int dmg = Random.NormalIntRange(minDamage, maxDamage) + - Math.max(ch.drRoll(),0); + if (dmg > 0) { + ch.damage(dmg, this); + } + } + } + } + + if (terrainAffected) { + Dungeon.observe(); + } + + } + + @Override + public int price() { + return 20 * quantity; + } + +} diff --git a/java/com/hmdzl/spspd/items/bombs/IceBomb.java b/java/com/hmdzl/spspd/items/bombs/IceBomb.java new file mode 100644 index 00000000..6a7dcc14 --- /dev/null +++ b/java/com/hmdzl/spspd/items/bombs/IceBomb.java @@ -0,0 +1,74 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 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 + */ +package com.hmdzl.spspd.items.bombs; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.Blob; +import com.hmdzl.spspd.actors.blobs.FrostGas; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.particles.SmokeParticle; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +import com.watabou.utils.Random; + +public class IceBomb extends Bomb { + + { + //name = "dizzy bomb"; + image = ItemSpriteSheet.ICE_BOMB; + } + + @Override + public void explode(int cell) { + super.explode(cell); + for (int n : Level.NEIGHBOURS9) { + int c = cell + n; + if (c >= 0 && c < Level.getLength()) { + if (Dungeon.visible[c]) { + CellEmitter.get(c).burst(SmokeParticle.FACTORY, 4); + } + GameScene.add(Blob.seed(c, 10, FrostGas.class)); + + + Char ch = Actor.findChar(c); + if (ch != null) { + // those not at the center of the blast take damage less + // consistently. + int minDamage = ch.HT/20; + int maxDamage = ch.HT/10; + + int dmg = Random.NormalIntRange(minDamage, maxDamage) + - Math.max(ch.drRoll(),0); + if (dmg > 0) { + ch.damage(dmg, this); + + } + } + } + } + } + + @Override + public int price() { + return 20 * quantity; + } +} diff --git a/java/com/hmdzl/spspd/items/bombs/LightBomb.java b/java/com/hmdzl/spspd/items/bombs/LightBomb.java new file mode 100644 index 00000000..9227a59e --- /dev/null +++ b/java/com/hmdzl/spspd/items/bombs/LightBomb.java @@ -0,0 +1,85 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 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 + */ +package com.hmdzl.spspd.items.bombs; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Blindness; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.particles.SmokeParticle; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.utils.Random; + +public class LightBomb extends Bomb { + + { + //name = "holy hand grenade"; + image = ItemSpriteSheet.LIGHT_BOMB; + } + + @Override + public void explode(int cell) { + super.explode(cell); + for (int n: Level.NEIGHBOURS9) { + int c = cell + n; + if (c >= 0 && c < Level.getLength()) { + if (Dungeon.visible[c]) { + CellEmitter.get(c).burst(SmokeParticle.FACTORY, 4); + } + + Char ch = Actor.findChar(c); + if (ch != null){ + Buff.affect(ch, Blindness.class,10f ); + if ( ch.properties().contains(Char.Property.UNDEAD) + || ch.properties().contains(Char.Property.UNKNOW) + || ch.properties().contains(Char.Property.MECH) + || ch.properties().contains(Char.Property.ELEMENT) + || ch.properties().contains(Char.Property.DEMONIC) + || ch.properties().contains(Char.Property.DRAGON) + || ch.properties().contains(Char.Property.BOSS) + || ch.properties().contains(Char.Property.MINIBOSS) + ) { + int dmg = Random.NormalIntRange(200, 400); + ch.damage(dmg, this); + } else { + int dmg = Random.NormalIntRange(50, 100); + ch.damage(dmg, this); + } + } + }} + + Dungeon.observe(); + } + + @Override + public int price() { + return 20 * quantity; + } + + public LightBomb() { + this(1); + } + + public LightBomb(int value) { + this.quantity = value; + } + +} diff --git a/java/com/hmdzl/spspd/items/bombs/MiniBomb.java b/java/com/hmdzl/spspd/items/bombs/MiniBomb.java new file mode 100644 index 00000000..54eb392e --- /dev/null +++ b/java/com/hmdzl/spspd/items/bombs/MiniBomb.java @@ -0,0 +1,82 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 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 + */ +package com.hmdzl.spspd.items.bombs; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.particles.SmokeParticle; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.Terrain; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +import com.watabou.utils.Random; + +public class MiniBomb extends Bomb { + + { + //name = "mini bomb"; + image = ItemSpriteSheet.MINI_BOMB; + } + + + @Override + public void explode(int cell) { + super.explode(cell); + boolean terrainAffected = false;{ + int c = cell; + + if (Dungeon.visible[c]) { + CellEmitter.get(c).burst(SmokeParticle.FACTORY, 4); + } + + if (Level.flamable[c]) { + Level.set(c, Terrain.EMBERS); + GameScene.updateMap(c); + terrainAffected = true; + } + + Char ch = Actor.findChar(c); + if (ch != null) { + // those not at the center of the blast take damage less + // consistently. + int minDamage = ch.HT/15; + int maxDamage = ch.HT/6; + + int dmg = Random.NormalIntRange(minDamage, maxDamage) - Math.max(ch.drRoll(),0); + if (dmg > 0) { + ch.damage(dmg, this); + } + } + + } + + if (terrainAffected) { + Dungeon.observe(); + } + + } + + @Override + public int price() { + return 10 * quantity; + } + +} diff --git a/java/com/hmdzl/spspd/items/bombs/StormBomb.java b/java/com/hmdzl/spspd/items/bombs/StormBomb.java new file mode 100644 index 00000000..2fb2a88a --- /dev/null +++ b/java/com/hmdzl/spspd/items/bombs/StormBomb.java @@ -0,0 +1,55 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 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 + */ +package com.hmdzl.spspd.items.bombs; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.blobs.Blob; +import com.hmdzl.spspd.actors.blobs.ElectriShock; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.BArray; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.PathFinder; + +public class StormBomb extends Bomb { + + { + image = ItemSpriteSheet.STORM_BOMB; + + } + + + @Override + public void explode(int cell) { + super.explode(cell); + PathFinder.buildDistanceMap( cell, BArray.not( Dungeon.level.solid, null ), 2 ); + for (int i = 0; i < PathFinder.distance.length; i++) { + if (PathFinder.distance[i] < Integer.MAX_VALUE) { + GameScene.add(Blob.seed(i, 20, ElectriShock.class)); + } + } + Sample.INSTANCE.play(Assets.SND_LIGHTNING); + } + + @Override + public int price() { + return 20 * quantity; + } + +} diff --git a/java/com/hmdzl/spspd/items/challengelists/CaveChallenge.java b/java/com/hmdzl/spspd/items/challengelists/CaveChallenge.java new file mode 100644 index 00000000..63a96c05 --- /dev/null +++ b/java/com/hmdzl/spspd/items/challengelists/CaveChallenge.java @@ -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 + */ +package com.hmdzl.spspd.items.challengelists; + +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class CaveChallenge extends ChallengeList { + + { + //name = "journal page sokoban practice"; + image = ItemSpriteSheet.CAVEKEY; + room=3; + + stackable = false; + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/challengelists/ChallengeList.java b/java/com/hmdzl/spspd/items/challengelists/ChallengeList.java new file mode 100644 index 00000000..10dfaf75 --- /dev/null +++ b/java/com/hmdzl/spspd/items/challengelists/ChallengeList.java @@ -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 + */ +package com.hmdzl.spspd.items.challengelists; + +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class ChallengeList extends Item { + + private static final String TXT_VALUE = "Journal Page"; + public int room; + + { + //name = "Challenge list"; + image = ItemSpriteSheet.JOURNAL_PAGE; + + stackable = false; + unique = true; + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + +} diff --git a/java/com/hmdzl/spspd/items/challengelists/CityChallenge.java b/java/com/hmdzl/spspd/items/challengelists/CityChallenge.java new file mode 100644 index 00000000..e124f139 --- /dev/null +++ b/java/com/hmdzl/spspd/items/challengelists/CityChallenge.java @@ -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 + */ +package com.hmdzl.spspd.items.challengelists; + +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class CityChallenge extends ChallengeList { + + { + //name = "journal page sokoban practice"; + image = ItemSpriteSheet.CITYKEY; + room=4; + + stackable = false; + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/challengelists/CourageChallenge.java b/java/com/hmdzl/spspd/items/challengelists/CourageChallenge.java new file mode 100644 index 00000000..19f66da8 --- /dev/null +++ b/java/com/hmdzl/spspd/items/challengelists/CourageChallenge.java @@ -0,0 +1,38 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.challengelists; + +import com.hmdzl.spspd.Statistics; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class CourageChallenge extends ChallengeList { + + { + //name = "journal page sokoban practice"; + image = ItemSpriteSheet.COURAGETRIAL; + room=5; + + stackable = false; + } + + @Override + public int price() { + if (Statistics.deepestFloor < 26){return 9000 * quantity;} + else {return 300*quantity;} + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/challengelists/PowerChallenge.java b/java/com/hmdzl/spspd/items/challengelists/PowerChallenge.java new file mode 100644 index 00000000..9bb8b16b --- /dev/null +++ b/java/com/hmdzl/spspd/items/challengelists/PowerChallenge.java @@ -0,0 +1,38 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.challengelists; + +import com.hmdzl.spspd.Statistics; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class PowerChallenge extends ChallengeList { + + { + //name = "journal page sokoban practice"; + image = ItemSpriteSheet.POWERTRIAL; + room=6; + + stackable = false; + } + + @Override + public int price() { + if (Statistics.deepestFloor < 26){return 9000 * quantity;} + else {return 500*quantity;} + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/challengelists/PrisonChallenge.java b/java/com/hmdzl/spspd/items/challengelists/PrisonChallenge.java new file mode 100644 index 00000000..d3c2493f --- /dev/null +++ b/java/com/hmdzl/spspd/items/challengelists/PrisonChallenge.java @@ -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 + */ +package com.hmdzl.spspd.items.challengelists; + +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class PrisonChallenge extends ChallengeList { + + { + //name = "journal page sokoban practice"; + image = ItemSpriteSheet.PRISONKEY; + room=2; + + stackable = false; + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/challengelists/SewerChallenge.java b/java/com/hmdzl/spspd/items/challengelists/SewerChallenge.java new file mode 100644 index 00000000..2544108c --- /dev/null +++ b/java/com/hmdzl/spspd/items/challengelists/SewerChallenge.java @@ -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 + */ +package com.hmdzl.spspd.items.challengelists; + +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class SewerChallenge extends ChallengeList { + + { + //name = "journal page sokoban practice"; + image = ItemSpriteSheet.SEWERSKEY; + room=1; + + stackable = false; + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/challengelists/WisdomChallenge.java b/java/com/hmdzl/spspd/items/challengelists/WisdomChallenge.java new file mode 100644 index 00000000..7a2dd6d0 --- /dev/null +++ b/java/com/hmdzl/spspd/items/challengelists/WisdomChallenge.java @@ -0,0 +1,38 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.challengelists; + +import com.hmdzl.spspd.Statistics; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class WisdomChallenge extends ChallengeList { + + { + //name = "journal page sokoban practice"; + image = ItemSpriteSheet.WISDOMTRIAL; + room=7; + + stackable = false; + } + + @Override + public int price() { + if (Statistics.deepestFloor < 26){return 9000 * quantity;} + else {return 600*quantity;} + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/eggs/BlueDragonEgg.java b/java/com/hmdzl/spspd/items/eggs/BlueDragonEgg.java new file mode 100644 index 00000000..6043cd30 --- /dev/null +++ b/java/com/hmdzl/spspd/items/eggs/BlueDragonEgg.java @@ -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 + */ +package com.hmdzl.spspd.items.eggs; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.mobs.pets.BlueDragon; + +import com.hmdzl.spspd.actors.mobs.pets.PET; + +import com.hmdzl.spspd.effects.Pushing; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.noosa.tweeners.AlphaTweener; + +public class BlueDragonEgg extends Egg { + + public static final float TIME_TO_USE = 1; + + public static final int LERY_FIRE = 10; + + + { + //name = "shadow dragon egg"; + image = ItemSpriteSheet.BLUE_DRAGONEGG; + unique = true; + stackable = false; + } + + public int startMoves = 0; + public int moves = 0; + public int burns = 0; + public int freezes = 20; + public int poisons = 0; + public int lits = 0; + public int summons = 0; + public int light = 0; + + @Override + public void execute(Hero hero, String action) { + if (action.equals(AC_BREAK)) { + + BlueDragon pet = new BlueDragon(); + eggHatch(pet); + + hero.next(); + + } + + else if (action.equals(AC_SHAKE)) { + + GLog.w(Messages.get(Egg.class,"kick")); + + } else { + + super.execute(hero, action); + + } + + } + + public void eggHatch (PET pet) { + + int spawnPos = getSpawnPos(); + if (spawnPos != -1 && !Dungeon.hero.haspet) { + + pet.spawn(1); + pet.HP = pet.HT; + pet.pos = spawnPos; + pet.state = pet.HUNTING; + + GameScene.add(pet); + Actor.addDelayed(new Pushing(pet, Dungeon.hero.pos, spawnPos), -1f); + + pet.sprite.alpha(0); + pet.sprite.parent.add(new AlphaTweener(pet.sprite, 1, 0.15f)); + + detach(Dungeon.hero.belongings.backpack); + GLog.w(Messages.get(Egg.class,"hatch")); + Dungeon.hero.haspet=true; + + assignPet(pet); + + } else { + + Dungeon.hero.spend(LeryFireEgg.TIME_TO_USE); + GLog.w(Messages.get(Egg.class,"notready")); + + } + } + + private void assignPet(PET pet){ + + Dungeon.hero.petType=pet.type; + Dungeon.hero.petLevel=pet.level; + + Dungeon.hero.petHP=pet.HP; + Dungeon.hero.petExperience=pet.experience; + Dungeon.hero.petCooldown=pet.cooldown; + } + + @Override + public int price() { + return 500 * quantity; + } + +} diff --git a/java/com/hmdzl/spspd/items/eggs/CocoCatEgg.java b/java/com/hmdzl/spspd/items/eggs/CocoCatEgg.java new file mode 100644 index 00000000..939b664c --- /dev/null +++ b/java/com/hmdzl/spspd/items/eggs/CocoCatEgg.java @@ -0,0 +1,137 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.eggs; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.mobs.pets.CocoCat; +import com.hmdzl.spspd.actors.mobs.pets.PET; + +import com.hmdzl.spspd.effects.Pushing; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.noosa.tweeners.AlphaTweener; +import com.watabou.utils.Random; + +public class CocoCatEgg extends Egg { + + public static final float TIME_TO_USE = 1; + + { + image = ItemSpriteSheet.RANDOWNEGG; + unique = true; + stackable = false; + } + + @Override + public void execute(Hero hero, String action) { + + if (action.equals(AC_BREAK)) { + + CocoCat pet = new CocoCat(); + eggHatch(pet); + + hero.next(); + + } + + else if (action.equals(AC_SHAKE)) { + + GLog.w(Messages.get(Egg.class,"kick")); + + } else { + + super.execute(hero, action); + + } + + + + } + + public int getSpawnPos(){ + int newPos = -1; + int pos = Dungeon.hero.pos; + ArrayList candidates = new ArrayList(); + boolean[] passable = Level.passable; + + for (int n : Level.NEIGHBOURS8) { + int c = pos + n; + if (passable[c] && Actor.findChar(c) == null) { + candidates.add(c); + } + } + + newPos = candidates.size() > 0 ? Random.element(candidates) : -1; + + return newPos; + } + + + public void eggHatch (PET pet) { + + int spawnPos = getSpawnPos(); + if (spawnPos != -1 && !Dungeon.hero.haspet) { + + pet.spawn(1); + pet.HP = pet.HT; + pet.pos = spawnPos; + pet.state = pet.HUNTING; + + GameScene.add(pet); + Actor.addDelayed(new Pushing(pet, Dungeon.hero.pos, spawnPos), -1f); + + pet.sprite.alpha(0); + pet.sprite.parent.add(new AlphaTweener(pet.sprite, 1, 0.15f)); + + detach(Dungeon.hero.belongings.backpack); + GLog.w(Messages.get(Egg.class,"hatch")); + Dungeon.hero.haspet=true; + + assignPet(pet); + + } else { + + Dungeon.hero.spend(CocoCatEgg.TIME_TO_USE); + GLog.w(Messages.get(Egg.class,"notready")); + + } + } + + private void assignPet(PET pet){ + + Dungeon.hero.petType=pet.type; + Dungeon.hero.petLevel=pet.level; + + Dungeon.hero.petHP=pet.HP; + Dungeon.hero.petExperience=pet.experience; + Dungeon.hero.petCooldown=pet.cooldown; + } + + @Override + public int price() { + return 500 * quantity; + } + +} diff --git a/java/com/hmdzl/spspd/items/eggs/EasterEgg.java b/java/com/hmdzl/spspd/items/eggs/EasterEgg.java new file mode 100644 index 00000000..e1512a7e --- /dev/null +++ b/java/com/hmdzl/spspd/items/eggs/EasterEgg.java @@ -0,0 +1,138 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2014 Oleg Dolya + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.items.eggs; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.mobs.pets.Bunny; + +import com.hmdzl.spspd.actors.mobs.pets.PET; + +import com.hmdzl.spspd.effects.Pushing; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.noosa.tweeners.AlphaTweener; + +public class EasterEgg extends Egg { + + public static final float TIME_TO_USE = 1; + + public static final int BUNNY = 10; + + + { + //name = "egg"; + image = ItemSpriteSheet.RABBITEGG; + unique = true; + stackable = false; + } + + @Override + public void execute(Hero hero, String action) { + + if (action.equals(AC_BREAK)) { + + Bunny pet = new Bunny(); + eggHatch(pet); + + hero.next(); + + } + + else if (action.equals(AC_SHAKE)) { + + GLog.w(Messages.get(Egg.class,"kick")); + + + } else { + + super.execute(hero, action); + + } + + + + } + + /*public int getSpawnPos(){ + int newPos = -1; + int pos = Dungeon.hero.pos; + ArrayList candidates = new ArrayList(); + boolean[] passable = Level.passable; + + for (int n : Level.NEIGHBOURS8) { + int c = pos + n; + if (passable[c] && Actor.findChar(c) == null) { + candidates.add(c); + } + } + + newPos = candidates.size() > 0 ? Random.element(candidates) : -1; + + return newPos; + }*/ + + + public void eggHatch (PET pet) { + + int spawnPos = getSpawnPos(); + if (spawnPos != -1 && !Dungeon.hero.haspet) { + + pet.spawn(1); + pet.HP = pet.HT; + pet.pos = spawnPos; + pet.state = pet.HUNTING; + + GameScene.add(pet); + Actor.addDelayed(new Pushing(pet, Dungeon.hero.pos, spawnPos), -1f); + + pet.sprite.alpha(0); + pet.sprite.parent.add(new AlphaTweener(pet.sprite, 1, 0.15f)); + + detach(Dungeon.hero.belongings.backpack); + GLog.w(Messages.get(Egg.class,"hatch")); + Dungeon.hero.haspet=true; + assignPet(pet); + + } else { + + Dungeon.hero.spend(EasterEgg.TIME_TO_USE); + GLog.w(Messages.get(Egg.class,"notready")); + + } + } + + private void assignPet(PET pet){ + + Dungeon.hero.petType=pet.type; + Dungeon.hero.petLevel=pet.level; + + Dungeon.hero.petHP=pet.HP; + Dungeon.hero.petExperience=pet.experience; + Dungeon.hero.petCooldown=pet.cooldown; + } + + @Override + public int price() { + return 500 * quantity; + } + +} diff --git a/java/com/hmdzl/spspd/items/eggs/Egg.java b/java/com/hmdzl/spspd/items/eggs/Egg.java new file mode 100644 index 00000000..04db8b84 --- /dev/null +++ b/java/com/hmdzl/spspd/items/eggs/Egg.java @@ -0,0 +1,401 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.eggs; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.Statistics; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.mobs.pets.BlueDragon; +import com.hmdzl.spspd.actors.mobs.pets.BugDragon; +import com.hmdzl.spspd.actors.mobs.pets.GoldDragon; +import com.hmdzl.spspd.actors.mobs.pets.GreenDragon; +import com.hmdzl.spspd.actors.mobs.pets.LeryFire; +import com.hmdzl.spspd.actors.mobs.pets.LightDragon; +import com.hmdzl.spspd.actors.mobs.pets.PET; +import com.hmdzl.spspd.actors.mobs.pets.RedDragon; +import com.hmdzl.spspd.actors.mobs.pets.Scorpion; +import com.hmdzl.spspd.actors.mobs.pets.ShadowDragon; +import com.hmdzl.spspd.actors.mobs.pets.Spider; + +import com.hmdzl.spspd.actors.mobs.pets.Velocirooster; +import com.hmdzl.spspd.actors.mobs.pets.VioletDragon; +import com.hmdzl.spspd.effects.Pushing; +import com.hmdzl.spspd.effects.particles.SparkParticle; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.noosa.tweeners.AlphaTweener; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public class Egg extends Item { + + private static final String TXT_PREVENTING = "This is not the best place to try that."; + private static final String TXT_NOTREADY = "Something tells you it's not ready yet."; + private static final String TXT_YOLK = "Ewww. Gross, uncooked egg of a random creature."; + private static final String TXT_HATCH = "Something hatches!"; + private static final String TXT_SCRATCH = "Something scratches back!"; + private static final String TXT_SLITHERS = "Something squirms inside!"; + private static final String TXT_KICKS = "Something powerful kicks back!"; + private static final String TXT_SLOSH = "Just some sloshing around."; + private static final String TXT_ZAP = "Ouch! Something zaps you back!."; + + public static final float TIME_TO_USE = 1; + + public static final String AC_BREAK = "BREAK"; + public static final String AC_SHAKE = "SHAKE"; + + public static final int RED_DRAGON = 20; + public static final int GREEN_DRAGON = 20; + public static final int BLUE_DRAGON = Dungeon.getMonth()==11 ? 10 : 20; + public static final int VIOLET_DRAGON = 20; + public static final int SPIDER = 1000; + public static final int SCORPION = 2000; + public static final int VELOCIROOSTER = 5; + public static final int LIGHT_DRAGON = 20; + public static final int SHADOW_DRAGON = 20; + + + { + //name = "egg"; + image = ItemSpriteSheet.EGG; + unique = true; + stackable = false; + } + + public int startMoves = 0; + public int moves = 0; + public int burns = 0; + public int freezes = 0; + public int poisons = 0; + public int lits = 0; + public int summons = 0; + public int light = 0; + + private static final String STARTMOVES = "startMoves"; + private static final String MOVES = "moves"; + private static final String BURNS = "burns"; + private static final String FREEZES = "freezes"; + private static final String POISONS = "poisons"; + private static final String LITS = "lits"; + private static final String SUMMONS = "summons"; + private static final String LIGHT = "light"; + + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(STARTMOVES, startMoves); + bundle.put(MOVES, moves); + bundle.put(BURNS, burns); + bundle.put(FREEZES, freezes); + bundle.put(POISONS, poisons); + bundle.put(LITS, lits); + bundle.put(SUMMONS, summons); + bundle.put(LIGHT, light); + + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + startMoves = bundle.getInt(STARTMOVES); + moves = bundle.getInt(MOVES); + burns = bundle.getInt(BURNS); + freezes = bundle.getInt(FREEZES); + poisons = bundle.getInt(POISONS); + lits = bundle.getInt(LITS); + summons = bundle.getInt(SUMMONS); + light = bundle.getInt(LIGHT); + + } + + public int checkMoves () { + return moves; + } + public int checkBurns () { + return burns; + } + public int checkFreezes () { + return freezes; + } + public int checkPoisons () { + return poisons; + } + public int checkLits () { + return lits; + } + public int checkSummons () { + return summons; + } + + public int checkLight () { + return light; + } + + @Override + public boolean doPickUp(Hero hero) { + + GLog.w(Messages.get(Egg.class,"warmhome")); + + Egg egg = hero.belongings.getItem(Egg.class); + if (egg!=null){ + GLog.w(Messages.get(Egg.class,"onlyone")); + } + + return super.doPickUp(hero); + } + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + if (Dungeon.hero.haspet == false & Dungeon.depth < 26) actions.add(AC_BREAK); + actions.add(AC_SHAKE); + + return actions; + } + + @Override + public void execute(Hero hero, String action) { + + if (action.equals(AC_BREAK)) { + + boolean hatch = false; + if (checkFreezes()>=BLUE_DRAGON && checkPoisons()>=VIOLET_DRAGON && checkBurns()>=RED_DRAGON && checkLits()>=GREEN_DRAGON + && checkLight()>=SHADOW_DRAGON && checkSummons()>=LIGHT_DRAGON && checkMoves()>=SCORPION){ + if (Dungeon.getMonth()==9 || Random.Int(50) == 0){ + BugDragon pet = new BugDragon(); + eggHatch(pet); + hatch=true; + } else { + GoldDragon pet = new GoldDragon(); + eggHatch(pet); + hatch=true; + } + } else if (checkLight()>= 20 ){ + ShadowDragon pet = new ShadowDragon(); + eggHatch(pet); + hatch=true; + //spawn ShadowDragon + + } else if (checkFreezes()>=5 && checkPoisons()>=5 && checkBurns()>=5 && checkLits()>=5 && checkMoves()>=50){ + LeryFire pet = new LeryFire(); + eggHatch(pet); + hatch=true; + //spawn leryfire + } else if (checkFreezes()>=BLUE_DRAGON) { + BlueDragon pet = new BlueDragon(); + eggHatch(pet); + hatch=true; + //spawn ice dragon + } else if (checkSummons()>=LIGHT_DRAGON) { + LightDragon pet = new LightDragon(); + eggHatch(pet); + hatch=true; + } else if (checkPoisons()>=VIOLET_DRAGON) { + VioletDragon pet = new VioletDragon(); + eggHatch(pet); + hatch=true; + //spawn green dragon + } else if (checkLits()>=GREEN_DRAGON) { + GreenDragon pet = new GreenDragon(); + eggHatch(pet); + hatch=true; + //spawn lit dragon + } else if (checkBurns()>=RED_DRAGON) { + RedDragon pet = new RedDragon(); + eggHatch(pet); + hatch=true; + //spawn red dragon + } else if (checkBurns()>=VELOCIROOSTER) { + Velocirooster pet = new Velocirooster(); + eggHatch(pet); + hatch=true; + //spawn velocirooster + } else if (checkMoves()>=SCORPION) { + Scorpion pet = new Scorpion(); + eggHatch(pet); + hatch=true; + //spawn spider + } else if (checkMoves()>=SPIDER) { + Spider pet = new Spider(); + eggHatch(pet); + hatch=true; + //spawn bat + } else if (checkMoves()>=100) { + Dungeon.level.drop(new RandomEgg(),hero.pos).sprite.drop(); + + } + + if (!hatch) { + detach(Dungeon.hero.belongings.backpack); + GLog.w(Messages.get(Egg.class,"yolk")); + } + + Statistics.eggBreak++; + Badges.validateEggBreak(); + hero.next(); + + } + + else if (action.equals(AC_SHAKE)) { + + boolean alive = false; + + + + if (checkFreezes()>=BLUE_DRAGON && checkPoisons()>=VIOLET_DRAGON && checkBurns()>=RED_DRAGON && checkLits()>=GREEN_DRAGON + && checkLight()>=SHADOW_DRAGON && checkSummons()>=LIGHT_DRAGON && checkMoves()>=SCORPION) { + GLog.w(Messages.get(Egg.class,"zap")); + Dungeon.hero.sprite.centerEmitter().burst(SparkParticle.FACTORY, 3); + Dungeon.hero.sprite.flash(); + Dungeon.hero.damage(1, this); + alive = true; + + } else if (checkSummons()>=SHADOW_DRAGON || checkLight()>=LIGHT_DRAGON || checkFreezes()>=BLUE_DRAGON + || checkPoisons()>=VIOLET_DRAGON || checkLits()>=GREEN_DRAGON || checkBurns()>=RED_DRAGON) { + GLog.w(Messages.get(Egg.class,"kick")); + alive = true; + + } else if (checkBurns()>=VELOCIROOSTER) { + GLog.w(Messages.get(Egg.class,"scratch")); + alive = true; + //spawn velocirooster + } else if (checkMoves()>=SCORPION) { + GLog.w(Messages.get(Egg.class,"slithers")); + alive = true; + //spawn spider + } else if (checkMoves()>=SPIDER) { + GLog.w(Messages.get(Egg.class,"slithers")); + alive = true; + //spawn scorpion + } + + if (!alive) { + GLog.w(Messages.get(Egg.class,"slosh")); + } + + } else { + + super.execute(hero, action); + + } + + + + } + + public int getSpawnPos(){ + int newPos = -1; + int pos = Dungeon.hero.pos; + ArrayList candidates = new ArrayList(); + boolean[] passable = Level.passable; + + for (int n : Level.NEIGHBOURS8) { + int c = pos + n; + if (passable[c] && Actor.findChar(c) == null) { + candidates.add(c); + } + } + + newPos = candidates.size() > 0 ? Random.element(candidates) : -1; + + return newPos; + } + + + public void eggHatch (PET pet) { + + int spawnPos = getSpawnPos(); + if (spawnPos != -1 && !Dungeon.hero.haspet) { + + pet.spawn(1); + pet.HP = pet.HT; + pet.pos = spawnPos; + pet.state = pet.HUNTING; + + GameScene.add(pet); + Actor.addDelayed(new Pushing(pet, Dungeon.hero.pos, spawnPos), -1f); + + pet.sprite.alpha(0); + pet.sprite.parent.add(new AlphaTweener(pet.sprite, 1, 0.15f)); + + detach(Dungeon.hero.belongings.backpack); + GLog.w(Messages.get(Egg.class,"hatch")); + Dungeon.hero.haspet=true; + + assignPet(pet); + + } else { + + Dungeon.hero.spend(Egg.TIME_TO_USE); + GLog.w(Messages.get(Egg.class,"notready")); + Statistics.eggBreak--; + Badges.validateEggBreak(); + + } + } + + + private void assignPet(PET pet){ + + Dungeon.hero.petType=pet.type; + Dungeon.hero.petLevel=pet.level; + + Dungeon.hero.petHP=pet.HP; + Dungeon.hero.petExperience=pet.experience; + Dungeon.hero.petCooldown=pet.cooldown; + } + + @Override + public int price() { + return 50 * quantity; + } + + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + @Override + public String info() { + String info = desc(); + info += "\n\n" + Messages.get(this, "moves",moves); + info += "\n" + Messages.get(this, "burns",burns); + info += "\n" + Messages.get(this, "freezes",freezes); + info += "\n" + Messages.get(this, "poisons",poisons); + info += "\n" + Messages.get(this, "lits",lits); + info += "\n" + Messages.get(this, "summons",summons); + info += "\n" + Messages.get(this, "light",light); + + return info; + } +} diff --git a/java/com/hmdzl/spspd/items/eggs/GoldDragonEgg.java b/java/com/hmdzl/spspd/items/eggs/GoldDragonEgg.java new file mode 100644 index 00000000..c38633ee --- /dev/null +++ b/java/com/hmdzl/spspd/items/eggs/GoldDragonEgg.java @@ -0,0 +1,126 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.eggs; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.mobs.pets.BugDragon; +import com.hmdzl.spspd.actors.mobs.pets.GoldDragon; +import com.hmdzl.spspd.actors.mobs.pets.PET; + +import com.hmdzl.spspd.effects.Pushing; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.noosa.tweeners.AlphaTweener; +import com.watabou.utils.Random; + +public class GoldDragonEgg extends Egg { + + public static final float TIME_TO_USE = 1; + { + //name = "GoldDragon egg"; + image = ItemSpriteSheet.GOLD_DRAGONEGG; + unique = true; + stackable = false; + } + + public int moves = 5000; + public int burns = 20; + public int freezes = 20; + public int poisons = 20; + public int lits = 20; + public int summons = 20; + public int light = 20; + + @Override + public void execute(Hero hero, String action) { + if (action.equals(AC_BREAK)) { + if (Dungeon.getMonth()==9 || Random.Int(50) == 0){ + BugDragon pet = new BugDragon(); + eggHatch(pet); + } else { + GoldDragon pet = new GoldDragon(); + eggHatch(pet); + } + hero.next(); + + } + + else if (action.equals(AC_SHAKE)) { + + GLog.w(Messages.get(Egg.class,"kick")); + + } else { + + super.execute(hero, action); + + } + + + + } + + public void eggHatch (PET pet) { + + int spawnPos = getSpawnPos(); + if (spawnPos != -1 && !Dungeon.hero.haspet) { + + pet.spawn(1); + pet.HP = pet.HT; + pet.pos = spawnPos; + pet.state = pet.HUNTING; + + GameScene.add(pet); + Actor.addDelayed(new Pushing(pet, Dungeon.hero.pos, spawnPos), -1f); + + pet.sprite.alpha(0); + pet.sprite.parent.add(new AlphaTweener(pet.sprite, 1, 0.15f)); + + detach(Dungeon.hero.belongings.backpack); + GLog.w(Messages.get(Egg.class,"hatch")); + Dungeon.hero.haspet=true; + + assignPet(pet); + + } else { + + Dungeon.hero.spend(LeryFireEgg.TIME_TO_USE); + GLog.w(Messages.get(Egg.class,"notready")); + + } + } + + private void assignPet(PET pet){ + + Dungeon.hero.petType=pet.type; + Dungeon.hero.petLevel=pet.level; + + Dungeon.hero.petHP=pet.HP; + Dungeon.hero.petExperience=pet.experience; + Dungeon.hero.petCooldown=pet.cooldown; + } + + @Override + public int price() { + return 500 * quantity; + } + +} diff --git a/java/com/hmdzl/spspd/items/eggs/GreenDragonEgg.java b/java/com/hmdzl/spspd/items/eggs/GreenDragonEgg.java new file mode 100644 index 00000000..212c7c68 --- /dev/null +++ b/java/com/hmdzl/spspd/items/eggs/GreenDragonEgg.java @@ -0,0 +1,242 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.eggs; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.hero.Hero; + +import com.hmdzl.spspd.actors.mobs.pets.GreenDragon; +import com.hmdzl.spspd.actors.mobs.pets.PET; + +import com.hmdzl.spspd.effects.Pushing; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.noosa.tweeners.AlphaTweener; +import com.watabou.utils.Bundle; + +public class GreenDragonEgg extends Egg { + + public static final float TIME_TO_USE = 1; + + public static final int LERY_FIRE = 10; + + + { + //name = "shadow dragon egg"; + image = ItemSpriteSheet.GREEN_DRAGONEGG; + unique = true; + stackable = false; + } + + public int startMoves = 0; + public int moves = 0; + public int burns = 0; + public int freezes = 0; + public int poisons = 0; + public int lits = 20; + public int summons = 0; + public int light = 0; + + private static final String STARTMOVES = "startMoves"; + private static final String MOVES = "moves"; + private static final String BURNS = "burns"; + private static final String FREEZES = "freezes"; + private static final String POISONS = "poisons"; + private static final String LITS = "lits"; + private static final String SUMMONS = "summons"; + private static final String LIGHT = "light"; + + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(STARTMOVES, startMoves); + bundle.put(MOVES, moves); + bundle.put(BURNS, burns); + bundle.put(FREEZES, freezes); + bundle.put(POISONS, poisons); + bundle.put(LITS, lits); + bundle.put(SUMMONS, summons); + bundle.put(LIGHT, light); + + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + startMoves = bundle.getInt(STARTMOVES); + moves = bundle.getInt(MOVES); + burns = bundle.getInt(BURNS); + freezes = bundle.getInt(FREEZES); + poisons = bundle.getInt(POISONS); + lits = bundle.getInt(LITS); + summons = bundle.getInt(SUMMONS); + light = bundle.getInt(LIGHT); + + } + + public int checkMoves () { + return moves; + } + public int checkBurns () { + return burns; + } + public int checkFreezes () { + return freezes; + } + public int checkPoisons () { + return poisons; + } + public int checkLits () { + return lits; + } + public int checkSummons () { + return summons; + } + + public int checkLight () { + return light; + } + + /*@Override + public boolean doPickUp(Hero hero) { + + GLog.w("The egg likes to be warm in your pack."); + + Egg egg = hero.belongings.getItem(Egg.class); + if (egg!=null){ + GLog.w("You can probably only keep one egg warm at a time."); + } + + return super.doPickUp(hero); + } */ + + /*@Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + actions.add(AC_BREAK); + actions.add(AC_SHAKE); + + return actions; + }*/ + + @Override + public void execute(Hero hero, String action) { + + /* + if (action == AC_BREAK) { + + if (Dungeon.depth>26) { + hero.spend(EasterEgg.TIME_TO_USE); + GLog.w(TXT_PREVENTING); + return; + } + } + */ + + if (action.equals(AC_BREAK)) { + + GreenDragon pet = new GreenDragon(); + eggHatch(pet); + + hero.next(); + + } + + else if (action.equals(AC_SHAKE)) { + + GLog.w(Messages.get(Egg.class,"kick")); + + } else { + + super.execute(hero, action); + + } + + + + } + + /*public int getSpawnPos(){ + int newPos = -1; + int pos = Dungeon.hero.pos; + ArrayList candidates = new ArrayList(); + boolean[] passable = Level.passable; + + for (int n : Level.NEIGHBOURS8) { + int c = pos + n; + if (passable[c] && Actor.findChar(c) == null) { + candidates.add(c); + } + } + + newPos = candidates.size() > 0 ? Random.element(candidates) : -1; + + return newPos; + }*/ + + + public void eggHatch (PET pet) { + + int spawnPos = getSpawnPos(); + if (spawnPos != -1 && !Dungeon.hero.haspet) { + + pet.spawn(1); + pet.HP = pet.HT; + pet.pos = spawnPos; + pet.state = pet.HUNTING; + + GameScene.add(pet); + Actor.addDelayed(new Pushing(pet, Dungeon.hero.pos, spawnPos), -1f); + + pet.sprite.alpha(0); + pet.sprite.parent.add(new AlphaTweener(pet.sprite, 1, 0.15f)); + + detach(Dungeon.hero.belongings.backpack); + GLog.w(Messages.get(Egg.class,"hatch")); + Dungeon.hero.haspet=true; + + assignPet(pet); + + } else { + + Dungeon.hero.spend(LeryFireEgg.TIME_TO_USE); + GLog.w(Messages.get(Egg.class,"notready")); + + } + } + + private void assignPet(PET pet){ + + Dungeon.hero.petType=pet.type; + Dungeon.hero.petLevel=pet.level; + + Dungeon.hero.petHP=pet.HP; + Dungeon.hero.petExperience=pet.experience; + Dungeon.hero.petCooldown=pet.cooldown; + } + + @Override + public int price() { + return 500 * quantity; + } + +} diff --git a/java/com/hmdzl/spspd/items/eggs/LeryFireEgg.java b/java/com/hmdzl/spspd/items/eggs/LeryFireEgg.java new file mode 100644 index 00000000..28969e4e --- /dev/null +++ b/java/com/hmdzl/spspd/items/eggs/LeryFireEgg.java @@ -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 + */ +package com.hmdzl.spspd.items.eggs; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.hero.Hero; + +import com.hmdzl.spspd.actors.mobs.pets.LeryFire; +import com.hmdzl.spspd.actors.mobs.pets.PET; + +import com.hmdzl.spspd.effects.Pushing; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.noosa.tweeners.AlphaTweener; + +public class LeryFireEgg extends Egg { + + public static final float TIME_TO_USE = 1; + { + image = ItemSpriteSheet.FIREEGG; + unique = true; + stackable = false; + } + + public int startMoves = 0; + public int moves = 0; + public int burns = 1; + public int freezes = 1; + public int poisons = 1; + public int lits = 1; + public int summons = 0; + public int light = 0; + + @Override + public void execute(Hero hero, String action) { + + if (action.equals(AC_BREAK)) { + + LeryFire pet = new LeryFire(); + eggHatch(pet); + + hero.next(); + + } + + else if (action.equals(AC_SHAKE)) { + + GLog.w(Messages.get(Egg.class,"kick")); + + } else { + + super.execute(hero, action); + + } + + } + + public void eggHatch (PET pet) { + + int spawnPos = getSpawnPos(); + if (spawnPos != -1 && !Dungeon.hero.haspet) { + + pet.spawn(1); + pet.HP = pet.HT; + pet.pos = spawnPos; + pet.state = pet.HUNTING; + + GameScene.add(pet); + Actor.addDelayed(new Pushing(pet, Dungeon.hero.pos, spawnPos), -1f); + + pet.sprite.alpha(0); + pet.sprite.parent.add(new AlphaTweener(pet.sprite, 1, 0.15f)); + + detach(Dungeon.hero.belongings.backpack); + GLog.w(Messages.get(Egg.class,"hatch")); + Dungeon.hero.haspet=true; + + assignPet(pet); + + } else { + + Dungeon.hero.spend(LeryFireEgg.TIME_TO_USE); + GLog.w(Messages.get(Egg.class,"notready")); + + } + } + + private void assignPet(PET pet){ + + Dungeon.hero.petType=pet.type; + Dungeon.hero.petLevel=pet.level; + + Dungeon.hero.petHP=pet.HP; + Dungeon.hero.petExperience=pet.experience; + Dungeon.hero.petCooldown=pet.cooldown; + } + + @Override + public int price() { + return 500 * quantity; + } + +} diff --git a/java/com/hmdzl/spspd/items/eggs/LightDragonEgg.java b/java/com/hmdzl/spspd/items/eggs/LightDragonEgg.java new file mode 100644 index 00000000..e772288c --- /dev/null +++ b/java/com/hmdzl/spspd/items/eggs/LightDragonEgg.java @@ -0,0 +1,123 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.eggs; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.mobs.pets.LightDragon; +import com.hmdzl.spspd.actors.mobs.pets.PET; + +import com.hmdzl.spspd.effects.Pushing; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.noosa.tweeners.AlphaTweener; + +public class LightDragonEgg extends Egg { + + public static final float TIME_TO_USE = 1; + + { + image = ItemSpriteSheet.LIGHT_DRAGONEGG; + unique = true; + stackable = false; + } + + public int startMoves = 0; + public int moves = 0; + public int burns = 0; + public int freezes = 0; + public int poisons = 0; + public int lits = 0; + public int summons = 20; + public int light = 0; + + @Override + public void execute(Hero hero, String action) { + + if (action.equals(AC_BREAK)) { + + LightDragon pet = new LightDragon(); + eggHatch(pet); + + hero.next(); + + } + + else if (action.equals(AC_SHAKE)) { + + GLog.w(Messages.get(Egg.class,"kick")); + + } else { + + super.execute(hero, action); + + } + + + + } + + public void eggHatch (PET pet) { + + int spawnPos = getSpawnPos(); + if (spawnPos != -1 && !Dungeon.hero.haspet) { + + pet.spawn(1); + pet.HP = pet.HT; + pet.pos = spawnPos; + pet.state = pet.HUNTING; + + GameScene.add(pet); + Actor.addDelayed(new Pushing(pet, Dungeon.hero.pos, spawnPos), -1f); + + pet.sprite.alpha(0); + pet.sprite.parent.add(new AlphaTweener(pet.sprite, 1, 0.15f)); + + detach(Dungeon.hero.belongings.backpack); + GLog.w(Messages.get(Egg.class,"hatch")); + Dungeon.hero.haspet=true; + + assignPet(pet); + + } else { + + Dungeon.hero.spend(LeryFireEgg.TIME_TO_USE); + GLog.w(Messages.get(Egg.class,"notready")); + + } + } + + private void assignPet(PET pet){ + + Dungeon.hero.petType=pet.type; + Dungeon.hero.petLevel=pet.level; + + Dungeon.hero.petHP=pet.HP; + Dungeon.hero.petExperience=pet.experience; + Dungeon.hero.petCooldown=pet.cooldown; + } + + @Override + public int price() { + return 500 * quantity; + } + +} diff --git a/java/com/hmdzl/spspd/items/eggs/RandomEgg.java b/java/com/hmdzl/spspd/items/eggs/RandomEgg.java new file mode 100644 index 00000000..5b4ee5d2 --- /dev/null +++ b/java/com/hmdzl/spspd/items/eggs/RandomEgg.java @@ -0,0 +1,160 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.eggs; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.Statistics; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.hero.Hero; + +import com.hmdzl.spspd.actors.mobs.pets.Fly; +import com.hmdzl.spspd.actors.mobs.pets.GentleCrab; +import com.hmdzl.spspd.actors.mobs.pets.Monkey; +import com.hmdzl.spspd.actors.mobs.pets.PET; +import com.hmdzl.spspd.actors.mobs.pets.RibbonRat; +import com.hmdzl.spspd.actors.mobs.pets.Snake; +import com.hmdzl.spspd.actors.mobs.pets.Stone; + +import com.hmdzl.spspd.effects.Pushing; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.noosa.tweeners.AlphaTweener; +import com.watabou.utils.Random; + +public class RandomEgg extends Egg { + + public static final float TIME_TO_USE = 1; + + { + image = ItemSpriteSheet.RANDOWNEGG; + unique = true; + stackable = false; + } + + @Override + public void execute(Hero hero, String action) { + if (action.equals(AC_BREAK)) { + if (Random.Int(120)<20){ + Snake pet = new Snake(); + eggHatch(pet); + } else if (Random.Int(100)< 20) { + Fly pet = new Fly(); + eggHatch(pet); + } else if (Random.Int(80)<20) { + RibbonRat pet = new RibbonRat(); + eggHatch(pet); + } else if (Random.Int(60)<20) { + GentleCrab pet = new GentleCrab(); + eggHatch(pet); + } else if (Random.Int(40)<20) { + Stone pet = new Stone(); + eggHatch(pet); + } else { + Monkey pet = new Monkey(); + eggHatch(pet); + } + Statistics.eggBreak++; + Badges.validateEggBreak(); + hero.next(); + } + + else if (action.equals(AC_SHAKE)) { + + GLog.w(Messages.get(Egg.class,"kick")); + + } else { + + super.execute(hero, action); + + } + + + + } + + public int getSpawnPos(){ + int newPos = -1; + int pos = Dungeon.hero.pos; + ArrayList candidates = new ArrayList(); + boolean[] passable = Level.passable; + + for (int n : Level.NEIGHBOURS8) { + int c = pos + n; + if (passable[c] && Actor.findChar(c) == null) { + candidates.add(c); + } + } + + newPos = candidates.size() > 0 ? Random.element(candidates) : -1; + + return newPos; + } + + + public void eggHatch (PET pet) { + + int spawnPos = getSpawnPos(); + if (spawnPos != -1 && !Dungeon.hero.haspet) { + + pet.spawn(1); + pet.HP = pet.HT; + pet.pos = spawnPos; + pet.state = pet.HUNTING; + + GameScene.add(pet); + Actor.addDelayed(new Pushing(pet, Dungeon.hero.pos, spawnPos), -1f); + + pet.sprite.alpha(0); + pet.sprite.parent.add(new AlphaTweener(pet.sprite, 1, 0.15f)); + + detach(Dungeon.hero.belongings.backpack); + GLog.w(Messages.get(Egg.class,"hatch")); + Dungeon.hero.haspet=true; + + assignPet(pet); + + } else { + + Dungeon.hero.spend(CocoCatEgg.TIME_TO_USE); + GLog.w(Messages.get(Egg.class,"notready")); + + } + } + + private void assignPet(PET pet){ + + Dungeon.hero.petType=pet.type; + Dungeon.hero.petLevel=pet.level; + + Dungeon.hero.petHP=pet.HP; + Dungeon.hero.petExperience=pet.experience; + Dungeon.hero.petCooldown=pet.cooldown; + } + + @Override + public int price() { + return 500 * quantity; + } + +} diff --git a/java/com/hmdzl/spspd/items/eggs/RedDragonEgg.java b/java/com/hmdzl/spspd/items/eggs/RedDragonEgg.java new file mode 100644 index 00000000..5883e42d --- /dev/null +++ b/java/com/hmdzl/spspd/items/eggs/RedDragonEgg.java @@ -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 + */ +package com.hmdzl.spspd.items.eggs; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.hero.Hero; + +import com.hmdzl.spspd.actors.mobs.pets.PET; +import com.hmdzl.spspd.actors.mobs.pets.RedDragon; + +import com.hmdzl.spspd.effects.Pushing; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.noosa.tweeners.AlphaTweener; + +public class RedDragonEgg extends Egg { + + public static final float TIME_TO_USE = 1; + + { + image = ItemSpriteSheet.RED_DRAGONEGG; + unique = true; + stackable = false; + } + + public int startMoves = 0; + public int moves = 0; + public int burns = 20; + public int freezes = 0; + public int poisons = 0; + public int lits = 0; + public int summons = 0; + public int light = 0; + + @Override + public void execute(Hero hero, String action) { + + if (action.equals(AC_BREAK)) { + + RedDragon pet = new RedDragon(); + eggHatch(pet); + + hero.next(); + + } + + else if (action.equals(AC_SHAKE)) { + + GLog.w(Messages.get(Egg.class,"kick")); + + } else { + + super.execute(hero, action); + + } + + } + + public void eggHatch (PET pet) { + + int spawnPos = getSpawnPos(); + if (spawnPos != -1 && !Dungeon.hero.haspet) { + + pet.spawn(1); + pet.HP = pet.HT; + pet.pos = spawnPos; + pet.state = pet.HUNTING; + + GameScene.add(pet); + Actor.addDelayed(new Pushing(pet, Dungeon.hero.pos, spawnPos), -1f); + + pet.sprite.alpha(0); + pet.sprite.parent.add(new AlphaTweener(pet.sprite, 1, 0.15f)); + + detach(Dungeon.hero.belongings.backpack); + GLog.w(Messages.get(Egg.class,"hatch")); + Dungeon.hero.haspet=true; + + assignPet(pet); + + } else { + + Dungeon.hero.spend(LeryFireEgg.TIME_TO_USE); + GLog.w(Messages.get(Egg.class,"notready")); + + } + } + + private void assignPet(PET pet){ + + Dungeon.hero.petType=pet.type; + Dungeon.hero.petLevel=pet.level; + + Dungeon.hero.petHP=pet.HP; + Dungeon.hero.petExperience=pet.experience; + Dungeon.hero.petCooldown=pet.cooldown; + } + + @Override + public int price() { + return 500 * quantity; + } + +} diff --git a/java/com/hmdzl/spspd/items/eggs/ScorpionEgg.java b/java/com/hmdzl/spspd/items/eggs/ScorpionEgg.java new file mode 100644 index 00000000..ea192890 --- /dev/null +++ b/java/com/hmdzl/spspd/items/eggs/ScorpionEgg.java @@ -0,0 +1,116 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.eggs; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.hero.Hero; + +import com.hmdzl.spspd.actors.mobs.pets.PET; +import com.hmdzl.spspd.actors.mobs.pets.Scorpion; + +import com.hmdzl.spspd.effects.Pushing; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.noosa.tweeners.AlphaTweener; + +public class ScorpionEgg extends Egg { + + public static final float TIME_TO_USE = 1; + { + image = ItemSpriteSheet.SCORPIONEGG; + unique = true; + stackable = false; + } + + public int startMoves = 5000; + public int moves = 0; + public int burns = 0; + public int freezes = 0; + public int poisons = 0; + public int lits = 0; + public int summons = 0; + public int light = 0; + + @Override + public void execute(Hero hero, String action) { + + if (action.equals(AC_BREAK)) { + + Scorpion pet = new Scorpion(); + eggHatch(pet); + + hero.next(); + + } + + else if (action.equals(AC_SHAKE)) { + GLog.w(Messages.get(Egg.class,"kick")); + } else { + super.execute(hero, action); + } + } + + public void eggHatch (PET pet) { + + int spawnPos = getSpawnPos(); + if (spawnPos != -1 && !Dungeon.hero.haspet) { + + pet.spawn(1); + pet.HP = pet.HT; + pet.pos = spawnPos; + pet.state = pet.HUNTING; + + GameScene.add(pet); + Actor.addDelayed(new Pushing(pet, Dungeon.hero.pos, spawnPos), -1f); + + pet.sprite.alpha(0); + pet.sprite.parent.add(new AlphaTweener(pet.sprite, 1, 0.15f)); + + detach(Dungeon.hero.belongings.backpack); + GLog.w(Messages.get(Egg.class,"hatch")); + Dungeon.hero.haspet=true; + + assignPet(pet); + + } else { + + Dungeon.hero.spend(LeryFireEgg.TIME_TO_USE); + GLog.w(Messages.get(Egg.class,"notready")); + + } + } + + private void assignPet(PET pet){ + + Dungeon.hero.petType=pet.type; + Dungeon.hero.petLevel=pet.level; + + Dungeon.hero.petHP=pet.HP; + Dungeon.hero.petExperience=pet.experience; + Dungeon.hero.petCooldown=pet.cooldown; + } + + @Override + public int price() { + return 500 * quantity; + } + +} diff --git a/java/com/hmdzl/spspd/items/eggs/ShadowDragonEgg.java b/java/com/hmdzl/spspd/items/eggs/ShadowDragonEgg.java new file mode 100644 index 00000000..6b9a24c2 --- /dev/null +++ b/java/com/hmdzl/spspd/items/eggs/ShadowDragonEgg.java @@ -0,0 +1,111 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.eggs; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.mobs.pets.PET; +import com.hmdzl.spspd.actors.mobs.pets.ShadowDragon; +import com.hmdzl.spspd.effects.Pushing; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.noosa.tweeners.AlphaTweener; + +public class ShadowDragonEgg extends Egg { + + public static final float TIME_TO_USE = 1; + { + //name = "shadow dragon egg"; + image = ItemSpriteSheet.SHADOWEGG; + unique = true; + stackable = false; + } + + public int startMoves = 0; + public int moves = 0; + public int burns = 0; + public int freezes = 0; + public int poisons = 0; + public int lits = 0; + public int summons = 0; + public int light = 20; + + @Override + public void execute(Hero hero, String action) { + + if (action.equals(AC_BREAK)) { + ShadowDragon pet = new ShadowDragon(); + eggHatch(pet); + hero.next(); + } + else if (action.equals(AC_SHAKE)) { + GLog.w(Messages.get(Egg.class,"kick")); + } else { + super.execute(hero, action); + } + } + + public void eggHatch (PET pet) { + + int spawnPos = getSpawnPos(); + if (spawnPos != -1 && !Dungeon.hero.haspet) { + + pet.spawn(1); + pet.HP = pet.HT; + pet.pos = spawnPos; + pet.state = pet.HUNTING; + + GameScene.add(pet); + Actor.addDelayed(new Pushing(pet, Dungeon.hero.pos, spawnPos), -1f); + + pet.sprite.alpha(0); + pet.sprite.parent.add(new AlphaTweener(pet.sprite, 1, 0.15f)); + + detach(Dungeon.hero.belongings.backpack); + GLog.w(Messages.get(Egg.class,"hatch")); + Dungeon.hero.haspet=true; + + assignPet(pet); + + } else { + + Dungeon.hero.spend(ShadowDragonEgg.TIME_TO_USE); + GLog.w(Messages.get(Egg.class,"notready")); + + } + } + + private void assignPet(PET pet){ + + Dungeon.hero.petType=pet.type; + Dungeon.hero.petLevel=pet.level; + + Dungeon.hero.petHP=pet.HP; + Dungeon.hero.petExperience=pet.experience; + Dungeon.hero.petCooldown=pet.cooldown; + } + + @Override + public int price() { + return 500 * quantity; + } + +} diff --git a/java/com/hmdzl/spspd/items/eggs/SpiderEgg.java b/java/com/hmdzl/spspd/items/eggs/SpiderEgg.java new file mode 100644 index 00000000..5f261506 --- /dev/null +++ b/java/com/hmdzl/spspd/items/eggs/SpiderEgg.java @@ -0,0 +1,134 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.eggs; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.hero.Hero; + +import com.hmdzl.spspd.actors.mobs.pets.PET; +import com.hmdzl.spspd.actors.mobs.pets.Spider; + +import com.hmdzl.spspd.effects.Pushing; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.noosa.tweeners.AlphaTweener; + +public class SpiderEgg extends Egg { + + public static final float TIME_TO_USE = 1; + { + image = ItemSpriteSheet.SPIDEREGG; + unique = true; + stackable = false; + } + + public int startMoves = 1000; + public int moves = 0; + public int burns = 0; + public int freezes = 0; + public int poisons = 0; + public int lits = 0; + public int summons = 0; + public int light = 0; + + @Override + public void execute(Hero hero, String action) { + + /* + if (action == AC_BREAK) { + + if (Dungeon.depth>26) { + hero.spend(EasterEgg.TIME_TO_USE); + GLog.w(TXT_PREVENTING); + return; + } + } + */ + + if (action.equals(AC_BREAK)) { + + Spider pet = new Spider(); + eggHatch(pet); + + hero.next(); + + } + + else if (action.equals(AC_SHAKE)) { + + GLog.w(Messages.get(Egg.class,"kick")); + + } else { + + super.execute(hero, action); + + } + + + + } + + public void eggHatch (PET pet) { + + int spawnPos = getSpawnPos(); + if (spawnPos != -1 && !Dungeon.hero.haspet) { + + pet.spawn(1); + pet.HP = pet.HT; + pet.pos = spawnPos; + pet.state = pet.HUNTING; + + GameScene.add(pet); + Actor.addDelayed(new Pushing(pet, Dungeon.hero.pos, spawnPos), -1f); + + pet.sprite.alpha(0); + pet.sprite.parent.add(new AlphaTweener(pet.sprite, 1, 0.15f)); + + detach(Dungeon.hero.belongings.backpack); + GLog.w(Messages.get(Egg.class,"hatch")); + Dungeon.hero.haspet=true; + + assignPet(pet); + + } else { + + Dungeon.hero.spend(LeryFireEgg.TIME_TO_USE); + GLog.w(Messages.get(Egg.class,"notready")); + + } + } + + private void assignPet(PET pet){ + + Dungeon.hero.petType=pet.type; + Dungeon.hero.petLevel=pet.level; + + Dungeon.hero.petHP=pet.HP; + Dungeon.hero.petExperience=pet.experience; + Dungeon.hero.petCooldown=pet.cooldown; + } + + @Override + public int price() { + return 500 * quantity; + } + +} diff --git a/java/com/hmdzl/spspd/items/eggs/VelociroosterEgg.java b/java/com/hmdzl/spspd/items/eggs/VelociroosterEgg.java new file mode 100644 index 00000000..faabad1b --- /dev/null +++ b/java/com/hmdzl/spspd/items/eggs/VelociroosterEgg.java @@ -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 + */ +package com.hmdzl.spspd.items.eggs; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.hero.Hero; + +import com.hmdzl.spspd.actors.mobs.pets.PET; + +import com.hmdzl.spspd.actors.mobs.pets.Velocirooster; +import com.hmdzl.spspd.effects.Pushing; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.noosa.tweeners.AlphaTweener; + +public class VelociroosterEgg extends Egg { + + public static final float TIME_TO_USE = 1; + + { + image = ItemSpriteSheet.VELOCIROOSTEREGG; + unique = true; + stackable = false; + } + + public int startMoves = 0; + public int moves = 0; + public int burns = 5; + public int freezes = 0; + public int poisons = 0; + public int lits = 0; + public int summons = 0; + public int light = 0; + + @Override + public void execute(Hero hero, String action) { + + if (action.equals(AC_BREAK)) { + + Velocirooster pet = new Velocirooster(); + eggHatch(pet); + + hero.next(); + + } + + else if (action.equals(AC_SHAKE)) { + + GLog.w(Messages.get(Egg.class,"kick")); + + } else { + + super.execute(hero, action); + + } + } + + public void eggHatch (PET pet) { + + int spawnPos = getSpawnPos(); + if (spawnPos != -1 && !Dungeon.hero.haspet) { + + pet.spawn(1); + pet.HP = pet.HT; + pet.pos = spawnPos; + pet.state = pet.HUNTING; + + GameScene.add(pet); + Actor.addDelayed(new Pushing(pet, Dungeon.hero.pos, spawnPos), -1f); + + pet.sprite.alpha(0); + pet.sprite.parent.add(new AlphaTweener(pet.sprite, 1, 0.15f)); + + detach(Dungeon.hero.belongings.backpack); + GLog.w(Messages.get(Egg.class,"hatch")); + Dungeon.hero.haspet=true; + + assignPet(pet); + + } else { + + Dungeon.hero.spend(LeryFireEgg.TIME_TO_USE); + GLog.w(Messages.get(Egg.class,"notready")); + + } + } + + private void assignPet(PET pet){ + + Dungeon.hero.petType=pet.type; + Dungeon.hero.petLevel=pet.level; + + Dungeon.hero.petHP=pet.HP; + Dungeon.hero.petExperience=pet.experience; + Dungeon.hero.petCooldown=pet.cooldown; + } + + @Override + public int price() { + return 500 * quantity; + } + +} diff --git a/java/com/hmdzl/spspd/items/eggs/VioletDragonEgg.java b/java/com/hmdzl/spspd/items/eggs/VioletDragonEgg.java new file mode 100644 index 00000000..8f69951a --- /dev/null +++ b/java/com/hmdzl/spspd/items/eggs/VioletDragonEgg.java @@ -0,0 +1,126 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.eggs; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.hero.Hero; + +import com.hmdzl.spspd.actors.mobs.pets.PET; + +import com.hmdzl.spspd.actors.mobs.pets.VioletDragon; +import com.hmdzl.spspd.effects.Pushing; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.noosa.tweeners.AlphaTweener; + +public class VioletDragonEgg extends Egg { + + public static final float TIME_TO_USE = 1; + + public static final int LERY_FIRE = 10; + + + { + //name = "shadow dragon egg"; + image = ItemSpriteSheet.VIOLET_DRAGONEGG; + unique = true; + stackable = false; + } + + public int startMoves = 0; + public int moves = 0; + public int burns = 0; + public int freezes = 0; + public int poisons = 20; + public int lits = 0; + public int summons = 0; + public int light = 0; + + @Override + public void execute(Hero hero, String action) { + + if (action.equals(AC_BREAK)) { + + VioletDragon pet = new VioletDragon(); + eggHatch(pet); + + hero.next(); + + } + + else if (action.equals(AC_SHAKE)) { + + GLog.w(Messages.get(Egg.class,"kick")); + + } else { + + super.execute(hero, action); + + } + + } + + public void eggHatch (PET pet) { + + int spawnPos = getSpawnPos(); + if (spawnPos != -1 && !Dungeon.hero.haspet) { + + pet.spawn(1); + pet.HP = pet.HT; + pet.pos = spawnPos; + pet.state = pet.HUNTING; + + GameScene.add(pet); + Actor.addDelayed(new Pushing(pet, Dungeon.hero.pos, spawnPos), -1f); + + pet.sprite.alpha(0); + pet.sprite.parent.add(new AlphaTweener(pet.sprite, 1, 0.15f)); + + detach(Dungeon.hero.belongings.backpack); + GLog.w(Messages.get(Egg.class,"hatch")); + Dungeon.hero.haspet=true; + + assignPet(pet); + + } else { + + Dungeon.hero.spend(LeryFireEgg.TIME_TO_USE); + GLog.w(Messages.get(Egg.class,"notready")); + + } + } + + private void assignPet(PET pet){ + + Dungeon.hero.petType=pet.type; + Dungeon.hero.petLevel=pet.level; + + Dungeon.hero.petHP=pet.HP; + Dungeon.hero.petExperience=pet.experience; + Dungeon.hero.petCooldown=pet.cooldown; + } + + @Override + public int price() { + return 500 * quantity; + } + +} diff --git a/java/com/hmdzl/spspd/items/eggs/YearPetEgg.java b/java/com/hmdzl/spspd/items/eggs/YearPetEgg.java new file mode 100644 index 00000000..edfea121 --- /dev/null +++ b/java/com/hmdzl/spspd/items/eggs/YearPetEgg.java @@ -0,0 +1,118 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.eggs; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.hero.Hero; + +import com.hmdzl.spspd.actors.mobs.pets.PET; + +import com.hmdzl.spspd.actors.mobs.pets.YearPet; +import com.hmdzl.spspd.effects.Pushing; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.noosa.tweeners.AlphaTweener; + +public class YearPetEgg extends Egg { + + public static final float TIME_TO_USE = 1; + + + { + //name = "year egg"; + image = ItemSpriteSheet.RANDOWNEGG; + unique = true; + stackable = false; + } + + + @Override + public void execute(Hero hero, String action) { + + if (action.equals(AC_BREAK)) { + + YearPet pet = new YearPet(); + eggHatch(pet); + + hero.next(); + + } + + else if (action.equals(AC_SHAKE)) { + + GLog.w(Messages.get(Egg.class,"kick")); + + } else { + + super.execute(hero, action); + + } + + + + } + + public void eggHatch (PET pet) { + + int spawnPos = getSpawnPos(); + if (spawnPos != -1 && !Dungeon.hero.haspet) { + + pet.spawn(1); + pet.HP = pet.HT; + pet.pos = spawnPos; + pet.state = pet.HUNTING; + + GameScene.add(pet); + Actor.addDelayed(new Pushing(pet, Dungeon.hero.pos, spawnPos), -1f); + + pet.sprite.alpha(0); + pet.sprite.parent.add(new AlphaTweener(pet.sprite, 1, 0.15f)); + + detach(Dungeon.hero.belongings.backpack); + GLog.w(Messages.get(Egg.class,"hatch")); + Dungeon.hero.haspet=true; + + assignPet(pet); + + } else { + + Dungeon.hero.spend(TIME_TO_USE); + GLog.w(Messages.get(Egg.class,"notready")); + + } + } + + private void assignPet(PET pet){ + + Dungeon.hero.petType=pet.type; + Dungeon.hero.petLevel=pet.level; + + Dungeon.hero.petHP=pet.HP; + Dungeon.hero.petExperience=pet.experience; + Dungeon.hero.petCooldown=pet.cooldown; + } + + @Override + public int price() { + return 500 * quantity; + } + +} diff --git a/java/com/hmdzl/spspd/items/food/Food.java b/java/com/hmdzl/spspd/items/food/Food.java new file mode 100644 index 00000000..f39a4b3a --- /dev/null +++ b/java/com/hmdzl/spspd/items/food/Food.java @@ -0,0 +1,150 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.food; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.Statistics; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Locked; +import com.hmdzl.spspd.actors.buffs.Recharging; +import com.hmdzl.spspd.actors.buffs.Hunger; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.hero.HeroClass; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.effects.SpellSprite; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.scrolls.ScrollOfRecharging; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; +import com.hmdzl.spspd.messages.Messages; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Random; + +public class Food extends Item { + + private static final float TIME_TO_EAT = 3f; + + public static final String AC_EAT = "EAT"; + + public float energy = Hunger.HUNGRY; + + public int hornValue = 3; + + { + stackable = true; + //name = "ration of food"; + image = ItemSpriteSheet.RATION; + defaultAction = AC_EAT; + } + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + if (hero.buff(Locked.class) == null){ + actions.add(AC_EAT); + } + return actions; + } + + @Override + public void execute(Hero hero, String action) { + if (action.equals(AC_EAT)) { + + if (hero.buff(Locked.class) != null ) { + GLog.w(Messages.get(Food.class, "locked")); + } else { + if (!(Dungeon.hero.heroClass == HeroClass.FOLLOWER ) || (Dungeon.hero.heroClass == HeroClass.FOLLOWER && Random.Int(10)>=1 )) + detach(hero.belongings.backpack); + + hero.buff(Hunger.class).satisfy(energy); + int healEnergy = Math.max(7, Math.round(energy / 40)); + switch (hero.heroClass) { + case WARRIOR: + if (hero.HP < hero.HT) { + hero.HP = Math.min(hero.HP + Random.Int(3, healEnergy), hero.HT); + hero.sprite.emitter() + .burst(Speck.factory(Speck.HEALING), 1); + } + break; + case MAGE: + Buff.affect(hero, Recharging.class, 4f); + ScrollOfRecharging.charge(hero); + if (hero.HP < hero.HT) { + hero.HP = Math.min((hero.HP + Random.Int(1, 3)), hero.HT); + hero.sprite.emitter() + .burst(Speck.factory(Speck.HEALING), 1); + } + break; + case ROGUE: + if (hero.HP < hero.HT) { + hero.HP = Math.min((hero.HP + Random.Int(1, 3)), hero.HT); + hero.sprite.emitter() + .burst(Speck.factory(Speck.HEALING), 1); + } + case HUNTRESS: + if (hero.HP < hero.HT) { + hero.HP = Math.min((hero.HP + Random.Int(1, 3)), hero.HT); + hero.sprite.emitter() + .burst(Speck.factory(Speck.HEALING), 1); + } + break; + case PERFORMER: + if (hero.HP < hero.HT) { + hero.HP = Math.min((hero.HP + Random.Int(1, 3)), hero.HT); + hero.sprite.emitter() + .burst(Speck.factory(Speck.HEALING), 1); + } + break; + } + + hero.sprite.operate(hero.pos); + hero.busy(); + SpellSprite.show(hero, SpellSprite.FOOD); + Sample.INSTANCE.play(Assets.SND_EAT); + + hero.spend(TIME_TO_EAT); + + Statistics.foodEaten++; + Badges.validateFoodEaten(); + } + } else { + + super.execute(hero, action); + + } + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + @Override + public int price() { + return 5 * quantity; + } +} diff --git a/java/com/hmdzl/spspd/items/food/Honey.java b/java/com/hmdzl/spspd/items/food/Honey.java new file mode 100644 index 00000000..c84d0af2 --- /dev/null +++ b/java/com/hmdzl/spspd/items/food/Honey.java @@ -0,0 +1,64 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.food; + +import com.hmdzl.spspd.actors.buffs.Bleeding; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Cripple; +import com.hmdzl.spspd.actors.buffs.Poison; +import com.hmdzl.spspd.actors.buffs.Weakness; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.food.Food; +import com.hmdzl.spspd.items.food.completefood.CompleteFood; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.utils.Random; + +public class Honey extends Food { + + { + //name = "Honey"; + image = ItemSpriteSheet.POTION_HONEY; + + energy = 50; + hornValue = 0; + } + + @Override + public void execute(Hero hero, String action) { + + super.execute(hero, action); + + if (action.equals(AC_EAT)) { + hero.HT = hero.HT + (Random.Int(4, 8)); + //hero.HP = hero.HP+Math.min(((hero.HT-hero.HP)/2), hero.HT-hero.HP); + //Buff.detach(hero, Poison.class); + //Buff.detach(hero, Cripple.class); + //Buff.detach(hero, Weakness.class); + //Buff.detach(hero, Bleeding.class); + + //hero.sprite.emitter().start(Speck.factory(Speck.HEALING), 0.4f, 4); + + } + } + + @Override + public int price() { + return 500 * quantity; + } +} diff --git a/java/com/hmdzl/spspd/items/food/Nut.java b/java/com/hmdzl/spspd/items/food/Nut.java new file mode 100644 index 00000000..7156a575 --- /dev/null +++ b/java/com/hmdzl/spspd/items/food/Nut.java @@ -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 + */ +package com.hmdzl.spspd.items.food; + +import com.hmdzl.spspd.actors.buffs.Barkskin; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.items.food.Food; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.utils.Random; + +public class Nut extends Food { + + { + //name = "dungeon nut"; + image = ItemSpriteSheet.SEED_TOASTEDDUNGEONNUT; + energy = 10; + //message = "Crunch Crunch."; + hornValue = 1; + + } + + @Override + public void execute(Hero hero, String action) { + + super.execute(hero, action); + + if (action.equals(AC_EAT)) { + + hero.HP += 1; + switch (Random.Int(10)) { + case 0: + Buff.affect(hero, Barkskin.class).level(hero.HT / 4); + break; + } + } + } + + + @Override + public int price() { + return 1 * quantity; + } +} diff --git a/java/com/hmdzl/spspd/items/food/ToastedNut.java b/java/com/hmdzl/spspd/items/food/ToastedNut.java new file mode 100644 index 00000000..c8431163 --- /dev/null +++ b/java/com/hmdzl/spspd/items/food/ToastedNut.java @@ -0,0 +1,64 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.food; + +import com.hmdzl.spspd.actors.buffs.Barkskin; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.utils.Random; + +public class ToastedNut extends Nut { + + { + //name = "toasted dungeon nut"; + image = ItemSpriteSheet.SEED_TOASTEDDUNGEONNUT; + energy = 20; + hornValue = 2; + } + + @Override + public void execute(Hero hero, String action) { + + super.execute(hero, action); + + if (action.equals(AC_EAT)) { + + switch (Random.Int(2)) { + case 0: + Buff.affect(hero, Barkskin.class).level(hero.HT); + break; + case 1: + Buff.affect(hero, Barkskin.class).level(hero.HT*2); + break; + } + } + } + + @Override + public int price() { + return 1 * quantity; + } + public static Food cook(Nut ingredient) { + ToastedNut result = new ToastedNut(); + result.quantity = ingredient.quantity(); + return result; + } +} + + diff --git a/java/com/hmdzl/spspd/items/food/Vegetable.java b/java/com/hmdzl/spspd/items/food/Vegetable.java new file mode 100644 index 00000000..c4a470d2 --- /dev/null +++ b/java/com/hmdzl/spspd/items/food/Vegetable.java @@ -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 + */ +package com.hmdzl.spspd.items.food; + +import com.hmdzl.spspd.actors.buffs.Bleeding; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Cripple; +import com.hmdzl.spspd.actors.buffs.Poison; +import com.hmdzl.spspd.actors.buffs.Weakness; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class Vegetable extends Food { + + { + stackable = true; + //name = "ration of food"; + image = ItemSpriteSheet.EAT_GRASS; + energy = 20; + hornValue = 1; + + } + + @Override + public void execute(Hero hero, String action) { + super.execute(hero, action); + + if (action.equals(AC_EAT)){ + Buff.detach(hero, Poison.class); + Buff.detach(hero, Cripple.class); + Buff.detach(hero, Weakness.class); + Buff.detach(hero, Bleeding.class); + } + } + + @Override + public int price() { + return 1 * quantity; + } +} diff --git a/java/com/hmdzl/spspd/items/food/WaterItem.java b/java/com/hmdzl/spspd/items/food/WaterItem.java new file mode 100644 index 00000000..a352bce3 --- /dev/null +++ b/java/com/hmdzl/spspd/items/food/WaterItem.java @@ -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 + */ +package com.hmdzl.spspd.items.food; + +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class WaterItem extends Food { + + { + //name = "water"; + image = ItemSpriteSheet.DEWDROP; + energy = 1; + //message = "Crunch Crunch."; + hornValue = 0; + + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + @Override + public int price() { + return 1 * quantity; + } + +} diff --git a/java/com/hmdzl/spspd/items/food/completefood/AflyFood.java b/java/com/hmdzl/spspd/items/food/completefood/AflyFood.java new file mode 100644 index 00000000..b8e80f8d --- /dev/null +++ b/java/com/hmdzl/spspd/items/food/completefood/AflyFood.java @@ -0,0 +1,54 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.food.completefood; + +import com.hmdzl.spspd.actors.buffs.AflyBless; +import com.hmdzl.spspd.actors.buffs.Bleeding; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Cripple; +import com.hmdzl.spspd.actors.buffs.Poison; +import com.hmdzl.spspd.actors.buffs.Weakness; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.items.food.Food; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class AflyFood extends CompleteFood { + + { + //name = "AflyFood"; + image = ItemSpriteSheet.AFLY_FOOD; + energy = 200; + hornValue = 3; + + } + + @Override + public int price() { + return 2 * quantity; + } + + @Override + public void execute(Hero hero, String action) { + super.execute(hero, action); + if (action.equals(AC_EAT)){ + Buff.affect(hero, AflyBless.class,150f); + hero.belongings.observeS(); + } + } + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/food/completefood/Chickennugget.java b/java/com/hmdzl/spspd/items/food/completefood/Chickennugget.java new file mode 100644 index 00000000..455c98b7 --- /dev/null +++ b/java/com/hmdzl/spspd/items/food/completefood/Chickennugget.java @@ -0,0 +1,37 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.food.completefood; + +import com.hmdzl.spspd.items.food.Food; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class Chickennugget extends CompleteFood { + + { + //name = "chickennugget"; + image = ItemSpriteSheet.CHICKENNUGGET; + energy = 170; + hornValue = 3; + } + + @Override + public int price() { + return 2 * quantity; + } + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/food/completefood/Chocolate.java b/java/com/hmdzl/spspd/items/food/completefood/Chocolate.java new file mode 100644 index 00000000..d0aaf469 --- /dev/null +++ b/java/com/hmdzl/spspd/items/food/completefood/Chocolate.java @@ -0,0 +1,51 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.food.completefood; + +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.ShieldArmor; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.food.Food; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class Chocolate extends CompleteFood { + + { + //name = "Chocolate"; + image = ItemSpriteSheet.CHOCOLATE; + energy = 600; + hornValue = 5; + + } + + @Override + public int price() { + return 60 * quantity; + } + + @Override + public void execute(Hero hero, String action) { + super.execute(hero, action); + + if (action.equals(AC_EAT)){ + Buff.affect(hero, ShieldArmor.class).level(150); + } + } + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/food/completefood/CompleteFood.java b/java/com/hmdzl/spspd/items/food/completefood/CompleteFood.java new file mode 100644 index 00000000..94e4207e --- /dev/null +++ b/java/com/hmdzl/spspd/items/food/completefood/CompleteFood.java @@ -0,0 +1,34 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.food.completefood; + +import com.hmdzl.spspd.items.food.Food; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class CompleteFood extends Food { + + { + stackable = true; + //name = "ration of food"; + image = ItemSpriteSheet.RATION; + + + } + + +} diff --git a/java/com/hmdzl/spspd/items/food/completefood/Crystalnucleus.java b/java/com/hmdzl/spspd/items/food/completefood/Crystalnucleus.java new file mode 100644 index 00000000..663f7e25 --- /dev/null +++ b/java/com/hmdzl/spspd/items/food/completefood/Crystalnucleus.java @@ -0,0 +1,38 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.food.completefood; + +import com.hmdzl.spspd.items.food.Food; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class Crystalnucleus extends CompleteFood { + + { + //name = "crystalnucleus"; + image = ItemSpriteSheet.NORNORANGE; + energy = 1; + hornValue = 1; + + } + + @Override + public int price() { + return 1000 * quantity; + } + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/food/completefood/Foamedbeverage.java b/java/com/hmdzl/spspd/items/food/completefood/Foamedbeverage.java new file mode 100644 index 00000000..928f37b8 --- /dev/null +++ b/java/com/hmdzl/spspd/items/food/completefood/Foamedbeverage.java @@ -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 + */ +package com.hmdzl.spspd.items.food.completefood; + +import com.hmdzl.spspd.actors.buffs.Bleeding; +import com.hmdzl.spspd.actors.buffs.Bless; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Cripple; +import com.hmdzl.spspd.actors.buffs.Poison; +import com.hmdzl.spspd.actors.buffs.Weakness; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.food.Food; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class Foamedbeverage extends CompleteFood { + + { + //name = "foamedbeverage"; + image = ItemSpriteSheet.FOAMED; + energy = 20; + hornValue = 1; + + } + + @Override + public int price() { + return 5 * quantity; + } + + @Override + public void execute(Hero hero, String action) { + super.execute(hero, action); + + if (action.equals(AC_EAT)){ + Buff.detach(hero, Poison.class); + Buff.detach(hero, Cripple.class); + Buff.detach(hero, Weakness.class); + Buff.detach(hero, Bleeding.class); + Buff.affect(hero, Bless.class, 50f); + } +} + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/food/completefood/FoodFans.java b/java/com/hmdzl/spspd/items/food/completefood/FoodFans.java new file mode 100644 index 00000000..5f5cf974 --- /dev/null +++ b/java/com/hmdzl/spspd/items/food/completefood/FoodFans.java @@ -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 + */ +package com.hmdzl.spspd.items.food.completefood; + +import com.hmdzl.spspd.actors.buffs.Bless; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.ShieldArmor; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.food.Food; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class FoodFans extends CompleteFood { + + { + //name = "FoodFans"; + image = ItemSpriteSheet.FOODFANS; + energy = 150; + hornValue = 2; + + } + + @Override + public int price() { + return 20 * quantity; + } + + @Override + public void execute(Hero hero, String action) { + super.execute(hero, action); + + if (action.equals(AC_EAT)){ + Buff.affect(hero, ShieldArmor.class).level(75); + Buff.affect(hero, Bless.class,50f); + } + } + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/food/completefood/Frenchfries.java b/java/com/hmdzl/spspd/items/food/completefood/Frenchfries.java new file mode 100644 index 00000000..1fbd6b20 --- /dev/null +++ b/java/com/hmdzl/spspd/items/food/completefood/Frenchfries.java @@ -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 + */ +package com.hmdzl.spspd.items.food.completefood; + +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Haste; +import com.hmdzl.spspd.actors.buffs.ShieldArmor; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.food.Food; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class Frenchfries extends CompleteFood { + + { + //name = "Frenchfries"; + image = ItemSpriteSheet.FRENCHFRIES; + energy = 150; + hornValue = 2; + + } + + @Override + public int price() { + return 20 * quantity; + } + + @Override + public void execute(Hero hero, String action) { + super.execute(hero, action); + + if (action.equals(AC_EAT)){ + Buff.affect(hero, ShieldArmor.class).level(75); + Buff.affect(hero, Haste.class,50f); + } + } + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/food/completefood/Fruitsalad.java b/java/com/hmdzl/spspd/items/food/completefood/Fruitsalad.java new file mode 100644 index 00000000..1b9d9690 --- /dev/null +++ b/java/com/hmdzl/spspd/items/food/completefood/Fruitsalad.java @@ -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 + */ +package com.hmdzl.spspd.items.food.completefood; + +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.food.Food; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class Fruitsalad extends CompleteFood { + + { + //name = "fruitsalad"; + image = ItemSpriteSheet.FRUITSALAD; + energy = 130; + hornValue = 3; + + } + + @Override + public int price() { + return 2 * quantity; + } + + @Override + public void execute(Hero hero, String action) { + super.execute(hero, action); + + if (action.equals(AC_EAT)){ + hero.HP+= hero.HT/3; + hero.sprite.emitter().start(Speck.factory(Speck.HEALING), 0.4f, 5); + } + } + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/food/completefood/Garbage.java b/java/com/hmdzl/spspd/items/food/completefood/Garbage.java new file mode 100644 index 00000000..944d2ed7 --- /dev/null +++ b/java/com/hmdzl/spspd/items/food/completefood/Garbage.java @@ -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 + */ +package com.hmdzl.spspd.items.food.completefood; + +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.food.Food; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class Garbage extends CompleteFood { + + { + //name = "Garbage"; + image = ItemSpriteSheet.ERROR_FOOD; + energy = 1; + hornValue = 0; + + } + @Override + public int price() { + return 10 * quantity; + } + @Override + public void execute(Hero hero, String action) { + super.execute(hero, action); + + if (action.equals(AC_EAT)){ + int damage = hero.HT/5; + hero.damage(damage, this); + hero.sprite.emitter().start(Speck.factory(Speck.ROCK), 0.07f, 5); + + } + } + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/food/completefood/Gel.java b/java/com/hmdzl/spspd/items/food/completefood/Gel.java new file mode 100644 index 00000000..897c81e2 --- /dev/null +++ b/java/com/hmdzl/spspd/items/food/completefood/Gel.java @@ -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 + */ +package com.hmdzl.spspd.items.food.completefood; + +import com.hmdzl.spspd.actors.buffs.Bleeding; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Cripple; +import com.hmdzl.spspd.actors.buffs.Poison; +import com.hmdzl.spspd.actors.buffs.Weakness; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.food.Food; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.utils.Random; + +public class Gel extends CompleteFood { + + { + //name = "Gel"; + image = ItemSpriteSheet.UPGRADEGOO_VIOLET; + + energy = 10; + hornValue = 0; + } + + private static ItemSprite.Glowing BLUE = new ItemSprite.Glowing(0x0000FF); + + @Override + public ItemSprite.Glowing glowing() { + return BLUE; + } + @Override + public int price() { + return 50 * quantity; + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/food/completefood/GoldenNut.java b/java/com/hmdzl/spspd/items/food/completefood/GoldenNut.java new file mode 100644 index 00000000..cf0f37dc --- /dev/null +++ b/java/com/hmdzl/spspd/items/food/completefood/GoldenNut.java @@ -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 + */ +package com.hmdzl.spspd.items.food.completefood; + +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.sprites.CharSprite; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.utils.Random; + +public class GoldenNut extends CompleteFood { + + { + //name = "golden dungeon nut"; + image = ItemSpriteSheet.SEED_GOLDENDUNGEONNUT; + energy = 100; + hornValue = 2; + } + + @Override + public void execute(Hero hero, String action) { + + super.execute(hero, action); + + if (action.equals(AC_EAT)) { + + switch (Random.Int(2)) { + case 0: + hero.HT+=60; + hero.STR+=1; + hero.sprite.showStatus(CharSprite.POSITIVE, "+1 str, +60 ht"); + + Badges.validateStrengthAttained(); + break; + case 1: + hero.HT+=30; + hero.STR+=2; + hero.sprite.showStatus(CharSprite.POSITIVE, "+2 str, +30 ht"); + + Badges.validateStrengthAttained(); + break; + } + } + } + +} + + diff --git a/java/com/hmdzl/spspd/items/food/completefood/Hamburger.java b/java/com/hmdzl/spspd/items/food/completefood/Hamburger.java new file mode 100644 index 00000000..82f46d5c --- /dev/null +++ b/java/com/hmdzl/spspd/items/food/completefood/Hamburger.java @@ -0,0 +1,51 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.food.completefood; + +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.DefenceUp; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.food.Food; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class Hamburger extends CompleteFood { + + { + //name = "hamburger"; + image = ItemSpriteSheet.HAMBURGER; + energy = 770; + hornValue = 6; + + } + + @Override + public int price() { + return 10 * quantity; + } + + @Override + public void execute(Hero hero, String action) { + super.execute(hero, action); + + if (action.equals(AC_EAT)){ + hero.HP+= hero.HT/5; + hero.sprite.emitter().start(Speck.factory(Speck.HEART), 0.2f, 5); + } + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/food/completefood/Herbmeat.java b/java/com/hmdzl/spspd/items/food/completefood/Herbmeat.java new file mode 100644 index 00000000..9aad497d --- /dev/null +++ b/java/com/hmdzl/spspd/items/food/completefood/Herbmeat.java @@ -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 + */ +package com.hmdzl.spspd.items.food.completefood; + +import com.hmdzl.spspd.actors.buffs.Bleeding; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Cripple; +import com.hmdzl.spspd.actors.buffs.Poison; +import com.hmdzl.spspd.actors.buffs.Weakness; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.items.food.Food; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class Herbmeat extends CompleteFood { + + { + //name = "Herbmeat"; + image = ItemSpriteSheet.HERB_MEAT; + energy = 180; + hornValue = 3; + + } + + @Override + public int price() { + return 2 * quantity; + } + + @Override + public void execute(Hero hero, String action) { + super.execute(hero, action); + if (action.equals(AC_EAT)){ + Buff.detach(hero, Poison.class); + Buff.detach(hero, Cripple.class); + Buff.detach(hero, Weakness.class); + Buff.detach(hero, Bleeding.class); + } + } + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/food/completefood/Honey.java b/java/com/hmdzl/spspd/items/food/completefood/Honey.java new file mode 100644 index 00000000..9111f7fc --- /dev/null +++ b/java/com/hmdzl/spspd/items/food/completefood/Honey.java @@ -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 + */ +package com.hmdzl.spspd.items.food.completefood; + +import com.hmdzl.spspd.actors.buffs.Bleeding; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Cripple; +import com.hmdzl.spspd.actors.buffs.Poison; +import com.hmdzl.spspd.actors.buffs.Weakness; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.food.Food; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.utils.Random; + +public class Honey extends CompleteFood { + + { + //name = "Honey"; + image = ItemSpriteSheet.POTION_HONEY; + energy = 50; + hornValue = 0; + } + + @Override + public void execute(Hero hero, String action) { + + super.execute(hero, action); + + if (action.equals(AC_EAT)) { + hero.HT = hero.HT + (Random.Int(4, 8)); + //hero.HP = hero.HP+Math.min(((hero.HT-hero.HP)/2), hero.HT-hero.HP); + //Buff.detach(hero, Poison.class); + //Buff.detach(hero, Cripple.class); + //Buff.detach(hero, Weakness.class); + //Buff.detach(hero, Bleeding.class); + + //hero.sprite.emitter().start(Speck.factory(Speck.HEALING), 0.4f, 4); + + } + } + + @Override + public int price() { + return 500 * quantity; + } +} diff --git a/java/com/hmdzl/spspd/items/food/completefood/HoneyGel.java b/java/com/hmdzl/spspd/items/food/completefood/HoneyGel.java new file mode 100644 index 00000000..ea5fe75e --- /dev/null +++ b/java/com/hmdzl/spspd/items/food/completefood/HoneyGel.java @@ -0,0 +1,71 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2014 Oleg Dolya + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.items.food.completefood; + +import com.hmdzl.spspd.actors.buffs.Bleeding; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Cripple; +import com.hmdzl.spspd.actors.buffs.Poison; +import com.hmdzl.spspd.actors.buffs.Weakness; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.food.Food; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.utils.Random; + +public class HoneyGel extends CompleteFood { + + { + //name = "HoneyGel"; + image = ItemSpriteSheet.UPGRADEGOO_YELLOW; + + energy = 20; + hornValue = 2; + } + + private static ItemSprite.Glowing YELLOW = new ItemSprite.Glowing( 0xFFFF44 ); + + @Override + public ItemSprite.Glowing glowing() { + return YELLOW; + } + + @Override + public void execute(Hero hero, String action) { + + super.execute(hero, action); + + if (action.equals(AC_EAT)) { + hero.HT = hero.HT + (Random.Int(4, 8)); + //hero.HP = hero.HP+Math.min(((hero.HT-hero.HP)/2), hero.HT-hero.HP); + //Buff.detach(hero, Poison.class); + //Buff.detach(hero, Cripple.class); + //Buff.detach(hero, Weakness.class); + //Buff.detach(hero, Bleeding.class); + + //hero.sprite.emitter().start(Speck.factory(Speck.HEALING), 0.4f, 4); + + } + } + + @Override + public int price() { + return 500 * quantity; + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/food/completefood/HoneyWater.java b/java/com/hmdzl/spspd/items/food/completefood/HoneyWater.java new file mode 100644 index 00000000..f05be46b --- /dev/null +++ b/java/com/hmdzl/spspd/items/food/completefood/HoneyWater.java @@ -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 + */ +package com.hmdzl.spspd.items.food.completefood; + +import com.hmdzl.spspd.actors.buffs.Bleeding; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Cripple; +import com.hmdzl.spspd.actors.buffs.Poison; +import com.hmdzl.spspd.actors.buffs.Weakness; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.food.Food; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.utils.Random; + +public class HoneyWater extends CompleteFood { + + { + //name = "HoneyWater"; + image = ItemSpriteSheet.HONEYWATER; + + energy = 10; + hornValue = 2; + } + + @Override + public void execute(Hero hero, String action) { + + super.execute(hero, action); + + if (action.equals(AC_EAT)) { + hero.HT = hero.HT + (Random.Int(4, 8)); + //hero.HP = hero.HP+Math.min(((hero.HT-hero.HP)/2), hero.HT-hero.HP); + Buff.detach(hero, Poison.class); + Buff.detach(hero, Cripple.class); + Buff.detach(hero, Weakness.class); + Buff.detach(hero, Bleeding.class); + hero.sprite.emitter().start(Speck.factory(Speck.HEALING), 0.4f, 4); + + } + } + + @Override + public int price() { + return 100 * quantity; + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/food/completefood/Honeymeat.java b/java/com/hmdzl/spspd/items/food/completefood/Honeymeat.java new file mode 100644 index 00000000..7bb653d2 --- /dev/null +++ b/java/com/hmdzl/spspd/items/food/completefood/Honeymeat.java @@ -0,0 +1,57 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.food.completefood; + +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.items.food.Food; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.utils.Random; + +public class Honeymeat extends CompleteFood { + + { + //name = "honeymeat"; + image = ItemSpriteSheet.HONEYMEAT; + energy = 150; + hornValue = 3; + + } + + public void execute(Hero hero, String action) { + + super.execute(hero, action); + + if (action.equals(AC_EAT)) { + hero.HT = hero.HT + (Random.Int(5, 10)); + //hero.HP = hero.HP+Math.min(((hero.HT-hero.HP)/2), hero.HT-hero.HP); + //Buff.detach(hero, Poison.class); + //Buff.detach(hero, Cripple.class); + //Buff.detach(hero, Weakness.class); + //Buff.detach(hero, Bleeding.class); + + //hero.sprite.emitter().start(Speck.factory(Speck.HEALING), 0.4f, 4); + + } + } + + @Override + public int price() { + return 2 * quantity; + } + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/food/completefood/Honeyrice.java b/java/com/hmdzl/spspd/items/food/completefood/Honeyrice.java new file mode 100644 index 00000000..ebce28bc --- /dev/null +++ b/java/com/hmdzl/spspd/items/food/completefood/Honeyrice.java @@ -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 + */ +package com.hmdzl.spspd.items.food.completefood; + +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.items.food.Food; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.utils.Random; + +public class Honeyrice extends CompleteFood { + + { + //name = "honeyrice"; + image = ItemSpriteSheet.RICE; + energy = 400; + hornValue = 3; + + } + + + private static ItemSprite.Glowing YELLOW = new ItemSprite.Glowing( 0xFFFF44 ); + + @Override + public ItemSprite.Glowing glowing() { + return YELLOW; + } + + public void execute(Hero hero, String action) { + + super.execute(hero, action); + + if (action.equals(AC_EAT)) { + hero.HT = hero.HT + (Random.Int(5, 10)); + //hero.HP = hero.HP+Math.min(((hero.HT-hero.HP)/2), hero.HT-hero.HP); + //Buff.detach(hero, Poison.class); + //Buff.detach(hero, Cripple.class); + //Buff.detach(hero, Weakness.class); + //Buff.detach(hero, Bleeding.class); + + //hero.sprite.emitter().start(Speck.factory(Speck.HEALING), 0.4f, 4); + + } + } + + @Override + public int price() { + return 4 * quantity; + } + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/food/completefood/Icecream.java b/java/com/hmdzl/spspd/items/food/completefood/Icecream.java new file mode 100644 index 00000000..9740d2a7 --- /dev/null +++ b/java/com/hmdzl/spspd/items/food/completefood/Icecream.java @@ -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 + */ +package com.hmdzl.spspd.items.food.completefood; + +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Burning; +import com.hmdzl.spspd.actors.buffs.Poison; +import com.hmdzl.spspd.actors.buffs.Weakness; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.food.Food; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.utils.Random; + +public class Icecream extends CompleteFood { + + { + //name = "icecream"; + image = ItemSpriteSheet.ICECREAM; + energy = 90; + hornValue = 3; + + } + + public void execute(Hero hero, String action) { + + super.execute(hero, action); + + if (action.equals(AC_EAT)) { + hero.HT = hero.HT + (Random.Int(5, 12)); + hero.HP = hero.HP+Math.min(((hero.HT-hero.HP)/2), hero.HT-hero.HP); + Buff.detach(hero, Poison.class); + Buff.detach(hero, Burning.class); + Buff.detach(hero, Weakness.class); + //Buff.detach(hero, Bleeding.class); + + hero.sprite.emitter().start(Speck.factory(Speck.HEALING), 0.4f, 4); + + } + } + + @Override + public int price() { + return 1 * quantity; + } + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/food/completefood/Kebab.java b/java/com/hmdzl/spspd/items/food/completefood/Kebab.java new file mode 100644 index 00000000..e1c1103b --- /dev/null +++ b/java/com/hmdzl/spspd/items/food/completefood/Kebab.java @@ -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 + */ +package com.hmdzl.spspd.items.food.completefood; + +import com.hmdzl.spspd.items.food.Food; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class Kebab extends CompleteFood { + + { + //name = "kebab"; + image = ItemSpriteSheet.KEBAB; + energy = 330; + hornValue = 3; + + } + private static ItemSprite.Glowing BROWN = new ItemSprite.Glowing(0xCC6600); + + @Override + public ItemSprite.Glowing glowing() { + return BROWN; + } + @Override + public int price() { + return 5 * quantity; + } + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/food/completefood/Meatroll.java b/java/com/hmdzl/spspd/items/food/completefood/Meatroll.java new file mode 100644 index 00000000..70c585a2 --- /dev/null +++ b/java/com/hmdzl/spspd/items/food/completefood/Meatroll.java @@ -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 + */ +package com.hmdzl.spspd.items.food.completefood; + +import com.hmdzl.spspd.actors.buffs.Bleeding; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Cripple; +import com.hmdzl.spspd.actors.buffs.Poison; +import com.hmdzl.spspd.actors.buffs.Weakness; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.food.Food; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.utils.Random; + +public class Meatroll extends CompleteFood { + + { + //name = "meatroll"; + image = ItemSpriteSheet.HOTDOG; + + energy = 250; + hornValue = 2; + } + + private static ItemSprite.Glowing BROWN = new ItemSprite.Glowing(0xCC6600); + + @Override + public ItemSprite.Glowing glowing() { + return BROWN; + } + + @Override + public int price() { + return 3 * quantity; + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/food/completefood/PerfectFood.java b/java/com/hmdzl/spspd/items/food/completefood/PerfectFood.java new file mode 100644 index 00000000..daebd9a0 --- /dev/null +++ b/java/com/hmdzl/spspd/items/food/completefood/PerfectFood.java @@ -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 + */ +package com.hmdzl.spspd.items.food.completefood; + +import com.hmdzl.spspd.actors.buffs.BerryRegeneration; +import com.hmdzl.spspd.actors.buffs.Bless; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Haste; +import com.hmdzl.spspd.actors.buffs.Levitation; +import com.hmdzl.spspd.actors.buffs.Light; +import com.hmdzl.spspd.actors.buffs.Recharging; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.food.Food; +import com.hmdzl.spspd.items.scrolls.ScrollOfRecharging; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.utils.Random; + +public class PerfectFood extends CompleteFood { + + { + //name = "perfect food"; + image = ItemSpriteSheet.PERFECT_FOOD; + energy = 600; + hornValue = 10; + } + + @Override + public void execute(Hero hero, String action) { + super.execute(hero, action); + + if (action.equals(AC_EAT)){ + hero.HT = hero.HT + (Random.Int(4, 8)); + Buff.affect(hero, BerryRegeneration.class).level(10); + Buff.affect(hero, Bless.class,10f); + Buff.affect(hero, Light.class,50f); + hero.HP = Math.min(hero.HP + hero.HT/10, hero.HT); + Buff.affect(hero, Haste.class,5f); + Buff.affect(hero, Levitation.class,5f); + Buff.affect( hero, Recharging.class, 2f ); //half of a charge + ScrollOfRecharging.charge( hero ); + hero.sprite.emitter().start(Speck.factory(Speck.HEALING), 0.4f, 4); + } + } + + @Override + public int price() { + return 50 * quantity; + } + +} diff --git a/java/com/hmdzl/spspd/items/food/completefood/PetFood.java b/java/com/hmdzl/spspd/items/food/completefood/PetFood.java new file mode 100644 index 00000000..545ca0c6 --- /dev/null +++ b/java/com/hmdzl/spspd/items/food/completefood/PetFood.java @@ -0,0 +1,38 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.food.completefood; + +import com.hmdzl.spspd.items.food.Food; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class PetFood extends CompleteFood { + + { + //name = "PetFood"; + image = ItemSpriteSheet.PETFOOD; + energy = 10; + hornValue = 1; + + } + + @Override + public int price() { + return 1 * quantity; + } + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/food/completefood/Porksoup.java b/java/com/hmdzl/spspd/items/food/completefood/Porksoup.java new file mode 100644 index 00000000..259576d5 --- /dev/null +++ b/java/com/hmdzl/spspd/items/food/completefood/Porksoup.java @@ -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 + */ +package com.hmdzl.spspd.items.food.completefood; + +import com.hmdzl.spspd.actors.buffs.Bleeding; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Cripple; +import com.hmdzl.spspd.actors.buffs.Poison; +import com.hmdzl.spspd.actors.buffs.Weakness; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.items.food.Food; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class Porksoup extends CompleteFood { + + { + //name = "porksoup"; + image = ItemSpriteSheet.MEATSOUP; + energy = 200; + hornValue = 3; + + } + private static ItemSprite.Glowing BROWN = new ItemSprite.Glowing(0xCC6600); + + @Override + public ItemSprite.Glowing glowing() { + return BROWN; + } + @Override + public int price() { + return 3 * quantity; + } + + public void execute(Hero hero, String action) { + super.execute(hero, action); + if (action.equals(AC_EAT)){ + Buff.detach(hero, Poison.class); + Buff.detach(hero, Cripple.class); + Buff.detach(hero, Weakness.class); + Buff.detach(hero, Bleeding.class); + } + } + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/food/completefood/Ricefood.java b/java/com/hmdzl/spspd/items/food/completefood/Ricefood.java new file mode 100644 index 00000000..10ac98b2 --- /dev/null +++ b/java/com/hmdzl/spspd/items/food/completefood/Ricefood.java @@ -0,0 +1,38 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.food.completefood; + +import com.hmdzl.spspd.items.food.Food; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class Ricefood extends CompleteFood { + + { + //name = "rice"; + image = ItemSpriteSheet.RICE; + energy = 450; + hornValue = 3; + + } + + @Override + public int price() { + return 3 * quantity; + } + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/food/completefood/Vegetablekebab.java b/java/com/hmdzl/spspd/items/food/completefood/Vegetablekebab.java new file mode 100644 index 00000000..8aed51e2 --- /dev/null +++ b/java/com/hmdzl/spspd/items/food/completefood/Vegetablekebab.java @@ -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 + */ +package com.hmdzl.spspd.items.food.completefood; + +import com.hmdzl.spspd.actors.buffs.Bleeding; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Cripple; +import com.hmdzl.spspd.actors.buffs.Poison; +import com.hmdzl.spspd.actors.buffs.Weakness; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.items.food.Food; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class Vegetablekebab extends CompleteFood { + + { + //name = "vegetablekebab"; + image = ItemSpriteSheet.KEBAB; + energy = 150; + hornValue = 2; + + } + private static ItemSprite.Glowing GREEN = new ItemSprite.Glowing(0x22CC44); + @Override + public ItemSprite.Glowing glowing() { + return GREEN; + } + + @Override + public int price() { + return 2 * quantity; + } + + public void execute(Hero hero, String action) { + super.execute(hero, action); + if (action.equals(AC_EAT)){ + Buff.detach(hero, Poison.class); + Buff.detach(hero, Cripple.class); + Buff.detach(hero, Weakness.class); + Buff.detach(hero, Bleeding.class); + } + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/food/completefood/Vegetableroll.java b/java/com/hmdzl/spspd/items/food/completefood/Vegetableroll.java new file mode 100644 index 00000000..dae73957 --- /dev/null +++ b/java/com/hmdzl/spspd/items/food/completefood/Vegetableroll.java @@ -0,0 +1,61 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.food.completefood; + +import com.hmdzl.spspd.actors.buffs.Bleeding; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Cripple; +import com.hmdzl.spspd.actors.buffs.Poison; +import com.hmdzl.spspd.actors.buffs.Weakness; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.food.Food; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.utils.Random; + +public class Vegetableroll extends CompleteFood { + + { + //name = "vegetableroll"; + image = ItemSpriteSheet.HOTDOG; + + energy = 170; + hornValue = 2; + } + private static ItemSprite.Glowing GREEN = new ItemSprite.Glowing(0x22CC44); + @Override + public ItemSprite.Glowing glowing() { + return GREEN; + } + + @Override + public int price() { + return 6 * quantity; + } + public void execute(Hero hero, String action) { + super.execute(hero, action); + if (action.equals(AC_EAT)){ + Buff.detach(hero, Poison.class); + Buff.detach(hero, Cripple.class); + Buff.detach(hero, Weakness.class); + Buff.detach(hero, Bleeding.class); + } + } + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/food/completefood/Vegetablesoup.java b/java/com/hmdzl/spspd/items/food/completefood/Vegetablesoup.java new file mode 100644 index 00000000..9d32b943 --- /dev/null +++ b/java/com/hmdzl/spspd/items/food/completefood/Vegetablesoup.java @@ -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 + */ +package com.hmdzl.spspd.items.food.completefood; + +import com.hmdzl.spspd.actors.buffs.Bleeding; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Cripple; +import com.hmdzl.spspd.actors.buffs.Poison; +import com.hmdzl.spspd.actors.buffs.Weakness; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.items.food.Food; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class Vegetablesoup extends CompleteFood { + + { + //name = "vegetablesoup"; + image = ItemSpriteSheet.VEGETABLESOUP; + energy = 90; + hornValue = 3; + + } + + @Override + public int price() { + return 1 * quantity; + } + + public void execute(Hero hero, String action) { + super.execute(hero, action); + if (action.equals(AC_EAT)){ + Buff.detach(hero, Poison.class); + Buff.detach(hero, Cripple.class); + Buff.detach(hero, Weakness.class); + Buff.detach(hero, Bleeding.class); + } + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/food/fruit/Blackberry.java b/java/com/hmdzl/spspd/items/food/fruit/Blackberry.java new file mode 100644 index 00000000..00b1742b --- /dev/null +++ b/java/com/hmdzl/spspd/items/food/fruit/Blackberry.java @@ -0,0 +1,74 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.food.fruit; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.buffs.BerryRegeneration; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.MindVision; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Random; + +public class Blackberry extends Fruit { + + { + //name = "dungeon black berry"; + image = ItemSpriteSheet.SEED_BLACKBERRY; + energy = 50; + hornValue = 1; + + } + + @Override + public void execute(Hero hero, String action) { + + super.execute(hero, action); + + if (action.equals(AC_EAT)) { + + switch (Random.Int(10)) { + case 1: + Buff.affect(hero, MindVision.class, MindVision.DURATION); + Dungeon.observe(); + Buff.affect(hero, BerryRegeneration.class).level(hero.HT); + GLog.w("The berry releases energy your body!"); + break; + case 0: case 2: case 3: case 4: case 5: + case 6: case 7: case 8: case 9: case 10: + GLog.w("The berry releases energy into your body!"); + Buff.affect(hero, BerryRegeneration.class).level(hero.HT/2); + break; + } + } + } + + @Override + public int price() { + return 10 * quantity; + } + + public Blackberry() { + this(1); + } + + public Blackberry(int value) { + this.quantity = value; + } +} diff --git a/java/com/hmdzl/spspd/items/food/fruit/Blandfruit.java b/java/com/hmdzl/spspd/items/food/fruit/Blandfruit.java new file mode 100644 index 00000000..288fb916 --- /dev/null +++ b/java/com/hmdzl/spspd/items/food/fruit/Blandfruit.java @@ -0,0 +1,240 @@ +package com.hmdzl.spspd.items.food.fruit; + + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.FrostImbue; +import com.hmdzl.spspd.actors.buffs.Recharging; +import com.hmdzl.spspd.actors.buffs.EarthImbue; +import com.hmdzl.spspd.actors.buffs.FireImbue; +import com.hmdzl.spspd.actors.buffs.Hunger; +import com.hmdzl.spspd.actors.buffs.ToxicImbue; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.effects.SpellSprite; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.potions.Potion; +import com.hmdzl.spspd.items.potions.PotionOfExperience; +import com.hmdzl.spspd.items.potions.PotionOfFrost; +import com.hmdzl.spspd.items.potions.PotionOfHealing; +import com.hmdzl.spspd.items.potions.PotionOfInvisibility; +import com.hmdzl.spspd.items.potions.PotionOfLevitation; +import com.hmdzl.spspd.items.potions.PotionOfLiquidFlame; +import com.hmdzl.spspd.items.potions.PotionOfMindVision; +import com.hmdzl.spspd.items.potions.PotionOfOverHealing; +import com.hmdzl.spspd.items.potions.PotionOfParalyticGas; +import com.hmdzl.spspd.items.potions.PotionOfPurity; +import com.hmdzl.spspd.items.potions.PotionOfStrength; +import com.hmdzl.spspd.items.potions.PotionOfToxicGas; +import com.hmdzl.spspd.items.scrolls.ScrollOfRecharging; +import com.hmdzl.spspd.plants.Plant.Seed; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; +import com.hmdzl.spspd.messages.Messages; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Bundle; + +/** + * Created by debenhame on 12/08/2014. + */ +public class Blandfruit extends Fruit { + + public Potion potionAttrib = null; + public ItemSprite.Glowing potionGlow = null; + + { + //name = "Blandfruit"; + stackable = true; + image = ItemSpriteSheet.BLANDFRUIT; + energy = 50; + hornValue = 6; // only applies when blandfruit is cooked + + } + + @Override + public boolean isSimilar(Item item) { + if (item instanceof Blandfruit) { + if (potionAttrib == null) { + if (((Blandfruit) item).potionAttrib == null) + return true; + } else if (((Blandfruit) item).potionAttrib != null) { + if (((Blandfruit) item).potionAttrib.getClass() == potionAttrib + .getClass()) + return true; + } + } + return false; + } + + @Override + public void execute(Hero hero, String action) { + if (action.equals(AC_EAT)) { + + if (potionAttrib == null) { + + GLog.w( Messages.get(this, "raw")); + + } else { + + hero.buff(Hunger.class).satisfy(150); + + detach(hero.belongings.backpack); + + hero.spend(1f); + hero.busy(); + + if (potionAttrib instanceof PotionOfLiquidFlame) { + GLog.i(Messages.get(this, "fire_msg")); + Buff.affect(hero, FireImbue.class).set(FireImbue.DURATION); + } else if (potionAttrib instanceof PotionOfToxicGas) { + GLog.i(Messages.get(this, "toxic_msg")); + Buff.affect(hero, ToxicImbue.class) + .set(ToxicImbue.DURATION); + } else if (potionAttrib instanceof PotionOfParalyticGas) { + GLog.i(Messages.get(this, "para_msg")); + Buff.affect(hero, EarthImbue.class, EarthImbue.DURATION); + } else if (potionAttrib instanceof PotionOfFrost) { + GLog.i(Messages.get(this, "frost_msg")); + Buff.affect(hero, FrostImbue.class, FrostImbue.DURATION); + } else + potionAttrib.apply(hero); + + Sample.INSTANCE.play(Assets.SND_EAT); + SpellSprite.show(hero, SpellSprite.FOOD); + hero.sprite.operate(hero.pos); + + switch (hero.heroClass) { + case WARRIOR: + if (hero.HP < hero.HT) { + hero.HP = Math.min(hero.HP + 5, hero.HT); + hero.sprite.emitter().burst( + Speck.factory(Speck.HEALING), 1); + } + break; + case MAGE: + Buff.affect( hero, Recharging.class, 4f ); + ScrollOfRecharging.charge(hero); + break; + case ROGUE: + case HUNTRESS: + case PERFORMER: + case SOLDIER: + case FOLLOWER: + break; + } + } + } else { + super.execute(hero, action); + } + } + + @Override + public String desc() { + if (potionAttrib== null) return super.desc(); + else return Messages.get(this, "desc_cooked"); + } + + @Override + public int price() { + return 20 * quantity; + } + + public Item cook(Seed seed) { + + try { + return imbuePotion((Potion) seed.alchemyClass.newInstance()); + } catch (Exception e) { + return null; + } + + } + + public Item imbuePotion(Potion potion) { + + potionAttrib = potion; + potionAttrib.ownedByFruit = true; + + potionAttrib.image = ItemSpriteSheet.BLANDFRUIT; + + if (potionAttrib instanceof PotionOfHealing){ + name = Messages.get(this, "sunfruit"); + potionGlow = new ItemSprite.Glowing( 0x2EE62E ); + } else if (potionAttrib instanceof PotionOfStrength){ + name = Messages.get(this, "rotfruit"); + potionGlow = new ItemSprite.Glowing( 0xCC0022 ); + } else if (potionAttrib instanceof PotionOfParalyticGas){ + name = Messages.get(this, "earthfruit"); + potionGlow = new ItemSprite.Glowing( 0x67583D ); + } else if (potionAttrib instanceof PotionOfInvisibility){ + name = Messages.get(this, "blindfruit"); + potionGlow = new ItemSprite.Glowing( 0xE5D273 ); + } else if (potionAttrib instanceof PotionOfLiquidFlame){ + name = Messages.get(this, "firefruit"); + potionGlow = new ItemSprite.Glowing( 0xFF7F00 ); + } else if (potionAttrib instanceof PotionOfFrost){ + name = Messages.get(this, "icefruit"); + potionGlow = new ItemSprite.Glowing( 0x66B3FF ); + } else if (potionAttrib instanceof PotionOfMindVision){ + name = Messages.get(this, "fadefruit"); + potionGlow = new ItemSprite.Glowing( 0xB8E6CF ); + } else if (potionAttrib instanceof PotionOfToxicGas){ + name = Messages.get(this, "sorrowfruit"); + potionGlow = new ItemSprite.Glowing( 0xA15CE5 ); + } else if (potionAttrib instanceof PotionOfLevitation) { + name = Messages.get(this, "stormfruit"); + potionGlow = new ItemSprite.Glowing( 0x1C3A57 ); + } else if (potionAttrib instanceof PotionOfPurity) { + name = Messages.get(this, "dreamfruit"); + potionGlow = new ItemSprite.Glowing( 0x8E2975 ); + } else if (potionAttrib instanceof PotionOfExperience) { + name = Messages.get(this, "starfruit"); + potionGlow = new ItemSprite.Glowing( 0xA79400 ); + }else if (potionAttrib instanceof PotionOfOverHealing) { + name = Messages.get(this, "heartfruit"); + potionGlow = new ItemSprite.Glowing( 0xB20000 ); + + } + + return this; + } + + public static final String POTIONATTRIB = "potionattrib"; + + @Override + public void cast(final Hero user, int dst) { + if (potionAttrib instanceof PotionOfLiquidFlame + || potionAttrib instanceof PotionOfToxicGas + || potionAttrib instanceof PotionOfParalyticGas + || potionAttrib instanceof PotionOfFrost + || potionAttrib instanceof PotionOfLevitation + || potionAttrib instanceof PotionOfPurity) { + potionAttrib.cast(user, dst); + detach(user.belongings.backpack); + } else { + super.cast(user, dst); + } + + } + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(POTIONATTRIB, potionAttrib); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + if (bundle.contains(POTIONATTRIB)) { + imbuePotion((Potion) bundle.get(POTIONATTRIB)); + + } + } + + @Override + public ItemSprite.Glowing glowing() { + return potionGlow; + } + +} diff --git a/java/com/hmdzl/spspd/items/food/fruit/Blueberry.java b/java/com/hmdzl/spspd/items/food/fruit/Blueberry.java new file mode 100644 index 00000000..4ca26986 --- /dev/null +++ b/java/com/hmdzl/spspd/items/food/fruit/Blueberry.java @@ -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 + */ +package com.hmdzl.spspd.items.food.fruit; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.buffs.Awareness; +import com.hmdzl.spspd.actors.buffs.BerryRegeneration; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.Terrain; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.messages.Messages; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Random; + +public class Blueberry extends Fruit { + + { + //name = "dungeon blue berry"; + image = ItemSpriteSheet.SEED_BLUEBERRY; + energy = 50; + hornValue = 1; + + } + + + private static final String TXT_PREVENTING = Messages.get(Blueberry.class,"stop"); + + @Override + public void execute(Hero hero, String action) { + + super.execute(hero, action); + + if (action.equals(AC_EAT)) { + + if (Random.Float()<0.75f) { + + int length = Level.getLength(); + //int[] map = Dungeon.level.map; + boolean[] mapped = Dungeon.level.mapped; + boolean[] discoverable = Level.discoverable; + + //boolean noticed = false; + + for (int i = 0; i < length; i++) { + + //int terr = map[i]; + + if (discoverable[i]) { + + mapped[i] = true; + //if ((Terrain.flags[terr] & Terrain.SECRET) != 0) { + + //Level.set(i, Terrain.discover(terr)); + //GameScene.updateMap(i); + //Dungeon.level.discover( i ); + + //if (Dungeon.visible[i]) { + //GameScene.discoverTile(i, terr); + //discover(i); + + //noticed = true; + //} + //} + } + } + Dungeon.observe(); + + //if (noticed) { + //Sample.INSTANCE.play(Assets.SND_SECRET); + //} + + Buff.affect(hero, Awareness.class, 10f); + + } else { + + Buff.affect(hero, BerryRegeneration.class).level(hero.HT+hero.HT); + + int length = Level.getLength(); + int[] map = Dungeon.level.map; + boolean[] mapped = Dungeon.level.mapped; + boolean[] discoverable = Level.discoverable; + + boolean noticed = false; + + for (int i = 0; i < length; i++) { + + int terr = map[i]; + + if (discoverable[i]) { + + mapped[i] = true; + if ((Terrain.flags[terr] & Terrain.SECRET) != 0) { + + Dungeon.level.discover( i ); + + if (Dungeon.visible[i]) { + GameScene.discoverTile(i, terr); + discover(i); + + noticed = true; + } + } + } + } + Dungeon.observe(); + + if (noticed) { + Sample.INSTANCE.play(Assets.SND_SECRET); + } + + Buff.affect(hero, Awareness.class, 10f); + Dungeon.observe(); + + } + } + } + + public static void discover(int cell) { + CellEmitter.get(cell).start(Speck.factory(Speck.DISCOVER), 0.1f, 4); + } + + @Override + public int price() { + return 10 * quantity; + } + + public Blueberry() { + this(1); + } + + public Blueberry(int value) { + this.quantity = value; + } + +} diff --git a/java/com/hmdzl/spspd/items/food/fruit/Cloudberry.java b/java/com/hmdzl/spspd/items/food/fruit/Cloudberry.java new file mode 100644 index 00000000..c2a29adf --- /dev/null +++ b/java/com/hmdzl/spspd/items/food/fruit/Cloudberry.java @@ -0,0 +1,80 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.food.fruit; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.buffs.BerryRegeneration; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Haste; +import com.hmdzl.spspd.actors.buffs.Levitation; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.utils.Random; + +public class Cloudberry extends Fruit { + + { + //name = "dungeon cloud berry"; + image = ItemSpriteSheet.SEED_CLOUDBERRY; + energy = 50; + hornValue = 1; + + } + + private int duration = 10; + @Override + public void execute(Hero hero, String action) { + + super.execute(hero, action); + + if (action.equals(AC_EAT)) { + + switch (Random.Int(10)) { + case 0: case 1: case 2: case 3: case 4: case 5: + Buff.affect(hero, Haste.class, Haste.DURATION); + break; + case 6: case 7: case 8: + Buff.affect(hero, Haste.class, Haste.DURATION); + if(Dungeon.depth<51){Buff.affect(hero, Levitation.class, duration); + } + + break; + case 9: case 10: + Buff.affect(hero, Haste.class, Haste.DURATION); + if(Dungeon.depth<51){Buff.affect(hero, Levitation.class, duration*2); + } + + Buff.affect(hero, BerryRegeneration.class).level(hero.HT); + break; + } + } + } + + @Override + public int price() { + return 5 * quantity; + } + + public Cloudberry() { + this(1); + } + + public Cloudberry(int value) { + this.quantity = value; + } +} diff --git a/java/com/hmdzl/spspd/items/food/fruit/Fruit.java b/java/com/hmdzl/spspd/items/food/fruit/Fruit.java new file mode 100644 index 00000000..88390157 --- /dev/null +++ b/java/com/hmdzl/spspd/items/food/fruit/Fruit.java @@ -0,0 +1,34 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.food.fruit; + +import com.hmdzl.spspd.items.food.Food; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class Fruit extends Food { + + { + stackable = true; + //name = "ration of food"; + image = ItemSpriteSheet.RATION; + + + } + + +} diff --git a/java/com/hmdzl/spspd/items/food/fruit/FullMoonberry.java b/java/com/hmdzl/spspd/items/food/fruit/FullMoonberry.java new file mode 100644 index 00000000..745db0c9 --- /dev/null +++ b/java/com/hmdzl/spspd/items/food/fruit/FullMoonberry.java @@ -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 + */ +package com.hmdzl.spspd.items.food.fruit; + +import com.hmdzl.spspd.actors.buffs.Barkskin; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.FullMoonStrength; +import com.hmdzl.spspd.actors.buffs.Light; +import com.hmdzl.spspd.actors.buffs.Strength; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.items.food.Food; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.utils.Random; + +public class FullMoonberry extends Fruit { + + { + //name = "dungeon full moon berry"; + image = ItemSpriteSheet.SEED_FULLMOONBERRY; + energy = 50; + hornValue = 1; + + } + + @Override + public void execute(Hero hero, String action) { + + super.execute(hero, action); + + if (action.equals(AC_EAT)) { + + switch (Random.Int(2)) { + case 0: + Buff.affect(hero, Strength.class); + Buff.affect(hero, FullMoonStrength.class); + Buff.affect(hero, Light.class, Light.DURATION); + break; + case 1: + Buff.affect(hero, Strength.class); + Buff.affect(hero, FullMoonStrength.class); + Buff.affect(hero, Barkskin.class).level(hero.HT*2); + Buff.affect(hero, Light.class, Light.DURATION); + break; + } + } + } + + + @Override + public int price() { + return 5 * quantity; + } + + public FullMoonberry() { + this(1); + } + + public FullMoonberry(int value) { + this.quantity = value; + } +} diff --git a/java/com/hmdzl/spspd/items/food/fruit/Moonberry.java b/java/com/hmdzl/spspd/items/food/fruit/Moonberry.java new file mode 100644 index 00000000..e5416fae --- /dev/null +++ b/java/com/hmdzl/spspd/items/food/fruit/Moonberry.java @@ -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 + */ +package com.hmdzl.spspd.items.food.fruit; + +import com.hmdzl.spspd.actors.buffs.Barkskin; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Strength; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.items.food.Food; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.utils.Random; + +public class Moonberry extends Fruit { + + { + //name = "dungeon moon berry"; + image = ItemSpriteSheet.SEED_MOONBERRY; + energy = 50; + hornValue = 1; + + } + + @Override + public void execute(Hero hero, String action) { + + super.execute(hero, action); + + if (action.equals(AC_EAT)) { + + switch (Random.Int(2)) { + case 0: + Buff.affect(hero, Strength.class); + break; + case 1: + Buff.affect(hero, Strength.class); + Buff.affect(hero, Barkskin.class).level(hero.HT*2); + break; + } + } + } + + @Override + public int price() { + return 10 * quantity; + } + + public Moonberry() { + this(1); + } + + public Moonberry(int value) { + this.quantity = value; + } +} diff --git a/java/com/hmdzl/spspd/items/food/meatfood/ChargrilledMeat.java b/java/com/hmdzl/spspd/items/food/meatfood/ChargrilledMeat.java new file mode 100644 index 00000000..219596a6 --- /dev/null +++ b/java/com/hmdzl/spspd/items/food/meatfood/ChargrilledMeat.java @@ -0,0 +1,49 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.food.meatfood; + +import com.hmdzl.spspd.items.food.Food; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class ChargrilledMeat extends MeatFood { + + { + //name = "chargrilled meat"; + image = ItemSpriteSheet.STEAK; + energy = 100; + hornValue = 1; + + } + + @Override + public int price() { + return 2 * quantity; + } + + public static Food cook(MysteryMeat ingredient) { + ChargrilledMeat result = new ChargrilledMeat(); + result.quantity = ingredient.quantity(); + return result; + } + + public static Food cook(Meat ingredient) { + ChargrilledMeat result = new ChargrilledMeat(); + result.quantity = ingredient.quantity(); + return result; + } +} diff --git a/java/com/hmdzl/spspd/items/food/meatfood/FrozenCarpaccio.java b/java/com/hmdzl/spspd/items/food/meatfood/FrozenCarpaccio.java new file mode 100644 index 00000000..b351208f --- /dev/null +++ b/java/com/hmdzl/spspd/items/food/meatfood/FrozenCarpaccio.java @@ -0,0 +1,102 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.food.meatfood; + +import com.hmdzl.spspd.actors.buffs.Barkskin; +import com.hmdzl.spspd.actors.buffs.Bleeding; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Cripple; +import com.hmdzl.spspd.actors.buffs.Drowsy; +import com.hmdzl.spspd.actors.buffs.Invisibility; +import com.hmdzl.spspd.actors.buffs.Poison; +import com.hmdzl.spspd.actors.buffs.Slow; +import com.hmdzl.spspd.actors.buffs.Vertigo; +import com.hmdzl.spspd.actors.buffs.Weakness; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.food.Food; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Random; + +public class FrozenCarpaccio extends MeatFood { + + { + //name = "frozen carpaccio"; + image = ItemSpriteSheet.CARPACCIO; + energy = 85; + hornValue = 1; + } + + @Override + public void execute(Hero hero, String action) { + + super.execute(hero, action); + + if (action.equals(AC_EAT)) { + effect(hero); + } + } + + @Override + public int price() { + return 3 * quantity; + }; + + public static void effect(Hero hero){ + switch (Random.Int( 5 )) { + case 0: + GLog.i( Messages.get(FrozenCarpaccio.class, "invisbility") ); + Buff.affect( hero, Invisibility.class, Invisibility.DURATION ); + break; + case 1: + GLog.i( Messages.get(FrozenCarpaccio.class, "hard") ); + Buff.affect( hero, Barkskin.class ).level( hero.HT / 4 ); + break; + case 2: + GLog.i( Messages.get(FrozenCarpaccio.class, "refresh") ); + Buff.detach( hero, Poison.class ); + Buff.detach( hero, Cripple.class ); + Buff.detach( hero, Weakness.class ); + Buff.detach( hero, Bleeding.class ); + Buff.detach( hero, Drowsy.class ); + Buff.detach( hero, Slow.class ); + Buff.detach( hero, Vertigo.class); + break; + case 3: + GLog.i( Messages.get(FrozenCarpaccio.class, "better") ); + if (hero.HP < hero.HT) { + hero.HP = Math.min( hero.HP + hero.HT / 4, hero.HT ); + hero.sprite.emitter().burst( Speck.factory( Speck.HEALING ), 1 ); + } + break; + } + } + + public static Food cook(MysteryMeat ingredient) { + FrozenCarpaccio result = new FrozenCarpaccio(); + result.quantity = ingredient.quantity(); + return result; + } + public static Food cook(Meat ingredient) { + FrozenCarpaccio result = new FrozenCarpaccio(); + result.quantity = ingredient.quantity(); + return result; + } +} diff --git a/java/com/hmdzl/spspd/items/food/meatfood/Meat.java b/java/com/hmdzl/spspd/items/food/meatfood/Meat.java new file mode 100644 index 00000000..76e093f1 --- /dev/null +++ b/java/com/hmdzl/spspd/items/food/meatfood/Meat.java @@ -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 + */ +package com.hmdzl.spspd.items.food.meatfood; + +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Poison; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Random; + +public class Meat extends MeatFood { + + { + //name = "monster meat"; + image = ItemSpriteSheet.MEAT; + energy = 100; + hornValue = 1; + + } + + @Override + public void execute(Hero hero, String action) { + + super.execute(hero, action); + + if (action.equals(AC_EAT)) { + + switch (Random.Int(15)) { + case 0: + GLog.w(Messages.get(this,"bad")); + Buff.affect(hero, Poison.class).set( + Poison.durationFactor(hero) * hero.HT / 5); + break; + } + } + } + + @Override + public int price() { + return 2 * quantity; + } + +} diff --git a/java/com/hmdzl/spspd/items/food/meatfood/MeatFood.java b/java/com/hmdzl/spspd/items/food/meatfood/MeatFood.java new file mode 100644 index 00000000..1f9cf242 --- /dev/null +++ b/java/com/hmdzl/spspd/items/food/meatfood/MeatFood.java @@ -0,0 +1,34 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.food.meatfood; + +import com.hmdzl.spspd.items.food.Food; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class MeatFood extends Food { + + { + stackable = true; + //name = "ration of food"; + image = ItemSpriteSheet.RATION; + + + } + + +} diff --git a/java/com/hmdzl/spspd/items/food/meatfood/MysteryMeat.java b/java/com/hmdzl/spspd/items/food/meatfood/MysteryMeat.java new file mode 100644 index 00000000..8e46375a --- /dev/null +++ b/java/com/hmdzl/spspd/items/food/meatfood/MysteryMeat.java @@ -0,0 +1,74 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.food.meatfood; + +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Burning; +import com.hmdzl.spspd.actors.buffs.Paralysis; +import com.hmdzl.spspd.actors.buffs.Poison; +import com.hmdzl.spspd.actors.buffs.Roots; +import com.hmdzl.spspd.actors.buffs.Slow; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Random; + +public class MysteryMeat extends MeatFood { + + { + //name = "mystery meat"; + image = ItemSpriteSheet.MYSTERYMEAT; + energy = 75; + hornValue = 1; + } + + @Override + public void execute(Hero hero, String action) { + + super.execute(hero, action); + + if (action.equals(AC_EAT)) { + + switch (Random.Int(5)) { + case 0: + GLog.w(Messages.get(this,"hot")); + Buff.affect(hero, Burning.class).reignite(hero); + break; + case 1: + GLog.w(Messages.get(this,"legs")); + Buff.prolong(hero, Roots.class, Paralysis.duration(hero)); + break; + case 2: + GLog.w(Messages.get(this,"bad")); + Buff.affect(hero, Poison.class).set( + Poison.durationFactor(hero) * hero.HT / 5); + break; + case 3: + GLog.w(Messages.get(this,"stuffed")); + Buff.prolong(hero, Slow.class, Slow.duration(hero)); + break; + } + } + } + + @Override + public int price() { + return 2 * quantity; + }; +} diff --git a/java/com/hmdzl/spspd/items/food/staplefood/NormalRation.java b/java/com/hmdzl/spspd/items/food/staplefood/NormalRation.java new file mode 100644 index 00000000..efed94a2 --- /dev/null +++ b/java/com/hmdzl/spspd/items/food/staplefood/NormalRation.java @@ -0,0 +1,37 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.food.staplefood; + +import com.hmdzl.spspd.items.food.Food; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class NormalRation extends StapleFood { + + { + //name = "ration food "; + image = ItemSpriteSheet.RATION; + energy = 300; + hornValue = 3; + } + + + @Override + public int price() { + return 5 * quantity; + } +} diff --git a/java/com/hmdzl/spspd/items/food/staplefood/OverpricedRation.java b/java/com/hmdzl/spspd/items/food/staplefood/OverpricedRation.java new file mode 100644 index 00000000..35225e4d --- /dev/null +++ b/java/com/hmdzl/spspd/items/food/staplefood/OverpricedRation.java @@ -0,0 +1,37 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.food.staplefood; + +import com.hmdzl.spspd.items.food.Food; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class OverpricedRation extends StapleFood { + + { + //name = "overpriced food ration"; + image = ItemSpriteSheet.OVERPRICED; + energy = 200; + hornValue = 2; + } + + + @Override + public int price() { + return 3 * quantity; + } +} diff --git a/java/com/hmdzl/spspd/items/food/staplefood/Pasty.java b/java/com/hmdzl/spspd/items/food/staplefood/Pasty.java new file mode 100644 index 00000000..00c4362b --- /dev/null +++ b/java/com/hmdzl/spspd/items/food/staplefood/Pasty.java @@ -0,0 +1,230 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.food.staplefood; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.buffs.BerryRegeneration; +import com.hmdzl.spspd.actors.buffs.Bless; +import com.hmdzl.spspd.actors.buffs.Blindness; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Haste; +import com.hmdzl.spspd.actors.buffs.Levitation; +import com.hmdzl.spspd.actors.buffs.Light; +import com.hmdzl.spspd.actors.buffs.MindVision; +import com.hmdzl.spspd.actors.buffs.Recharging; +import com.hmdzl.spspd.actors.buffs.Vertigo; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.effects.particles.FlameParticle; +import com.hmdzl.spspd.items.scrolls.ScrollOfRecharging; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; + +import java.util.Calendar; + +public class Pasty extends StapleFood { + + //TODO: implement fun stuff for other holidays + //TODO: probably should externalize this if I want to add any more festive stuff. + private enum Holiday{ + NONE, + SPRING, + STUDENT, + EASTER, //TBD + HWEEN,//2nd week of october though first day of november + THANK, + XMAS, //3rd week of december through first week of january + CHILD, + WORKER + } + + private static Holiday holiday; + + static{ + + holiday = Holiday.NONE; + + final Calendar calendar = Calendar.getInstance(); + switch(calendar.get(Calendar.MONTH)){ + case Calendar.JANUARY: + if (calendar.get(Calendar.WEEK_OF_MONTH) == 1) + holiday = Holiday.XMAS; + if (calendar.get(Calendar.DAY_OF_MONTH) >=18) + holiday = Holiday.SPRING; + break; + case Calendar.FEBRUARY: + if(calendar.get(Calendar.DAY_OF_MONTH)<=28) + holiday = Holiday.SPRING; + break; + case Calendar.APRIL: + holiday = Holiday.EASTER; + break; + case Calendar.MAY: + if(calendar.get(Calendar.DAY_OF_MONTH)<=7) + holiday = Holiday.WORKER; + break; + case Calendar.JUNE: + if(calendar.get(Calendar.DAY_OF_MONTH)<=3) + holiday = Holiday.CHILD; + break; + case Calendar.JULY: + case Calendar.AUGUST: + holiday = Holiday.STUDENT; + break; + case Calendar.OCTOBER: + if (calendar.get(Calendar.WEEK_OF_MONTH) >= 2) + holiday = Holiday.HWEEN; + break; + case Calendar.NOVEMBER: + if (calendar.get(Calendar.DAY_OF_MONTH) == 1) + holiday = Holiday.HWEEN; + if (calendar.get(Calendar.WEEK_OF_MONTH) >= 2) + holiday = Holiday.THANK; + break; + case Calendar.DECEMBER: + if (calendar.get(Calendar.WEEK_OF_MONTH) <= 1) + holiday = Holiday.THANK; + if (calendar.get(Calendar.WEEK_OF_MONTH) >= 3) + holiday = Holiday.XMAS; + break; + } + } + + { + switch(holiday){ + case NONE: + name = Messages.get(this, "pasty"); + image = ItemSpriteSheet.PASTY; + break; + case SPRING: + name = Messages.get(this,"assorted"); + image = ItemSpriteSheet.SPRING_ASSORTED; + break; + case EASTER: + name = Messages.get(this,"egg"); + image = ItemSpriteSheet.EASTER_EGG; + break; + case STUDENT: + name = Messages.get(this,"book"); + image = ItemSpriteSheet.KNOWNLADGE_FOOD; + break; + case HWEEN: + name = Messages.get(this, "pie"); + image = ItemSpriteSheet.PUMPKIN_PIE; + break; + case THANK: + name = Messages.get(this, "turkey"); + image = ItemSpriteSheet.TURKEY_MEAT; + break; + case XMAS: + name = Messages.get(this, "cane"); + image = ItemSpriteSheet.CANDY_CANE; + break; + case WORKER: + name = Messages.get(this, "bread"); + image = ItemSpriteSheet.BRICK; + break; + case CHILD: + name = Messages.get(this, "jelly"); + image = ItemSpriteSheet.JELLY_SWORD; + break; + } + + energy = 400; + + + } + + @Override + public void execute(Hero hero, String action) { + super.execute(hero, action); + + if (action.equals(AC_EAT)){ + switch(holiday){ + case NONE: + break; //do nothing extra + case SPRING: + Buff.affect(hero, BerryRegeneration.class).level(5); + hero.sprite.emitter().burst( Speck.factory( Speck.HEALING ), 1 ); + break; + case EASTER: + Buff.affect(hero, Bless.class,5f); + hero.sprite.emitter().start(Speck.factory(Speck.UP), 0.2f, 3); + break; + case STUDENT: + Buff.affect(hero, Light.class,50f); + Buff.affect(hero, MindVision.class,50f); + hero.sprite.emitter().start(FlameParticle.FACTORY, 0.2f, 3); + break; + case HWEEN: + //heals for 10% max hp + hero.HP = Math.min(hero.HP + hero.HT/10, hero.HT); + hero.sprite.emitter().burst( Speck.factory( Speck.HEALING ), 1 ); + break; + case THANK: + Buff.affect(hero, Haste.class,5f); + Buff.affect(hero, Levitation.class,5f); + break; + case XMAS: + Buff.affect( hero, Recharging.class, 2f ); //half of a charge + ScrollOfRecharging.charge( hero ); + break; + case WORKER: + Dungeon.gold +=500; + GLog.p(Messages.get(Pasty.class,"worker")); + break; + case CHILD: + hero.HP = hero.HT; + hero.HT +=3; + Buff.affect(hero,Blindness.class, 20f); + Buff.affect(hero,Vertigo.class, 20f); + break; + } + } + } + + @Override + public String info() { + switch(holiday){ + case NONE: default: + return Messages.get(this, "pasty_desc"); + case SPRING: + return Messages.get(this, "assorted_desc"); + case EASTER: + return Messages.get(this, "egg_desc"); + case STUDENT: + return Messages.get(this, "book_desc"); + case HWEEN: + return Messages.get(this, "pie_desc"); + case THANK: + return Messages.get(this, "turkey_desc"); + case XMAS: + return Messages.get(this, "cane_desc"); + case WORKER: + return Messages.get(this, "bread_desc"); + case CHILD: + return Messages.get(this, "jelly_desc"); + } + } + + @Override + public int price() { + return 100 * quantity; + } +} diff --git a/java/com/hmdzl/spspd/items/food/staplefood/StapleFood.java b/java/com/hmdzl/spspd/items/food/staplefood/StapleFood.java new file mode 100644 index 00000000..f367067e --- /dev/null +++ b/java/com/hmdzl/spspd/items/food/staplefood/StapleFood.java @@ -0,0 +1,34 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.food.staplefood; + +import com.hmdzl.spspd.items.food.Food; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class StapleFood extends Food { + + { + stackable = true; + //name = "ration of food"; + image = ItemSpriteSheet.RATION; + + + } + + +} diff --git a/java/com/hmdzl/spspd/items/food/vegetable/BattleFlower.java b/java/com/hmdzl/spspd/items/food/vegetable/BattleFlower.java new file mode 100644 index 00000000..5181b40c --- /dev/null +++ b/java/com/hmdzl/spspd/items/food/vegetable/BattleFlower.java @@ -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 + */ +package com.hmdzl.spspd.items.food.vegetable; + +import com.hmdzl.spspd.actors.buffs.Arcane; +import com.hmdzl.spspd.actors.buffs.AttackUp; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.DefenceUp; +import com.hmdzl.spspd.actors.buffs.TargetShoot; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class BattleFlower extends Vegetable { + + { + stackable = true; + //name = "ration of food"; + image = ItemSpriteSheet.STAR_FLOWER; + energy = 20; + hornValue = 1; + + } + + @Override + public void execute(Hero hero, String action) { + super.execute(hero, action); + + if (action.equals(AC_EAT)){ + Buff.affect(hero, AttackUp.class,30f).level(25); + Buff.affect(hero, DefenceUp.class,30f).level(25); + Buff.affect(hero, Arcane.class,30f); + Buff.affect(hero, TargetShoot.class,30f); + } + } + + @Override + public int price() { + return 1 * quantity; + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/food/vegetable/DreamLeaf.java b/java/com/hmdzl/spspd/items/food/vegetable/DreamLeaf.java new file mode 100644 index 00000000..5a1f6d85 --- /dev/null +++ b/java/com/hmdzl/spspd/items/food/vegetable/DreamLeaf.java @@ -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 + */ +package com.hmdzl.spspd.items.food.vegetable; + +import com.hmdzl.spspd.actors.buffs.ArmorBreak; +import com.hmdzl.spspd.actors.buffs.AttackDown; +import com.hmdzl.spspd.actors.buffs.Bleeding; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Cripple; +import com.hmdzl.spspd.actors.buffs.Poison; +import com.hmdzl.spspd.actors.buffs.Weakness; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class DreamLeaf extends Vegetable { + + { + stackable = true; + //name = "ration of food"; + image = ItemSpriteSheet.DREAM_L; + energy = 20; + hornValue = 1; + + } + + @Override + public void execute(Hero hero, String action) { + super.execute(hero, action); + + if (action.equals(AC_EAT)){ + Buff.detach(hero, Poison.class); + Buff.detach(hero, Cripple.class); + Buff.detach(hero, Weakness.class); + Buff.detach(hero, Bleeding.class); + Buff.detach(hero, AttackDown.class); + Buff.detach(hero, ArmorBreak.class); + } + } + + @Override + public int price() { + return 1 * quantity; + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/food/vegetable/HealGrass.java b/java/com/hmdzl/spspd/items/food/vegetable/HealGrass.java new file mode 100644 index 00000000..4e66ca9f --- /dev/null +++ b/java/com/hmdzl/spspd/items/food/vegetable/HealGrass.java @@ -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 + */ +package com.hmdzl.spspd.items.food.vegetable; + +import com.hmdzl.spspd.actors.buffs.BerryRegeneration; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class HealGrass extends Vegetable { + + { + stackable = true; + //name = "ration of food"; + image = ItemSpriteSheet.HEAL_L; + energy = 20; + hornValue = 1; + + } + + @Override + public void execute(Hero hero, String action) { + super.execute(hero, action); + + if (action.equals(AC_EAT)){ + hero.HP = Math.min(hero.HP + hero.HT/5, hero.HT); + Buff.affect(hero, BerryRegeneration.class).level(20); + } + } + + @Override + public int price() { + return 1 * quantity; + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/food/vegetable/NutVegetable.java b/java/com/hmdzl/spspd/items/food/vegetable/NutVegetable.java new file mode 100644 index 00000000..eff2c050 --- /dev/null +++ b/java/com/hmdzl/spspd/items/food/vegetable/NutVegetable.java @@ -0,0 +1,49 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.food.vegetable; + +import com.hmdzl.spspd.actors.buffs.Barkskin; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class NutVegetable extends Vegetable { + + { + stackable = true; + //name = "ration of food"; + image = ItemSpriteSheet.EAT_GRASS; + energy = 20; + hornValue = 1; + + } + + @Override + public void execute(Hero hero, String action) { + super.execute(hero, action); + + if (action.equals(AC_EAT)){ + Buff.affect(hero, Barkskin.class).level(hero.HT ); + } + } + + @Override + public int price() { + return 1 * quantity; + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/food/vegetable/Vegetable.java b/java/com/hmdzl/spspd/items/food/vegetable/Vegetable.java new file mode 100644 index 00000000..8106872c --- /dev/null +++ b/java/com/hmdzl/spspd/items/food/vegetable/Vegetable.java @@ -0,0 +1,32 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.food.vegetable; + +import com.hmdzl.spspd.items.food.Food; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class Vegetable extends Food { + + { + stackable = true; + //name = "ration of food"; + image = ItemSpriteSheet.EAT_GRASS; + + } + +} diff --git a/java/com/hmdzl/spspd/items/journalpages/EnergyCore.java b/java/com/hmdzl/spspd/items/journalpages/EnergyCore.java new file mode 100644 index 00000000..93b568e4 --- /dev/null +++ b/java/com/hmdzl/spspd/items/journalpages/EnergyCore.java @@ -0,0 +1,32 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.journalpages; + +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class EnergyCore extends JournalPage { + + + { + //name = "journal page Otiluke"; + image = ItemSpriteSheet.JOURNAL_PAGE; + room=7; + + stackable = false; + } +} diff --git a/java/com/hmdzl/spspd/items/journalpages/JournalPage.java b/java/com/hmdzl/spspd/items/journalpages/JournalPage.java new file mode 100644 index 00000000..28138753 --- /dev/null +++ b/java/com/hmdzl/spspd/items/journalpages/JournalPage.java @@ -0,0 +1,51 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.journalpages; + +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class JournalPage extends Item { + + private static final String TXT_VALUE = "Journal Page"; + public int room; + + { + //name = "journal page"; + image = ItemSpriteSheet.JOURNAL_PAGE; + + stackable = false; + unique = true; + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + @Override + public int price() { + return 150 * quantity; + } + +} diff --git a/java/com/hmdzl/spspd/items/journalpages/SafeSpotPage.java b/java/com/hmdzl/spspd/items/journalpages/SafeSpotPage.java new file mode 100644 index 00000000..477449f7 --- /dev/null +++ b/java/com/hmdzl/spspd/items/journalpages/SafeSpotPage.java @@ -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 + */ +package com.hmdzl.spspd.items.journalpages; + +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class SafeSpotPage extends JournalPage { + + { + //name = "safe spot"; + image = ItemSpriteSheet.JOURNAL_PAGE; + room=0; + + stackable = false; + } +} diff --git a/java/com/hmdzl/spspd/items/journalpages/Sokoban1.java b/java/com/hmdzl/spspd/items/journalpages/Sokoban1.java new file mode 100644 index 00000000..5515b681 --- /dev/null +++ b/java/com/hmdzl/spspd/items/journalpages/Sokoban1.java @@ -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 + */ +package com.hmdzl.spspd.items.journalpages; + +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class Sokoban1 extends JournalPage { + + { + //name = "journal page sokoban practice"; + image = ItemSpriteSheet.JOURNAL_PAGE; + room=1; + + stackable = false; + } +} diff --git a/java/com/hmdzl/spspd/items/journalpages/Sokoban2.java b/java/com/hmdzl/spspd/items/journalpages/Sokoban2.java new file mode 100644 index 00000000..da7929fe --- /dev/null +++ b/java/com/hmdzl/spspd/items/journalpages/Sokoban2.java @@ -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 + */ +package com.hmdzl.spspd.items.journalpages; + +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class Sokoban2 extends JournalPage { + + { + //name = "journal page sokoban castle"; + image = ItemSpriteSheet.JOURNAL_PAGE; + room=2; + + stackable = false; + } +} diff --git a/java/com/hmdzl/spspd/items/journalpages/Sokoban3.java b/java/com/hmdzl/spspd/items/journalpages/Sokoban3.java new file mode 100644 index 00000000..daf1f44c --- /dev/null +++ b/java/com/hmdzl/spspd/items/journalpages/Sokoban3.java @@ -0,0 +1,32 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.journalpages; + +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class Sokoban3 extends JournalPage { + + + { + //name = "journal page sokoban portals"; + image = ItemSpriteSheet.JOURNAL_PAGE; + room=3; + + stackable = false; + } +} diff --git a/java/com/hmdzl/spspd/items/journalpages/Sokoban4.java b/java/com/hmdzl/spspd/items/journalpages/Sokoban4.java new file mode 100644 index 00000000..2ecb193c --- /dev/null +++ b/java/com/hmdzl/spspd/items/journalpages/Sokoban4.java @@ -0,0 +1,32 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.journalpages; + +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class Sokoban4 extends JournalPage { + + + { + //name = "journal page sokoban puzzles"; + image = ItemSpriteSheet.JOURNAL_PAGE; + room=4; + + stackable = false; + } +} diff --git a/java/com/hmdzl/spspd/items/journalpages/Town.java b/java/com/hmdzl/spspd/items/journalpages/Town.java new file mode 100644 index 00000000..fdc99703 --- /dev/null +++ b/java/com/hmdzl/spspd/items/journalpages/Town.java @@ -0,0 +1,32 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.journalpages; + +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class Town extends JournalPage { + + { + //name = "journal page Dolyahaven"; + image = ItemSpriteSheet.JOURNAL_PAGE; + room=5; + + stackable = false; + } + +} diff --git a/java/com/hmdzl/spspd/items/journalpages/Vault.java b/java/com/hmdzl/spspd/items/journalpages/Vault.java new file mode 100644 index 00000000..e941687e --- /dev/null +++ b/java/com/hmdzl/spspd/items/journalpages/Vault.java @@ -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 + */ +package com.hmdzl.spspd.items.journalpages; + +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class Vault extends JournalPage { + + { + //name = "journal page vault"; + image = ItemSpriteSheet.JOURNAL_PAGE; + room=6; + + stackable = false; + } + + +} diff --git a/java/com/hmdzl/spspd/items/keys/GoldenKey.java b/java/com/hmdzl/spspd/items/keys/GoldenKey.java new file mode 100644 index 00000000..3684907e --- /dev/null +++ b/java/com/hmdzl/spspd/items/keys/GoldenKey.java @@ -0,0 +1,36 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.keys; + +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class GoldenKey extends Key { + + { + image = ItemSpriteSheet.GOLDEN_KEY; + } + + public GoldenKey() { + this(0); + } + + public GoldenKey(int depth) { + super(); + this.depth = depth; + } +} diff --git a/java/com/hmdzl/spspd/items/keys/GoldenSkeletonKey.java b/java/com/hmdzl/spspd/items/keys/GoldenSkeletonKey.java new file mode 100644 index 00000000..9263a516 --- /dev/null +++ b/java/com/hmdzl/spspd/items/keys/GoldenSkeletonKey.java @@ -0,0 +1,45 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.keys; + +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.sprites.ItemSprite.Glowing; + +public class GoldenSkeletonKey extends Key { + + { + //name = "golden skeleton key"; + image = ItemSpriteSheet.SPKEY; + } + + public GoldenSkeletonKey() { + this(0); + } + + public GoldenSkeletonKey(int depth) { + super(); + this.depth = depth; + } + + private static final Glowing WHITE = new Glowing(0xFFFFCC); + + @Override + public Glowing glowing() { + return WHITE; + } +} diff --git a/java/com/hmdzl/spspd/items/keys/IronKey.java b/java/com/hmdzl/spspd/items/keys/IronKey.java new file mode 100644 index 00000000..a072a9b7 --- /dev/null +++ b/java/com/hmdzl/spspd/items/keys/IronKey.java @@ -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 + */ +package com.hmdzl.spspd.items.keys; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.items.bags.Bag; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + + +public class IronKey extends Key { + + public static int curDepthQuantity = 0; + + { + //name = "iron key"; + image = ItemSpriteSheet.IRON_KEY; + } + + public IronKey() { + this(0); + } + + public IronKey(int depth) { + super(); + this.depth = depth; + } + + @Override + public boolean collect(Bag bag) { + boolean result = super.collect(bag); + if (result && depth == Dungeon.depth && Dungeon.hero != null) { + Dungeon.hero.belongings.countIronKeys(); + } + return result; + } + + @Override + public void onDetach() { + if (depth == Dungeon.depth) { + Dungeon.hero.belongings.countIronKeys(); + } + } +} diff --git a/java/com/hmdzl/spspd/items/keys/Key.java b/java/com/hmdzl/spspd/items/keys/Key.java new file mode 100644 index 00000000..f0dcdb8b --- /dev/null +++ b/java/com/hmdzl/spspd/items/keys/Key.java @@ -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 + */ +package com.hmdzl.spspd.items.keys; + +import com.hmdzl.spspd.items.Item; +import com.watabou.utils.Bundle; + +public class Key extends Item { + + public static final float TIME_TO_UNLOCK = 1f; + + { + stackable = true; + unique = true; + } + + public int depth; + + @Override + public boolean isSimilar(Item item) { + return item.getClass() == getClass() && ((Key) item).depth == depth; + } + + private static final String DEPTH = "depth"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(DEPTH, depth); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + depth = bundle.getInt(DEPTH); + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + +} diff --git a/java/com/hmdzl/spspd/items/keys/SkeletonKey.java b/java/com/hmdzl/spspd/items/keys/SkeletonKey.java new file mode 100644 index 00000000..ea22e5d2 --- /dev/null +++ b/java/com/hmdzl/spspd/items/keys/SkeletonKey.java @@ -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 + */ +package com.hmdzl.spspd.items.keys; + +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class SkeletonKey extends Key { + + { + image = ItemSpriteSheet.SKELETON_KEY; + stackable = false; + } + + public SkeletonKey() { + this(0); + } + + public SkeletonKey(int depth) { + super(); + this.depth = depth; + } + + @Override + public boolean isSimilar(Item item) { + return false; + } + +} diff --git a/java/com/hmdzl/spspd/items/medicine/BlueMilk.java b/java/com/hmdzl/spspd/items/medicine/BlueMilk.java new file mode 100644 index 00000000..eefba4d2 --- /dev/null +++ b/java/com/hmdzl/spspd/items/medicine/BlueMilk.java @@ -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 + */ +package com.hmdzl.spspd.items.medicine; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.buffs.BerryRegeneration; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Haste; +import com.hmdzl.spspd.actors.buffs.Slow; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.items.food.Food; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Random; + +public class BlueMilk extends Pill { + + { + //name = "blue milk mushroom"; + image = ItemSpriteSheet.MUSHROOM_BLUEMILK; + + } + + @Override + public void execute(Hero hero, String action) { + + if (action.equals(AC_EAT)) { + + if (Dungeon.bossLevel()){ + GLog.w(Messages.get(Food.class,"bosslevel")); + return; + } + + } + + if (action.equals(AC_EAT)) { + + switch (Random.Int(10)) { + case 1: + for (Mob mob : Dungeon.level.mobs.toArray(new Mob[0])) { + Buff.affect(mob, Slow.class, Slow.duration(mob)); + } + Buff.affect(hero, Haste.class, 20f); + Buff.affect(hero, BerryRegeneration.class).level(hero.HP/2); + break; + case 0: case 2: case 3: case 4: case 5: + case 6: case 7: case 8: case 9: case 10: + for (Mob mob : Dungeon.level.mobs.toArray(new Mob[0])) { + Buff.affect(mob, Slow.class, Slow.duration(mob)); + Buff.affect(mob, BerryRegeneration.class).level(mob.HP/2); + } + Buff.affect(hero, Haste.class, 20f); + Buff.affect(hero, BerryRegeneration.class).level(hero.HP/2); + break; + } + } + + super.execute(hero, action); + } + + @Override + public int price() { + return 5 * quantity; + } + + public BlueMilk() { + this(1); + } + + public BlueMilk(int value) { + this.quantity = value; + } +} diff --git a/java/com/hmdzl/spspd/items/medicine/DeathCap.java b/java/com/hmdzl/spspd/items/medicine/DeathCap.java new file mode 100644 index 00000000..f29500d1 --- /dev/null +++ b/java/com/hmdzl/spspd/items/medicine/DeathCap.java @@ -0,0 +1,87 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.medicine; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.buffs.Blindness; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.items.food.Food; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Random; + +public class DeathCap extends Pill { + + { + //name = "death cap mushroom"; + image = ItemSpriteSheet.MUSHROOM_DEATHCAP; + + } + + @Override + public void execute(Hero hero, String action) { + + if (action.equals(AC_EAT)) { + + if (Dungeon.bossLevel()){ + GLog.w(Messages.get(Food.class,"bosslevel")); + return; + } + + } + + if (action.equals(AC_EAT)) { + switch (Random.Int(10)) { + case 1: + for (Mob mob : Dungeon.level.mobs.toArray(new Mob[0])) { + mob.damage(Math.max(5,Math.round(mob.HP/2)), this); + } + hero.damage(Math.max(1,Math.round(hero.HP/4)), this); + Buff.prolong(hero, Blindness.class, Random.Int(5, 7)); + break; + case 0: case 2: case 3: case 4: case 5: + case 6: case 7: case 8: case 9: case 10: + for (Mob mob : Dungeon.level.mobs.toArray(new Mob[0])) { + mob.damage(Math.max(3,Math.round(mob.HP/2)), this); + mob.aggro(hero); + } + hero.damage(Math.max(1,Math.round(hero.HP/4)), this); + Buff.prolong(hero, Blindness.class, Random.Int(6, 9)); + break; + } + } + + super.execute(hero, action); + } + + @Override + public int price() { + return 5 * quantity; + } + + public DeathCap() { + this(1); + } + + public DeathCap(int value) { + this.quantity = value; + } +} diff --git a/java/com/hmdzl/spspd/items/medicine/Earthstar.java b/java/com/hmdzl/spspd/items/medicine/Earthstar.java new file mode 100644 index 00000000..483267aa --- /dev/null +++ b/java/com/hmdzl/spspd/items/medicine/Earthstar.java @@ -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 + */ +package com.hmdzl.spspd.items.medicine; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.buffs.Bleeding; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Cripple; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.items.food.Food; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Random; + +public class Earthstar extends Pill { + + { + //name = "earthstar mushroom"; + image = ItemSpriteSheet.MUSHROOM_EARTHSTAR; + + } + + @Override + public void execute(Hero hero, String action) { + + if (action.equals(AC_EAT)) { + + if (Dungeon.bossLevel()){ + GLog.w(Messages.get(Food.class,"bosslevel")); + return; + } + + } + + if (action.equals(AC_EAT)) { + + switch (Random.Int(10)) { + case 1: + for (Mob mob : Dungeon.level.mobs.toArray(new Mob[0])) { + int damage = Math.max(0,(Dungeon.depth + 3) - Random.IntRange(0, mob.drRoll() / 2)); + Buff.affect(mob, Bleeding.class).set(damage); + Buff.prolong(mob, Cripple.class, Cripple.DURATION*2); + } + int damage = Math.max(0,(Dungeon.depth) - Random.IntRange(0, hero.drRoll())); + hero.damage(Math.max(1,Math.round(hero.HP/2)), this); + Buff.affect(hero, Bleeding.class).set(damage); + Buff.prolong(hero, Cripple.class, Cripple.DURATION); + break; + case 0: case 2: case 3: case 4: case 5: + case 6: case 7: case 8: case 9: case 10: + for (Mob mob : Dungeon.level.mobs.toArray(new Mob[0])) { + int mobdamage = Math.max(0,(Dungeon.depth + 3) - Random.IntRange(0, mob.drRoll() / 2)); + Buff.affect(mob, Bleeding.class).set(mobdamage); + Buff.prolong(mob, Cripple.class, Cripple.DURATION*2); + } + int herodamage = Math.max(0,(Dungeon.depth) - Random.IntRange(0, hero.drRoll()/2)); + hero.damage(Math.max(1,Math.round(hero.HP/2)), this); + Buff.affect(hero, Bleeding.class).set(herodamage); + Buff.prolong(hero, Cripple.class, Cripple.DURATION); + break; + } + } + + super.execute(hero, action); + } + + @Override + public int price() { + return 5 * quantity; + } + + public Earthstar() { + this(1); + } + + public Earthstar(int value) { + this.quantity = value; + } +} diff --git a/java/com/hmdzl/spspd/items/medicine/GoldenJelly.java b/java/com/hmdzl/spspd/items/medicine/GoldenJelly.java new file mode 100644 index 00000000..427da137 --- /dev/null +++ b/java/com/hmdzl/spspd/items/medicine/GoldenJelly.java @@ -0,0 +1,85 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.medicine; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Roots; +import com.hmdzl.spspd.actors.buffs.Vertigo; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.items.food.Food; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Random; + +public class GoldenJelly extends Pill { + + { + //name = "golden jelly mushroom"; + image = ItemSpriteSheet.MUSHROOM_GOLDENJELLY; + + } + + @Override + public void execute(Hero hero, String action) { + + if (action.equals(AC_EAT)) { + + if (Dungeon.bossLevel()){ + GLog.w(Messages.get(Food.class,"bosslevel")); + return; + } + + } + + if (action.equals(AC_EAT)) { + + switch (Random.Int(10)) { + case 1: + for (Mob mob : Dungeon.level.mobs.toArray(new Mob[0])) { + Buff.prolong(mob, Roots.class, 20); + } + Buff.affect(hero, Vertigo.class, 1f); + break; + case 0: case 2: case 3: case 4: case 5: + case 6: case 7: case 8: case 9: case 10: + for (Mob mob : Dungeon.level.mobs.toArray(new Mob[0])) { + Buff.prolong(mob, Roots.class, 10); + } + Buff.affect(hero, Vertigo.class, 3f); + break; + } + } + super.execute(hero, action); + } + + @Override + public int price() { + return 5 * quantity; + } + + public GoldenJelly() { + this(1); + } + + public GoldenJelly(int value) { + this.quantity = value; + } +} diff --git a/java/com/hmdzl/spspd/items/medicine/GreenSpore.java b/java/com/hmdzl/spspd/items/medicine/GreenSpore.java new file mode 100644 index 00000000..c6b50943 --- /dev/null +++ b/java/com/hmdzl/spspd/items/medicine/GreenSpore.java @@ -0,0 +1,54 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.medicine; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Dewcharge; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.utils.GLog; + +public class GreenSpore extends Pill { + { + //name = "Green Sporre"; + image = ItemSpriteSheet.MUSHROOM_LICHEN; + + } + + @Override + public void execute(Hero hero, String action) { + + super.execute(hero, action); + + if (action.equals(AC_EAT)) { + if (!Dungeon.dewWater && !Dungeon.dewDraw){ + GLog.w(Messages.get(this,"not_time")); + return; + } + else Buff.affect(hero, Dewcharge.class, 100f); + } + } + + @Override + public int price() { + return 20 * quantity; + }; + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/medicine/Hardpill.java b/java/com/hmdzl/spspd/items/medicine/Hardpill.java new file mode 100644 index 00000000..b09799a4 --- /dev/null +++ b/java/com/hmdzl/spspd/items/medicine/Hardpill.java @@ -0,0 +1,49 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.medicine; + +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.DefenceUp; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class Hardpill extends Pill { + + { + //name = "hardpill"; + image = ItemSpriteSheet.PILL_DEF; + + } + + @Override + public void execute(Hero hero, String action) { + super.execute(hero, action); + + if (action.equals(AC_EAT)){ + Buff.affect(hero, DefenceUp.class,200f).level(50); + hero.sprite.emitter().start(Speck.factory(Speck.UP), 0.4f, 4); + } + } + + @Override + public int price() { + return 50 * quantity; + } + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/medicine/JackOLantern.java b/java/com/hmdzl/spspd/items/medicine/JackOLantern.java new file mode 100644 index 00000000..c85fe3cf --- /dev/null +++ b/java/com/hmdzl/spspd/items/medicine/JackOLantern.java @@ -0,0 +1,84 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.medicine; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.blobs.Blob; +import com.hmdzl.spspd.actors.blobs.Fire; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.items.food.Food; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Random; + +public class JackOLantern extends Pill { + + { + //name = "jack o lantern mushroom"; + image = ItemSpriteSheet.MUSHROOM_LANTERN; + + } + + @Override + public void execute(Hero hero, String action) { + + if (action.equals(AC_EAT)) { + + if (Dungeon.bossLevel()){ + GLog.w(Messages.get(Food.class,"bosslevel")); + return; + } + + } + + if (action.equals(AC_EAT)) { + switch (Random.Int(10)) { + case 1: + for (Mob mob : Dungeon.level.mobs.toArray(new Mob[0])) { + GameScene.add(Blob.seed(mob.pos, 3, Fire.class)); + } + break; + case 0: case 2: case 3: case 4: case 5: + case 6: case 7: case 8: case 9: case 10: + for (Mob mob : Dungeon.level.mobs.toArray(new Mob[0])) { + if(Random.Int(2)==0){GameScene.add(Blob.seed(mob.pos, 3, Fire.class));} + } + if(Random.Int(5)==0){GameScene.add(Blob.seed(hero.pos, 2, Fire.class));} + break; + } + } + + super.execute(hero, action); + } + + @Override + public int price() { + return 5 * quantity; + } + + public JackOLantern() { + this(1); + } + + public JackOLantern(int value) { + this.quantity = value; + } +} diff --git a/java/com/hmdzl/spspd/items/medicine/Magicpill.java b/java/com/hmdzl/spspd/items/medicine/Magicpill.java new file mode 100644 index 00000000..ca243487 --- /dev/null +++ b/java/com/hmdzl/spspd/items/medicine/Magicpill.java @@ -0,0 +1,49 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.medicine; + +import com.hmdzl.spspd.actors.buffs.Arcane; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class Magicpill extends Pill { + + { + //name = "magicpill"; + image = ItemSpriteSheet.PILL_MIG; + + } + + @Override + public void execute(Hero hero, String action) { + super.execute(hero, action); + + if (action.equals(AC_EAT)){ + Buff.affect(hero, Arcane.class,200f); + hero.sprite.emitter().start(Speck.factory(Speck.UP), 0.4f, 4); + } + } + + @Override + public int price() { + return 50 * quantity; + } + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/medicine/Musicpill.java b/java/com/hmdzl/spspd/items/medicine/Musicpill.java new file mode 100644 index 00000000..2a8878e7 --- /dev/null +++ b/java/com/hmdzl/spspd/items/medicine/Musicpill.java @@ -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 + */ +package com.hmdzl.spspd.items.medicine; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Rhythm; +import com.hmdzl.spspd.actors.buffs.Rhythm2; +import com.hmdzl.spspd.actors.buffs.WarGroove; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.hero.HeroClass; +import com.hmdzl.spspd.actors.hero.HeroSubClass; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class Musicpill extends Pill { + + { + //name = "speedpill"; + image = ItemSpriteSheet.PILL_MUC; + + } + + @Override + public void execute(Hero hero, String action) { + super.execute(hero, action); + + if (action.equals(AC_EAT)){ + Buff.affect(hero, Rhythm.class,200f); + if (Dungeon.hero.heroClass == HeroClass.PERFORMER) + Buff.affect(hero, WarGroove.class); + if (Dungeon.hero.subClass == HeroSubClass.SUPERSTAR) + Buff.affect(hero, Rhythm2.class,200f); + hero.sprite.emitter().start(Speck.factory(Speck.UP), 0.4f, 4); + } + } + + @Override + public int price() { + return 50 * quantity; + } + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/medicine/Pill.java b/java/com/hmdzl/spspd/items/medicine/Pill.java new file mode 100644 index 00000000..be7018f1 --- /dev/null +++ b/java/com/hmdzl/spspd/items/medicine/Pill.java @@ -0,0 +1,141 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.medicine; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.Statistics; +import com.hmdzl.spspd.actors.buffs.Locked; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.hero.HeroClass; +import com.hmdzl.spspd.effects.SpellSprite; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.food.Food; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; +import com.hmdzl.spspd.messages.Messages; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Random; + +public class Pill extends Item { + + private static final float TIME_TO_EAT = 1f; + + public static final String AC_EAT = "EAT"; + + { + stackable = true; + //name = "pill"; + image = ItemSpriteSheet.NULLWARN; + defaultAction = AC_EAT; + + } + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + if (hero.buff(Locked.class) == null){ + actions.add(AC_EAT); + } + return actions; + } + + @Override + public void execute(Hero hero, String action) { + if (action.equals(AC_EAT)) { + + if (hero.buff(Locked.class) != null ) { + GLog.w(Messages.get(Food.class, "locked")); + } else { + if (!(Dungeon.hero.heroClass == HeroClass.FOLLOWER ) || (Dungeon.hero.heroClass == HeroClass.FOLLOWER && Random.Int(10)>=1 )) + detach(hero.belongings.backpack); + /*int healEnergy = Math.max(7, Math.round(energy / 40)); + switch (hero.heroClass) { + case WARRIOR: + if (hero.HP < hero.HT) { + hero.HP = Math.min(hero.HP + Random.Int(3, healEnergy), hero.HT); + hero.sprite.emitter() + .burst(Speck.factory(Speck.HEALING), 1); + } + break; + case MAGE: + Buff.affect(hero, Recharging.class, 4f); + ScrollOfRecharging.charge(hero); + if (hero.HP < hero.HT) { + hero.HP = Math.min((hero.HP + Random.Int(1, 3)), hero.HT); + hero.sprite.emitter() + .burst(Speck.factory(Speck.HEALING), 1); + } + break; + case ROGUE: + if (hero.HP < hero.HT) { + hero.HP = Math.min((hero.HP + Random.Int(1, 3)), hero.HT); + hero.sprite.emitter() + .burst(Speck.factory(Speck.HEALING), 1); + } + case HUNTRESS: + if (hero.HP < hero.HT) { + hero.HP = Math.min((hero.HP + Random.Int(1, 3)), hero.HT); + hero.sprite.emitter() + .burst(Speck.factory(Speck.HEALING), 1); + } + break; + case PERFORMER: + if (hero.HP < hero.HT) { + hero.HP = Math.min((hero.HP + Random.Int(1, 3)), hero.HT); + hero.sprite.emitter() + .burst(Speck.factory(Speck.HEALING), 1); + } + break; + } +*/ + hero.sprite.operate(hero.pos); + hero.busy(); + SpellSprite.show(hero, SpellSprite.FOOD); + Sample.INSTANCE.play(Assets.SND_EAT); + + hero.spend(TIME_TO_EAT); + + Statistics.foodEaten++; + Badges.validateFoodEaten(); + } + } else { + + super.execute(hero, action); + + } + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + @Override + public int price() { + return 5 * quantity; + } +} diff --git a/java/com/hmdzl/spspd/items/medicine/PixieParasol.java b/java/com/hmdzl/spspd/items/medicine/PixieParasol.java new file mode 100644 index 00000000..4990a37a --- /dev/null +++ b/java/com/hmdzl/spspd/items/medicine/PixieParasol.java @@ -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 + */ +package com.hmdzl.spspd.items.medicine; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.buffs.BerryRegeneration; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Drowsy; +import com.hmdzl.spspd.actors.buffs.Paralysis; +import com.hmdzl.spspd.actors.buffs.Vertigo; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.food.Food; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Random; + +public class PixieParasol extends Pill { + + { + //name = "pixie parasol mushroom"; + image = ItemSpriteSheet.MUSHROOM_PIXIEPARASOL; + + } + + @Override + public void execute(Hero hero, String action) { + + if (action.equals(AC_EAT)) { + + if (Dungeon.bossLevel()){ + GLog.w(Messages.get(Food.class,"bosslevel")); + return; + } + + } + + if (action.equals(AC_EAT)) { + switch (Random.Int(10)) { + case 1: + for (Mob mob : Dungeon.level.mobs.toArray(new Mob[0])) { + Buff.affect(mob, Drowsy.class); + Buff.prolong(mob, Paralysis.class, Random.IntRange(10, 16)); + mob.sprite.centerEmitter().start(Speck.factory(Speck.NOTE), 0.3f, 5); + } + Buff.affect(hero, BerryRegeneration.class).level(hero.HP/2); + break; + case 0: case 2: case 3: case 4: case 5: + case 6: case 7: case 8: case 9: case 10: + for (Mob mob : Dungeon.level.mobs.toArray(new Mob[0])) { + Buff.affect(mob, Drowsy.class); + Buff.prolong(mob, Paralysis.class, Random.IntRange(10, 16)); + mob.sprite.centerEmitter().start(Speck.factory(Speck.NOTE), 0.3f, 5); + } + Buff.affect(hero, Vertigo.class, 5f); + Buff.affect(hero, BerryRegeneration.class).level(hero.HP/2); + break; + } + } + + super.execute(hero, action); + } + + @Override + public int price() { + return 5 * quantity; + } + + public PixieParasol() { + this(1); + } + + public PixieParasol(int value) { + this.quantity = value; + } +} diff --git a/java/com/hmdzl/spspd/items/medicine/Powerpill.java b/java/com/hmdzl/spspd/items/medicine/Powerpill.java new file mode 100644 index 00000000..b25309fa --- /dev/null +++ b/java/com/hmdzl/spspd/items/medicine/Powerpill.java @@ -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 + */ +package com.hmdzl.spspd.items.medicine; + +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Muscle; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class Powerpill extends Pill { + + { + //name = "powerpill"; + image = ItemSpriteSheet.PILL_STR; + + } + + @Override + public void execute(Hero hero, String action) { + super.execute(hero, action); + + if (action.equals(AC_EAT)){ + Buff.affect(hero, Muscle.class,200f); + hero.sprite.emitter().start(Speck.factory(Speck.UP), 0.4f, 4); + } + } + @Override + public int price() { + return 50 * quantity; + } + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/medicine/Shootpill.java b/java/com/hmdzl/spspd/items/medicine/Shootpill.java new file mode 100644 index 00000000..27c2f1b8 --- /dev/null +++ b/java/com/hmdzl/spspd/items/medicine/Shootpill.java @@ -0,0 +1,49 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.medicine; + +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.TargetShoot; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class Shootpill extends Pill { + + { + //name = "shootpill"; + image = ItemSpriteSheet.PILL_SOT; + + } + + @Override + public void execute(Hero hero, String action) { + super.execute(hero, action); + + if (action.equals(AC_EAT)){ + Buff.affect(hero, TargetShoot.class,200f); + hero.sprite.emitter().start(Speck.factory(Speck.UP), 0.4f, 4); + } + } + + @Override + public int price() { + return 50 * quantity; + } + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/medicine/Smashpill.java b/java/com/hmdzl/spspd/items/medicine/Smashpill.java new file mode 100644 index 00000000..277922de --- /dev/null +++ b/java/com/hmdzl/spspd/items/medicine/Smashpill.java @@ -0,0 +1,49 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.medicine; + +import com.hmdzl.spspd.actors.buffs.AttackUp; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class Smashpill extends Pill { + + { + //name = "smashpill"; + image = ItemSpriteSheet.PILL_ATK; + + } + + @Override + public void execute(Hero hero, String action) { + super.execute(hero, action); + + if (action.equals(AC_EAT)){ + Buff.affect(hero, AttackUp.class,200f).level(50); + hero.sprite.emitter().start(Speck.factory(Speck.UP), 0.4f, 4); + } + } + + @Override + public int price() { + return 50 * quantity; + } + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/misc/Ankhshield.java b/java/com/hmdzl/spspd/items/misc/Ankhshield.java new file mode 100644 index 00000000..da5cf8a7 --- /dev/null +++ b/java/com/hmdzl/spspd/items/misc/Ankhshield.java @@ -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 + */ +package com.hmdzl.spspd.items.misc; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Shieldblock; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Bundle; +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.watabou.noosa.audio.Sample; + + + + + public class Ankhshield extends Item { + { + //name = "Ankh Shield"; + image = ItemSpriteSheet.SHIELD; + defaultAction = AC_DEFENCE; + unique = true; + + } + + private static final String AC_DEFENCE = "DEFENCE"; + public final int fullCharge = 250; + public int charge = 0; + private static final String CHARGE = "charge"; + + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(CHARGE, charge); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + charge = bundle.getInt(CHARGE); + } + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + if (charge >= 120){ + actions.add(AC_DEFENCE); + } + actions.remove(AC_DROP); + actions.remove(AC_THROW); + return actions; + } + + + @Override + public void execute(final Hero hero, String action) { + if (action.equals(AC_DEFENCE)) { + if (charge < 120) + GLog.i(Messages.get(this, "rest")); + else { + + curUser = hero; + GameScene.flash(0x009900); + Sample.INSTANCE.play(Assets.SND_TELEPORT); + + for (Mob mob : Dungeon.level.mobs.toArray(new Mob[0])) { + if (Level.fieldOfView[mob.pos]) { + mob.damage(5, this); + Buff.prolong(mob, Shieldblock.class, 3); + } + } + + charge -= 120; + updateQuickslot(); + } + } else { + + super.execute(hero, action); + } + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + + @Override + public String info() { + String info = desc(); + info += "\n\n" + Messages.get(this,"charge",charge,fullCharge); + return info; + } + + @Override + public String status() { + return Messages.format("%d", (int)charge/120); + } + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/misc/AttackShield.java b/java/com/hmdzl/spspd/items/misc/AttackShield.java new file mode 100644 index 00000000..bcb993e1 --- /dev/null +++ b/java/com/hmdzl/spspd/items/misc/AttackShield.java @@ -0,0 +1,225 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.misc; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.ArmorBreak; +import com.hmdzl.spspd.actors.buffs.AttackUp; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Vertigo; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.Splash; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.weapon.missiles.MissileWeapon; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.CellSelector; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +import java.util.ArrayList; + +public class AttackShield extends Item { + + { + //name = "AttackShield"; + image = ItemSpriteSheet.ATTACKSHIELD; + + stackable = false; + unique = true; + defaultAction = AC_CAST; + + } + + private static final String AC_CAST = "CAST"; + private static final String AC_BlAST = "BLAST"; + public final int fullCharge = 20; + public int charge = 0; + private static final String CHARGE = "charge"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(CHARGE, charge); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + charge = bundle.getInt(CHARGE); + } + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions( hero ); + if (charge >= 10){ + actions.add(AC_CAST); + } + if (charge >= 20){ + actions.add(AC_BlAST); + } + actions.remove( AC_THROW ); + actions.remove( AC_DROP ); + return actions; + } + + @Override + public void execute(final Hero hero, String action) { + super.execute(hero, action); + if (action.equals(AC_CAST)) { + curUser = hero; + if (charge < 10) { + GLog.i(Messages.get(this, "rest")); + } else GameScene.selectCell(shooter); + } else if (action.equals(AC_BlAST)) { + curUser = hero; + if (charge < 20) { + GLog.i(Messages.get(this, "rest")); + return; + } else { + if (curUser.buff(LongBuff.class) == null) Buff.affect(curUser,LongBuff.class); + Buff.prolong(hero, ArmorBreak.class, 100f).level(50); + Buff.prolong(hero, AttackUp.class, 50f).level(100); + charge -= 20; + } + } + + } + + @Override + public String desc() { + String info = super.desc(); + info += "\n\n" + Messages.get(AttackShield.class, "damage",min(),max()); + info += "\n\n" + Messages.get(AttackShield.class, "charge",charge,fullCharge); + return info; + } + + public int level() { + return Dungeon.hero == null ? 0 : Dungeon.hero.lvl/5; + } + + @Override + public int visiblyUpgraded() { + return level(); + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + public int min() { + return 1 + Dungeon.hero.lvl; + } + + public int max() { + return 3 + Dungeon.hero.lvl*2; + } + + public int damageRoll(Hero owner) { + int damage = Random.Int(min(), max()); + return Math.round(damage); + } + + private int targetPos; + + public AttackShieldAmmo Ammo(){ + return new AttackShieldAmmo(); + } + + public class AttackShieldAmmo extends MissileWeapon { + + { + image = ItemSpriteSheet.DUST; + ACU = 1000; + } + + public int damageRoll(Hero owner) { + return AttackShield.this.damageRoll(owner); + } + + @Override + protected void onThrow( int cell ) { + Char enemy = Actor.findChar( cell ); + if (enemy == null || enemy == curUser) { + parent = null; + Splash.at( cell, 0xCC99FFFF, 1 ); + } else { + if (!curUser.shoot( enemy, this )) { + Splash.at(cell, 0xCC99FFFF, 1); + } + } + } + + @Override + public void proc(Char attacker, Char defender, int damage) { + + if (defender.properties().contains(Char.Property.BOSS) || defender.properties().contains(Char.Property.MINIBOSS)){ + defender.damage((int)(0.25* defender.HT * (defender.HP/defender.HT)) ,this); + } else { + defender.damage((int) (0.5 * defender.HT * (defender.HP / defender.HT)), this); + Buff.prolong(defender, Vertigo.class, 5f); + } + super.proc(attacker, defender, damage); + } + + @Override + public void cast(final Hero user, final int dst) { + final int cell = throwPos( user, dst ); + AttackShield.this.targetPos = cell; + charge-=10; + super.cast(user, dst); + } + + } + private CellSelector.Listener shooter = new CellSelector.Listener() { + @Override + public void onSelect( Integer target ) { + if (target != null) { + Ammo().cast(curUser, target); + } + } + @Override + public String prompt() { + return Messages.get(AttackShield.class, "prompt"); + } + }; + + public static class LongBuff extends Buff { + + @Override + public boolean act() { + spend(TICK); + return true; + } + + public void dispel(){ + detach(); + } + } + +} + diff --git a/java/com/hmdzl/spspd/items/misc/AttackShoes.java b/java/com/hmdzl/spspd/items/misc/AttackShoes.java new file mode 100644 index 00000000..8125c160 --- /dev/null +++ b/java/com/hmdzl/spspd/items/misc/AttackShoes.java @@ -0,0 +1,134 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.misc; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.scenes.CellSelector; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.messages.Messages; +import com.watabou.utils.Callback; + + +public class AttackShoes extends Item { + { + //name = "AttackShoes"; + image = ItemSpriteSheet.JUMP; + defaultAction = AC_JUMP; + unique = true; + + } + + private static int JUMP_TIME = 2; + private static final String AC_JUMP = "JUMP"; + + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + actions.add(AC_JUMP); + actions.remove(AC_DROP); + actions.remove(AC_THROW); + return actions; + } + + protected CellSelector.Listener jumper = new CellSelector.Listener() { + + @Override + public void onSelect(Integer target) { + if (target != null && target != curUser.pos) { + + Ballistica route = new Ballistica(curUser.pos, target, Ballistica.PROJECTILE); + int cell = route.collisionPos; + int dist = Level.distance(curUser.pos, cell); + int range = 3; + //if (Actor.findChar(cell) != null && cell != curUser.pos) + // cell = route.path.get(route.dist - 1); + + if (dist > 3) { + range = dist - 3; + cell = route.path.get(route.dist - range); + } + + final int dest = cell; + curUser.busy(); + curUser.sprite.jump(curUser.pos, cell, new Callback() { + @Override + public void call() { + curUser.move(dest); + Dungeon.level.press(dest, curUser); + Dungeon.observe(); + for (int i = 0; i < Level.NEIGHBOURS8.length; i++) { + Char mob = Actor.findChar(curUser.pos + + Level.NEIGHBOURS8[i]); + if (mob != null && mob != curUser && mob.isAlive()) { + mob.damage(30 + Dungeon.hero.lvl * 3, this); + } + } + + CellEmitter.center(dest).burst( + Speck.factory(Speck.DUST), 10); + curUser.spendAndNext(JUMP_TIME); + updateQuickslot(); + } + }); + } + } + public String prompt() { + return Messages.get(Jumpshoes.class, "prompt"); + } + }; + + @Override + public void execute(final Hero hero, String action) { + if (action.equals(AC_JUMP)) { + curUser = hero; + GameScene.selectCell(jumper); + } else { + super.execute(hero, action); + } + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + @Override + public String info() { + String info = desc(); + return info; + } + + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/misc/AutoPotion.java b/java/com/hmdzl/spspd/items/misc/AutoPotion.java new file mode 100644 index 00000000..4a1ef0e8 --- /dev/null +++ b/java/com/hmdzl/spspd/items/misc/AutoPotion.java @@ -0,0 +1,51 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.misc; + +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class AutoPotion extends MiscEquippable { + + { + image = ItemSpriteSheet.ARTIFACT; + unique = true; + } + + @Override + protected MiscBuff buff() { + return new AutoHealPotion(); + } + + public class AutoHealPotion extends MiscBuff { + } + + @Override + public boolean isIdentified() { + return true; + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public int price() { + return 500 * quantity; + } +} diff --git a/java/com/hmdzl/spspd/items/misc/BShovel.java b/java/com/hmdzl/spspd/items/misc/BShovel.java new file mode 100644 index 00000000..616268c7 --- /dev/null +++ b/java/com/hmdzl/spspd/items/misc/BShovel.java @@ -0,0 +1,173 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Yet Another Pixel Dungeon + * Copyright (C) 2015-2016 Considered Hamster + * + * 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 + */ +package com.hmdzl.spspd.items.misc; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.buffs.Awareness; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Haste; +import com.hmdzl.spspd.actors.buffs.Hunger; +import com.hmdzl.spspd.actors.buffs.MechArmor; +import com.hmdzl.spspd.actors.buffs.MindVision; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.Terrain; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.ui.BuffIndicator; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +import java.util.ArrayList; + +public class BShovel extends Item { + + public static final String AC_USE = "USE"; + + private static final float TIME_TO_DIG = 1f; + + { + //name = "Shovel"; + image = ItemSpriteSheet.BSHOVEL; + defaultAction = AC_USE; + unique = true; + + } + + public final int fullCharge = 150; + public int charge = 0; + private static final String CHARGE = "charge"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(CHARGE, charge); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + charge = bundle.getInt(CHARGE); + } + + @Override + public ArrayList actions(Hero hero ) { + ArrayList actions = super.actions( hero ); + if (charge >= 75){ + actions.add(AC_USE); + } + actions.remove( AC_THROW ); + actions.remove( AC_DROP ); + return actions; + } + + @Override + public void execute( final Hero hero, String action ) { + if( action.equals( AC_USE ) ){ + if(charge < 75){ + GLog.i(Messages.get(BShovel.class, "break")); + return; + } else { + for (int n : Level.NEIGHBOURS4) { + int c = hero.pos + n; + + if (c >= 0 && c < Level.getLength()) { + if (Dungeon.level.map[c] == Terrain.WALL && Level.insideMap(c)) { + Level.set(c, Terrain.DOOR); + GameScene.updateMap(c); + Dungeon.observe(); + } + } + } + hero.spend(TIME_TO_DIG); + hero.busy(); + Hunger hunger = hero.buff(Hunger.class); + if (hunger != null && !hunger.isStarving()) { + hunger.satisfy(-10); + BuffIndicator.refreshHero(); + } + charge-=75; + + switch (Random.Int (6)) { + case 0 : + Buff.affect(hero,MindVision.class,5f); + GLog.p(Messages.get(BShovel.class,"mob")); + break; + case 1 : + Buff.affect(hero,Haste.class,5f); + GLog.p(Messages.get(BShovel.class,"haste")); + break; + case 2 : + Buff.affect(hero,Awareness.class,5f); + GLog.p(Messages.get(BShovel.class,"item")); + break; + case 3 : + Dungeon.gold+=Dungeon.hero.lvl*10; + GLog.p(Messages.get(BShovel.class,"gold")); + break; + case 4 : + Dungeon.hero.HP=Dungeon.hero.HT; + GLog.p(Messages.get(BShovel.class,"heal")); + break; + case 5 : + Buff.affect(hero,MechArmor.class).level(30); + GLog.p(Messages.get(BShovel.class,"mech")); + break; + default: + break; + } + updateQuickslot(); + hero.onOperateComplete(); + + return; + } + } else { + super.execute(hero, action); + } + } + + @Override + public String status() { + return Messages.format("%d", (int)charge/75); + } + + @Override + public String info() { + String info = desc(); + info += "\n\n" + Messages.get(BShovel.class, "charge",charge,fullCharge); + return info; + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + +} diff --git a/java/com/hmdzl/spspd/items/misc/CopyBall.java b/java/com/hmdzl/spspd/items/misc/CopyBall.java new file mode 100644 index 00000000..e20ef7ce --- /dev/null +++ b/java/com/hmdzl/spspd/items/misc/CopyBall.java @@ -0,0 +1,181 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Yet Another Pixel Dungeon + * Copyright (C) 2015-2016 Considered Hamster + * + * 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 + */ +package com.hmdzl.spspd.items.misc; + +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.ArmorBreak; +import com.hmdzl.spspd.actors.buffs.AttackDown; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Corruption; +import com.hmdzl.spspd.actors.buffs.Vertigo; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.Splash; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.weapon.missiles.MissileWeapon; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.CellSelector; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Bundle; + +import java.util.ArrayList; + +public class CopyBall extends Item { + + public static final String AC_USE = "USE"; + private static final float TIME_TO_DIG = 1f; + + { + image = ItemSpriteSheet.COPY_BALL; + defaultAction = AC_USE; + + unique = true; + + } + + public final int fullCharge = 50; + public int charge = 0; + private static final String CHARGE = "charge"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(CHARGE, charge); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + charge = bundle.getInt(CHARGE); + } + + @Override + public ArrayList actions(Hero hero ) { + ArrayList actions = super.actions( hero ); + if (charge >= 10) { + actions.add(AC_USE); + } + actions.remove( AC_THROW ); + actions.remove( AC_DROP ); + return actions; + } + + @Override + public void execute( final Hero hero, String action ) { + if( action.equals( AC_USE ) ) { + curUser = hero; + if (charge < 10) { + GLog.i(Messages.get(CopyBall.class, "break")); + } else GameScene.selectCell(shooter); + } else super.execute(hero, action); + + + } + + @Override + public String status() { + return Messages.format("%d", (int)charge/10); + } + + @Override + public String info() { + String info = desc(); + info += "\n\n" + Messages.get(CopyBall.class, "charge",charge,fullCharge); + return info; + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + + private int targetPos; + + public CopyBallAmmo Ammo(){ + return new CopyBallAmmo(); + } + + public class CopyBallAmmo extends MissileWeapon { + + { + image = ItemSpriteSheet.COPY_BALL; + ACU = 1000; + } + + public int damageRoll(Hero owner) { + return 0; + } + + @Override + protected void onThrow( int cell ) { + Char enemy = Actor.findChar( cell ); + if (enemy == null || enemy == curUser) { + parent = null; + Splash.at( cell, 0xCC99FFFF, 1 ); + } else { + if (!curUser.shoot( enemy, this )) { + Splash.at(cell, 0xCC99FFFF, 1); + } + } + } + + @Override + public void proc(Char attacker, Char defender, int damage) { + if (defender.properties().contains(Char.Property.BOSS) || defender.properties().contains(Char.Property.MINIBOSS)){ + Buff.affect(defender, AttackDown.class, 10f).level(35); + Buff.affect(defender, ArmorBreak.class, 10f).level(35); + Buff.prolong(defender, Vertigo.class, 5f); + } else { + Buff.affect(defender,Corruption.class); + } + super.proc(attacker, defender, damage); + } + + @Override + public void cast(final Hero user, final int dst) { + final int cell = throwPos( user, dst ); + CopyBall.this.targetPos = cell; + charge-=10; + super.cast(user, dst); + } + + } + private CellSelector.Listener shooter = new CellSelector.Listener() { + @Override + public void onSelect( Integer target ) { + if (target != null) { + Ammo().cast(curUser, target); + } + } + @Override + public String prompt() { + return Messages.get(CopyBall.class, "prompt"); + } + }; +} diff --git a/java/com/hmdzl/spspd/items/misc/DanceLion.java b/java/com/hmdzl/spspd/items/misc/DanceLion.java new file mode 100644 index 00000000..f04d6dee --- /dev/null +++ b/java/com/hmdzl/spspd/items/misc/DanceLion.java @@ -0,0 +1,162 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.misc; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.buffs.Arcane; +import com.hmdzl.spspd.actors.buffs.AttackUp; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.DefenceUp; +import com.hmdzl.spspd.actors.buffs.GlassShield; +import com.hmdzl.spspd.actors.buffs.Invisibility; +import com.hmdzl.spspd.actors.buffs.Levitation; +import com.hmdzl.spspd.actors.buffs.Recharging; +import com.hmdzl.spspd.actors.buffs.Rhythm; +import com.hmdzl.spspd.actors.buffs.Rhythm2; +import com.hmdzl.spspd.actors.buffs.ShieldArmor; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.hero.HeroSubClass; +import com.hmdzl.spspd.items.Item; + +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.windows.WndItem; +import com.watabou.utils.Bundle; + +public class DanceLion extends Item { + + { + //name = "DanceLion"; + image = ItemSpriteSheet.DANCE_LION; + unique = true; + defaultAction = AC_CHOOSE; + } + + public final int fullCharge = 100; + public int charge = 0; + + public static final String AC_CHOOSE = "CHOOSE"; + + public static final String AC_SPIN = "SPIN"; + public static final String AC_STAND = "STAND"; + public static final String AC_BACK = "BACK"; + public static final String AC_RUSH = "RUSH"; + public static final String AC_JUMP = "JUMP"; + + private static final String CHARGE = "charge"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(CHARGE, charge); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + charge = bundle.getInt(CHARGE); + } + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + actions.remove(AC_DROP); + actions.remove(AC_THROW); + if (charge > 40) { + actions.add(AC_SPIN); + actions.add(AC_STAND); + actions.add(AC_BACK); + actions.add(AC_RUSH); + actions.add(AC_JUMP); + } + return actions; + } + + @Override + public void execute(Hero hero, String action) { + + curUser = Dungeon.hero; + + if (action.equals( AC_CHOOSE )){ + + GameScene.show(new WndItem(null, this, true)); + + } else if (action.equals(AC_SPIN)) { + Buff.affect(curUser, Rhythm.class,20f); + if(hero.subClass == HeroSubClass.SUPERSTAR){ + Buff.affect(curUser,Rhythm2.class,20f); + } + charge -= 40; + hero.spendAndNext(1f); + } else if (action.equals(AC_STAND)) { + Buff.affect(curUser,DefenceUp.class,20f).level(30); + if(hero.subClass == HeroSubClass.SUPERSTAR){ + Buff.affect(curUser,ShieldArmor.class).level(Dungeon.hero.lvl*2); + } + charge -= 40; + hero.spendAndNext(1f); + } else if (action.equals(AC_BACK)) { + Buff.affect(curUser, Recharging.class,10f); + if(hero.subClass == HeroSubClass.SUPERSTAR){ + Buff.affect(curUser,Arcane.class,20f); + } + charge -= 40; + hero.spendAndNext(1f); + } else if (action.equals(AC_RUSH)) { + Buff.affect(curUser, AttackUp.class,20f).level(30); + if(hero.subClass == HeroSubClass.SUPERSTAR){ + Buff.affect(curUser,Invisibility.class,20f); + } + charge -= 40; + hero.spendAndNext(1f); + } else if (action.equals(AC_JUMP)) { + Buff.affect(curUser, Levitation.class,20f); + if(hero.subClass == HeroSubClass.SUPERSTAR){ + Buff.affect(curUser,GlassShield.class).turns(2); + } + charge -= 40; + hero.spendAndNext(1f); + } else { + super.execute(hero, action); + } + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + @Override + public String desc() { + String info = super.desc(); + info += "\n\n" + Messages.get(AttackShield.class, "charge",charge,fullCharge); + return info; + } + @Override + public String status() { + return Messages.format("%d", (int)charge/40); + } +} diff --git a/java/com/hmdzl/spspd/items/misc/DemoScroll.java b/java/com/hmdzl/spspd/items/misc/DemoScroll.java new file mode 100644 index 00000000..da490a8e --- /dev/null +++ b/java/com/hmdzl/spspd/items/misc/DemoScroll.java @@ -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 + */ +package com.hmdzl.spspd.items.misc; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.ResultDescriptions; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.items.Item; + +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public class DemoScroll extends Item { + + public static final String AC_READ = "READ"; + { + //name = "DemoScroll"; + image = ItemSpriteSheet.DEMO_SCROLL; + + stackable = false; + charge = 0; + //defaultAction = AC_READ; + } + + public static int charge; + private static final String CHARGE = "charge"; + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + if (charge < hero.lvl && hero.HT > hero.lvl) actions.add(AC_READ); + return actions; + } + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(CHARGE, charge); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + charge = bundle.getInt(CHARGE); + } + + @Override + public void execute(Hero hero, String action) { + + if (action.equals(AC_READ)) { + + switch (Random.Int (4)) { + case 0 : + hero.hitSkill++; + GLog.w(Messages.get(this, "hitup")); + break; + case 1 : + hero.evadeSkill++; + GLog.w(Messages.get(this, "evaup")); + break; + case 2 : + hero.magicSkill++; + GLog.w(Messages.get(this, "migup")); + break; + case 3 : + hero.STR++; + GLog.w(Messages.get(this, "strup")); + break; + default: + + break; + } + charge ++; + hero.sprite.operate(hero.pos); + hero.busy(); + hero.spend(2f); + int dmg = Random.Int(6,Dungeon.hero.lvl); + hero.damage(dmg,this); + if (!hero.isAlive()) { + Dungeon.fail(Messages.format(ResultDescriptions.ITEM)); + //GLog.n("The Chalice sucks your life essence dry..."); + } + Dungeon.hero.HT-= Math.min(dmg,hero.HT-1); + GLog.w(Messages.get(this, "htdown")); + //hero.hitSkill++; + //hero.evadeSkill++; + //hero.magicSkill++; + + //detach(hero.belongings.backpack); + } else { + super.execute(hero, action); + + } + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } +} diff --git a/java/com/hmdzl/spspd/items/misc/FaithSign.java b/java/com/hmdzl/spspd/items/misc/FaithSign.java new file mode 100644 index 00000000..79dd0fa4 --- /dev/null +++ b/java/com/hmdzl/spspd/items/misc/FaithSign.java @@ -0,0 +1,131 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.misc; + +import java.util.ArrayList; + +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.faithbuff.BalanceFaith; +import com.hmdzl.spspd.actors.buffs.faithbuff.DemonFaith; +import com.hmdzl.spspd.actors.buffs.faithbuff.HumanFaith; +import com.hmdzl.spspd.actors.buffs.faithbuff.LifeFaith; +import com.hmdzl.spspd.actors.buffs.faithbuff.MechFaith; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.items.Item; + +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.windows.WndItem; + +public class FaithSign extends Item { + + { + //name = "faithsign"; + image = ItemSpriteSheet.FAITH_SIGN; + unique = true; + defaultAction = AC_CHOOSE; + } + + public static final String AC_CHOOSE = "CHOOSE"; + + public static final String AC_DEMON = "DEMON"; + public static final String AC_HUMAN = "HUMAN"; + public static final String AC_MECH = "MECH"; + public static final String AC_LIFE = "LIFE"; + public static final String AC_BALANCE = "BALANCE"; + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + actions.remove(AC_DROP); + actions.remove(AC_THROW); + actions.add(AC_DEMON); + actions.add(AC_HUMAN); + actions.add(AC_MECH); + actions.add(AC_LIFE); + actions.add(AC_BALANCE); + return actions; + } + + @Override + public void execute(Hero hero, String action) { + + if (action.equals( AC_CHOOSE )){ + + GameScene.show(new WndItem(null, this, true)); + + } else if (action.equals(AC_DEMON)) { + Buff.detach(hero,DemonFaith.class); + Buff.detach(hero,HumanFaith.class); + Buff.detach(hero,MechFaith.class); + Buff.detach(hero,LifeFaith.class); + Buff.detach(hero,BalanceFaith.class); + Buff.affect(hero,DemonFaith.class); + hero.spendAndNext(1f); + + } else if (action.equals(AC_HUMAN)) { + Buff.detach(hero,DemonFaith.class); + Buff.detach(hero,HumanFaith.class); + Buff.detach(hero,MechFaith.class); + Buff.detach(hero,LifeFaith.class); + Buff.detach(hero,BalanceFaith.class); + Buff.affect(hero,HumanFaith.class); + hero.spendAndNext(1f); + + } else if (action.equals(AC_MECH)) { + Buff.detach(hero,DemonFaith.class); + Buff.detach(hero,HumanFaith.class); + Buff.detach(hero,MechFaith.class); + Buff.detach(hero,LifeFaith.class); + Buff.detach(hero,BalanceFaith.class); + Buff.affect(hero,MechFaith.class); + hero.spendAndNext(1f); + + } else if (action.equals(AC_LIFE)) { + Buff.detach(hero,DemonFaith.class); + Buff.detach(hero,HumanFaith.class); + Buff.detach(hero,MechFaith.class); + Buff.detach(hero,LifeFaith.class); + Buff.detach(hero,BalanceFaith.class); + Buff.affect(hero,LifeFaith.class); + hero.spendAndNext(1f); + + } else if (action.equals(AC_BALANCE)) { + Buff.detach(hero,DemonFaith.class); + Buff.detach(hero,HumanFaith.class); + Buff.detach(hero,MechFaith.class); + Buff.detach(hero,LifeFaith.class); + Buff.detach(hero,BalanceFaith.class); + Buff.affect(hero,BalanceFaith.class); + hero.spendAndNext(1f); + } else { + super.execute(hero, action); + } + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + +} diff --git a/java/com/hmdzl/spspd/items/misc/FourClover.java b/java/com/hmdzl/spspd/items/misc/FourClover.java new file mode 100644 index 00000000..25e662de --- /dev/null +++ b/java/com/hmdzl/spspd/items/misc/FourClover.java @@ -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 + */ +package com.hmdzl.spspd.items.misc; + +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class FourClover extends MiscEquippable { + + { + image = ItemSpriteSheet.FOURCLOVER; + unique = true; + + } + + @Override + protected MiscBuff buff() { + return new FourCloverBless(); + } + + public class FourCloverBless extends MiscBuff { + } + + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + + @Override + public int price() { + return 500 * quantity; + } + +} diff --git a/java/com/hmdzl/spspd/items/misc/GnollMark.java b/java/com/hmdzl/spspd/items/misc/GnollMark.java new file mode 100644 index 00000000..cbf64d86 --- /dev/null +++ b/java/com/hmdzl/spspd/items/misc/GnollMark.java @@ -0,0 +1,169 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Yet Another Pixel Dungeon + * Copyright (C) 2015-2016 Considered Hamster + * + * 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 + */ +package com.hmdzl.spspd.items.misc; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.actors.buffs.Arcane; +import com.hmdzl.spspd.actors.buffs.AttackUp; +import com.hmdzl.spspd.actors.buffs.BerryRegeneration; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.DefenceUp; +import com.hmdzl.spspd.actors.buffs.Disarm; +import com.hmdzl.spspd.actors.buffs.HighLight; +import com.hmdzl.spspd.actors.buffs.Locked; +import com.hmdzl.spspd.actors.buffs.Recharging; +import com.hmdzl.spspd.actors.buffs.Rhythm; +import com.hmdzl.spspd.actors.buffs.ShieldArmor; +import com.hmdzl.spspd.actors.buffs.Silent; +import com.hmdzl.spspd.actors.buffs.Weakness; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.particles.ElmoParticle; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.windows.WndItem; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Bundle; + +import java.util.ArrayList; + +public class GnollMark extends Item { + + public static final String AC_LIGHT = "LIGHT"; + public static final String AC_DARK = "DARK"; + public static final String AC_EARTH = "EARTH"; + private static final String AC_CHOOSE = "CHOOSE"; + private static final float TIME_TO_DIG = 1f; + + { + image = ItemSpriteSheet.GNOLL_MARK; + defaultAction = AC_CHOOSE; + + unique = true; + + } + + public final int fullCharge = 40; + public int charge = 0; + private static final String CHARGE = "charge"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(CHARGE, charge); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + charge = bundle.getInt(CHARGE); + } + + @Override + public ArrayList actions(Hero hero ) { + ArrayList actions = super.actions( hero ); + if (charge >= 20) { + actions.add(AC_LIGHT); + actions.add(AC_DARK); + actions.add(AC_EARTH); + } + actions.remove( AC_THROW ); + actions.remove( AC_DROP ); + return actions; + } + + @Override + public void execute( final Hero hero, String action ) { + if (action.equals( AC_CHOOSE )) { + + GameScene.show(new WndItem(null, this, true)); + + } else if( action.equals( AC_LIGHT ) ) { + curUser = hero; + Buff.affect(hero, HighLight.class, 40f); + Buff.affect(hero, AttackUp.class, 40f).level(80); + Buff.affect(hero, DefenceUp.class, 40f).level(80); + Buff.affect(hero, Silent.class, 40f); + Buff.affect(hero, Locked.class, 40f); + hero.sprite.emitter().burst(ElmoParticle.FACTORY, 12); + Sample.INSTANCE.play(Assets.SND_BURNING); + hero.spendAndNext(1f); + updateQuickslot(); + charge-=20; + + } else if( action.equals( AC_DARK ) ) { + curUser = hero; + Buff.affect(hero, Recharging.class, 40f); + Buff.affect(hero, Arcane.class, 40f); + Buff.affect(hero, Weakness.class, 40f); + Buff.affect(hero, Disarm.class, 40f); + + hero.sprite.emitter().burst(ElmoParticle.FACTORY, 12); + Sample.INSTANCE.play(Assets.SND_BURNING); + hero.spendAndNext(1f); + updateQuickslot(); + charge-=20; + + } else if (action.equals( AC_EARTH )){ + curUser = hero; + + curUser.HP += curUser.HT/5; + Buff.affect(hero, ShieldArmor.class).level(hero.HT/5); + Buff.affect(hero, BerryRegeneration.class).level(hero.HT / 5); + Buff.affect(hero, Rhythm.class, 40f); + + + hero.sprite.emitter().burst(ElmoParticle.FACTORY, 12); + Sample.INSTANCE.play(Assets.SND_BURNING); + hero.spendAndNext(1f); + updateQuickslot(); + charge-=20; + + } else super.execute(hero, action); + + + } + + @Override + public String status() { + return Messages.format("%d", (int)charge/25); + } + + @Override + public String info() { + String info = desc(); + info += "\n\n" + Messages.get(this, "charge",charge,fullCharge); + return info; + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + +} diff --git a/java/com/hmdzl/spspd/items/misc/GunOfSoldier.java b/java/com/hmdzl/spspd/items/misc/GunOfSoldier.java new file mode 100644 index 00000000..34c5ce9d --- /dev/null +++ b/java/com/hmdzl/spspd/items/misc/GunOfSoldier.java @@ -0,0 +1,175 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Yet Another Pixel Dungeon + * Copyright (C) 2015-2016 Considered Hamster + * + * 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 + */ +package com.hmdzl.spspd.items.misc; + +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.Splash; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.weapon.missiles.MissileWeapon; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.CellSelector; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Bundle; + +import java.util.ArrayList; + +public class GunOfSoldier extends Item { + + public static final String AC_USE = "USE"; + + private static final float TIME_TO_DIG = 1f; + + { + image = ItemSpriteSheet.GUN_S; + defaultAction = AC_USE; + unique = true; + usesTargeting = true; + } + + public final int fullCharge = 225; + public int charge = 0; + private static final String CHARGE = "charge"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(CHARGE, charge); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + charge = bundle.getInt(CHARGE); + } + + @Override + public ArrayList actions(Hero hero ) { + ArrayList actions = super.actions( hero ); + if (charge >= 75){ + actions.add(AC_USE); + } + actions.remove( AC_THROW ); + actions.remove( AC_DROP ); + return actions; + } + + @Override + public void execute( final Hero hero, String action ) { + if( action.equals( AC_USE ) ){ + curUser = hero; + if (charge < 75) { + GLog.i(Messages.get(GunOfSoldier.class, "break")); + } else GameScene.selectCell( shooter ); + } else { + super.execute(hero, action); + + } + } + + @Override + public String status() { + return Messages.format("%d", (int)charge/75); + } + + @Override + public String info() { + String info = desc(); + info += "\n\n" + Messages.get(GunOfSoldier.class, "charge",charge,fullCharge); + return info; + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + private int targetPos; + + public SoldierAmmo Ammo(){ + return new SoldierAmmo(); + } + + public class SoldierAmmo extends MissileWeapon { + + { + image = ItemSpriteSheet.BOLA; + ACU = 1000; + } + + public int damageRoll(Hero owner) { + return 0; + } + + @Override + protected void onThrow( int cell ) { + Char enemy = Actor.findChar( cell ); + if (enemy == null || enemy == curUser) { + parent = null; + Splash.at( cell, 0xCC99FFFF, 1 ); + } else { + if (!curUser.shoot( enemy, this )) { + Splash.at(cell, 0xCC99FFFF, 1); + } + } + } + + @Override + public void proc(Char attacker, Char defender, int damage) { + + if (defender.properties().contains(Char.Property.BOSS) || defender.properties().contains(Char.Property.MINIBOSS)){ + defender.damage(Math.min(defender.HT - defender.HP,defender.HT/6),this); + } else { + defender.damage(Math.min(defender.HT - defender.HP,defender.HT/3),this); + } + super.proc(attacker, defender, damage); + } + + @Override + public void cast(final Hero user, final int dst) { + final int cell = throwPos( user, dst ); + GunOfSoldier.this.targetPos = cell; + charge-=75; + super.cast(user, dst); + } + + } + private CellSelector.Listener shooter = new CellSelector.Listener() { + @Override + public void onSelect( Integer target ) { + if (target != null) { + Ammo().cast(curUser, target); + } + } + @Override + public String prompt() { + return Messages.get(GunOfSoldier.class, "prompt"); + } + }; +} diff --git a/java/com/hmdzl/spspd/items/misc/HealBag.java b/java/com/hmdzl/spspd/items/misc/HealBag.java new file mode 100644 index 00000000..cf985303 --- /dev/null +++ b/java/com/hmdzl/spspd/items/misc/HealBag.java @@ -0,0 +1,151 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.misc; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.ArmorBreak; +import com.hmdzl.spspd.actors.buffs.AttackDown; +import com.hmdzl.spspd.actors.buffs.Bleeding; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Cripple; +import com.hmdzl.spspd.actors.buffs.Poison; +import com.hmdzl.spspd.actors.buffs.Weakness; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.items.Item; + +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public class HealBag extends Item { + + { + //name = "healbag"; + image = ItemSpriteSheet.HEAL_BAG; + unique = true; + defaultAction = AC_HEAL; + } + + public final int fullCharge = 100; + public int charge = 0; + + public static final String AC_HEAL = "HEAL"; + public static final String AC_COOK = "COOK"; + + private static final String CHARGE = "charge"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(CHARGE, charge); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + charge = bundle.getInt(CHARGE); + } + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + actions.remove(AC_DROP); + actions.remove(AC_THROW); + if (charge > 50) { + actions.add(AC_HEAL); + } + if (charge > 75) { + actions.add(AC_COOK); + } + return actions; + } + + @Override + public void execute(Hero hero, String action) { + + curUser = Dungeon.hero; + + if (action.equals(AC_HEAL)) { + if (charge < 50) { + GLog.p(Messages.get(this, "need_charge")); + } else { + for (int n : Level.NEIGHBOURS9) { + int c = curUser.pos + n; + Char mob = Actor.findChar(c); + if (mob != null && mob.HP < mob.HT * 0.75) { + mob.HP += (int) (mob.HT / 2); + } + } + charge -= 50; + + Buff.detach(hero, Poison.class); + Buff.detach(hero, Cripple.class); + Buff.detach(hero, Weakness.class); + Buff.detach(hero, Bleeding.class); + Buff.detach(hero, AttackDown.class); + Buff.detach(hero, ArmorBreak.class); + + hero.spendAndNext(1f); + } + } else if (action.equals(AC_COOK)) { + + if (Random.Int(2) == 0) { + Dungeon.level.drop(Generator.random(Generator.Category.POTION), Dungeon.hero.pos).sprite.drop(Dungeon.hero.pos); + } else if (Random.Int(5) == 0) { + Dungeon.level.drop(Generator.random(Generator.Category.HIGHFOOD), Dungeon.hero.pos).sprite.drop(Dungeon.hero.pos); + } else if (Random.Int(2) == 0) { + Dungeon.level.drop(Generator.random(Generator.Category.MUSHROOM), Dungeon.hero.pos).sprite.drop(Dungeon.hero.pos); + } else { + Dungeon.level.drop(Generator.random(Generator.Category.PILL), Dungeon.hero.pos).sprite.drop(Dungeon.hero.pos); + } + charge -= 75; + hero.spendAndNext(1f); + } else { + super.execute(hero, action); + } + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + @Override + public String desc() { + String info = super.desc(); + info += "\n\n" + Messages.get(AttackShield.class, "charge",charge,fullCharge); + return info; + } + @Override + public String status() { + return Messages.format("%d", (int)charge/40); + } +} diff --git a/java/com/hmdzl/spspd/items/misc/HorseTotem.java b/java/com/hmdzl/spspd/items/misc/HorseTotem.java new file mode 100644 index 00000000..a0ded215 --- /dev/null +++ b/java/com/hmdzl/spspd/items/misc/HorseTotem.java @@ -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 + */ +package com.hmdzl.spspd.items.misc; + +import java.util.ArrayList; + +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class HorseTotem extends MiscEquippable { + + { + image = ItemSpriteSheet.HORSE_TOTEM; + unique = true; + + } + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + actions.remove(AC_DROP); + actions.remove(AC_THROW); + return actions; + } + + @Override + protected MiscBuff buff() { + return new HorseTotemBless(); + } + + public class HorseTotemBless extends MiscBuff { + + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + +} diff --git a/java/com/hmdzl/spspd/items/misc/JumpF.java b/java/com/hmdzl/spspd/items/misc/JumpF.java new file mode 100644 index 00000000..444cd897 --- /dev/null +++ b/java/com/hmdzl/spspd/items/misc/JumpF.java @@ -0,0 +1,177 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.misc; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.Terrain; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.plants.Plant; +import com.hmdzl.spspd.scenes.CellSelector; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Callback; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + + +public class JumpF extends Item { + { + //name = "Jump Shoes"; + image = ItemSpriteSheet.JUMP; + defaultAction = AC_JUMP; + unique = true; + + } + + private static int JUMP_TIME = 1; + private static final String AC_JUMP = "JUMP"; + private static final String TXT_ERROR = "Too far away"; + public final int fullCharge = 25; + public int charge = 0; + private static final String CHARGE = "charge"; + + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(CHARGE, charge); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + charge = bundle.getInt(CHARGE); + } + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + if (charge >= 8){ + actions.add(AC_JUMP); + } + actions.remove(AC_DROP); + actions.remove(AC_THROW); + return actions; + } + + protected CellSelector.Listener jumper = new CellSelector.Listener() { + + @Override + public void onSelect(Integer target) { + if (target != null && target != curUser.pos) { + Ballistica route = new Ballistica(curUser.pos, target, (Ballistica.STOP_TARGET | Ballistica.STOP_TERRAIN)); + int cell = route.collisionPos; + int dist = Level.distance(curUser.pos, cell); + int range = 3; + //if (Actor.findChar( cell ) != null && cell != curUser.pos) + //cell = route.path.get(route.dist-1); + + if (dist > 3) { + range = dist - 3; + cell = route.path.get(route.dist - range); + } + + final int dest = cell; + curUser.busy(); + curUser.sprite.jump(curUser.pos, cell, new Callback() { + @Override + public void call() { + if (Dungeon.level.map[curUser.pos] != Terrain.ENTRANCE && + Dungeon.level.map[curUser.pos] != Terrain.EXIT + && Level.insideMap(curUser.pos)) { + Level.set(curUser.pos, Terrain.HIGH_GRASS); + GameScene.updateMap(curUser.pos); + } + curUser.move(dest); + //Dungeon.level.press(dest, curUser); + //Dungeon.observe(); + + //for (int i = 0; i < Level.NEIGHBOURS8.length; i++) { + //Char mob = Actor.findChar(curUser.pos + //+ Level.NEIGHBOURS8[i]); + //} + + //CellEmitter.center(dest).burst( + //Speck.factory(Speck.DUST), 10); + curUser.spendAndNext(JUMP_TIME); + + if (Random.Int(10) > 8 ){ + Plant.Seed seed = (Plant.Seed) Generator.random(Generator.Category.SEED3); + Dungeon.level.plant(seed, dest); + } + charge -= 8; + Dungeon.observe(); + updateQuickslot(); + } + }); + } + } + + + public String prompt() { + return Messages.get(Jumpshoes.class, "prompt"); + } + }; + + @Override + public void execute(final Hero hero, String action) { + if (action.equals(AC_JUMP)) { + if (charge < 8) + GLog.i(Messages.get(Jumpshoes.class, "rest")); + else { + curUser = hero; + GameScene.selectCell(jumper); + } + } else { + + super.execute(hero, action); + } + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + + @Override + public String info() { + String info = desc(); + info += "\n\n" + Messages.get(Jumpshoes.class, "charge",charge,fullCharge); + return info; + } + + @Override + public String status() { + return Messages.format("%d", (int)charge/8); + } + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/misc/JumpH.java b/java/com/hmdzl/spspd/items/misc/JumpH.java new file mode 100644 index 00000000..a41da25e --- /dev/null +++ b/java/com/hmdzl/spspd/items/misc/JumpH.java @@ -0,0 +1,196 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.misc; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.weapon.missiles.EscapeKnive; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.scenes.CellSelector; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Callback; +import com.watabou.utils.Bundle; +import java.util.HashMap; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.sprites.MissileSprite; +import com.watabou.utils.Random; + + + + public class JumpH extends Item { + { + //name = "Jump Shoes"; + image = ItemSpriteSheet.JUMP; + defaultAction = AC_JUMP; +unique = true; + + } + + private static int JUMP_TIME = 1; + private static final String AC_JUMP = "JUMP"; + public final int fullCharge = 50; + public int charge = 0; + private static final String CHARGE = "charge"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(CHARGE, charge); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + charge = bundle.getInt(CHARGE); + } + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + if (charge >= 15){ + actions.add(AC_JUMP); + } + actions.remove(AC_DROP); + actions.remove(AC_THROW); + return actions; + } + + protected CellSelector.Listener jumper = new CellSelector.Listener() { + + private HashMap targets = new HashMap(); + + @Override + public void onSelect(Integer target) { + if (target != null && target != curUser.pos) { + + Ballistica route = new Ballistica(curUser.pos, target, Ballistica.PROJECTILE); + int cell = route.collisionPos; + int dist = Level.distance(curUser.pos, cell); + int range = 3; + if (Actor.findChar( cell ) != null && cell != curUser.pos) + cell = route.path.get(route.dist-1); + + if (dist > 3) { + range = dist - 3; + cell = route.path.get(route.dist - range); + } + + final int dest = cell; + curUser.busy(); + curUser.sprite.jump(curUser.pos, cell, new Callback() { + @Override + public void call() { + curUser.move(dest); + Dungeon.level.press(dest, curUser); + Dungeon.observe(); + + //for (int i = 0; i < Level.NEIGHBOURS8.length; i++) { + //Char mob = Actor.findChar(curUser.pos + //+ Level.NEIGHBOURS8[i]); + //} + if (Random.Int(10) > 3 ){ + Item proto = new EscapeKnive(); + + for (Mob mob : Dungeon.level.mobs) { + if (Level.fieldOfView[mob.pos] && (Dungeon.level.distance(curUser.pos, mob.pos) <= 7) && mob.isAlive()) { + Callback callback = new Callback() { + @Override + public void call() { + curUser.attack(targets.get(this)); + targets.remove(this); + if (targets.isEmpty()) { + //curUser.spendAndNext(curUser.attackDelay()); + curUser.spendAndNext(0.1f); + } + } + }; + + ((MissileSprite) curUser.sprite.parent.recycle(MissileSprite.class)).reset(curUser.pos, mob.pos, proto, callback); + + targets.put(callback, mob); + } + } + } + CellEmitter.center(dest).burst( + Speck.factory(Speck.DUST), 10); + curUser.spendAndNext(JUMP_TIME); + charge -= 15; + updateQuickslot(); + + } + + + }); + } + } + + + public String prompt() { + return Messages.get(Jumpshoes.class, "prompt"); + } + }; + + @Override + public void execute(final Hero hero, String action) { + if (action.equals(AC_JUMP)) { + if (charge < 15) + GLog.i(Messages.get(Jumpshoes.class, "rest")); + else { + curUser = hero; + GameScene.selectCell(jumper); + } + } else { + + super.execute(hero, action); + } + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + + @Override + public String info() { + String info = desc(); + info += "\n\n" + Messages.get(Jumpshoes.class, "charge",charge,fullCharge); + return info; + } + + @Override + public String status() { + return Messages.format("%d", (int)charge/15); + } + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/misc/JumpM.java b/java/com/hmdzl/spspd/items/misc/JumpM.java new file mode 100644 index 00000000..f99f5fbb --- /dev/null +++ b/java/com/hmdzl/spspd/items/misc/JumpM.java @@ -0,0 +1,175 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.misc; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.buffs.Arcane; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.scrolls.ScrollOfTeleportation; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.scenes.CellSelector; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + + +public class JumpM extends Item { + { + //name = "Jump Shoes"; + image = ItemSpriteSheet.JUMP; + defaultAction = AC_JUMP; + unique = true; + + } + + private static int JUMP_TIME = 1; + private static final String AC_JUMP = "JUMP"; + private static final String TXT_ERROR = "Too far away"; + public final int fullCharge = 50; + public int charge = 0; + private static final String CHARGE = "charge"; + + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(CHARGE, charge); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + charge = bundle.getInt(CHARGE); + } + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + if (charge >= 15){ + actions.add(AC_JUMP); + } + actions.remove(AC_DROP); + actions.remove(AC_THROW); + return actions; + } + + protected CellSelector.Listener jumper = new CellSelector.Listener() { + + @Override + public void onSelect(Integer target) { + if (target != null && target != curUser.pos) { + Ballistica route = new Ballistica(curUser.pos, target, (Ballistica.STOP_TARGET | Ballistica.STOP_TERRAIN)); + int cell = route.collisionPos; + int dist = Level.distance(curUser.pos, cell); + int range = 3; + //if (Actor.findChar( cell ) != null && cell != curUser.pos) + //cell = route.path.get(route.dist-1); + + if (dist > 3) { + range = dist - 3; + cell = route.path.get(route.dist - range); + } + + final int dest = cell; + ScrollOfTeleportation.appear( curUser, dest ); + CellEmitter.get(dest).burst(Speck.factory(Speck.WOOL), 10); + Sample.INSTANCE.play(Assets.SND_PUFF); + Dungeon.level.press( dest, curUser ); + Dungeon.observe(); + curUser.spendAndNext(JUMP_TIME); + if (Random.Int(10) > 3 ){ + Buff.affect(curUser, Arcane.class, 10f);} + charge -= 15; + updateQuickslot(); + + /*curUser.busy(); + curUser.sprite.jump(curUser.pos, cell, new Callback() { + @Override + public void call() { + curUser.move(dest); + Dungeon.level.press(dest, curUser); + Dungeon.observe(); + CellEmitter.center(dest).burst( + Speck.factory(Speck.DUST), 10); + curUser.spendAndNext(JUMP_TIME); + if (Random.Int(10) > 3 ){ + Buff.affect(curUser, Recharging.class, 4f);} + charge -= 15; + updateQuickslot(); + } + });*/ + } + } + + + public String prompt() { + return Messages.get(Jumpshoes.class, "prompt"); + } + }; + + @Override + public void execute(final Hero hero, String action) { + if (action.equals(AC_JUMP)) { + if (charge < 15) + GLog.i(Messages.get(Jumpshoes.class, "rest")); + else { + curUser = hero; + GameScene.selectCell(jumper); + } + } else { + + super.execute(hero, action); + } + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + + @Override + public String info() { + String info = desc(); + info += "\n\n" + Messages.get(Jumpshoes.class, "charge",charge,fullCharge); + return info; + } + + @Override + public String status() { + return Messages.format("%d", (int)charge/15); + } + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/misc/JumpP.java b/java/com/hmdzl/spspd/items/misc/JumpP.java new file mode 100644 index 00000000..b79a4d34 --- /dev/null +++ b/java/com/hmdzl/spspd/items/misc/JumpP.java @@ -0,0 +1,171 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.misc; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.buffs.GlassShield; +import com.hmdzl.spspd.actors.buffs.Rhythm; +import com.hmdzl.spspd.actors.buffs.Rhythm2; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.hero.HeroSubClass; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.scenes.CellSelector; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Callback; +import com.watabou.utils.Bundle; + +import static com.hmdzl.spspd.Dungeon.hero; + + +public class JumpP extends Item { + { + //name = "Jump Shoes"; + image = ItemSpriteSheet.JUMP; + defaultAction = AC_JUMP; + unique = true; + + } + + private static int JUMP_TIME = 1; + private static final String AC_JUMP = "JUMP"; + public final int fullCharge = 20; + public int charge = 0; + private static final String CHARGE = "charge"; + + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(CHARGE, charge); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + charge = bundle.getInt(CHARGE); + } + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + if (charge >= 10){ + actions.add(AC_JUMP); + } + actions.remove(AC_DROP); + actions.remove(AC_THROW); + return actions; + } + + protected CellSelector.Listener jumper = new CellSelector.Listener() { + @Override + public void onSelect(Integer target) { + if (target != null && target != curUser.pos) { + + Ballistica route = new Ballistica(curUser.pos, target, Ballistica.PROJECTILE); + int cell = route.collisionPos; + int dist = Level.distance(curUser.pos, cell); + int range = 3; + if (Actor.findChar( cell ) != null && cell != curUser.pos) + cell = route.path.get(route.dist-1); + + if (dist > 3) { + range = dist - 3; + cell = route.path.get(route.dist - range); + } + + final int dest = cell; + curUser.busy(); + curUser.sprite.jump(curUser.pos, cell, new Callback() { + @Override + public void call() { + curUser.move(dest); + Dungeon.level.press(dest, curUser); + Dungeon.observe(); + + //CellEmitter.center(dest).burst( + //Speck.factory(Speck.DUST), 10); + curUser.spendAndNext(JUMP_TIME); + Buff.affect(curUser, GlassShield.class).turns(1); + Buff.affect(curUser, Rhythm.class,5f); + if(hero.subClass == HeroSubClass.SUPERSTAR){ + //Buff.affect(curUser,Rhythm.class,50); + Buff.affect(curUser,Rhythm2.class,5); + } + //Buff.affect(curUser, Rhythm2.class,10f); + charge -= 10; + updateQuickslot(); + } + }); + + + } + } + + public String prompt() { + return Messages.get(Jumpshoes.class, "prompt"); + } + }; + + @Override + public void execute(final Hero hero, String action) { + if (action.equals(AC_JUMP)) { + if (charge < 10) + GLog.i(Messages.get(Jumpshoes.class, "rest")); + else { + curUser = hero; + GameScene.selectCell(jumper); + } + } else { + + super.execute(hero, action); + } + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + + @Override + public String info() { + String info = desc(); + info += "\n\n" + Messages.get(Jumpshoes.class, "charge",charge,fullCharge); + return info; + } + + @Override + public String status() { + return Messages.format("%d", (int)charge/10); + } + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/misc/JumpR.java b/java/com/hmdzl/spspd/items/misc/JumpR.java new file mode 100644 index 00000000..96662326 --- /dev/null +++ b/java/com/hmdzl/spspd/items/misc/JumpR.java @@ -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 + */ +package com.hmdzl.spspd.items.misc; + +import java.util.ArrayList; + +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Levitation; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Invisibility; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.scenes.CellSelector; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Callback; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + + +public class JumpR extends Item { + { + //name = "Jump Shoes"; + image = ItemSpriteSheet.JUMP; + defaultAction = AC_JUMP; + unique = true; + + } + + private static int JUMP_TIME = 1; + private static final String AC_JUMP = "JUMP"; + public final int fullCharge = 40; + public int charge = 0; + private static final String CHARGE = "charge"; + + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(CHARGE, charge); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + charge = bundle.getInt(CHARGE); + } + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + if (charge >= 10){ + actions.add(AC_JUMP); + } + actions.remove(AC_DROP); + actions.remove(AC_THROW); + return actions; + } + + protected CellSelector.Listener jumper = new CellSelector.Listener() { + + @Override + public void onSelect(Integer target) { + if (target != null && target != curUser.pos) { + + Ballistica route = new Ballistica(curUser.pos, target,Ballistica.PROJECTILE); + int cell = route.collisionPos; + int dist = Level.distance(curUser.pos, cell); + int range = 2; + if (Actor.findChar( cell ) != null && cell != curUser.pos) + cell = route.path.get(route.dist-1); + + if (dist > 2) { + range = dist - 2; + cell = route.path.get(route.dist - range); + } + + final int dest = cell; + Buff.prolong(curUser, Levitation.class,2f); + curUser.busy(); + curUser.sprite.jump(curUser.pos, cell, new Callback() { + @Override + public void call() { + curUser.move(dest); + //Dungeon.level.press(dest, curUser); + //Dungeon.observe(); + + for (int i = 0; i < Level.NEIGHBOURS8.length; i++) { + Char mob = Actor.findChar(curUser.pos + + Level.NEIGHBOURS8[i]); + } + + //CellEmitter.center(dest).burst( + //Speck.factory(Speck.DUST), 10); + curUser.spendAndNext(JUMP_TIME); + if (Random.Int(10) > 3 ){ + Buff.prolong(curUser, Invisibility.class,5);} + charge -= 10; + updateQuickslot(); + } + }); + } + } + + + public String prompt() { + return Messages.get(Jumpshoes.class, "prompt"); + } + }; + + @Override + public void execute(final Hero hero, String action) { + if (action.equals(AC_JUMP)) { + if (charge < 10) + GLog.i(Messages.get(Jumpshoes.class, "rest")); + else { + curUser = hero; + GameScene.selectCell(jumper); + } + } else { + + super.execute(hero, action); + } + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + + @Override + public String info() { + String info = desc(); + info += "\n\n" + Messages.get(Jumpshoes.class, "charge",charge,fullCharge); + return info; + } + + @Override + public String status() { + return Messages.format("%d", (int)charge/10); + } + + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/misc/JumpS.java b/java/com/hmdzl/spspd/items/misc/JumpS.java new file mode 100644 index 00000000..43ff8e75 --- /dev/null +++ b/java/com/hmdzl/spspd/items/misc/JumpS.java @@ -0,0 +1,169 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.misc; + +import java.util.ArrayList; + +import com.hmdzl.spspd.actors.buffs.TargetShoot; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.scenes.CellSelector; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Callback; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + + +public class JumpS extends Item { + { + //name = "Jump Shoes"; + image = ItemSpriteSheet.JUMP; + defaultAction = AC_JUMP; + unique = true; + + } + + private static int JUMP_TIME = 1; + private static final String AC_JUMP = "JUMP"; + private static final String TXT_ERROR = "Too far away"; + public final int fullCharge = 30; + public int charge = 0; + private static final String CHARGE = "charge"; + + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(CHARGE, charge); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + charge = bundle.getInt(CHARGE); + } + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + if (charge >= 15){ + actions.add(AC_JUMP); + } + actions.remove(AC_DROP); + actions.remove(AC_THROW); + return actions; + } + + protected CellSelector.Listener jumper = new CellSelector.Listener() { + + @Override + public void onSelect(Integer target) { + if (target != null && target != curUser.pos) { + Ballistica route = new Ballistica(curUser.pos, target, (Ballistica.STOP_TARGET | Ballistica.STOP_TERRAIN)); + int cell = route.collisionPos; + int dist = Level.distance(curUser.pos, cell); + int range = 3; + //if (Actor.findChar( cell ) != null && cell != curUser.pos) + //cell = route.path.get(route.dist-1); + + if (dist > 3) { + range = dist - 3; + cell = route.path.get(route.dist - range); + } + + final int dest = cell; + curUser.belongings.relord(); + curUser.busy(); + curUser.sprite.jump(curUser.pos, cell, new Callback() { + @Override + public void call() { + curUser.move(dest); + //Dungeon.level.press(dest, curUser); + //Dungeon.observe(); + + //for (int i = 0; i < Level.NEIGHBOURS8.length; i++) { + //Char mob = Actor.findChar(curUser.pos + //+ Level.NEIGHBOURS8[i]); + //} + + //CellEmitter.center(dest).burst( + //Speck.factory(Speck.DUST), 10); + curUser.spendAndNext(JUMP_TIME); + + if (Random.Int(10) > 3 ){ + curUser.belongings.relord(); + Buff.affect(curUser, TargetShoot.class, 10f); + } + charge -= 10; + updateQuickslot(); + } + }); + } + } + + + public String prompt() { + return Messages.get(Jumpshoes.class, "prompt"); + } + }; + + @Override + public void execute(final Hero hero, String action) { + if (action.equals(AC_JUMP)) { + if (charge < 10) + GLog.i(Messages.get(Jumpshoes.class, "rest")); + else { + curUser = hero; + GameScene.selectCell(jumper); + } + } else { + + super.execute(hero, action); + } + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + + @Override + public String info() { + String info = desc(); + info += "\n\n" + Messages.get(Jumpshoes.class, "charge",charge,fullCharge); + return info; + } + + @Override + public String status() { + return Messages.format("%d", (int)charge/10); + } + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/misc/JumpW.java b/java/com/hmdzl/spspd/items/misc/JumpW.java new file mode 100644 index 00000000..eca3ae12 --- /dev/null +++ b/java/com/hmdzl/spspd/items/misc/JumpW.java @@ -0,0 +1,172 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.misc; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Paralysis; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.scenes.CellSelector; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Callback; +import com.watabou.utils.Random; +import com.watabou.utils.Bundle; + + + public class JumpW extends Item { + { + //name = "Jump Shoes"; + image = ItemSpriteSheet.JUMP; + defaultAction = AC_JUMP; + unique = true; + + } + + private static int JUMP_TIME = 1; + private static final String AC_JUMP = "JUMP"; + public final int fullCharge = 55; + public int charge = 0; + private static final String CHARGE = "charge"; + + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(CHARGE, charge); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + charge = bundle.getInt(CHARGE); + } + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + if (charge >= 25){ + actions.add(AC_JUMP); + } + actions.remove(AC_DROP); + actions.remove(AC_THROW); + return actions; + } + + protected CellSelector.Listener jumper = new CellSelector.Listener() { + @Override + public void onSelect(Integer target) { + if (target != null && target != curUser.pos) { + + Ballistica route = new Ballistica(curUser.pos, target, Ballistica.PROJECTILE); + int cell = route.collisionPos; + int dist = Level.distance(curUser.pos, cell); + int range = 5; + if (Actor.findChar( cell ) != null && cell != curUser.pos) + cell = route.path.get(route.dist-1); + + if (dist > 5) { + range = dist - 5; + cell = route.path.get(route.dist - range); + } + + final int dest = cell; + curUser.busy(); + curUser.sprite.jump(curUser.pos, cell, new Callback() { + @Override + public void call() { + curUser.move(dest); + Dungeon.level.press(dest, curUser); + Dungeon.observe(); + + for (int i = 0; i < Level.NEIGHBOURS8.length; i++) { + Char mob = Actor.findChar(curUser.pos + + Level.NEIGHBOURS8[i]); + if (mob != null && mob != curUser && Random.Int(10)>2 ) { + Buff.prolong(mob, Paralysis.class, 3); + } + } + + CellEmitter.center(dest).burst( + Speck.factory(Speck.DUST), 10); + curUser.spendAndNext(JUMP_TIME); + //Buff.affect(curUser, AttackUp.class, 10f).level(50); + charge -= 25; + updateQuickslot(); + } + }); + + + } + } + + public String prompt() { + return Messages.get(Jumpshoes.class, "prompt"); + } + }; + + @Override + public void execute(final Hero hero, String action) { + if (action.equals(AC_JUMP)) { + if (charge < 25) + GLog.i(Messages.get(Jumpshoes.class, "rest")); + else { + curUser = hero; + GameScene.selectCell(jumper); + } + } else { + + super.execute(hero, action); + } + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + + @Override + public String info() { + String info = desc(); + info += "\n\n" + Messages.get(Jumpshoes.class, "charge",charge,fullCharge); + return info; + } + + @Override + public String status() { + return Messages.format("%d", (int)charge/25); + } + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/misc/Jumpshoes.java b/java/com/hmdzl/spspd/items/misc/Jumpshoes.java new file mode 100644 index 00000000..af4db847 --- /dev/null +++ b/java/com/hmdzl/spspd/items/misc/Jumpshoes.java @@ -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 + */ +package com.hmdzl.spspd.items.misc; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.scenes.CellSelector; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Callback; +import com.watabou.utils.Bundle; + + + public class Jumpshoes extends Item { + { + //name = "Jump Shoes"; + image = ItemSpriteSheet.JUMP; + defaultAction = AC_JUMP; + unique = true; + + } + + private static int JUMP_TIME = 1; + private static final String AC_JUMP = "JUMP"; + public final int fullCharge = 50; + public int charge = 0; + private static final String CHARGE = "charge"; + + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(CHARGE, charge); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + charge = bundle.getInt(CHARGE); + } + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + if (charge >= 10){ + actions.add(AC_JUMP); + } + actions.remove(AC_DROP); + actions.remove(AC_THROW); + return actions; + } + + protected CellSelector.Listener jumper = new CellSelector.Listener() { + + @Override + public void onSelect(Integer target) { + if (target != null && target != curUser.pos) { + + Ballistica route = new Ballistica(curUser.pos, target, Ballistica.PROJECTILE); + int cell = route.collisionPos; + int dist = Level.distance(curUser.pos, cell); + int range = 3; + if (Actor.findChar( cell ) != null && cell != curUser.pos) + cell = route.path.get(route.dist-1); + + if (dist > 3) { + range = dist - 3; + cell = route.path.get(route.dist - range); + } + + final int dest = cell; + + if (Ballistica.distance > 4){ + GLog.w(Messages.get(Jumpshoes.class, "error")); + return; + } else { + curUser.busy(); + curUser.sprite.jump(curUser.pos, cell, new Callback() { + @Override + public void call() { + curUser.move(dest); + Dungeon.level.press(dest, curUser); + Dungeon.observe(); + + for (int i = 0; i < Level.NEIGHBOURS8.length; i++) { + Char mob = Actor.findChar(curUser.pos + + Level.NEIGHBOURS8[i]); + } + + CellEmitter.center(dest).burst( + Speck.factory(Speck.DUST), 10); + curUser.spendAndNext(JUMP_TIME); + charge -= 10; + updateQuickslot(); + } + }); + } + } + } + + public String prompt() { + return Messages.get(Jumpshoes.class, "prompt"); + } + }; + + @Override + public void execute(final Hero hero, String action) { + if (action.equals(AC_JUMP)) { + if (charge < 10) + GLog.i(Messages.get(this, "rest")); + else { + curUser = hero; + GameScene.selectCell(jumper); + } + } else { + + super.execute(hero, action); + } + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + + @Override + public String info() { + String info = desc(); + info += "\n\n" + Messages.get(this, "charge",charge,fullCharge); + return info; + } + + @Override + public String status() { + return Messages.format("%d", (int)charge/10); + } + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/misc/LuckyBadge.java b/java/com/hmdzl/spspd/items/misc/LuckyBadge.java new file mode 100644 index 00000000..3598a669 --- /dev/null +++ b/java/com/hmdzl/spspd/items/misc/LuckyBadge.java @@ -0,0 +1,49 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.misc; + +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class LuckyBadge extends MiscEquippable { + + { + //name = "LuckyBadge"; + image = ItemSpriteSheet.LUCKY_BADGE; + + unique = true; + + } + + @Override + protected MiscBuff buff() { + return new GreatLucky(); + } + + public class GreatLucky extends MiscBuff { + } + + @Override + public boolean isIdentified() { + return true; + } + + @Override + public boolean isUpgradable() { + return true; + } +} diff --git a/java/com/hmdzl/spspd/items/misc/MKbox.java b/java/com/hmdzl/spspd/items/misc/MKbox.java new file mode 100644 index 00000000..35b3006c --- /dev/null +++ b/java/com/hmdzl/spspd/items/misc/MKbox.java @@ -0,0 +1,112 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.misc; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.buffs.BoxStar; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.FireImbue; +import com.hmdzl.spspd.actors.buffs.FrostImbue; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.items.Ankh; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.items.Item; + +import com.hmdzl.spspd.items.weapon.melee.zero.WoodenHammer; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Random; + +public class MKbox extends Item { + + public static final String AC_USE = "USE"; + + public static final float TIME_TO_USE = 1; + + { + //name = "MKbox"; + image = ItemSpriteSheet.MK_BOX; + defaultAction = AC_USE; + unique = true; + stackable = false; + } + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + actions.add(AC_USE); + return actions; + } + + @Override + public void execute(Hero hero, String action) { + + if (action.equals(AC_USE)) { + if (Dungeon.gold < 100){ + GLog.p(Messages.get(MKbox.class, "need_gold")); + } else { + Dungeon.gold -= 100; + hero.spend(TIME_TO_USE); + hero.busy(); + + hero.sprite.operate(hero.pos); + if (Random.Int(50) == 0) { + Buff.affect(hero,BoxStar.class,30f); + GLog.p(Messages.get(MKbox.class, "star")); + } else if (Random.Int(49) == 0) { + Dungeon.gold += 500; + GLog.p(Messages.get(MKbox.class, "coin")); + //GLog.p(Messages.get(MKbox.class,"mbox")); + } else if (Random.Int(48) < 3) { + Dungeon.level.drop(new Ankh(), Dungeon.hero.pos).sprite.drop(Dungeon.hero.pos); + GLog.p(Messages.get(MKbox.class, "1up")); + } else if (Random.Int(45) < 20) { + WoodenHammer wh = new WoodenHammer(); + Dungeon.level.drop(wh, Dungeon.hero.pos).sprite.drop(Dungeon.hero.pos); + GLog.p(Messages.get(MKbox.class, "hammer")); + } else if (Random.Int(25) < 20) { + Dungeon.level.drop(Generator.random(Generator.Category.MUSHROOM), Dungeon.hero.pos).sprite.drop(Dungeon.hero.pos); + GLog.p(Messages.get(MKbox.class, "mushroom")); + } else if (Random.Int(2) == 1) { + Buff.affect(hero,FireImbue.class).set(FireImbue.DURATION); + GLog.p(Messages.get(MKbox.class, "flowerf")); + } else { + Buff.affect(hero, FrostImbue.class, FrostImbue.DURATION); + GLog.p(Messages.get(MKbox.class, "floweri")); + } + } + } else { + super.execute(hero, action); + + } + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + +} diff --git a/java/com/hmdzl/spspd/items/misc/MechPocket.java b/java/com/hmdzl/spspd/items/misc/MechPocket.java new file mode 100644 index 00000000..13e309ec --- /dev/null +++ b/java/com/hmdzl/spspd/items/misc/MechPocket.java @@ -0,0 +1,81 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.misc; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.particles.ElmoParticle; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.items.Item; + +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.noosa.audio.Sample; + +public class MechPocket extends Item { + + public static final String AC_USE = "USE"; + + public static final float TIME_TO_USE = 1; + + { + //name = "MechPocket"; + image = ItemSpriteSheet.MECH_POCKET; + defaultAction = AC_USE; + unique = true; + stackable = false; + } + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + actions.add(AC_USE); + return actions; + } + + @Override + public void execute(Hero hero, String action) { + + if (action.equals(AC_USE)) { + curUser = hero; + Sample.INSTANCE.play(Assets.SND_BURNING); + curUser.sprite.emitter().burst(ElmoParticle.FACTORY, 12); + curUser.spendAndNext(1f); + for(int i=0; i<20; i++) { + Dungeon.level.drop(Generator.random(), hero.pos).sprite.drop(); + } + detach(curUser.belongings.backpack); + } else { + super.execute(hero, action); + + } + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + +} diff --git a/java/com/hmdzl/spspd/items/misc/MiscEquippable.java b/java/com/hmdzl/spspd/items/misc/MiscEquippable.java new file mode 100644 index 00000000..a8e01549 --- /dev/null +++ b/java/com/hmdzl/spspd/items/misc/MiscEquippable.java @@ -0,0 +1,210 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.misc; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.KindofMisc; +import com.hmdzl.spspd.items.artifacts.Artifact; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.utils.GLog; + +public class MiscEquippable extends KindofMisc { + + + private static final float TIME_TO_EQUIP = 1f; + private static final String TXT_TO_STRING = "%s"; + private static final String TXT_TO_STRING_LVL = "%s%+d"; + protected Buff buff; + + public MiscEquippable() { + super(); + } + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + actions.add(isEquipped(hero) ? AC_UNEQUIP : AC_EQUIP); + return actions; + } + + @Override + public boolean doEquip(Hero hero) { + + if (hero.belongings.misc1 != null && hero.belongings.misc2 != null && hero.belongings.misc3 != null) { + + GLog.w(Messages.get(Artifact.class, "onlythree")); + return false; + + } else { + + if (hero.belongings.misc1 == null) { + hero.belongings.misc1 = this; + } else if (hero.belongings.misc2 == null){ + hero.belongings.misc2 = this; + } else { + hero.belongings.misc3 = this; + } + + detach(hero.belongings.backpack); + + activate(hero); + + cursedKnown = true; + if (cursed) { + equipCursed(hero); + GLog.n(Messages.get(Artifact.class, "cursed_worn")); + } + + hero.spendAndNext(TIME_TO_EQUIP); + return true; + + } + + } + + @Override + public void activate(Char ch) { + buff = buff(); + buff.attachTo(ch); + } + + @Override + public boolean doUnequip(Hero hero, boolean collect, boolean single) { + if (super.doUnequip(hero, collect, single)) { + + if (hero.belongings.misc1 == this) { + hero.belongings.misc1 = null; + } else if (hero.belongings.misc2 == this){ + hero.belongings.misc2 = null; + } else { + hero.belongings.misc3 = null; + } + + hero.remove(buff); + buff = null; + + return true; + + } else { + + return false; + + } + } + + @Override + public boolean isEquipped(Hero hero) { + return hero.belongings.misc1 == this || hero.belongings.misc2 == this || hero.belongings.misc3 == this ; + } + + @Override + public boolean isUpgradable() { + return true; + } + + @Override + public Item upgrade() { + + super.upgrade(); + + if (buff != null) { + + Char owner = buff.target; + buff.detach(); + if ((buff = buff()) != null) { + buff.attachTo(owner); + } + } + + return this; + } + + @Override + public int visiblyUpgraded() { + return level; + } + + @Override + public String info() { + if (cursed && cursedKnown && !isEquipped(Dungeon.hero)) { + + return desc() + "\n\n" + Messages.get(Artifact.class, "curse_known"); + + } else { + + return desc(); + } + } + + @Override + public String toString() { + if (levelKnown && level != 0) { + return Messages.format(TXT_TO_STRING_LVL, name(), + visiblyUpgraded()); + } else { + return Messages.format(TXT_TO_STRING, name()); + } + } + + @Override + public String status() { + return null; + } + + + protected MiscBuff buff() { + return null; + } + + public static int getBonus(Char target, Class type){ + int bonus = 0; + for (MiscBuff buff : target.buffs(type)) { + bonus += buff.level; + } + return bonus; + } + + public class MiscBuff extends Buff { + + public int level; + + public MiscBuff() { + level = MiscEquippable.this.level; + } + + @Override + public boolean attachTo(Char target) { + + return super.attachTo(target); + } + + @Override + public boolean act() { + + spend(TICK); + + return true; + } + } +} diff --git a/java/com/hmdzl/spspd/items/misc/MissileShield.java b/java/com/hmdzl/spspd/items/misc/MissileShield.java new file mode 100644 index 00000000..ee8a7c0b --- /dev/null +++ b/java/com/hmdzl/spspd/items/misc/MissileShield.java @@ -0,0 +1,208 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.misc; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.DefenceUp; +import com.hmdzl.spspd.actors.buffs.Paralysis; +import com.hmdzl.spspd.actors.buffs.ShieldArmor; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.Splash; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.weapon.missiles.MissileWeapon; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.CellSelector; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +import java.util.ArrayList; + +public class MissileShield extends Item { + + { + //name = "MissileShield"; + image = ItemSpriteSheet.WARRIORSHIELD; + + stackable = false; + unique = true; + defaultAction = AC_CAST; + } + + private static final String AC_CAST = "CAST"; + private static final String AC_SHIELD = "SHIELD"; + public final int fullCharge = 10; + public int charge = 0; + private static final String CHARGE = "charge"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(CHARGE, charge); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + charge = bundle.getInt(CHARGE); + } + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions( hero ); + if (charge > 9){ + actions.add(AC_CAST); + } + if (charge > 5){ + actions.add(AC_SHIELD); + } + actions.remove( AC_THROW ); + actions.remove( AC_DROP ); + return actions; + } + + @Override + public void execute(final Hero hero, String action) { + super.execute(hero, action); + if (action.equals(AC_CAST)) { + curUser = hero; + if (charge < 10) { + GLog.i(Messages.get(this, "rest")); + } else GameScene.selectCell(shooter); + } else if (action.equals(AC_SHIELD)) { + curUser = hero; + if (charge < 5) { + GLog.i(Messages.get(this, "rest")); + return; + } else { + Buff.prolong(hero, DefenceUp.class, 3f).level(50); + Buff.affect(hero, ShieldArmor.class).level(hero.lvl); + charge -= 5; + } + } + + } + + @Override + public String desc() { + String info = super.desc(); + info += "\n\n" + Messages.get(MissileShield.class, "damage",min(),max()); + info += "\n\n" + Messages.get(MissileShield.class, "charge",charge,fullCharge); + return info; + } + + public int level() { + return Dungeon.hero == null ? 0 : Dungeon.hero.lvl/5; + } + + @Override + public int visiblyUpgraded() { + return level(); + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + public int min() { + return 1 + Dungeon.hero.lvl/5; + } + + public int max() { + return 1 + Dungeon.hero.lvl/2; + } + + public int damageRoll(Hero owner) { + int damage = Random.Int(min(), max()); + return Math.round(damage); + } + + private int targetPos; + + public MissileShieldAmmo Ammo(){ + return new MissileShieldAmmo(); + } + + public class MissileShieldAmmo extends MissileWeapon { + + { + image = ItemSpriteSheet.WARRIORSHIELD; + ACU = 1000; + } + + public int damageRoll(Hero owner) { + return MissileShield.this.damageRoll(owner); + } + + @Override + protected void onThrow( int cell ) { + Char enemy = Actor.findChar( cell ); + if (enemy == null || enemy == curUser) { + parent = null; + Splash.at( cell, 0xCC99FFFF, 1 ); + } else { + if (!curUser.shoot( enemy, this )) { + Splash.at(cell, 0xCC99FFFF, 1); + } + } + } + + @Override + public void proc(Char attacker, Char defender, int damage) { + + if (defender.properties().contains(Char.Property.BOSS) || defender.properties().contains(Char.Property.MINIBOSS)){ + defender.damage(damage,this); + } + Buff.prolong(defender, Paralysis.class, 3); + super.proc(attacker, defender, damage); + } + + @Override + public void cast(final Hero user, final int dst) { + final int cell = throwPos( user, dst ); + MissileShield.this.targetPos = cell; + charge-=10; + super.cast(user, dst); + } + + } + private CellSelector.Listener shooter = new CellSelector.Listener() { + @Override + public void onSelect( Integer target ) { + if (target != null) { + Ammo().cast(curUser, target); + } + } + @Override + public String prompt() { + return Messages.get(MissileShield.class, "prompt"); + } + }; +} + diff --git a/java/com/hmdzl/spspd/items/misc/PotionOfMage.java b/java/com/hmdzl/spspd/items/misc/PotionOfMage.java new file mode 100644 index 00000000..12052139 --- /dev/null +++ b/java/com/hmdzl/spspd/items/misc/PotionOfMage.java @@ -0,0 +1,281 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Yet Another Pixel Dungeon + * Copyright (C) 2015-2016 Considered Hamster + * + * 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 + */ +package com.hmdzl.spspd.items.misc; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.Blob; +import com.hmdzl.spspd.actors.blobs.ConfusionGas; +import com.hmdzl.spspd.actors.blobs.DarkGas; +import com.hmdzl.spspd.actors.blobs.ParalyticGas; +import com.hmdzl.spspd.actors.blobs.StenchGas; +import com.hmdzl.spspd.actors.blobs.TarGas; +import com.hmdzl.spspd.actors.blobs.ToxicGas; +import com.hmdzl.spspd.actors.buffs.Arcane; +import com.hmdzl.spspd.actors.buffs.ArmorBreak; +import com.hmdzl.spspd.actors.buffs.AttackDown; +import com.hmdzl.spspd.actors.buffs.AttackUp; +import com.hmdzl.spspd.actors.buffs.BerryRegeneration; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.DefenceUp; +import com.hmdzl.spspd.actors.buffs.HighLight; +import com.hmdzl.spspd.actors.buffs.Hot; +import com.hmdzl.spspd.actors.buffs.Recharging; +import com.hmdzl.spspd.actors.buffs.Rhythm; +import com.hmdzl.spspd.actors.buffs.Roots; +import com.hmdzl.spspd.actors.buffs.Shocked; +import com.hmdzl.spspd.actors.buffs.Slow; +import com.hmdzl.spspd.actors.buffs.Wet; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.Splash; +import com.hmdzl.spspd.effects.particles.ElmoParticle; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.weapon.missiles.MissileWeapon; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.CellSelector; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +import java.util.ArrayList; + +public class PotionOfMage extends Item { + + public static final String AC_USE = "USE"; + public static final String AC_DRINK = "DRINK"; + public static final String AC_SHATTERED = "SHATTERED"; + private static final float TIME_TO_DIG = 1f; + + { + image = ItemSpriteSheet.POTION_OF_MAGE; + defaultAction = AC_USE; + + unique = true; + + } + + public final int fullCharge = 100; + public int charge = 0; + private static final String CHARGE = "charge"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(CHARGE, charge); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + charge = bundle.getInt(CHARGE); + } + + @Override + public ArrayList actions(Hero hero ) { + ArrayList actions = super.actions( hero ); + if (charge >= 70) { + actions.add(AC_USE); + actions.add(AC_SHATTERED); + } + if (charge >= 50){ + actions.add(AC_DRINK); + } + actions.remove( AC_THROW ); + actions.remove( AC_DROP ); + return actions; + } + + @Override + public void execute( final Hero hero, String action ) { + if( action.equals( AC_USE ) ) { + curUser = hero; + if (charge < 70) { + GLog.i(Messages.get(PotionOfMage.class, "break")); + } else GameScene.selectCell(shooter); + + } else if( action.equals( AC_SHATTERED ) ) { + curUser = hero; + if (charge < 70) { + GLog.i(Messages.get(PotionOfMage.class, "break")); + } else GameScene.selectCell(Shattered); + + } else if (action.equals( AC_DRINK )){ + curUser = hero; + if (charge < 50) { + GLog.i(Messages.get(PotionOfMage.class, "break")); + } else { + switch (Random.Int(7)) { + case 0: + Buff.affect(hero, HighLight.class, 10f); + break; + case 1: + Buff.affect(hero, AttackUp.class, 10f).level(35); + break; + case 2: + Buff.affect(hero, DefenceUp.class, 10f).level(35); + break; + case 3: + Buff.affect(hero, Recharging.class, 10f); + break; + case 4: + Buff.affect(hero, Arcane.class, 10f); + break; + case 5: + Buff.affect(hero, BerryRegeneration.class).level(hero.HP / 2); + break; + case 6: + Buff.affect(hero, Rhythm.class, 10f); + break; + default: + break; + } + hero.sprite.emitter().burst(ElmoParticle.FACTORY, 12); + Sample.INSTANCE.play(Assets.SND_BURNING); + hero.spendAndNext(1f); + updateQuickslot(); + charge-=50; + } + } else super.execute(hero, action); + + + } + + @Override + public String status() { + return Messages.format("%d", (int)charge/70); + } + + @Override + public String info() { + String info = desc(); + info += "\n\n" + Messages.get(PotionOfMage.class, "charge",charge,fullCharge); + return info; + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + private CellSelector.Listener Shattered = new CellSelector.Listener(){ + @Override + public void onSelect(Integer target) { + if (target != null && (Dungeon.level.visited[target] || Dungeon.level.mapped[target])){ + GameScene.add(Blob.seed(target, 15, ToxicGas.class)); + GameScene.add(Blob.seed(target, 15, ConfusionGas.class)); + GameScene.add(Blob.seed(target, 15, ParalyticGas.class)); + GameScene.add(Blob.seed(target, 15, DarkGas.class)); + GameScene.add(Blob.seed(target, 15, TarGas.class)); + GameScene.add(Blob.seed(target, 15, StenchGas.class)); + charge-= 70; + Dungeon.hero.spendAndNext(1f); + updateQuickslot(); + } + } + @Override + public String prompt() { + return Messages.get(PotionOfMage.class, "prompt"); + } + }; + + private int targetPos; + + public MageAmmo Ammo(){ + return new MageAmmo(); + } + + public class MageAmmo extends MissileWeapon { + + { + image = ItemSpriteSheet.POTION_OF_MAGE; + ACU = 1000; + } + + public int damageRoll(Hero owner) { + return 0; + } + + @Override + protected void onThrow( int cell ) { + Char enemy = Actor.findChar( cell ); + if (enemy == curUser || enemy == null) { + parent = null; + Splash.at(cell, 0xCC99FFFF, 1); + //} else if (enemy == null){ + //GameScene.add(Blob.seed(cell, 10, ToxicGas.class)); + //GameScene.add(Blob.seed(cell, 10, ConfusionGas.class)); + //GameScene.add(Blob.seed(cell, 15, ParalyticGas.class)); + //GameScene.add(Blob.seed(cell, 15, DarkGas.class)); + //GameScene.add(Blob.seed(cell, 10, TarGas.class)); + //GameScene.add(Blob.seed(cell, 10, StenchGas.class)); + } else { + if (!curUser.shoot( enemy, this )) { + Splash.at(cell, 0xCC99FFFF, 1); + } + } + } + + @Override + public void proc(Char attacker, Char defender, int damage) { + + Buff.affect(defender, AttackDown.class, 10f).level(35); + Buff.affect(defender, ArmorBreak.class, 10f).level(35); + Buff.affect(defender, Slow.class, 10f); + Buff.affect(defender, Hot.class,10f); + Buff.affect(defender, Wet.class, 10f); + Buff.affect(defender, Shocked.class, 10f); + Buff.affect(defender, Roots.class, 10f); + + super.proc(attacker, defender, damage); + } + + @Override + public void cast(final Hero user, final int dst) { + final int cell = throwPos( user, dst ); + PotionOfMage.this.targetPos = cell; + charge-=70; + super.cast(user, dst); + } + + } + private CellSelector.Listener shooter = new CellSelector.Listener() { + @Override + public void onSelect( Integer target ) { + if (target != null) { + Ammo().cast(curUser, target); + } + } + @Override + public String prompt() { + return Messages.get(PotionOfMage.class, "prompt"); + } + }; +} diff --git a/java/com/hmdzl/spspd/items/misc/RangeBag.java b/java/com/hmdzl/spspd/items/misc/RangeBag.java new file mode 100644 index 00000000..07900191 --- /dev/null +++ b/java/com/hmdzl/spspd/items/misc/RangeBag.java @@ -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 + */ +package com.hmdzl.spspd.items.misc; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; + +public class RangeBag extends MiscEquippable { + + { + image = ItemSpriteSheet.RANGE_BAG; + unique = true; + defaultAction = AC_BUY; + } + + public static final String AC_BUY = "BUY"; + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + actions.remove(AC_DROP); + actions.remove(AC_THROW); + actions.add(AC_BUY); + return actions; + } + + @Override + public void execute(Hero hero, String action) { + + curUser = Dungeon.hero; + + if (action.equals( AC_BUY )){ + if (Dungeon.gold < 500 ) { + GLog.p(Messages.get(this, "need_gold")); + } else { + Dungeon.gold -= 500; + hero.spend(1f); + hero.busy(); + + hero.sprite.operate(hero.pos); + Dungeon.level.drop(Generator.random(Generator.Category.LINKDROP), Dungeon.hero.pos).sprite.drop(Dungeon.hero.pos); + + } + } else { + super.execute(hero, action); + } + } + + @Override + protected MiscBuff buff() { + return new RangeBagBless(); + } + + public class RangeBagBless extends MiscBuff { + + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + +} diff --git a/java/com/hmdzl/spspd/items/misc/SavageHelmet.java b/java/com/hmdzl/spspd/items/misc/SavageHelmet.java new file mode 100644 index 00000000..bfc12834 --- /dev/null +++ b/java/com/hmdzl/spspd/items/misc/SavageHelmet.java @@ -0,0 +1,71 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2014 Oleg Dolya + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.items.misc; + +import java.util.ArrayList; + +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.DamageUp; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.utils.Random; + +public class SavageHelmet extends MiscEquippable { + + { + image = ItemSpriteSheet.HELMET; + unique = true; + + } + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + actions.remove(AC_DROP); + actions.remove(AC_THROW); + return actions; + } + + @Override + protected MiscBuff buff() { + return new SavageHelmetBless(); + } + + public class SavageHelmetBless extends MiscBuff { + + public int absorb(int damage) { + int x = Random.Int(1,damage/2); + damage -=x; + Buff.affect(target, DamageUp.class).level(x); + return damage; + } + + } + + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + +} diff --git a/java/com/hmdzl/spspd/items/misc/Shovel.java b/java/com/hmdzl/spspd/items/misc/Shovel.java new file mode 100644 index 00000000..402449f5 --- /dev/null +++ b/java/com/hmdzl/spspd/items/misc/Shovel.java @@ -0,0 +1,179 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Yet Another Pixel Dungeon + * Copyright (C) 2015-2016 Considered Hamster + * + * 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 + */ +package com.hmdzl.spspd.items.misc; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Hunger; +import com.hmdzl.spspd.actors.buffs.WarGroove; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.Terrain; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.ui.BuffIndicator; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Bundle; +import com.watabou.utils.Callback; + +import java.util.ArrayList; + +public class Shovel extends Item { + + public static final String AC_USE = "USE"; + public static final String AC_BUILD = "BUILD"; + + private static final float TIME_TO_DIG = 1f; + + { + //name = "Shovel"; + image = ItemSpriteSheet.SHOVEL; + defaultAction = AC_USE; + unique = true; + + } + + public final int fullCharge = 120; + public int charge = 0; + private static final String CHARGE = "charge"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(CHARGE, charge); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + charge = bundle.getInt(CHARGE); + } + + @Override + public ArrayList actions(Hero hero ) { + ArrayList actions = super.actions( hero ); + if (charge >= 40){ + actions.add(AC_USE); + } + if (charge >= 100){ + actions.add(AC_BUILD); + } + actions.remove( AC_THROW ); + actions.remove( AC_DROP ); + return actions; + } + + @Override + public void execute( final Hero hero, String action ) { + if( action.equals( AC_USE ) ){ + for (int i = 0; i < Level.NEIGHBOURS4.length; i++) { + + final int pos = hero.pos + Level.NEIGHBOURS4[i]; + if(charge < 40){ + GLog.i(Messages.get(Shovel.class, "break")); + return; + } else if (Dungeon.level.map[pos] == Terrain.WALL && Level.insideMap(pos)) { + hero.spend(TIME_TO_DIG); + hero.busy(); + hero.sprite.attack(pos, new Callback() { + @Override + public void call() { + CellEmitter.center(pos).burst( + Speck.factory(Speck.STAR), 7); + Sample.INSTANCE.play(Assets.SND_EVOKE); + Level.set(pos, Terrain.EMBERS); + GameScene.updateMap(pos); + + Hunger hunger = hero.buff(Hunger.class); + if (hunger != null && !hunger.isStarving()) { + hunger.satisfy(-10); + BuffIndicator.refreshHero(); + } + Buff.affect(hero,WarGroove.class); + charge-=50; + updateQuickslot(); + hero.onOperateComplete(); + } + }); + return; + } + } + } else if ( action.equals( AC_BUILD )){ + for (int n : Level.NEIGHBOURS4) { + int c = hero.pos + n; + if (c >= 0 && c < Level.getLength()) { + if ((Dungeon.level.map[c] == Terrain.EMPTY || + Dungeon.level.map[c] == Terrain.EMPTY_DECO || + Dungeon.level.map[c] == Terrain.EMPTY_SP || + Dungeon.level.map[c] == Terrain.GRASS )&& Level.insideMap(c)) { + Level.set(c, Terrain.WALL); + GameScene.updateMap(c); + Dungeon.observe(); + } + } + } + hero.spend(TIME_TO_DIG); + hero.busy(); + Hunger hunger = hero.buff(Hunger.class); + if (hunger != null && !hunger.isStarving()) { + hunger.satisfy(-10); + BuffIndicator.refreshHero(); + } + charge-=100; + updateQuickslot(); + hero.onOperateComplete(); + return; + } else { + super.execute(hero, action); + + } + } + + @Override + public String status() { + return Messages.format("%d", (int)charge/40); + } + + @Override + public String info() { + String info = desc(); + info += "\n\n" + Messages.get(Shovel.class, "charge",charge,fullCharge); + return info; + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + +} diff --git a/java/com/hmdzl/spspd/items/misc/SkillOfAtk.java b/java/com/hmdzl/spspd/items/misc/SkillOfAtk.java new file mode 100644 index 00000000..c239b154 --- /dev/null +++ b/java/com/hmdzl/spspd/items/misc/SkillOfAtk.java @@ -0,0 +1,80 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.misc; + +import java.util.ArrayList; + +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.items.Item; + +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; + +public class SkillOfAtk extends Item { + + { + //name = "Skill of atk"; + image = ItemSpriteSheet.SKILL_ATK; + + stackable = false; + + defaultAction = AC_READ; + } + + + public static final String AC_READ = "READ"; + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + actions.add(AC_READ); + return actions; + } + + @Override + public void execute(Hero hero, String action) { + + if (action.equals(AC_READ)) { + + hero.hitSkill++; + //hero.evadeSkill++; + //hero.magicSkill++; + GLog.w(Messages.get(this, "skillup")); + detach(hero.belongings.backpack); + } else { + super.execute(hero, action); + + } + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + @Override + public int price() { + return 50 * quantity; + } + +} diff --git a/java/com/hmdzl/spspd/items/misc/SkillOfDef.java b/java/com/hmdzl/spspd/items/misc/SkillOfDef.java new file mode 100644 index 00000000..71d9db2f --- /dev/null +++ b/java/com/hmdzl/spspd/items/misc/SkillOfDef.java @@ -0,0 +1,80 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.misc; + +import java.util.ArrayList; + +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.items.Item; + +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; + +public class SkillOfDef extends Item { + + { + //name = "Skill of def"; + image = ItemSpriteSheet.SKILL_DEF; + + stackable = false; + + defaultAction = AC_READ; + } + + + public static final String AC_READ = "READ"; + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + actions.add(AC_READ); + return actions; + } + + @Override + public void execute(Hero hero, String action) { + + if (action.equals(AC_READ)) { + + //hero.hitSkill++; + hero.evadeSkill++; + //hero.magicSkill++; + GLog.w(Messages.get(this, "skillup")); + detach(hero.belongings.backpack); + } else { + super.execute(hero, action); + + } + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + @Override + public int price() { + return 100 * quantity; + } + +} diff --git a/java/com/hmdzl/spspd/items/misc/SkillOfMig.java b/java/com/hmdzl/spspd/items/misc/SkillOfMig.java new file mode 100644 index 00000000..3c897ad5 --- /dev/null +++ b/java/com/hmdzl/spspd/items/misc/SkillOfMig.java @@ -0,0 +1,80 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.misc; + +import java.util.ArrayList; + +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.items.Item; + +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; + +public class SkillOfMig extends Item { + + { + //name = "Skill of mig"; + image = ItemSpriteSheet.SKILL_MIG; + + stackable = false; + + defaultAction = AC_READ; + } + + + public static final String AC_READ = "READ"; + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + actions.add(AC_READ); + return actions; + } + + @Override + public void execute(Hero hero, String action) { + + if (action.equals(AC_READ)) { + + //hero.hitSkill++; + //hero.evadeSkill++; + hero.magicSkill++; + GLog.w(Messages.get(this, "skillup")); + detach(hero.belongings.backpack); + } else { + super.execute(hero, action); + + } + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + @Override + public int price() { + return 200 * quantity; + } + +} diff --git a/java/com/hmdzl/spspd/items/misc/Spectacles.java b/java/com/hmdzl/spspd/items/misc/Spectacles.java new file mode 100644 index 00000000..33c1da54 --- /dev/null +++ b/java/com/hmdzl/spspd/items/misc/Spectacles.java @@ -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 + */ +package com.hmdzl.spspd.items.misc; + +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class Spectacles extends MiscEquippable { + + { + image = ItemSpriteSheet.OTILUKES_SPECS; + unique = true; + } + + @Override + protected MiscBuff buff() { + return new MagicSight(); + } + + public class MagicSight extends MiscBuff { + } + + @Override + public boolean isIdentified() { + return true; + } + + @Override + public boolean isUpgradable() { + return false; + } + +} diff --git a/java/com/hmdzl/spspd/items/misc/UndeadBook.java b/java/com/hmdzl/spspd/items/misc/UndeadBook.java new file mode 100644 index 00000000..7122effb --- /dev/null +++ b/java/com/hmdzl/spspd/items/misc/UndeadBook.java @@ -0,0 +1,107 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.misc; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Dewcharge; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.items.Ankh; +import com.hmdzl.spspd.items.Item; + +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Bundle; + +public class UndeadBook extends Item { + + public static final String AC_READ = "READ"; + + public static final String AC_BLESS = "BLESS"; + + { + //name = "UndeadBook"; + image = ItemSpriteSheet.UNDEAD_BOOK; + + stackable = false; + charge = 0; + //defaultAction = AC_READ; + } + + public static int charge; + private static final String CHARGE = "charge"; + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + if (hero.HT > 10) actions.add(AC_READ); + if (charge < hero.lvl) actions.add(AC_BLESS); + return actions; + } + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(CHARGE, charge); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + charge = bundle.getInt(CHARGE); + } + + + @Override + public void execute(Hero hero, String action) { + + if (action.equals(AC_READ)) { + hero.HT -= 5; + Buff.affect(hero, Dewcharge.class, 100f); + GLog.p(Messages.get(this, "bless")); + } + + if (action.equals(AC_BLESS)) { + charge ++; + Dungeon.level.drop(new Ankh(), Dungeon.hero.pos).sprite.drop(Dungeon.hero.pos); + GLog.p(Messages.get(this, "1up")); + } else { + super.execute(hero, action); + + } + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + @Override + public int price() { + return 50 * quantity; + } + +} diff --git a/java/com/hmdzl/spspd/items/nornstone/BlueNornStone.java b/java/com/hmdzl/spspd/items/nornstone/BlueNornStone.java new file mode 100644 index 00000000..7b0480fb --- /dev/null +++ b/java/com/hmdzl/spspd/items/nornstone/BlueNornStone.java @@ -0,0 +1,45 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.nornstone; + +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class BlueNornStone extends NornStone { + + + { + type = 2; + //name = "norn stone"; + image = ItemSpriteSheet.NORNBLUE; + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + @Override + public int price() { + return 50 * quantity; + } +} diff --git a/java/com/hmdzl/spspd/items/nornstone/GreenNornStone.java b/java/com/hmdzl/spspd/items/nornstone/GreenNornStone.java new file mode 100644 index 00000000..1f292215 --- /dev/null +++ b/java/com/hmdzl/spspd/items/nornstone/GreenNornStone.java @@ -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 + */ +package com.hmdzl.spspd.items.nornstone; + +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class GreenNornStone extends NornStone { + + + { + type=1; + //name = "norn stone"; + image = ItemSpriteSheet.NORNGREEN; + } + + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + @Override + public int price() { + return 50 * quantity; + } +} diff --git a/java/com/hmdzl/spspd/items/nornstone/NornStone.java b/java/com/hmdzl/spspd/items/nornstone/NornStone.java new file mode 100644 index 00000000..4c5fa90d --- /dev/null +++ b/java/com/hmdzl/spspd/items/nornstone/NornStone.java @@ -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 + */ +package com.hmdzl.spspd.items.nornstone; + +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class NornStone extends Item { + + public int type=0; + + { + stackable = true; + //name = "norn stone"; + image = ItemSpriteSheet.NORNGREEN; + + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + @Override + public int price() { + return 100 * quantity; + } +} diff --git a/java/com/hmdzl/spspd/items/nornstone/OrangeNornStone.java b/java/com/hmdzl/spspd/items/nornstone/OrangeNornStone.java new file mode 100644 index 00000000..3a08ac80 --- /dev/null +++ b/java/com/hmdzl/spspd/items/nornstone/OrangeNornStone.java @@ -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 + */ +package com.hmdzl.spspd.items.nornstone; + +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class OrangeNornStone extends NornStone { + + + { + type=3; + //name = "norn stone"; + image = ItemSpriteSheet.NORNORANGE; + } + + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + @Override + public int price() { + return 50 * quantity; + } +} diff --git a/java/com/hmdzl/spspd/items/nornstone/PurpleNornStone.java b/java/com/hmdzl/spspd/items/nornstone/PurpleNornStone.java new file mode 100644 index 00000000..68942608 --- /dev/null +++ b/java/com/hmdzl/spspd/items/nornstone/PurpleNornStone.java @@ -0,0 +1,45 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.nornstone; + +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class PurpleNornStone extends NornStone { + + + { + type=4; + //name = "norn stone"; + image = ItemSpriteSheet.NORNPURPLE; + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + @Override + public int price() { + return 50 * quantity; + } +} diff --git a/java/com/hmdzl/spspd/items/nornstone/YellowNornStone.java b/java/com/hmdzl/spspd/items/nornstone/YellowNornStone.java new file mode 100644 index 00000000..ec739f10 --- /dev/null +++ b/java/com/hmdzl/spspd/items/nornstone/YellowNornStone.java @@ -0,0 +1,45 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.nornstone; + +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class YellowNornStone extends NornStone { + + + { + type=5; + //name = "norn stone"; + image = ItemSpriteSheet.NORNYELLOW; + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + @Override + public int price() { + return 50 * quantity; + } +} diff --git a/java/com/hmdzl/spspd/items/potions/Potion.java b/java/com/hmdzl/spspd/items/potions/Potion.java new file mode 100644 index 00000000..a9da3478 --- /dev/null +++ b/java/com/hmdzl/spspd/items/potions/Potion.java @@ -0,0 +1,313 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.potions; + +import java.util.ArrayList; +import java.util.HashSet; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.Challenges; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.Fire; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Burning; +import com.hmdzl.spspd.actors.buffs.Locked; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.hero.HeroClass; +import com.hmdzl.spspd.effects.Splash; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.ItemStatusHandler; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.Terrain; +import com.hmdzl.spspd.plants.Plant; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; +import com.hmdzl.spspd.windows.WndOptions; +import com.hmdzl.spspd.messages.Messages; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public class Potion extends Item { + + public static final String AC_DRINK = "DRINK"; + + private static final float TIME_TO_DRINK = Dungeon.isChallenged(Challenges.ITEM_PHOBIA)? 5f : 1f; + + protected Integer initials; + + private static final Class[] potions = { PotionOfHealing.class, + PotionOfExperience.class, PotionOfToxicGas.class, + PotionOfLiquidFlame.class, PotionOfStrength.class, + PotionOfParalyticGas.class, PotionOfLevitation.class, + PotionOfMindVision.class, PotionOfPurity.class, + PotionOfInvisibility.class, PotionOfMight.class, + PotionOfFrost.class, PotionOfMending.class, + PotionOfOverHealing.class}; + + private static final String[] colors = { "turquoise", "crimson", "azure", + "jade", "golden", "magenta", "charcoal", "ivory", "amber", + "bistre", "indigo", "silver", "aqua", "violet"}; + private static final Integer[] images = { ItemSpriteSheet.POTION_TURQUOISE, + ItemSpriteSheet.POTION_CRIMSON, ItemSpriteSheet.POTION_AZURE, + ItemSpriteSheet.POTION_JADE, ItemSpriteSheet.POTION_GOLDEN, + ItemSpriteSheet.POTION_MAGENTA, ItemSpriteSheet.POTION_CHARCOAL, + ItemSpriteSheet.POTION_IVORY, ItemSpriteSheet.POTION_AMBER, + ItemSpriteSheet.POTION_BISTRE, ItemSpriteSheet.POTION_INDIGO, + ItemSpriteSheet.POTION_SILVER, ItemSpriteSheet.POTION_AQUA, + ItemSpriteSheet.POTION_VIOLET}; + + private static ItemStatusHandler handler; + + private String color; + + public boolean ownedByFruit = false; + + { + stackable = true; + defaultAction = AC_DRINK; + } + + @SuppressWarnings("unchecked") + public static void initColors() { + handler = new ItemStatusHandler( + (Class[]) potions, colors, images); + } + + public static void save(Bundle bundle) { + handler.save(bundle); + } + + @SuppressWarnings("unchecked") + public static void restore(Bundle bundle) { + handler = new ItemStatusHandler( + (Class[]) potions, colors, images, bundle); + } + + public Potion() { + super(); + sync(); + } + + @Override + public void sync() { + super.sync(); + image = handler.image(this); + color = handler.label(this); + }; + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + actions.add(AC_DRINK); + return actions; + } + + @Override + public void execute(final Hero hero, String action) { + if (action.equals(AC_DRINK)) { + + if (hero.buff(Locked.class) != null) { + GLog.w(Messages.get(Potion.class, "locked")); + } else if (isKnown() + && (this instanceof PotionOfLiquidFlame + || this instanceof PotionOfToxicGas + || this instanceof PotionOfParalyticGas)) { + + GameScene.show(new WndOptions(Messages.get(Potion.class, "harmful"), + Messages.get(Potion.class, "sure_drink"), + Messages.get(Potion.class, "yes"), Messages.get(Potion.class, "no")) { + @Override + protected void onSelect(int index) { + if (index == 0) { + drink(hero); + } + } + + ; + }); + + } else { + drink(hero); + } + + } else { + + super.execute(hero, action); + + } + } + + @Override + public void doThrow(final Hero hero) { + + if (isKnown() + && (this instanceof PotionOfExperience + || this instanceof PotionOfHealing + || this instanceof PotionOfMindVision + || this instanceof PotionOfStrength + || this instanceof PotionOfInvisibility + || this instanceof PotionOfMight + || this instanceof PotionOfOverHealing + || this instanceof PotionOfMending)) { + + GameScene.show(new WndOptions( Messages.get(Potion.class, "beneficial"), + Messages.get(Potion.class, "sure_throw"), + Messages.get(Potion.class, "yes"), Messages.get(Potion.class, "no")) { + @Override + protected void onSelect(int index) { + if (index == 0) { + Potion.super.doThrow(hero); + } + }; + }); + + } else { + super.doThrow(hero); + } + } + + protected void drink(Hero hero) { + if (!(Dungeon.hero.heroClass == HeroClass.FOLLOWER ) || (Dungeon.hero.heroClass == HeroClass.FOLLOWER && Random.Int(10)>=1 )) + detach(hero.belongings.backpack); + + hero.spend(TIME_TO_DRINK); + hero.busy(); + apply(hero); + + Sample.INSTANCE.play(Assets.SND_DRINK); + + hero.sprite.operate(hero.pos); + } + + @Override + protected void onThrow(int cell) { + if (Dungeon.level.map[cell] == Terrain.WELL || Level.pit[cell] || Plant.checkPhase(cell)) { + + super.onThrow(cell); + + } else { + + shatter(cell); + + } + } + + public void apply(Hero hero) { + shatter(hero.pos); + } + + public void shatter(int cell) { + if (Dungeon.visible[cell]) { + GLog.i(Messages.get(Potion.class, "shatter", color())); + Sample.INSTANCE.play(Assets.SND_SHATTER); + splash(cell); + } + } + + @Override + public void cast(final Hero user, int dst) { + super.cast(user, dst); + } + + public boolean isKnown() { + return handler.isKnown(this); + } + + public void setKnown() { + if (!ownedByFruit) { + if (!isKnown()) { + handler.know(this); + } + + Badges.validateAllPotionsIdentified(); + } + } + + public Integer initials(){ + return isKnown() ? initials : null; + } + + protected String color() { + return Messages.get(Potion.class, color); + } + + @Override + public Item identify() { + + setKnown(); + return this; + } + + @Override + public String name() { + return isKnown() ? super.name() : Messages.get(Potion.class, "unknown_name", color()); + } + + @Override + public String info() { + return isKnown() ? + desc() : + Messages.get(Potion.class, "unknown_desc", color()); + } + + @Override + public boolean isIdentified() { + return isKnown(); + } + + @Override + public boolean isUpgradable() { + return false; + } + + public static HashSet> getKnown() { + return handler.known(); + } + + public static HashSet> getUnknown() { + return handler.unknown(); + } + + public static boolean allKnown() { + return handler.known().size() == potions.length; + } + + protected void splash(int cell) { + final int color = ItemSprite.pick(image, 8, 10); + Splash.at(cell, color, 5); + + Fire fire = (Fire) Dungeon.level.blobs.get(Fire.class); + if (fire != null) + fire.clear(cell); + + Char ch = Actor.findChar(cell); + if (ch != null) + Buff.detach(ch, Burning.class); + } + + @Override + public int price() { + return 20 * quantity; + } +} diff --git a/java/com/hmdzl/spspd/items/potions/PotionOfExperience.java b/java/com/hmdzl/spspd/items/potions/PotionOfExperience.java new file mode 100644 index 00000000..77e6d2f7 --- /dev/null +++ b/java/com/hmdzl/spspd/items/potions/PotionOfExperience.java @@ -0,0 +1,51 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.potions; + +import com.hmdzl.spspd.actors.buffs.Bless; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Haste; +import com.hmdzl.spspd.actors.buffs.Strength; +import com.hmdzl.spspd.actors.buffs.WarGroove; +import com.hmdzl.spspd.actors.hero.Hero; +import com.watabou.utils.Random; + +public class PotionOfExperience extends Potion { + + { + //name = "Potion of Experience"; + + initials = 0; + + + } + + @Override + public void apply(Hero hero) { + setKnown(); + //hero.earnExp(Random.Int(hero.maxExp()/2,hero.maxExp() - hero.exp)); + Buff.affect(hero, Bless.class, 50f); + Buff.affect(hero, Haste.class, 50f); + Buff.affect(hero,Strength.class); + } + + @Override + public int price() { + return isKnown() ? 80 * quantity : super.price(); + } +} diff --git a/java/com/hmdzl/spspd/items/potions/PotionOfFrost.java b/java/com/hmdzl/spspd/items/potions/PotionOfFrost.java new file mode 100644 index 00000000..5363ff01 --- /dev/null +++ b/java/com/hmdzl/spspd/items/potions/PotionOfFrost.java @@ -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 + */ +package com.hmdzl.spspd.items.potions; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.blobs.Fire; +import com.hmdzl.spspd.actors.blobs.Freezing; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.utils.BArray; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.PathFinder; + +public class PotionOfFrost extends Potion { + + private static final int DISTANCE = 2; + + { + //name = "Potion of Frost"; + initials = 1; + } + + @Override + public void shatter(int cell) { + + PathFinder.buildDistanceMap(cell, BArray.not(Level.losBlockLow, null), + DISTANCE); + + Fire fire = (Fire) Dungeon.level.blobs.get(Fire.class); + + boolean visible = false; + for (int i = 0; i < Level.getLength(); i++) { + if (PathFinder.distance[i] < Integer.MAX_VALUE) { + visible = Freezing.affect(i, fire) || visible; + } + } + + if (visible) { + splash(cell); + Sample.INSTANCE.play(Assets.SND_SHATTER); + + setKnown(); + } + } + + @Override + public int price() { + return isKnown() ? 50 * quantity : super.price(); + } +} diff --git a/java/com/hmdzl/spspd/items/potions/PotionOfHaste.java b/java/com/hmdzl/spspd/items/potions/PotionOfHaste.java new file mode 100644 index 00000000..adb14e13 --- /dev/null +++ b/java/com/hmdzl/spspd/items/potions/PotionOfHaste.java @@ -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 + */ +package com.hmdzl.spspd.items.potions; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Haste; +import com.hmdzl.spspd.actors.hero.Hero; +import com.watabou.noosa.audio.Sample; +import com.watabou.noosa.tweeners.AlphaTweener; + +public class PotionOfHaste extends Potion { + + private static final float ALPHA = 0.4f; + + { + //name = "Potion of Haste"; + initials = 2; + } + + @Override + public void apply(Hero hero) { + setKnown(); + Buff.affect(hero, Haste.class, Haste.DURATION); + //GLog.i("You are moving much faster!"); + Sample.INSTANCE.play(Assets.SND_MELD); + } + + /*@Override + public String desc() { + return "Drinking this potion will temporarily speed up your actions."; + }*/ + + @Override + public int price() { + return isKnown() ? 40 * quantity : super.price(); + } + + public static void melt(Char ch) { + if (ch.sprite.parent != null) { + ch.sprite.parent.add(new AlphaTweener(ch.sprite, ALPHA, 0.4f)); + } else { + ch.sprite.alpha(ALPHA); + } + } +} diff --git a/java/com/hmdzl/spspd/items/potions/PotionOfHealing.java b/java/com/hmdzl/spspd/items/potions/PotionOfHealing.java new file mode 100644 index 00000000..20bc384d --- /dev/null +++ b/java/com/hmdzl/spspd/items/potions/PotionOfHealing.java @@ -0,0 +1,64 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.potions; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.buffs.Bleeding; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Cripple; +import com.hmdzl.spspd.actors.buffs.Poison; +import com.hmdzl.spspd.actors.buffs.Weakness; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.hero.HeroSubClass; +import com.hmdzl.spspd.effects.Speck; + +public class PotionOfHealing extends Potion { + + { + //name = "Potion of Healing"; + + initials = 3; + + + } + + @Override + public void apply(Hero hero) { + setKnown(); + heal(Dungeon.hero); + } + + public static void heal(Hero hero) { + + if (Dungeon.hero.subClass == HeroSubClass.PASTOR){ + hero.HP = hero.HP+Math.min(hero.HT, (int)(hero.HT*1.5-hero.HP)); + } + hero.HP = hero.HP+Math.min(hero.HT, hero.HT-hero.HP); + Buff.detach(hero, Poison.class); + Buff.detach(hero, Cripple.class); + Buff.detach(hero, Weakness.class); + Buff.detach(hero, Bleeding.class); + + hero.sprite.emitter().start(Speck.factory(Speck.HEALING), 0.4f, 4); + } + + @Override + public int price() { + return isKnown() ? 30 * quantity : super.price(); + } +} diff --git a/java/com/hmdzl/spspd/items/potions/PotionOfInvisibility.java b/java/com/hmdzl/spspd/items/potions/PotionOfInvisibility.java new file mode 100644 index 00000000..1cc7514b --- /dev/null +++ b/java/com/hmdzl/spspd/items/potions/PotionOfInvisibility.java @@ -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 + */ +package com.hmdzl.spspd.items.potions; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.AttackUp; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Invisibility; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.items.misc.AutoPotion.AutoHealPotion; +import com.hmdzl.spspd.utils.GLog; +import com.hmdzl.spspd.messages.Messages; +import com.watabou.noosa.audio.Sample; +import com.watabou.noosa.tweeners.AlphaTweener; + +public class PotionOfInvisibility extends Potion { + + private static final float ALPHA = 0.4f; + + { + //name = "Potion of Invisibility"; + initials = 4; + } + + @Override + public void apply(Hero hero) { + setKnown(); + Buff.affect(hero, Invisibility.class, Dungeon.hero.buff(AutoHealPotion.class) != null ? Invisibility.DURATION*2 : Invisibility.DURATION); + Buff.affect(hero,AttackUp.class, 10f).level(20); + GLog.i(Messages.get(this, "invisible")); + Sample.INSTANCE.play(Assets.SND_MELD); + } + + @Override + public void execute(final Hero hero, String action) { + super.execute(hero, action); + } + + @Override + public int price() { + return isKnown() ? 40 * quantity : super.price(); + } + + public static void melt(Char ch) { + if (ch.sprite.parent != null) { + ch.sprite.parent.add(new AlphaTweener(ch.sprite, ALPHA, 0.4f)); + } else { + ch.sprite.alpha(ALPHA); + } + } +} diff --git a/java/com/hmdzl/spspd/items/potions/PotionOfLevitation.java b/java/com/hmdzl/spspd/items/potions/PotionOfLevitation.java new file mode 100644 index 00000000..02683765 --- /dev/null +++ b/java/com/hmdzl/spspd/items/potions/PotionOfLevitation.java @@ -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 + */ +package com.hmdzl.spspd.items.potions; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.blobs.Blob; +import com.hmdzl.spspd.actors.blobs.ConfusionGas; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.DefenceUp; +import com.hmdzl.spspd.actors.buffs.Levitation; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.noosa.audio.Sample; + +public class PotionOfLevitation extends Potion { + + { + //name = "Potion of Levitation"; + initials = 5; + } + + @Override + public void shatter(int cell) { + + if (Dungeon.visible[cell]) { + setKnown(); + + splash(cell); + Sample.INSTANCE.play(Assets.SND_SHATTER); + } + + GameScene.add(Blob.seed(cell, 1000, ConfusionGas.class)); + } + + @Override + public void apply(Hero hero) { + setKnown(); + Buff.affect(hero, Levitation.class, Levitation.DURATION); + Buff.affect(hero, DefenceUp.class, 10f).level(20); + GLog.i(Messages.get(this, "float")); + } + + @Override + public int price() { + return isKnown() ? 35 * quantity : super.price(); + } +} diff --git a/java/com/hmdzl/spspd/items/potions/PotionOfLiquidFlame.java b/java/com/hmdzl/spspd/items/potions/PotionOfLiquidFlame.java new file mode 100644 index 00000000..0d1c4b6c --- /dev/null +++ b/java/com/hmdzl/spspd/items/potions/PotionOfLiquidFlame.java @@ -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 + */ +package com.hmdzl.spspd.items.potions; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.blobs.Blob; +import com.hmdzl.spspd.actors.blobs.Fire; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.particles.FlameParticle; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.scenes.GameScene; +import com.watabou.noosa.audio.Sample; + +public class PotionOfLiquidFlame extends Potion { + + { + //name = "Potion of Liquid Flame"; + initials = 6; + } + + @Override + public void shatter(int cell) { + + if (Dungeon.visible[cell]) { + setKnown(); + + splash(cell); + Sample.INSTANCE.play(Assets.SND_SHATTER); + } + + for (int offset : Level.NEIGHBOURS9) { + if (Level.flamable[cell + offset] + || Actor.findChar(cell + offset) != null + || Dungeon.level.heaps.get(cell + offset) != null) { + + GameScene.add(Blob.seed(cell + offset, 2, Fire.class)); + + } else { + + CellEmitter.get(cell + offset).burst(FlameParticle.FACTORY, 2); + + } + } + } + + @Override + public int price() { + return isKnown() ? 40 * quantity : super.price(); + } +} diff --git a/java/com/hmdzl/spspd/items/potions/PotionOfMending.java b/java/com/hmdzl/spspd/items/potions/PotionOfMending.java new file mode 100644 index 00000000..d5d8e30a --- /dev/null +++ b/java/com/hmdzl/spspd/items/potions/PotionOfMending.java @@ -0,0 +1,77 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.potions; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.blobs.Blob; +import com.hmdzl.spspd.actors.blobs.HealLight; +import com.hmdzl.spspd.actors.buffs.BerryRegeneration; +import com.hmdzl.spspd.actors.buffs.Bleeding; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Cripple; +import com.hmdzl.spspd.actors.buffs.Poison; +import com.hmdzl.spspd.actors.buffs.Weakness; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.scenes.GameScene; +import com.watabou.noosa.audio.Sample; + +public class PotionOfMending extends Potion { + + { + //name = "Potion of Mending"; + initials = 7; + + } + + @Override + public void apply(Hero hero) { + setKnown(); + heal(Dungeon.hero); + } + + public static void heal(Hero hero) { + + Buff.affect(hero, BerryRegeneration.class).level(Math.max(0,hero.HT - hero.HP)); + Buff.detach(hero, Poison.class); + Buff.detach(hero, Cripple.class); + Buff.detach(hero, Weakness.class); + Buff.detach(hero, Bleeding.class); + + hero.sprite.emitter().start(Speck.factory(Speck.HEALING), 0.4f, 4); + } + + @Override + public void shatter(int cell) { + + if (Dungeon.visible[cell]) { + setKnown(); + + splash(cell); + Sample.INSTANCE.play(Assets.SND_SHATTER); + } + + GameScene.add(Blob.seed(cell, 500, HealLight.class)); + } + + @Override + public int price() { + return isKnown() ? 20 * quantity : super.price(); + } +} diff --git a/java/com/hmdzl/spspd/items/potions/PotionOfMight.java b/java/com/hmdzl/spspd/items/potions/PotionOfMight.java new file mode 100644 index 00000000..ff17d322 --- /dev/null +++ b/java/com/hmdzl/spspd/items/potions/PotionOfMight.java @@ -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 + */ +package com.hmdzl.spspd.items.potions; + +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.CharSprite; + +public class PotionOfMight extends Potion { + + { + //name = "Potion of Might"; + initials = 8; + + } + + @Override + public void apply(Hero hero) { + setKnown(); + + hero.HT += 15; + hero.HP += 15; + + hero.sprite.showStatus(CharSprite.POSITIVE, Messages.get(this, "msg_1")); + } + + + @Override + public int price() { + return isKnown() ? 200 * quantity : super.price(); + } +} diff --git a/java/com/hmdzl/spspd/items/potions/PotionOfMindVision.java b/java/com/hmdzl/spspd/items/potions/PotionOfMindVision.java new file mode 100644 index 00000000..243c99e2 --- /dev/null +++ b/java/com/hmdzl/spspd/items/potions/PotionOfMindVision.java @@ -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 + */ +package com.hmdzl.spspd.items.potions; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.buffs.Awareness; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.MindVision; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.items.misc.Spectacles.MagicSight; +import com.hmdzl.spspd.utils.GLog; +import com.hmdzl.spspd.messages.Messages; + +public class PotionOfMindVision extends Potion { + + { + //name = "Potion of Mind Vision"; + initials = 9; + } + + @Override + public void apply(Hero hero) { + setKnown(); + + Buff.affect(hero, MindVision.class, Dungeon.hero.buff(MagicSight.class) != null ? MindVision.DURATION*4 : MindVision.DURATION); + Buff.affect(hero, Awareness.class, Dungeon.hero.buff(MagicSight.class) != null ? 20f : 5f); + Dungeon.observe(); + + if (Dungeon.level.mobs.size() > 0) { + GLog.i( Messages.get(this, "see_mobs")); + } else { + GLog.i( Messages.get(this, "see_none")); + } + } + + @Override + public int price() { + return isKnown() ? 35 * quantity : super.price(); + } +} diff --git a/java/com/hmdzl/spspd/items/potions/PotionOfOverHealing.java b/java/com/hmdzl/spspd/items/potions/PotionOfOverHealing.java new file mode 100644 index 00000000..1b75c285 --- /dev/null +++ b/java/com/hmdzl/spspd/items/potions/PotionOfOverHealing.java @@ -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 + */ +package com.hmdzl.spspd.items.potions; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.buffs.Bleeding; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Cripple; +import com.hmdzl.spspd.actors.buffs.Poison; +import com.hmdzl.spspd.actors.buffs.Weakness; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.Speck; + +public class PotionOfOverHealing extends Potion { + + { + //name = "Potion of Life"; + initials = 10; + + } + + @Override + public void apply(Hero hero) { + setKnown(); + heal(Dungeon.hero); + //GLog.p("Your wounds heal completely."); + } + + public static void heal(Hero hero) { + + hero.HP = hero.HT+(hero.lvl*2); + Buff.detach(hero, Poison.class); + Buff.detach(hero, Cripple.class); + Buff.detach(hero, Weakness.class); + Buff.detach(hero, Bleeding.class); + hero.sprite.emitter().start(Speck.factory(Speck.HEALING), 0.4f, 4); + } + + @Override + public int price() { + return isKnown() ? 30 * quantity : super.price(); + } +} diff --git a/java/com/hmdzl/spspd/items/potions/PotionOfParalyticGas.java b/java/com/hmdzl/spspd/items/potions/PotionOfParalyticGas.java new file mode 100644 index 00000000..da4104b4 --- /dev/null +++ b/java/com/hmdzl/spspd/items/potions/PotionOfParalyticGas.java @@ -0,0 +1,51 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.potions; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.blobs.Blob; +import com.hmdzl.spspd.actors.blobs.ParalyticGas; +import com.hmdzl.spspd.scenes.GameScene; +import com.watabou.noosa.audio.Sample; + +public class PotionOfParalyticGas extends Potion { + + { + //name = "Potion of Paralytic Gas"; + initials = 11; + } + + @Override + public void shatter(int cell) { + + if (Dungeon.visible[cell]) { + setKnown(); + + splash(cell); + Sample.INSTANCE.play(Assets.SND_SHATTER); + } + + GameScene.add(Blob.seed(cell, 1000, ParalyticGas.class)); + } + + @Override + public int price() { + return isKnown() ? 40 * quantity : super.price(); + } +} diff --git a/java/com/hmdzl/spspd/items/potions/PotionOfPurity.java b/java/com/hmdzl/spspd/items/potions/PotionOfPurity.java new file mode 100644 index 00000000..64b82577 --- /dev/null +++ b/java/com/hmdzl/spspd/items/potions/PotionOfPurity.java @@ -0,0 +1,128 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.potions; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.blobs.Blob; +import com.hmdzl.spspd.actors.blobs.ConfusionGas; +import com.hmdzl.spspd.actors.blobs.ParalyticGas; +import com.hmdzl.spspd.actors.blobs.StenchGas; +import com.hmdzl.spspd.actors.blobs.ToxicGas; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.GasesImmunity; +import com.hmdzl.spspd.actors.buffs.HighLight; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.utils.BArray; +import com.hmdzl.spspd.utils.GLog; +import com.hmdzl.spspd.messages.Messages; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.PathFinder; + +public class PotionOfPurity extends Potion { + + private static final int DISTANCE = 5; + + { + //name = "Potion of Purification"; + initials = 12; + } + + @Override + public void shatter(int cell) { + + PathFinder.buildDistanceMap(cell, BArray.not(Level.losBlockLow, null), + DISTANCE); + + boolean procd = false; + + Blob[] blobs = { Dungeon.level.blobs.get(ToxicGas.class), + Dungeon.level.blobs.get(ParalyticGas.class), + Dungeon.level.blobs.get(ConfusionGas.class), + Dungeon.level.blobs.get(StenchGas.class) }; + + for (int j = 0; j < blobs.length; j++) { + + Blob blob = blobs[j]; + if (blob == null) { + continue; + } + + for (int i = 0; i < Level.getLength(); i++) { + if (PathFinder.distance[i] < Integer.MAX_VALUE) { + + int value = blob.cur[i]; + if (value > 0) { + + blob.cur[i] = 0; + blob.volume -= value; + procd = true; + + if (Dungeon.visible[i]) { + CellEmitter.get(i).burst( + Speck.factory(Speck.DISCOVER), 1); + } + } + + } + } + } + + boolean heroAffected = PathFinder.distance[Dungeon.hero.pos] < Integer.MAX_VALUE; + + if (procd) { + + if (Dungeon.visible[cell]) { + splash(cell); + Sample.INSTANCE.play(Assets.SND_SHATTER); + } + + setKnown(); + + if (heroAffected) { + GLog.p(Messages.get(this, "freshness")); + } + + } else { + + super.shatter(cell); + + if (heroAffected) { + GLog.i(Messages.get(this, "freshness") ); + setKnown(); + } + + } + } + + @Override + public void apply(Hero hero) { + GLog.w(Messages.get(this, "no_smell")); + Buff.prolong(hero, GasesImmunity.class, GasesImmunity.DURATION); + Buff.prolong(hero, HighLight.class, 10f); + setKnown(); + } + + @Override + public int price() { + return isKnown() ? 50 * quantity : super.price(); + } +} diff --git a/java/com/hmdzl/spspd/items/potions/PotionOfStrength.java b/java/com/hmdzl/spspd/items/potions/PotionOfStrength.java new file mode 100644 index 00000000..625255f5 --- /dev/null +++ b/java/com/hmdzl/spspd/items/potions/PotionOfStrength.java @@ -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 + */ +package com.hmdzl.spspd.items.potions; + +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.CharSprite; + +public class PotionOfStrength extends Potion { + + { + //name = "Potion of Strength"; + initials = 13; + + } + + @Override + public void apply(Hero hero) { + setKnown(); + + hero.STR++; + hero.HP += (hero.HT - hero.HP); + hero.sprite.showStatus(CharSprite.POSITIVE, Messages.get(this, "msg_1")); + Badges.validateStrengthAttained(); + } + + @Override + public int price() { + return isKnown() ? 100 * quantity : super.price(); + } +} diff --git a/java/com/hmdzl/spspd/items/potions/PotionOfToxicGas.java b/java/com/hmdzl/spspd/items/potions/PotionOfToxicGas.java new file mode 100644 index 00000000..d60d2405 --- /dev/null +++ b/java/com/hmdzl/spspd/items/potions/PotionOfToxicGas.java @@ -0,0 +1,51 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.potions; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.blobs.Blob; +import com.hmdzl.spspd.actors.blobs.ToxicGas; +import com.hmdzl.spspd.scenes.GameScene; +import com.watabou.noosa.audio.Sample; + +public class PotionOfToxicGas extends Potion { + + { + //name = "Potion of Toxic Gas"; + initials = 14; + } + + @Override + public void shatter(int cell) { + + if (Dungeon.visible[cell]) { + setKnown(); + + splash(cell); + Sample.INSTANCE.play(Assets.SND_SHATTER); + } + + GameScene.add(Blob.seed(cell, 1000, ToxicGas.class)); + } + + @Override + public int price() { + return isKnown() ? 40 * quantity : super.price(); + } +} diff --git a/java/com/hmdzl/spspd/items/quest/CorpseDust.java b/java/com/hmdzl/spspd/items/quest/CorpseDust.java new file mode 100644 index 00000000..919e9c21 --- /dev/null +++ b/java/com/hmdzl/spspd/items/quest/CorpseDust.java @@ -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 + */ +package com.hmdzl.spspd.items.quest; + +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class CorpseDust extends Item { + + { + //name = "corpse dust"; + image = ItemSpriteSheet.DUST; + + cursed = true; + cursedKnown = true; + + unique = true; + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + /*@Override + public String info() { + return "The ball of corpse dust doesn't differ outwardly from a regular dust ball. However, " + + "you know somehow that it's better to get rid of it as soon as possible."; + }*/ +} diff --git a/java/com/hmdzl/spspd/items/quest/DarkGold.java b/java/com/hmdzl/spspd/items/quest/DarkGold.java new file mode 100644 index 00000000..3ed94f77 --- /dev/null +++ b/java/com/hmdzl/spspd/items/quest/DarkGold.java @@ -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 + */ +package com.hmdzl.spspd.items.quest; + +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class DarkGold extends Item { + + { + //name = "dark gold ore"; + image = ItemSpriteSheet.ORE; + + stackable = true; + unique = true; + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + /*@Override + public String info() { + return "This metal is called dark not because of its color (it doesn't differ from the normal gold), " + + "but because it melts under the daylight, making it useless on the surface."; + }*/ + + @Override + public int price() { + return quantity; + } +} diff --git a/java/com/hmdzl/spspd/items/quest/DwarfToken.java b/java/com/hmdzl/spspd/items/quest/DwarfToken.java new file mode 100644 index 00000000..4d123e86 --- /dev/null +++ b/java/com/hmdzl/spspd/items/quest/DwarfToken.java @@ -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 + */ +package com.hmdzl.spspd.items.quest; + +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class DwarfToken extends Item { + + { + //name = "dwarf token"; + image = ItemSpriteSheet.TOKEN; + + stackable = true; + unique = true; + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + /*@Override + public String info() { + return "Many dwarves and some of their larger creations carry these small pieces of metal of unknown purpose. " + + "Maybe they are jewelry or maybe some kind of ID. Dwarves are strange folk."; + }*/ + + @Override + public int price() { + return quantity * 100; + } +} diff --git a/java/com/hmdzl/spspd/items/quest/GnollClothes.java b/java/com/hmdzl/spspd/items/quest/GnollClothes.java new file mode 100644 index 00000000..59d13129 --- /dev/null +++ b/java/com/hmdzl/spspd/items/quest/GnollClothes.java @@ -0,0 +1,49 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.quest; + +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class GnollClothes extends Item { + + { + //name = "GnollClothes"; + image = ItemSpriteSheet.GNOLL_ARMOR; + + stackable = true; + unique = true; + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + /*@Override + public String info() { + return "Many dwarves and some of their larger creations carry these small pieces of metal of unknown purpose. " + + "Maybe they are jewelry or maybe some kind of ID. Dwarves are strange folk."; + }*/ + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/quest/Mushroom.java b/java/com/hmdzl/spspd/items/quest/Mushroom.java new file mode 100644 index 00000000..b0b77407 --- /dev/null +++ b/java/com/hmdzl/spspd/items/quest/Mushroom.java @@ -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 + */ +package com.hmdzl.spspd.items.quest; + +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class Mushroom extends Item { + + //private static final String AC_END = "END THE GAME"; + + { + //name = "toadstool mushroom"; + image = ItemSpriteSheet.MUSHROOM; + + unique = true; + } + + /* + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + actions.add(AC_END); + return actions; + } + + @Override + public void execute(Hero hero, String action) { + if (action == AC_END) { + + showAmuletScene(false); + + } else { + + super.execute(hero, action); + + } + } + + +*/ + @Override + public boolean isIdentified() { + return true; + } + + @Override + public boolean isUpgradable() { + return false; + } +} diff --git a/java/com/hmdzl/spspd/items/quest/Pickaxe.java b/java/com/hmdzl/spspd/items/quest/Pickaxe.java new file mode 100644 index 00000000..c5b1ab13 --- /dev/null +++ b/java/com/hmdzl/spspd/items/quest/Pickaxe.java @@ -0,0 +1,232 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.quest; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Hunger; +import com.hmdzl.spspd.actors.buffs.Poison; +import com.hmdzl.spspd.actors.buffs.Ooze; +import com.hmdzl.spspd.actors.buffs.Bleeding; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.mobs.Bat; +import com.hmdzl.spspd.actors.mobs.ElderAvatar; +import com.hmdzl.spspd.actors.mobs.King; +import com.hmdzl.spspd.actors.mobs.LichDancer; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.weapon.Weapon; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.Terrain; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSprite.Glowing; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.ui.BuffIndicator; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Bundle; +import com.watabou.utils.Callback; +import com.watabou.utils.Random; + +public class Pickaxe extends Weapon { + + public static final String AC_MINE = "MINE"; + + public static final float TIME_TO_MINE = 2; + + private static final String TXT_NO_VEIN = "There is no dark gold vein near you to mine"; + + private static final Glowing BLOODY = new Glowing(0x550000); + + { + //name = "pickaxe"; + image = ItemSpriteSheet.PICKAXE; + + unique = true; + + defaultAction = AC_MINE; + + STR = 14; + MIN = 10; + MAX = 22; + } + + public boolean bloodStained = false; + + + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + actions.add(AC_MINE); + return actions; + } + + @Override + public void execute(final Hero hero, String action) { + + if (action == AC_MINE) { + + if ((Dungeon.depth < 11 || Dungeon.depth > 15) && !(Dungeon.depth==32)) { + GLog.w(Messages.get(this,"no_vein")); + return; + } + + for (int i = 0; i < Level.NEIGHBOURS8.length; i++) { + + final int pos = hero.pos + Level.NEIGHBOURS8[i]; + if (Dungeon.level.map[pos] == Terrain.WALL_DECO) { + + hero.spend(TIME_TO_MINE); + hero.busy(); + + hero.sprite.attack(pos, new Callback() { + + @Override + public void call() { + + CellEmitter.center(pos).burst( + Speck.factory(Speck.STAR), 7); + Sample.INSTANCE.play(Assets.SND_EVOKE); + + Level.set(pos, Terrain.WALL); + GameScene.updateMap(pos); + + DarkGold gold = new DarkGold(); + if (gold.doPickUp(Dungeon.hero)) { + GLog.i( Messages.get(Dungeon.hero, "you_now_have", gold.name())); + } else { + Dungeon.level.drop(gold, hero.pos).sprite + .drop(); + } + + Hunger hunger = hero.buff(Hunger.class); + if (hunger != null && !hunger.isStarving()) { + hunger.satisfy(-10); + BuffIndicator.refreshHero(); + } + + hero.onOperateComplete(); + } + }); + + return; + } + } + + GLog.w(Messages.get(this,"no_vein")); + + } else { + + super.execute(hero, action); + + } + } + + @Override + public boolean isUpgradable() { + return true; + } + + @Override + public Item upgrade() { + return upgrade(false); + } + + @Override + public Item upgrade(boolean enchant) { + + MIN += 3; + MAX += 3; + super.upgrade(enchant); + updateQuickslot(); + return this; + } + + @Override + public Item degrade() { + return super.degrade(); + } + + @Override + public boolean isIdentified() { + return true; + } + + @Override + public void proc(Char attacker, Char defender, int damage) { + if (!bloodStained && defender instanceof Bat ) { + bloodStained = true; + updateQuickslot(); + } + if (defender instanceof King.DwarfKingTomb || defender instanceof ElderAvatar.Obelisk || defender instanceof LichDancer.BatteryTomb){ + defender.damage(Random.Int(100,200), this); + } + + switch (Random.Int (10)) { + case 1 : + Buff.affect(defender, Bleeding.class).set(10); + break; + case 2 : + Buff.affect(defender, Ooze.class); + break; + case 3 : + Buff.affect(defender, Poison.class).set( + Random.Int(7, 10) * Poison.durationFactor(defender) ); + break; + default: + break; + } + + if (enchantment != null) { + enchantment.proc(this, attacker, defender, damage); + } + } + + private static final String BLOODSTAINED = "bloodStained"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + + bundle.put(BLOODSTAINED, bloodStained); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + + bloodStained = bundle.getBoolean(BLOODSTAINED); + } + + @Override + public Glowing glowing() { + return bloodStained ? BLOODY : null; + } + + /*@Override + public String info() { + return "This is a large and sturdy tool for breaking rocks. Probably it can be used as a weapon."; + }*/ +} diff --git a/java/com/hmdzl/spspd/items/quest/RatSkull.java b/java/com/hmdzl/spspd/items/quest/RatSkull.java new file mode 100644 index 00000000..03a8cf31 --- /dev/null +++ b/java/com/hmdzl/spspd/items/quest/RatSkull.java @@ -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 + */ +package com.hmdzl.spspd.items.quest; + +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +//this one's still hanging around to support quests from old saves +//TODO: remove this when saves from v0.2.1 are no longer supported +public class RatSkull extends Item { + + { + //name = "giant rat skull"; + image = ItemSpriteSheet.SKULL; + + unique = true; + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + /*@Override + public String info() { + return "It could be a nice hunting trophy, but it smells too bad to place it on a wall."; + }*/ + + @Override + public int price() { + return 100; + } +} diff --git a/java/com/hmdzl/spspd/items/reward/CaveReward.java b/java/com/hmdzl/spspd/items/reward/CaveReward.java new file mode 100644 index 00000000..91bc06a5 --- /dev/null +++ b/java/com/hmdzl/spspd/items/reward/CaveReward.java @@ -0,0 +1,99 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.reward; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.items.Item; + +import com.hmdzl.spspd.items.food.fruit.Blackberry; +import com.hmdzl.spspd.items.food.fruit.Blueberry; +import com.hmdzl.spspd.items.food.fruit.Cloudberry; +import com.hmdzl.spspd.items.food.fruit.Moonberry; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class CaveReward extends Item { + + public static final String AC_USE = "USE"; + + public static final float TIME_TO_USE = 1; + private static ItemSprite.Glowing WHITE = new ItemSprite.Glowing(0xFFFFFF); + + @Override + public ItemSprite.Glowing glowing() { + return WHITE; + } + { + //name = "reward"; + image = ItemSpriteSheet.PETFOOD; + + stackable = false; + } + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + actions.add(AC_USE); + return actions; + } + + @Override + public void execute(Hero hero, String action) { + + if (action.equals(AC_USE)) { + + hero.spend(TIME_TO_USE); + hero.busy(); + + hero.sprite.operate(hero.pos); + + Moonberry berry1 = new Moonberry(10); + Dungeon.level.drop(berry1, Dungeon.hero.pos).sprite.drop(Dungeon.hero.pos); + Cloudberry berry2 = new Cloudberry(10); + Dungeon.level.drop(berry2, Dungeon.hero.pos).sprite.drop(Dungeon.hero.pos); + Blueberry berry3 = new Blueberry(10); + Dungeon.level.drop(berry3, Dungeon.hero.pos).sprite.drop(Dungeon.hero.pos); + Blackberry berry4 = new Blackberry(10); + Dungeon.level.drop(berry4, Dungeon.hero.pos).sprite.drop(Dungeon.hero.pos); + + detach(hero.belongings.backpack); + + } else { + super.execute(hero, action); + + } + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + @Override + public int price() { + return 10 * quantity; + } +} diff --git a/java/com/hmdzl/spspd/items/reward/CityReward.java b/java/com/hmdzl/spspd/items/reward/CityReward.java new file mode 100644 index 00000000..1e6c51ff --- /dev/null +++ b/java/com/hmdzl/spspd/items/reward/CityReward.java @@ -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 + */ +package com.hmdzl.spspd.items.reward; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.items.Item; + +import com.hmdzl.spspd.items.food.completefood.Crystalnucleus; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class CityReward extends Item { + + public static final String AC_USE = "USE"; + + public static final float TIME_TO_USE = 1; + private static ItemSprite.Glowing YELLOW = new ItemSprite.Glowing( 0xFFFF44 ); + + @Override + public ItemSprite.Glowing glowing() { + return YELLOW; + } + { + //name = "reward"; + image = ItemSpriteSheet.PETFOOD; + + stackable = false; + } + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + actions.add(AC_USE); + return actions; + } + + @Override + public void execute(Hero hero, String action) { + + if (action.equals(AC_USE)) { + + hero.spend(TIME_TO_USE); + hero.busy(); + + hero.sprite.operate(hero.pos); + + Crystalnucleus cry = new Crystalnucleus(); + Dungeon.level.drop(cry, Dungeon.hero.pos).sprite.drop(Dungeon.hero.pos); + Dungeon.level.drop(cry, Dungeon.hero.pos).sprite.drop(Dungeon.hero.pos); + Dungeon.level.drop(cry, Dungeon.hero.pos).sprite.drop(Dungeon.hero.pos); + Dungeon.level.drop(cry, Dungeon.hero.pos).sprite.drop(Dungeon.hero.pos); + Dungeon.level.drop(cry, Dungeon.hero.pos).sprite.drop(Dungeon.hero.pos); + + detach(hero.belongings.backpack); + + } else { + super.execute(hero, action); + + } + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + @Override + public int price() { + return 10 * quantity; + } +} diff --git a/java/com/hmdzl/spspd/items/reward/PrisonReward.java b/java/com/hmdzl/spspd/items/reward/PrisonReward.java new file mode 100644 index 00000000..23d4eea4 --- /dev/null +++ b/java/com/hmdzl/spspd/items/reward/PrisonReward.java @@ -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 + */ +package com.hmdzl.spspd.items.reward; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.items.Item; + +import com.hmdzl.spspd.items.food.fruit.FullMoonberry; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class PrisonReward extends Item { + + public static final String AC_USE = "USE"; + + public static final float TIME_TO_USE = 1; + private static ItemSprite.Glowing BLUE = new ItemSprite.Glowing(0x0000FF); + + @Override + public ItemSprite.Glowing glowing() { + return BLUE; + } + + { + //name = "reward"; + image = ItemSpriteSheet.PETFOOD; + + stackable = false; + } + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + actions.add(AC_USE); + return actions; + } + + @Override + public void execute(Hero hero, String action) { + + if (action.equals(AC_USE)) { + + hero.spend(TIME_TO_USE); + hero.busy(); + + hero.sprite.operate(hero.pos); + + FullMoonberry berry = new FullMoonberry(); + Dungeon.level.drop(berry, Dungeon.hero.pos).sprite.drop(Dungeon.hero.pos); + + detach(hero.belongings.backpack); + } else { + super.execute(hero, action); + + } + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + @Override + public int price() { + return 10 * quantity; + } +} diff --git a/java/com/hmdzl/spspd/items/reward/SewerReward.java b/java/com/hmdzl/spspd/items/reward/SewerReward.java new file mode 100644 index 00000000..ce4e7546 --- /dev/null +++ b/java/com/hmdzl/spspd/items/reward/SewerReward.java @@ -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 + */ +package com.hmdzl.spspd.items.reward; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.StoneOre; + +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class SewerReward extends Item { + + public static final String AC_USE = "USE"; + + public static final float TIME_TO_USE = 1; + private static final ItemSprite.Glowing BLACK = new ItemSprite.Glowing(0x00000); + + @Override + public ItemSprite.Glowing glowing() { + return BLACK; + } + { + //name = "reward"; + image = ItemSpriteSheet.PETFOOD; + + stackable = false; + } + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + actions.add(AC_USE); + return actions; + } + + @Override + public void execute(Hero hero, String action) { + + if (action.equals(AC_USE)) { + + hero.spend(TIME_TO_USE); + hero.busy(); + + hero.sprite.operate(hero.pos); + + StoneOre ore = new StoneOre(20); + Dungeon.level.drop(ore, Dungeon.hero.pos).sprite.drop(Dungeon.hero.pos); + + detach(hero.belongings.backpack); + + } else { + super.execute(hero, action); + + } + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + @Override + public int price() { + return 10 * quantity; + } +} diff --git a/java/com/hmdzl/spspd/items/rings/Ring.java b/java/com/hmdzl/spspd/items/rings/Ring.java new file mode 100644 index 00000000..45034a08 --- /dev/null +++ b/java/com/hmdzl/spspd/items/rings/Ring.java @@ -0,0 +1,356 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.rings; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.ItemStatusHandler; +import com.hmdzl.spspd.items.KindofMisc; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public class Ring extends KindofMisc { + + private static final int TICKS_TO_KNOW = 200; + + private static final float TIME_TO_EQUIP = 1f; + + protected Buff buff; + + protected Integer initials; + + private static final Class[] rings = { RingOfAccuracy.class, + RingOfEvasion.class, RingOfElements.class, RingOfForce.class, + RingOfFuror.class, RingOfHaste.class, RingOfMagic.class, + RingOfMight.class, RingOfSharpshooting.class, RingOfTenacity.class, + RingOfEnergy.class, }; + private static final String[] gems = { "diamond", "opal", "garnet", "ruby", + "amethyst", "topaz", "onyx", "tourmaline", "emerald", "sapphire", + "quartz", "agate" }; + private static final Integer[] images = { ItemSpriteSheet.RING_DIAMOND, + ItemSpriteSheet.RING_OPAL, ItemSpriteSheet.RING_GARNET, + ItemSpriteSheet.RING_RUBY, ItemSpriteSheet.RING_AMETHYST, + ItemSpriteSheet.RING_TOPAZ, ItemSpriteSheet.RING_ONYX, + ItemSpriteSheet.RING_TOURMALINE, ItemSpriteSheet.RING_EMERALD, + ItemSpriteSheet.RING_SAPPHIRE, ItemSpriteSheet.RING_QUARTZ, + ItemSpriteSheet.RING_AGATE }; + + private static ItemStatusHandler handler; + + private String gem; + + private int ticksToKnow = TICKS_TO_KNOW; + + @SuppressWarnings("unchecked") + public static void initGems() { + handler = new ItemStatusHandler((Class[]) rings, + gems, images); + } + + public static void save(Bundle bundle) { + handler.save(bundle); + } + + @SuppressWarnings("unchecked") + public static void restore(Bundle bundle) { + handler = new ItemStatusHandler((Class[]) rings, + gems, images, bundle); + } + + public Ring() { + super(); + sync(); + } + + @Override + public void sync() { + super.sync(); + image = handler.image(this); + gem = handler.label(this); + } + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + actions.add(isEquipped(hero) ? AC_UNEQUIP : AC_EQUIP); + return actions; + } + + @Override + public boolean doEquip(Hero hero) { + + if (hero.belongings.misc1 != null && hero.belongings.misc2 != null && hero.belongings.misc3 != null) { + + GLog.w(Messages.get(Ring.class, "toomany")); + return false; + + } else { + + if (hero.belongings.misc1 == null) { + hero.belongings.misc1 = this; + } else if (hero.belongings.misc2 == null){ + hero.belongings.misc2 = this; + } else { + hero.belongings.misc3 = this; + } + + detach(hero.belongings.backpack); + + activate(hero); + + cursedKnown = true; + if (cursed) { + equipCursed(hero); + GLog.n(Messages.get(this, "cursed", this)); + } + + hero.spendAndNext(TIME_TO_EQUIP); + return true; + + } + + } + + @Override + public void activate(Char ch) { + buff = buff(); + buff.attachTo(ch); + } + + @Override + public boolean doUnequip(Hero hero, boolean collect, boolean single) { + if (super.doUnequip(hero, collect, single)) { + + if (hero.belongings.misc1 == this) { + hero.belongings.misc1 = null; + } else if (hero.belongings.misc2 == this) { + hero.belongings.misc2 = null; + } else { + hero.belongings.misc3 = null; + } + + hero.remove(buff); + buff = null; + + return true; + + } else { + + return false; + + } + } + + @Override + public boolean isEquipped(Hero hero) { + return hero.belongings.misc1 == this || hero.belongings.misc2 == this || hero.belongings.misc3 == this ; + } + + @Override + public Item upgrade() { + + super.upgrade(); + + if (buff != null) { + + Char owner = buff.target; + buff.detach(); + if ((buff = buff()) != null) { + buff.attachTo(owner); + } + } + + return this; + } + + public boolean isKnown() { + return handler.isKnown(this); + } + + protected void setKnown() { + if (!isKnown()) { + handler.know(this); + } + + Badges.validateAllRingsIdentified(); + } + + public String gem() { + return Messages.get(Ring.class, gem); + } + + @Override + public String name() { + return isKnown() ? super.name() : Messages.get(this, "unknown_name", gem()); + } + + @Override + public String info() { + + String desc = isKnown()? desc() : Messages.get(this, "unknown_desc", gem()); + + if (cursed && isEquipped( Dungeon.hero )) { + + desc += "\n\n" + Messages.get(Ring.class, "cursed_worn"); + + } else if (cursed && cursedKnown) { + + desc += "\n\n" + Messages.get(Ring.class, "curse_known", name()); + + } + + if (reinforced) { + desc += "\n\n" + Messages.get(Item.class, "reinforced"); + } + + if (isKnown()) { + desc += "\n\n" + statsInfo(); + } + + return desc; + } + + public Integer initials(){ + return isKnown() ? initials : null; + } + + protected String statsInfo(){ + return ""; + } + + @Override + public boolean isIdentified() { + return super.isIdentified() && isKnown(); + } + + @Override + public Item identify() { + setKnown(); + return super.identify(); + } + + @Override + public Item random() { + if (Random.Float() < 0.3f) { + level = -Random.Int(1, 3); + cursed = true; + } else + level = Random.Int(1, 2); + return this; + } + + public static boolean allKnown() { + return handler.known().size() == rings.length - 2; + } + + @Override + public int price() { + int price = 75; + if (cursed && cursedKnown) { + price /= 2; + } + if (levelKnown) { + if (level > 0) { + price *= (level + 1); + } else if (level < 0) { + price /= (1 - level); + } + } + if (price < 1) { + price = 1; + } + return price; + } + + protected RingBuff buff() { + return null; + } + + private static final String UNFAMILIRIARITY = "unfamiliarity"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(UNFAMILIRIARITY, ticksToKnow); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + if ((ticksToKnow = bundle.getInt(UNFAMILIRIARITY)) == 0) { + ticksToKnow = TICKS_TO_KNOW; + } + } + + public static int getBonus(Char target, Class type){ + int bonus = 0; + for (RingBuff buff : target.buffs(type)) { + bonus += buff.level; + } + return bonus; + } + + public class RingBuff extends Buff { + + //private static final String TXT_KNOWN = "This is a %s"; + + public int level; + + public RingBuff() { + level = Ring.this.level; + } + + @Override + public boolean attachTo(Char target) { + + /*if (target instanceof Hero + && ((Hero) target).heroClass == HeroClass.ROGUE + && !isKnown()) { + setKnown(); + GLog.i(Messages.get(Ring.class, "known", name())); + Badges.validateItemLevelAquired(Ring.this); + }*/ + + return super.attachTo(target); + } + + @Override + public boolean act() { + + //if (!isIdentified() && --ticksToKnow <= 0) { + //String gemName = name(); + //identify(); + //GLog.w(Messages.get(Ring.class, "identify", gemName, Ring.this.toString())); + //Badges.validateItemLevelAquired(Ring.this); + //} + + spend(TICK); + + return true; + } + } +} diff --git a/java/com/hmdzl/spspd/items/rings/RingOfAccuracy.java b/java/com/hmdzl/spspd/items/rings/RingOfAccuracy.java new file mode 100644 index 00000000..9d91c33f --- /dev/null +++ b/java/com/hmdzl/spspd/items/rings/RingOfAccuracy.java @@ -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 + */ +package com.hmdzl.spspd.items.rings; + +import com.hmdzl.spspd.messages.Messages; + +import java.text.DecimalFormat; + +public class RingOfAccuracy extends Ring { + + { + //name = "Ring of Accuracy"; + initials = 0; + } + + public String statsInfo() { + if (isIdentified()){ + return Messages.get(this, "stats",level,level/10); + } else { + return "???"; + } + } + + + @Override + protected RingBuff buff() { + return new Accuracy(); + } + + public class Accuracy extends RingBuff { + } +} diff --git a/java/com/hmdzl/spspd/items/rings/RingOfElements.java b/java/com/hmdzl/spspd/items/rings/RingOfElements.java new file mode 100644 index 00000000..5ce213da --- /dev/null +++ b/java/com/hmdzl/spspd/items/rings/RingOfElements.java @@ -0,0 +1,132 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.rings; + +import java.util.HashSet; + +import com.hmdzl.spspd.actors.blobs.ConfusionGas; +import com.hmdzl.spspd.actors.blobs.CorruptGas; +import com.hmdzl.spspd.actors.blobs.DarkGas; +import com.hmdzl.spspd.actors.blobs.ElectriShock; +import com.hmdzl.spspd.actors.blobs.FrostGas; +import com.hmdzl.spspd.actors.blobs.ParalyticGas; +import com.hmdzl.spspd.actors.blobs.ShockWeb; +import com.hmdzl.spspd.actors.blobs.SlowWeb; +import com.hmdzl.spspd.actors.blobs.ToxicGas; +import com.hmdzl.spspd.actors.blobs.VenomGas; +import com.hmdzl.spspd.actors.blobs.Web; +import com.hmdzl.spspd.actors.blobs.weather.WeatherOfRain; +import com.hmdzl.spspd.actors.blobs.weather.WeatherOfSand; +import com.hmdzl.spspd.actors.blobs.weather.WeatherOfSnow; +import com.hmdzl.spspd.actors.blobs.weather.WeatherOfSun; +import com.hmdzl.spspd.actors.buffs.Blindness; +import com.hmdzl.spspd.actors.buffs.Burning; +import com.hmdzl.spspd.actors.buffs.Disarm; +import com.hmdzl.spspd.actors.buffs.Locked; +import com.hmdzl.spspd.actors.buffs.Poison; +import com.hmdzl.spspd.actors.buffs.Silent; +import com.hmdzl.spspd.actors.mobs.BrokenRobot; +import com.hmdzl.spspd.actors.mobs.DM300; +import com.hmdzl.spspd.actors.mobs.Eye; +import com.hmdzl.spspd.actors.mobs.LitTower; +import com.hmdzl.spspd.actors.mobs.Otiluke; +import com.hmdzl.spspd.actors.mobs.GnollShaman; +import com.hmdzl.spspd.actors.mobs.Shell; +import com.hmdzl.spspd.actors.mobs.Warlock; +import com.hmdzl.spspd.actors.mobs.Yog; +import com.hmdzl.spspd.levels.traps.LightningTrap; +import com.hmdzl.spspd.levels.traps.SpearTrap; +import com.hmdzl.spspd.messages.Messages; +import com.watabou.utils.Random; + +public class RingOfElements extends Ring { + + { + //name = "Ring of Elements"; + initials = 1; + } + + public String statsInfo() { + if (isIdentified()){ + return Messages.get(this, "stats"); + } else { + return "???"; + } + } + + + @Override + protected RingBuff buff() { + return new Resistance(); + } + + private static final HashSet> EMPTY = new HashSet>(); + private static final HashSet> FULL; + static { + FULL = new HashSet>(); + FULL.add(Burning.class); + FULL.add(ToxicGas.class); + FULL.add(VenomGas.class); + FULL.add(SpearTrap.class); + FULL.add(ParalyticGas.class); + FULL.add(CorruptGas.class); + FULL.add(DarkGas.class); + FULL.add(ElectriShock.class); + FULL.add(FrostGas.class); + FULL.add(ConfusionGas.class); + FULL.add(ShockWeb.class); + FULL.add(SlowWeb.class); + FULL.add(Web.class); + FULL.add(Blindness.class); + FULL.add(Disarm.class); + FULL.add(Locked.class); + FULL.add(Silent.class); + FULL.add(WeatherOfRain.class); + FULL.add(WeatherOfSand.class); + FULL.add(WeatherOfSnow.class); + FULL.add(WeatherOfSun.class); + FULL.add(Poison.class); + FULL.add(LightningTrap.Electricity.class); + FULL.add(Warlock.class); + FULL.add(GnollShaman.class); + FULL.add(BrokenRobot.class); + FULL.add(DM300.class); + FULL.add(Eye.class); + FULL.add(Otiluke.class); + FULL.add(LitTower.class); + FULL.add(Shell.class); + FULL.add(Yog.BurningFist.class); + FULL.add(Yog.PinningFist.class); + + } + + public class Resistance extends RingBuff { + + public HashSet> resistances() { + if (Random.Int(level + 2) >= 2) { + return FULL; + } else { + return EMPTY; + } + } + + public float durationFactor() { + return level < 0 ? 1 : (1 + 0.5f * level) / (1 + level); + } + } +} diff --git a/java/com/hmdzl/spspd/items/rings/RingOfEnergy.java b/java/com/hmdzl/spspd/items/rings/RingOfEnergy.java new file mode 100644 index 00000000..110eeda1 --- /dev/null +++ b/java/com/hmdzl/spspd/items/rings/RingOfEnergy.java @@ -0,0 +1,33 @@ +package com.hmdzl.spspd.items.rings; + +import com.hmdzl.spspd.messages.Messages; + +import java.text.DecimalFormat; + +/** + * Created by debenhame on 10/09/2014. + */ +public class RingOfEnergy extends Ring { + // TODO: monitor this one as it goes, super hard to balance so you'll need + // some feedback. + { + //name = "Ring of Energy"; + initials = 11; + } + + public String statsInfo() { + if (isIdentified()){ + return Messages.get(this, "stats", new DecimalFormat("#.##").format(100f * (Math.pow(1.05f, level) - 1f))); + } else { + return "???"; + } + } + + @Override + protected RingBuff buff() { + return new Energy(); + } + + public class Energy extends RingBuff { + } +} diff --git a/java/com/hmdzl/spspd/items/rings/RingOfEvasion.java b/java/com/hmdzl/spspd/items/rings/RingOfEvasion.java new file mode 100644 index 00000000..b62543d9 --- /dev/null +++ b/java/com/hmdzl/spspd/items/rings/RingOfEvasion.java @@ -0,0 +1,45 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.rings; + +import com.hmdzl.spspd.messages.Messages; + +public class RingOfEvasion extends Ring { + + { + //name = "Ring of Evasion"; + initials = 2; + } + + public String statsInfo() { + if (isIdentified()){ + return Messages.get(this, "stats",level,level/5); + } else { + return "???"; + } + } + + + @Override + protected RingBuff buff() { + return new Evasion(); + } + + public class Evasion extends RingBuff { + } +} diff --git a/java/com/hmdzl/spspd/items/rings/RingOfForce.java b/java/com/hmdzl/spspd/items/rings/RingOfForce.java new file mode 100644 index 00000000..cdeb0a20 --- /dev/null +++ b/java/com/hmdzl/spspd/items/rings/RingOfForce.java @@ -0,0 +1,33 @@ +package com.hmdzl.spspd.items.rings; + +import com.hmdzl.spspd.messages.Messages; + +import java.text.DecimalFormat; + +/** + * Created by debenhame on 10/09/2014. + */ +public class RingOfForce extends Ring { + + { + //name = "Ring of Force"; + initials = 3; + } + + public String statsInfo() { + if (isIdentified()){ + return Messages.get(this, "stats", new DecimalFormat("#.##").format(100 * Math.min(3f,((level*1.00/10)*1f))), 3 + level, 3 * level + 12); + } else { + return "???"; + } + } + + + @Override + protected RingBuff buff() { + return new Force(); + } + + public class Force extends RingBuff { + } +} diff --git a/java/com/hmdzl/spspd/items/rings/RingOfFuror.java b/java/com/hmdzl/spspd/items/rings/RingOfFuror.java new file mode 100644 index 00000000..80475f23 --- /dev/null +++ b/java/com/hmdzl/spspd/items/rings/RingOfFuror.java @@ -0,0 +1,34 @@ +package com.hmdzl.spspd.items.rings; + +import com.hmdzl.spspd.messages.Messages; + +import java.text.DecimalFormat; + +/** + * Created by debenhame on 10/09/2014. + */ +public class RingOfFuror extends Ring { + + { + //name = "Ring of Furor"; + initials = 4; + } + + public String statsInfo() { + if (isIdentified()){ + return Messages.get(this, "stats",new DecimalFormat("#.##").format( Math.min(300f, level * 10f))); + } else { + return "???"; + } + } + + + @Override + protected RingBuff buff() { + return new Furor(); + } + + + public class Furor extends RingBuff { + } +} diff --git a/java/com/hmdzl/spspd/items/rings/RingOfHaste.java b/java/com/hmdzl/spspd/items/rings/RingOfHaste.java new file mode 100644 index 00000000..b6834ca6 --- /dev/null +++ b/java/com/hmdzl/spspd/items/rings/RingOfHaste.java @@ -0,0 +1,51 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.rings; + +import com.hmdzl.spspd.messages.Messages; + +import java.text.DecimalFormat; + +public class RingOfHaste extends Ring { + + { + //name = "Ring of Haste"; + initials = 5; + } + + public String statsInfo() { + if (isIdentified()){ + return Messages.get(this, "stats",new DecimalFormat("#.##").format(100f * Math.min(3,0.1*level))); + } else { + return "???"; + } + } + + + @Override + protected RingBuff buff() { + return new Haste(); + } + + + public class Haste extends RingBuff { + } + + + +} diff --git a/java/com/hmdzl/spspd/items/rings/RingOfMagic.java b/java/com/hmdzl/spspd/items/rings/RingOfMagic.java new file mode 100644 index 00000000..eb6bd77e --- /dev/null +++ b/java/com/hmdzl/spspd/items/rings/RingOfMagic.java @@ -0,0 +1,45 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.rings; + +import com.hmdzl.spspd.messages.Messages; + +public class RingOfMagic extends Ring { + + { + //name = "Ring of Magic"; + initials = 6; + } + + public String statsInfo() { + if (isIdentified()){ + return Messages.get(this, "stats", Math.min(30,level)); + } else { + return "???"; + } + } + + + @Override + protected RingBuff buff() { + return new Magic(); + } + + public class Magic extends RingBuff { + } +} diff --git a/java/com/hmdzl/spspd/items/rings/RingOfMight.java b/java/com/hmdzl/spspd/items/rings/RingOfMight.java new file mode 100644 index 00000000..bad00a53 --- /dev/null +++ b/java/com/hmdzl/spspd/items/rings/RingOfMight.java @@ -0,0 +1,33 @@ +package com.hmdzl.spspd.items.rings; + +import com.hmdzl.spspd.messages.Messages; + +/** + * Created by debenhame on 10/09/2014. + */ +public class RingOfMight extends Ring { + + { + //name = "Ring of Might"; + initials = 7; + } + + public String statsInfo() { + if (isIdentified()){ + return Messages.get(this, "stats",level/5,level*10); + } else { + return "???"; + } + } + + + + @Override + protected RingBuff buff() { + return new Might(); + } + + + public class Might extends RingBuff { + } +} diff --git a/java/com/hmdzl/spspd/items/rings/RingOfSharpshooting.java b/java/com/hmdzl/spspd/items/rings/RingOfSharpshooting.java new file mode 100644 index 00000000..e479c205 --- /dev/null +++ b/java/com/hmdzl/spspd/items/rings/RingOfSharpshooting.java @@ -0,0 +1,34 @@ +package com.hmdzl.spspd.items.rings; + +import com.hmdzl.spspd.messages.Messages; + +import java.text.DecimalFormat; + +/** + * Created by debenhame on 10/09/2014. + */ +public class RingOfSharpshooting extends Ring { + + { + //name = "Ring of Sharpshooting"; + initials = 8; + } + + public String statsInfo() { + if (isIdentified()){ + return Messages.get(this, "stats", level, new DecimalFormat("#.##").format(100f * (0.05*level))); + } else { + return "???"; + } + } + + + @Override + protected RingBuff buff() { + return new Aim(); + } + + + public class Aim extends RingBuff { + } +} diff --git a/java/com/hmdzl/spspd/items/rings/RingOfTenacity.java b/java/com/hmdzl/spspd/items/rings/RingOfTenacity.java new file mode 100644 index 00000000..01a13597 --- /dev/null +++ b/java/com/hmdzl/spspd/items/rings/RingOfTenacity.java @@ -0,0 +1,32 @@ +package com.hmdzl.spspd.items.rings; + +import com.hmdzl.spspd.messages.Messages; + +import java.text.DecimalFormat; + +/** + * Created by debenhame on 10/09/2014. + */ +public class RingOfTenacity extends Ring { + + { + //name = "Ring of Tenacity"; + initials = 9; + } + + public String statsInfo() { + if (isIdentified()){ + return Messages.get(this, "stats", new DecimalFormat("#.##").format(100f * Math.min(0.40, 1.00*level/75))); + } else { + return "???"; + } + } + + @Override + protected RingBuff buff() { + return new Tenacity(); + } + + public class Tenacity extends RingBuff { + } +} diff --git a/java/com/hmdzl/spspd/items/scrolls/InventoryScroll.java b/java/com/hmdzl/spspd/items/scrolls/InventoryScroll.java new file mode 100644 index 00000000..75b011e4 --- /dev/null +++ b/java/com/hmdzl/spspd/items/scrolls/InventoryScroll.java @@ -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 + */ +package com.hmdzl.spspd.items.scrolls; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.actors.buffs.Invisibility; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.windows.WndBag; +import com.hmdzl.spspd.windows.WndOptions; +import com.hmdzl.spspd.messages.Messages; +import com.watabou.noosa.audio.Sample; + +public abstract class InventoryScroll extends Scroll { + + protected String inventoryTitle = Messages.get(this, "inv_title"); + protected WndBag.Mode mode = WndBag.Mode.ALL; + + @Override + public void doRead() { + + if (!isKnown()) { + setKnown(); + identifiedByUse = true; + } else { + identifiedByUse = false; + } + + GameScene.selectItem( itemSelector, mode, inventoryTitle ); + } + + private void confirmCancelation() { + GameScene.show( new WndOptions( name(), Messages.get(this, "warning"), + Messages.get(this, "yes"), Messages.get(this, "no") ) { + @Override + protected void onSelect( int index ) { + switch (index) { + case 0: + curUser.spendAndNext( TIME_TO_READ ); + identifiedByUse = false; + break; + case 1: + GameScene.selectItem( itemSelector, mode, inventoryTitle ); + break; + } + } + public void onBackPressed() {}; + } ); + } + + protected abstract void onItemSelected( Item item ); + + protected static boolean identifiedByUse = false; + protected static WndBag.Listener itemSelector = new WndBag.Listener() { + @Override + public void onSelect( Item item ) { + + if (!(curItem instanceof InventoryScroll)){ + return; + } + + if (item != null) { + + ((InventoryScroll)curItem).onItemSelected( item ); + ((InventoryScroll)curItem).readAnimation(); + + Sample.INSTANCE.play( Assets.SND_READ ); + Invisibility.dispel(); + + } else if (identifiedByUse && !((Scroll)curItem).ownedByBook) { + + ((InventoryScroll)curItem).confirmCancelation(); + + } else if (!((Scroll)curItem).ownedByBook) { + + curItem.collect( curUser.belongings.backpack ); + + } + } + }; +} diff --git a/java/com/hmdzl/spspd/items/scrolls/Scroll.java b/java/com/hmdzl/spspd/items/scrolls/Scroll.java new file mode 100644 index 00000000..873b3da5 --- /dev/null +++ b/java/com/hmdzl/spspd/items/scrolls/Scroll.java @@ -0,0 +1,223 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.scrolls; + +import java.util.ArrayList; +import java.util.HashSet; + +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.Challenges; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.buffs.Blindness; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Locked; +import com.hmdzl.spspd.actors.buffs.Silent; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.hero.HeroClass; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.ItemStatusHandler; +import com.hmdzl.spspd.items.artifacts.UnstableSpellbook; +import com.hmdzl.spspd.sprites.HeroSprite; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public abstract class Scroll extends Item { + + public static final String AC_READ = "READ"; + + protected static final float TIME_TO_READ = 1f; + + protected int initials; + + private static final Class[] scrolls = { ScrollOfIdentify.class, + ScrollOfMagicMapping.class, ScrollOfRecharging.class, + ScrollOfRemoveCurse.class, ScrollOfTeleportation.class, + ScrollOfUpgrade.class, ScrollOfRage.class, ScrollOfTerror.class, + ScrollOfLullaby.class, ScrollOfMagicalInfusion.class, + ScrollOfPsionicBlast.class, ScrollOfMirrorImage.class, ScrollOfRegrowth.class, ScrollOfSacrifice.class }; + private static final String[] runes = { "KAUNAN", "SOWILO", "LAGUZ", + "YNGVI", "GYFU", "RAIDO", "ISAZ", "MANNAZ", "NAUDIZ", "BERKANAN", + "NCOSRANE", "TIWAZ", "NENDIL", "LIBRA" }; + private static final Integer[] images = { ItemSpriteSheet.SCROLL_KAUNAN, + ItemSpriteSheet.SCROLL_SOWILO, ItemSpriteSheet.SCROLL_LAGUZ, + ItemSpriteSheet.SCROLL_YNGVI, ItemSpriteSheet.SCROLL_GYFU, + ItemSpriteSheet.SCROLL_RAIDO, ItemSpriteSheet.SCROLL_ISAZ, + ItemSpriteSheet.SCROLL_MANNAZ, ItemSpriteSheet.SCROLL_NAUDIZ, + ItemSpriteSheet.SCROLL_BERKANAN, ItemSpriteSheet.SCROLL_NCOSRANE, + ItemSpriteSheet.SCROLL_TIWAZ, ItemSpriteSheet.SCROLL_NENDIL, ItemSpriteSheet.SCROLL_LIBRA }; + + private static ItemStatusHandler handler; + + private String rune; + + public boolean ownedByBook = false; + + { + stackable = true; + defaultAction = AC_READ; + } + + @SuppressWarnings("unchecked") + public static void initLabels() { + handler = new ItemStatusHandler( + (Class[]) scrolls, runes, images); + } + + public static void save(Bundle bundle) { + handler.save(bundle); + } + + @SuppressWarnings("unchecked") + public static void restore(Bundle bundle) { + handler = new ItemStatusHandler( + (Class[]) scrolls, runes, images, bundle); + } + + public Scroll() { + super(); + sync(); + } + + @Override + public void sync() { + super.sync(); + image = handler.image(this); + rune = handler.label(this); + }; + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + actions.add(AC_READ); + return actions; + } + + @Override + public void execute(Hero hero, String action) { + if (action.equals(AC_READ)) { + + if (hero.buff(Blindness.class) != null ) { + GLog.w(Messages.get(this, "blinded")); + } else if (hero.buff(Locked.class) != null ) { + GLog.w(Messages.get(this, "locked")); + } else if (hero.buff(Silent.class) != null ) { + GLog.w(Messages.get(this, "silent")); + } else if (hero.buff(UnstableSpellbook.bookRecharge.class) != null + && hero.buff(UnstableSpellbook.bookRecharge.class) + .isCursed() + && !(this instanceof ScrollOfRemoveCurse)) { + GLog.n(Messages.get(this, "cursed") ); + } else { + curUser = hero; + if (!(Dungeon.hero.heroClass == HeroClass.FOLLOWER ) || (Dungeon.hero.heroClass == HeroClass.FOLLOWER && Random.Int(10)>=1 )) + curItem = detach(hero.belongings.backpack); + doRead(); + //readAnimation(); + } + + } else { + + super.execute(hero, action); + + } + } + + public abstract void doRead(); + + //currently only used in scrolls owned by the unstable spellbook + public abstract void empoweredRead(); + + protected void readAnimation() { + curUser.spend( TIME_TO_READ ); + curUser.busy(); + ((HeroSprite)curUser.sprite).read(); + if (Dungeon.isChallenged(Challenges.ITEM_PHOBIA)){ + Buff.affect(curUser, Silent.class, 5f); + int damage = curUser.HT/10; + curUser.damage(damage, this); + } + } + + public boolean isKnown() { + return handler.isKnown(this); + } + + public void setKnown() { + if (!isKnown() && !ownedByBook) { + handler.know(this); + } + + Badges.validateAllScrollsIdentified(); + } + + @Override + public Item identify() { + setKnown(); + return super.identify(); + } + + public String rune() { + return Messages.get(Scroll.class, rune); + } + + @Override + public String name() { + return isKnown() ? name : Messages.get(this, "unknown_name", rune()); + } + + @Override + public String info() { + return isKnown() ? + desc() : + Messages.get(this, "unknown_desc", rune()); + } + + public Integer initials(){ + return isKnown() ? initials : null; + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return isKnown(); + } + + public static HashSet> getKnown() { + return handler.known(); + } + + public static HashSet> getUnknown() { + return handler.unknown(); + } + + public static boolean allKnown() { + return handler.known().size() == scrolls.length; + } + + @Override + public int price() { + return 20 * quantity; + } +} diff --git a/java/com/hmdzl/spspd/items/scrolls/ScrollOfIdentify.java b/java/com/hmdzl/spspd/items/scrolls/ScrollOfIdentify.java new file mode 100644 index 00000000..01f443a3 --- /dev/null +++ b/java/com/hmdzl/spspd/items/scrolls/ScrollOfIdentify.java @@ -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 + */ +package com.hmdzl.spspd.items.scrolls; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.effects.Identification; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.utils.GLog; +import com.hmdzl.spspd.windows.WndBag; +import com.hmdzl.spspd.messages.Messages; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Random; + +import java.util.ArrayList; + +public class ScrollOfIdentify extends InventoryScroll { + + { + //name = "Scroll of Identify"; + //inventoryTitle = "Select an item to identify"; + mode = WndBag.Mode.UNIDENTIFED; + consumedValue = 10; + initials = 1; + + } + + @Override + public void empoweredRead() { + ArrayList unIDed = new ArrayList<>(); + + for( Item i : curUser.belongings){ + if (!i.isIdentified()){ + unIDed.add(i); + } + } + + if (unIDed.size() > 1) { + Random.element(unIDed).identify(); + Sample.INSTANCE.play( Assets.SND_TELEPORT ); + } + + doRead(); + } + + @Override + protected void onItemSelected(Item item) { + + curUser.sprite.parent.add(new Identification(curUser.sprite.center() + .offset(0, -16))); + + item.identify(); + GLog.i(Messages.get(this, "it_is", item)); + readAnimation(); + Badges.validateItemLevelAquired(item); + } + + + + @Override + public int price() { + return isKnown() ? 30 * quantity : super.price(); + } +} diff --git a/java/com/hmdzl/spspd/items/scrolls/ScrollOfLullaby.java b/java/com/hmdzl/spspd/items/scrolls/ScrollOfLullaby.java new file mode 100644 index 00000000..f18f5191 --- /dev/null +++ b/java/com/hmdzl/spspd/items/scrolls/ScrollOfLullaby.java @@ -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 + */ +package com.hmdzl.spspd.items.scrolls; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.buffs.ArmorBreak; +import com.hmdzl.spspd.actors.buffs.AttackDown; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Drowsy; +import com.hmdzl.spspd.actors.buffs.Invisibility; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.utils.GLog; +import com.hmdzl.spspd.messages.Messages; +import com.watabou.noosa.audio.Sample; + +public class ScrollOfLullaby extends Scroll { + + { + //name = "Scroll of Lullaby"; + consumedValue = 5; + initials = 2; + } + + @Override + public void doRead() { + + curUser.sprite.centerEmitter() + .start(Speck.factory(Speck.NOTE), 0.3f, 5); + Sample.INSTANCE.play(Assets.SND_LULLABY); + Invisibility.dispel(); + + for (Mob mob : Dungeon.level.mobs.toArray(new Mob[0])) { + if (Level.fieldOfView[mob.pos]) { + Buff.affect(mob, Drowsy.class); + Buff.affect(mob, AttackDown.class,10f).level(50); + Buff.affect(mob, ArmorBreak.class,10f).level(50); + mob.sprite.centerEmitter().start(Speck.factory(Speck.NOTE), + 0.3f, 5); + } + } + + Buff.affect(curUser, Drowsy.class); + Buff.affect(curUser, AttackDown.class,10f).level(20); + Buff.affect(curUser, ArmorBreak.class,10f).level(20); + + GLog.i(Messages.get(this, "sooth")); + + setKnown(); + + readAnimation(); + } + + @Override + public void empoweredRead() { + doRead(); + for (Mob mob : Dungeon.level.mobs.toArray( new Mob[0] )) { + if (Level.fieldOfView[mob.pos]) { + Buff drowsy = mob.buff(Drowsy.class); + if (drowsy != null) drowsy.act(); + } + } + } + + @Override + public int price() { + return isKnown() ? 40 * quantity : super.price(); + } +} diff --git a/java/com/hmdzl/spspd/items/scrolls/ScrollOfMagicMapping.java b/java/com/hmdzl/spspd/items/scrolls/ScrollOfMagicMapping.java new file mode 100644 index 00000000..7ded8048 --- /dev/null +++ b/java/com/hmdzl/spspd/items/scrolls/ScrollOfMagicMapping.java @@ -0,0 +1,146 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.scrolls; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.buffs.Invisibility; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.effects.SpellSprite; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.Terrain; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.noosa.audio.Sample; + +public class ScrollOfMagicMapping extends Scroll { + + { + //name = "Scroll of Magic Mapping"; + consumedValue = 10; + initials = 4; + } + + @Override + public void doRead() { + + int length = Level.LENGTH; + //int[] map = Dungeon.level.map; + boolean[] mapped = Dungeon.level.mapped; + boolean[] discoverable = Level.discoverable; + + //boolean noticed = false; + + for (int i = 0; i < length; i++) { + + //int terr = map[i]; + + if (discoverable[i]) { + + mapped[i] = true; + //if ((Terrain.flags[terr] & Terrain.SECRET) != 0) { + + //Level.set(i, Terrain.discover(terr)); + //GameScene.updateMap(i); + //Dungeon.level.discover( i ); + + //if (Dungeon.visible[i]) { + //GameScene.discoverTile(i, terr); + //discover(i); + + //noticed = true; + //} + //} + } + } + Dungeon.observe(); + + GLog.i(Messages.get(this, "layout")); + //if (noticed) { + //Sample.INSTANCE.play(Assets.SND_SECRET); + //} + + //SpellSprite.show(curUser, SpellSprite.MAP); + //Sample.INSTANCE.play(Assets.SND_READ); + Invisibility.dispel(); + + setKnown(); + + readAnimation(); + } + + @Override + public void empoweredRead() { + doRead(); + int length = Level.LENGTH; + int[] map = Dungeon.level.map; + boolean[] mapped = Dungeon.level.mapped; + boolean[] discoverable = Level.discoverable; + + boolean noticed = false; + + for (int i = 0; i < length; i++) { + + int terr = map[i]; + + if (discoverable[i]) { + + mapped[i] = true; + if ((Terrain.flags[terr] & Terrain.SECRET) != 0) { + + //Level.set(i, Terrain.discover(terr)); + //GameScene.updateMap(i); + Dungeon.level.discover( i ); + + if (Dungeon.visible[i]) { + GameScene.discoverTile(i, terr); + discover(i); + + noticed = true; + } + } + } + } + Dungeon.observe(); + + GLog.i(Messages.get(this, "layout")); + if (noticed) { + Sample.INSTANCE.play(Assets.SND_SECRET); + } + + SpellSprite.show(curUser, SpellSprite.MAP); + Sample.INSTANCE.play(Assets.SND_READ); + Invisibility.dispel(); + + setKnown(); + + curUser.spendAndNext(TIME_TO_READ); + Dungeon.observe(); + } + + @Override + public int price() { + return isKnown() ? 50 * quantity : super.price(); + } + + public static void discover(int cell) { + CellEmitter.get(cell).start(Speck.factory(Speck.DISCOVER), 0.1f, 4); + } +} diff --git a/java/com/hmdzl/spspd/items/scrolls/ScrollOfMagicalInfusion.java b/java/com/hmdzl/spspd/items/scrolls/ScrollOfMagicalInfusion.java new file mode 100644 index 00000000..c7685c0c --- /dev/null +++ b/java/com/hmdzl/spspd/items/scrolls/ScrollOfMagicalInfusion.java @@ -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 + */ +package com.hmdzl.spspd.items.scrolls; + +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.armor.Armor; +import com.hmdzl.spspd.items.weapon.Weapon; +import com.hmdzl.spspd.utils.GLog; +import com.hmdzl.spspd.windows.WndBag; +import com.hmdzl.spspd.messages.Messages; + +public class ScrollOfMagicalInfusion extends InventoryScroll { + + { + //name = "Scroll of Magical Infusion"; + //inventoryTitle = "Select an item to infuse"; + mode = WndBag.Mode.ENCHANTABLE; + consumedValue = 15; + initials = 3; + + + } + + @Override + protected void onItemSelected(Item item) { + + ScrollOfRemoveCurse.uncurse(Dungeon.hero, item); + if (item instanceof Weapon) + ((Weapon) item).upgrade(true); + else + ((Armor) item).upgrade(true); + + GLog.p(Messages.get(this, "infuse", item.name())); + + Badges.validateItemLevelAquired(item); + + curUser.sprite.emitter().start(Speck.factory(Speck.UP), 0.2f, 3); + readAnimation(); + } + + @Override + public void empoweredRead() { + //does nothing for now, this should never happen. + } + + @Override + public int price() { + return isKnown() ? 100 * quantity : super.price(); + } +} diff --git a/java/com/hmdzl/spspd/items/scrolls/ScrollOfMirrorImage.java b/java/com/hmdzl/spspd/items/scrolls/ScrollOfMirrorImage.java new file mode 100644 index 00000000..e2f6d85e --- /dev/null +++ b/java/com/hmdzl/spspd/items/scrolls/ScrollOfMirrorImage.java @@ -0,0 +1,207 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.scrolls; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Invisibility; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.mobs.npcs.MirrorImage; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.utils.GLog; +import com.hmdzl.spspd.messages.Messages; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Bundle; +import com.watabou.utils.PathFinder; +import com.watabou.utils.Random; + +public class ScrollOfMirrorImage extends Scroll { + + private static final int NIMAGES = 3; + + { + //name = "Scroll of Mirror Image"; + consumedValue = 5; + initials = 5; + } + + private static final String TXT_PREVENTING = "Something scrambles the illusion magic! "; + + @Override + public void doRead() { + + if (Dungeon.depth>50){ + GLog.w( Messages.get(Scroll.class, "prevent")); + Sample.INSTANCE.play(Assets.SND_READ); + Invisibility.dispel(); + + setKnown(); + + curUser.spendAndNext(TIME_TO_READ); + return; + } + + ArrayList respawnPoints = new ArrayList(); + + for (int i = 0; i < Level.NEIGHBOURS8.length; i++) { + int p = curUser.pos + Level.NEIGHBOURS8[i]; + if (Actor.findChar(p) == null + && (Level.passable[p] || Level.avoid[p])) { + respawnPoints.add(p); + } + } + + int nImages = NIMAGES; + while (nImages > 0 && respawnPoints.size() > 0) { + int index = Random.index(respawnPoints); + + MirrorImage mob = new MirrorImage(); + mob.duplicate(curUser); + GameScene.add(mob); + ScrollOfTeleportation.appear(mob, respawnPoints.get(index)); + + respawnPoints.remove(index); + nImages--; + } + + if (nImages < NIMAGES) { + setKnown(); + } + + Sample.INSTANCE.play(Assets.SND_READ); + Invisibility.dispel(); + readAnimation(); + } + + @Override + public void empoweredRead() { + //spawns 2 images right away, delays 4 of them, 6 total. + new DelayedImageSpawner(6 - spawnImages(curUser, 2), 2, 3).attachTo(curUser); + + setKnown(); + + Sample.INSTANCE.play( Assets.SND_READ ); + Invisibility.dispel(); + + curUser.spendAndNext(TIME_TO_READ); + } + + //returns the number of images spawned + public static int spawnImages(Hero hero, int nImages ){ + + ArrayList respawnPoints = new ArrayList(); + + for (int i = 0; i < PathFinder.NEIGHBOURS8.length; i++) { + int p = hero.pos + PathFinder.NEIGHBOURS8[i]; + if (Actor.findChar( p ) == null && (Dungeon.level.passable[p] || Dungeon.level.avoid[p])) { + respawnPoints.add( p ); + } + } + + int spawned = 0; + while (nImages > 0 && respawnPoints.size() > 0) { + int index = Random.index( respawnPoints ); + + MirrorImage mob = new MirrorImage(); + mob.duplicate( hero ); + GameScene.add( mob ); + ScrollOfTeleportation.appear( mob, respawnPoints.get( index ) ); + + respawnPoints.remove( index ); + nImages--; + spawned++; + } + + return spawned; + } + + public static class DelayedImageSpawner extends Buff { + + public DelayedImageSpawner(){ + this(NIMAGES, NIMAGES, 1); + } + + public DelayedImageSpawner( int total, int perRound, float delay){ + super(); + totImages = total; + imPerRound = perRound; + this.delay = delay; + } + + private int totImages; + private int imPerRound; + private float delay; + + @Override + public boolean attachTo(Char target) { + if (super.attachTo(target)){ + spend(delay); + return true; + } else { + return false; + } + } + + @Override + public boolean act() { + + int spawned = spawnImages((Hero)target, Math.min(totImages, imPerRound)); + + totImages -= spawned; + + if (totImages <0){ + detach(); + } else { + spend( delay ); + } + + return true; + } + + private static final String TOTAL = "images"; + private static final String PER_ROUND = "per_round"; + private static final String DELAY = "delay"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put( TOTAL, totImages ); + bundle.put( PER_ROUND, imPerRound ); + bundle.put( DELAY, delay ); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + totImages = bundle.getInt( TOTAL ); + imPerRound = bundle.getInt( PER_ROUND ); + delay = bundle.getFloat( DELAY ); + } + } + + @Override + public int price() { + return isKnown() ? 30 * quantity : super.price(); + } +} diff --git a/java/com/hmdzl/spspd/items/scrolls/ScrollOfMultiUpgrade.java b/java/com/hmdzl/spspd/items/scrolls/ScrollOfMultiUpgrade.java new file mode 100644 index 00000000..741d4e3a --- /dev/null +++ b/java/com/hmdzl/spspd/items/scrolls/ScrollOfMultiUpgrade.java @@ -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 + */ +package com.hmdzl.spspd.items.scrolls; + +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.utils.GLog; +import com.hmdzl.spspd.windows.WndBag; + +public class ScrollOfMultiUpgrade extends InventoryScroll { + + private static final String TXT_LOOKS_BETTER = "your %s certainly looks better now"; + + { + name = "Scroll of Multi Upgrade"; + inventoryTitle = "Select an item to upgrade"; + mode = WndBag.Mode.UPGRADEABLE; + consumedValue = 10; + initials = 6; + + + } + + @Override + protected void onItemSelected(Item item) { + + ScrollOfRemoveCurse.uncurse(Dungeon.hero, item); + item.upgrade(); + + for(int i=1; i<6; i++){ + upgrade(curUser); + } + GLog.p(TXT_LOOKS_BETTER, item.name()); + + Badges.validateItemLevelAquired(item); + } + + @Override + public void empoweredRead() { + //does nothing for now, this should never happen. + } + + public static void upgrade(Hero hero) { + hero.sprite.emitter().start(Speck.factory(Speck.UP), 0.2f, 3); + } + + + + @Override + public String desc() { + return "This scroll will upgrade a single item five times, improving its quality. A wand will " + + "increase in power and in number of charges; a weapon will inflict more damage " + + "or find its mark more frequently; a suit of armor will deflect additional blows; " + + "the effect of a ring on its wearer will intensify. Weapons and armor will also " + + "require less strength to use, and any curses on the item will be lifted."; + } +} diff --git a/java/com/hmdzl/spspd/items/scrolls/ScrollOfPsionicBlast.java b/java/com/hmdzl/spspd/items/scrolls/ScrollOfPsionicBlast.java new file mode 100644 index 00000000..45f27034 --- /dev/null +++ b/java/com/hmdzl/spspd/items/scrolls/ScrollOfPsionicBlast.java @@ -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 + */ +package com.hmdzl.spspd.items.scrolls; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Blindness; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Invisibility; +import com.hmdzl.spspd.actors.buffs.Paralysis; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.scenes.GameScene; + +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Random; + +public class ScrollOfPsionicBlast extends Scroll { + + { + //name = "Scroll of Psionic Blast"; + consumedValue = 10; + initials = 7; + + + } + + @Override + public void doRead() { + + GameScene.flash(0xFFFFFF); + + Sample.INSTANCE.play(Assets.SND_BLAST); + Invisibility.dispel(); + + for (Mob mob : Dungeon.level.mobs.toArray(new Mob[0])) { + if (Level.fieldOfView[mob.pos] && !mob.properties().contains(Char.Property.BOSS)) { + mob.damage(mob.HT, this); + } else mob.damage(1, this); + } + + curUser.damage(Math.max(curUser.HT / 5, curUser.HP / 2), this); + Buff.prolong(curUser, Paralysis.class, Random.Int(4, 6)); + Buff.prolong(curUser, Blindness.class, Random.Int(6, 9)); + Dungeon.observe(); + + setKnown(); + + readAnimation(); + + } + + @Override + public void empoweredRead() { + GameScene.flash( 0xFFFFFF ); + + Sample.INSTANCE.play( Assets.SND_BLAST ); + Invisibility.dispel(); + + for (Mob mob : Dungeon.level.mobs.toArray( new Mob[0] )) { + if (Level.fieldOfView[mob.pos]) { + mob.damage(mob.HT, this ); + } + } + + setKnown(); + + curUser.spendAndNext(TIME_TO_READ); + } + + public boolean checkOriginalGenMobs (){ + for (Mob mob : Dungeon.level.mobs.toArray(new Mob[0])) { + if (mob.originalgen){return true;} + } + return false; + } + + @Override + public int price() { + return isKnown() ? 80 * quantity : super.price(); + } +} diff --git a/java/com/hmdzl/spspd/items/scrolls/ScrollOfRage.java b/java/com/hmdzl/spspd/items/scrolls/ScrollOfRage.java new file mode 100644 index 00000000..288b041a --- /dev/null +++ b/java/com/hmdzl/spspd/items/scrolls/ScrollOfRage.java @@ -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 + */ +package com.hmdzl.spspd.items.scrolls; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.buffs.Amok; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Invisibility; +import com.hmdzl.spspd.actors.buffs.Silent; +import com.hmdzl.spspd.actors.mobs.Mimic; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.Heap; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.utils.GLog; +import com.hmdzl.spspd.messages.Messages; +import com.watabou.noosa.audio.Sample; + +public class ScrollOfRage extends Scroll { + + { + //name = "Scroll of Rage"; + consumedValue = 5; + initials = 8; + } + + @Override + public void doRead() { + + for (Mob mob : Dungeon.level.mobs.toArray(new Mob[0])) { + mob.beckon(curUser.pos); + if (Level.fieldOfView[mob.pos]) { + Buff.prolong(mob, Amok.class, 5f); + Buff.affect(mob, Silent.class, 20f); + } + } + + for (Heap heap : Dungeon.level.heaps.values()) { + if (heap.type == Heap.Type.MIMIC) { + Mimic m = Mimic.spawnAt(heap.pos, heap.items); + if (m != null) { + m.beckon(curUser.pos); + heap.destroy(); + } + } + } + + GLog.w( Messages.get(this, "roar")); + setKnown(); + + curUser.sprite.centerEmitter().start(Speck.factory(Speck.SCREAM), 0.3f, + 3); + Sample.INSTANCE.play(Assets.SND_CHALLENGE); + Invisibility.dispel(); + + readAnimation(); + } + + @Override + public void empoweredRead() { + for (Mob mob : Dungeon.level.mobs.toArray( new Mob[0] )) { + if (Level.fieldOfView[mob.pos]) { + Buff.prolong(mob, Amok.class, 10f); + Buff.affect(mob, Silent.class, 40f); + } + } + + setKnown(); + + curUser.sprite.centerEmitter().start( Speck.factory( Speck.SCREAM ), 0.3f, 3 ); + Sample.INSTANCE.play( Assets.SND_READ ); + Invisibility.dispel(); + + curUser.spendAndNext(TIME_TO_READ); + } + + @Override + public int price() { + return isKnown() ? 30 * quantity : super.price(); + } + +} diff --git a/java/com/hmdzl/spspd/items/scrolls/ScrollOfRecharging.java b/java/com/hmdzl/spspd/items/scrolls/ScrollOfRecharging.java new file mode 100644 index 00000000..ba9a6596 --- /dev/null +++ b/java/com/hmdzl/spspd/items/scrolls/ScrollOfRecharging.java @@ -0,0 +1,73 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.scrolls; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.actors.buffs.Arcane; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Recharging; +import com.hmdzl.spspd.actors.buffs.Invisibility; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.SpellSprite; +import com.hmdzl.spspd.effects.particles.EnergyParticle; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.noosa.audio.Sample; +import com.hmdzl.spspd.messages.Messages; + +public class ScrollOfRecharging extends Scroll { + + public static final float BUFF_DURATION = 30f; + { + //name = "Scroll of Recharging"; + consumedValue = 10; + initials = 10; + } + + @Override + public void doRead() { + + Buff.affect(curUser, Recharging.class, BUFF_DURATION); + Buff.affect(curUser, Arcane.class, BUFF_DURATION); + charge(curUser); + + Sample.INSTANCE.play( Assets.SND_READ ); + Invisibility.dispel(); + + GLog.i(Messages.get(this, "surge")); + SpellSprite.show( curUser, SpellSprite.CHARGE ); + setKnown(); + + readAnimation(); + } + + @Override + public void empoweredRead() { + doRead(); + Buff.append(curUser, Recharging.class, BUFF_DURATION/3f); + } + + public static void charge( Hero hero ) { + hero.sprite.centerEmitter().burst( EnergyParticle.FACTORY, 15 ); + } + + @Override + public int price() { + return isKnown() ? 40 * quantity : super.price(); + } + +} diff --git a/java/com/hmdzl/spspd/items/scrolls/ScrollOfRegrowth.java b/java/com/hmdzl/spspd/items/scrolls/ScrollOfRegrowth.java new file mode 100644 index 00000000..5bcfc638 --- /dev/null +++ b/java/com/hmdzl/spspd/items/scrolls/ScrollOfRegrowth.java @@ -0,0 +1,64 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.scrolls; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.actors.blobs.Blob; +import com.hmdzl.spspd.actors.blobs.Water; +import com.hmdzl.spspd.actors.buffs.Invisibility; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.scenes.GameScene; +import com.watabou.noosa.audio.Sample; + +public class ScrollOfRegrowth extends Scroll { + + { + //name = "Scroll of Regrowth"; + consumedValue = 15; + initials = 9; + } + + @Override + public void doRead() { + int length = Level.getLength(); + + for (int i = 0; i < length; i++) { + + GameScene.add(Blob.seed(i, (2) * 20, Water.class)); + + } + + Sample.INSTANCE.play(Assets.SND_READ); + Invisibility.dispel(); + + setKnown(); + + readAnimation(); + } + + @Override + public void empoweredRead() { + //does nothing for now, this should never happen. + } + + @Override + public int price() { + return isKnown() ? 100 * quantity : super.price(); + } + +} diff --git a/java/com/hmdzl/spspd/items/scrolls/ScrollOfRemoveCurse.java b/java/com/hmdzl/spspd/items/scrolls/ScrollOfRemoveCurse.java new file mode 100644 index 00000000..d3bcd90e --- /dev/null +++ b/java/com/hmdzl/spspd/items/scrolls/ScrollOfRemoveCurse.java @@ -0,0 +1,112 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.scrolls; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Invisibility; +import com.hmdzl.spspd.actors.buffs.Weakness; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.Flare; +import com.hmdzl.spspd.effects.particles.ShadowParticle; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.bags.Bag; +import com.hmdzl.spspd.utils.GLog; +import com.hmdzl.spspd.messages.Messages; +import com.watabou.noosa.audio.Sample; + +public class ScrollOfRemoveCurse extends Scroll { + + { + //name = "Scroll of Remove Curse"; + consumedValue = 15; + initials = 11; + } + + @Override + public void doRead() { + + new Flare(6, 32).show(curUser.sprite, 2f); + Sample.INSTANCE.play(Assets.SND_READ); + Invisibility.dispel(); + + boolean procced = uncurse(curUser, + curUser.belongings.backpack.items.toArray(new Item[0])); + procced = uncurse(curUser, curUser.belongings.weapon, + curUser.belongings.armor, curUser.belongings.misc1, + curUser.belongings.misc2, curUser.belongings.misc3 ) + || procced; + + Buff.detach(curUser, Weakness.class); + + if (procced) { + GLog.p(Messages.get(this, "cleansed") ); + } else { + GLog.i(Messages.get(this, "not_cleansed")); + } + + setKnown(); + + readAnimation(); + } + + public static boolean uncurse(Hero hero, Item... items) { + + boolean procced = false; + for (int i = 0; i < items.length; i++) { + Item item = items[i]; + if (item != null && item.cursed) { + item.uncurse(); + if(item.level<0){item.upgrade((-item.level)*2);} //upgrade to reverse of negatives + if (item.cursed==false) {procced = true;} + } + if (item instanceof Bag) { + for (Item bagItem: ((Bag)item).items){ + if (bagItem != null && bagItem.cursed) { + bagItem.uncurse(); + if(bagItem.level<0){bagItem.upgrade((-bagItem.level)*2);} + if (bagItem.cursed==false) {procced = true;} + } + } + } + } + + if (procced) { + hero.sprite.emitter().start(ShadowParticle.UP, 0.05f, 10); + } + + return procced; + } + + @Override + public void empoweredRead() { + for (Item item : curUser.belongings){ + if (item.cursed){ + item.cursedKnown = true; + } + } + Sample.INSTANCE.play( Assets.SND_READ ); + Invisibility.dispel(); + doRead(); + } + + @Override + public int price() { + return isKnown() ? 30 * quantity : super.price(); + } +} diff --git a/java/com/hmdzl/spspd/items/scrolls/ScrollOfSacrifice.java b/java/com/hmdzl/spspd/items/scrolls/ScrollOfSacrifice.java new file mode 100644 index 00000000..68313f3a --- /dev/null +++ b/java/com/hmdzl/spspd/items/scrolls/ScrollOfSacrifice.java @@ -0,0 +1,62 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 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 + */ +package com.hmdzl.spspd.items.scrolls; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.CharSprite; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Random; + +public class ScrollOfSacrifice extends Scroll { + + { + //name = "Scroll of Sacrifice"; + consumedValue = 15; + initials = 15; + } + + @Override + public void doRead() { + + if(Dungeon.sacrifice==0){Dungeon.hero.HT +=5; + Dungeon.hero.sprite.showStatus(CharSprite.POSITIVE, Messages.get(this, "use_1")); + } + else if(Dungeon.sacrifice > 0){Dungeon.hero.STR++; + Dungeon.hero.sprite.showStatus(CharSprite.POSITIVE, Messages.get(this, "use_2")); + } + if(Dungeon.sacrifice > 1) {Dungeon.hero.HT-= Random.Int(5*Dungeon.sacrifice,Dungeon.hero.HT/5); + GLog.w(Messages.get(this, "use_lot")); + } + + if(Dungeon.hero.HP > Dungeon.hero.HT) + {Dungeon.hero.HP = Dungeon.hero.HT;} + + setKnown(); + + readAnimation(); + + Dungeon.sacrifice++; + } + + @Override + public void empoweredRead() { + //does nothing for now, this should never happen. + } + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/scrolls/ScrollOfTeleportation.java b/java/com/hmdzl/spspd/items/scrolls/ScrollOfTeleportation.java new file mode 100644 index 00000000..d0a6f551 --- /dev/null +++ b/java/com/hmdzl/spspd/items/scrolls/ScrollOfTeleportation.java @@ -0,0 +1,191 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.scrolls; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Invisibility; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.mobs.npcs.SheepSokoban; +import com.hmdzl.spspd.actors.mobs.npcs.SheepSokobanCorner; +import com.hmdzl.spspd.actors.mobs.npcs.SheepSokobanSwitch; +import com.hmdzl.spspd.effects.particles.ShadowParticle; +import com.hmdzl.spspd.actors.mobs.npcs.Sheep; +import com.hmdzl.spspd.items.wands.WandOfFlock; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.Terrain; +import com.hmdzl.spspd.scenes.CellSelector; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.utils.GLog; +import com.hmdzl.spspd.messages.Messages; +import com.watabou.noosa.Camera; +import com.watabou.noosa.audio.Sample; +import com.hmdzl.spspd.effects.Speck; +import com.watabou.noosa.tweeners.AlphaTweener; + +public class ScrollOfTeleportation extends Scroll { + + { + //name = "Scroll of Teleportation"; + consumedValue = 10; + initials = 12; + } + + @Override + public void doRead() { + + Sample.INSTANCE.play(Assets.SND_READ); + Invisibility.dispel(); + + teleportHero(curUser); + setKnown(); + + readAnimation(); + } + + @Override + public void empoweredRead() { + + if (Dungeon.bossLevel()){ + GLog.w( Messages.get(this, "no_tele") ); + return; + } + + GameScene.selectCell(new CellSelector.Listener() { + @Override + public void onSelect(Integer target) { + if (target != null) { + //time isn't spent + //((HeroSprite)curUser.sprite).read(); + teleportHeroLocation(curUser, target); + } + } + + @Override + public String prompt() { + return Messages.get(ScrollOfTeleportation.class, "prompt"); + } + }); + } + + public static void teleportHero(Hero hero) { + + int count = 10; + int pos; + do { + pos = Dungeon.level.randomRespawnCell(); + if (count-- <= 0) { + break; + } + } while (pos == -1); + + if (pos == -1 || Dungeon.bossLevel()) { + + GLog.w( Messages.get(ScrollOfTeleportation.class, "no_tele")); + + } else { + + ScrollOfTeleportation.appear(hero, pos); + Dungeon.level.press(pos, hero); + Dungeon.observe(); + + GLog.i(Messages.get(ScrollOfTeleportation.class, "tele")); + + } + } + + public static void teleportHeroLocation(Hero hero, int spot) { + + Char ch = Actor.findChar(spot); + boolean sheepchk = false; + + if (ch!=null && (ch instanceof SheepSokoban || ch instanceof SheepSokobanSwitch || ch instanceof SheepSokobanCorner || ch instanceof Sheep || ch instanceof WandOfFlock.MagicSheep)){ + sheepchk = true; + } + + if (Level.passable[spot] && (Actor.findChar(spot) == null || sheepchk)) { + + //GLog.i("clear"); + + if (Actor.findChar(spot) != null && sheepchk){ + Camera.main.shake(2, 0.3f); + ch.destroy(); + ch.sprite.killAndErase(); + ch.sprite.emitter().burst(ShadowParticle.UP, 5); + Level.set(spot, Terrain.WOOL_RUG); + GameScene.updateMap(spot); + } + + ScrollOfTeleportation.appear(hero, spot); + Dungeon.level.press(spot, hero); + Dungeon.observe(); + + GLog.i(Messages.get(ScrollOfTeleportation.class, "tele")); + } + + + else { + + int count = 10; + int pos; + do { + pos = Dungeon.level.randomRespawnCell(); + if (count-- <= 0) { + break; + } + } while (pos == -1); + + if (pos == -1) { + + GLog.w(Messages.get(Scroll.class, "deact")); + + } else { + + ScrollOfTeleportation.appear(hero, pos); + Dungeon.level.press(pos, hero); + Dungeon.observe(); + + GLog.i(Messages.get(ScrollOfTeleportation.class, "tele")); + + } + } + } + + public static void appear( Char ch, int pos ) { + + ch.sprite.interruptMotion(); + + ch.move( pos ); + ch.sprite.place( pos ); + + if (ch.invisible == 0) { + ch.sprite.alpha( 0 ); + ch.sprite.parent.add( new AlphaTweener( ch.sprite, 1, 0.4f ) ); + } + + ch.sprite.emitter().start( Speck.factory(Speck.LIGHT), 0.2f, 3 ); + Sample.INSTANCE.play( Assets.SND_TELEPORT ); + } + + @Override + public int price() { + return isKnown() ? 30 * quantity : super.price(); + } +} diff --git a/java/com/hmdzl/spspd/items/scrolls/ScrollOfTerror.java b/java/com/hmdzl/spspd/items/scrolls/ScrollOfTerror.java new file mode 100644 index 00000000..6208b1bd --- /dev/null +++ b/java/com/hmdzl/spspd/items/scrolls/ScrollOfTerror.java @@ -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 + */ +package com.hmdzl.spspd.items.scrolls; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Haste; +import com.hmdzl.spspd.actors.buffs.Invisibility; +import com.hmdzl.spspd.actors.buffs.Paralysis; +import com.hmdzl.spspd.actors.buffs.Terror; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.effects.Flare; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.utils.GLog; +import com.hmdzl.spspd.messages.Messages; +import com.watabou.noosa.audio.Sample; + +public class ScrollOfTerror extends Scroll { + + { + //name = "Scroll of Terror"; + consumedValue = 5; + initials = 13; + } + + @Override + public void doRead() { + + new Flare(5, 32).color(0xFF0000, true).show(curUser.sprite, 2f); + Sample.INSTANCE.play(Assets.SND_READ); + Invisibility.dispel(); + + int count = 0; + Mob affected = null; + for (Mob mob : Dungeon.level.mobs.toArray(new Mob[0])) { + if (Level.fieldOfView[mob.pos]) { + Buff.affect(mob, Terror.class, Terror.DURATION).object = curUser + .id(); + Buff.affect(mob, Haste.class, Terror.DURATION*.5f); + + count++; + affected = mob; + } + } + + switch (count) { + case 0: + GLog.i(Messages.get(this, "none")); + break; + case 1: + GLog.i(Messages.get(this, "one", affected.name)); + break; + default: + GLog.i(Messages.get(this, "many") ); + } + setKnown(); + + readAnimation(); + } + + @Override + public void empoweredRead() { + doRead(); + for (Mob mob : Dungeon.level.mobs.toArray( new Mob[0] )) { + if (Level.fieldOfView[mob.pos]) { + Terror t = mob.buff(Terror.class); + if (t != null){ + Buff.prolong(mob, Terror.class, Terror.DURATION*1.5f); + Buff.affect(mob, Paralysis.class, Terror.DURATION*.5f); + Buff.affect(mob, Haste.class, Terror.DURATION*.5f); + } + } + } + } + + @Override + public int price() { + return isKnown() ? 30 * quantity : super.price(); + } +} diff --git a/java/com/hmdzl/spspd/items/scrolls/ScrollOfUpgrade.java b/java/com/hmdzl/spspd/items/scrolls/ScrollOfUpgrade.java new file mode 100644 index 00000000..203ab614 --- /dev/null +++ b/java/com/hmdzl/spspd/items/scrolls/ScrollOfUpgrade.java @@ -0,0 +1,64 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.scrolls; + +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.windows.WndBag; + +public class ScrollOfUpgrade extends InventoryScroll { + + { + //name = "Scroll of Upgrade"; + //inventoryTitle = "Select an item to upgrade"; + mode = WndBag.Mode.UPGRADEABLE; + consumedValue = 15; + initials = 14; + + + } + + @Override + protected void onItemSelected(Item item) { + + ScrollOfRemoveCurse.uncurse(Dungeon.hero, item); + item.upgrade(); + + upgrade(curUser); + //GLog.p(Messages.get(this, "looks_better", item.name())); + readAnimation(); + Badges.validateItemLevelAquired(item); + } + + public static void upgrade(Hero hero) { + hero.sprite.emitter().start(Speck.factory(Speck.UP), 0.2f, 3); + } + + @Override + public void empoweredRead() { + //does nothing for now, this should never happen. + } + + @Override + public int price() { + return 100 * quantity; + } +} diff --git a/java/com/hmdzl/spspd/items/skills/ClassSkill.java b/java/com/hmdzl/spspd/items/skills/ClassSkill.java new file mode 100644 index 00000000..2e2cac80 --- /dev/null +++ b/java/com/hmdzl/spspd/items/skills/ClassSkill.java @@ -0,0 +1,236 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.skills; + +import java.util.ArrayList; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Invisibility; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.bags.Bag; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.windows.WndItem; +import com.watabou.utils.Bundle; + +import static com.hmdzl.spspd.Dungeon.hero; + +abstract public class ClassSkill extends Item { + + private static final String AC_CHOOSE = "CHOOSE"; + + private static final String AC_SPECIAL = "SPECIAL"; + private static final String AC_SPECIAL_TWO = "SPECIAL_TWO"; + private static final String AC_SPECIAL_THREE = "SPECIAL_THREE"; + private static final String AC_SPECIAL_FOUR = "SPECIAL_FOUR"; + //private static int SKILL_TIME = 1; + public float colddown = 0f; + public static int charge = 0; + protected SkillCharger skillcharger; + + { + defaultAction = AC_CHOOSE; + unique = true; + } + + public static ClassSkill upgrade(Hero owner) { + + ClassSkill classSkill = null; + + switch (owner.heroClass) { + case WARRIOR: + classSkill = new WarriorSkill(); + break; + case ROGUE: + classSkill = new RogueSkill(); + break; + case MAGE: + classSkill = new MageSkill(); + break; + case HUNTRESS: + classSkill = new HuntressSkill(); + break; + case PERFORMER: + classSkill = new PerformerSkill(); + break; + case SOLDIER: + classSkill = new SoldierSkill(); + break; + case FOLLOWER: + classSkill = new FollowerSkill(); + break; + } + classSkill.charge = 0; + return classSkill; + } + + @Override + public boolean collect( Bag container ) { + if (super.collect( container )) { + if (container.owner != null) { + charge( container.owner ); + } + return true; + } else { + return false; + } + } + + public void charge( Char owner ) { + if (skillcharger == null) skillcharger = new SkillCharger(); + skillcharger.attachTo( owner ); + } + + @Override + public void onDetach( ) { + stopCharging(); + } + + public void stopCharging() { + if (skillcharger != null) { + skillcharger.detach(); + skillcharger = null; + } + } + + private static final String COLDDOWN = "colddown"; + private static final String CHARGE = "charge"; + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(COLDDOWN, colddown); + bundle.put(CHARGE, charge); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + colddown = bundle.getInt(COLDDOWN); + charge = bundle.getInt(CHARGE); + } + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + actions.remove(AC_DROP); + actions.remove(AC_THROW); + if (colddown < 1){ + actions.add(AC_SPECIAL); + actions.add(AC_SPECIAL_TWO); + actions.add(AC_SPECIAL_THREE); + actions.add(AC_SPECIAL_FOUR); + } + + return actions; + } + + @Override + public void execute(Hero hero, String action) { + + if (action.equals( AC_CHOOSE )){ + + GameScene.show(new WndItem(null, this, true)); + + } else if (action.equals(AC_SPECIAL)) { + curUser = hero; + Invisibility.dispel(); + doSpecial(); + } else if (action.equals(AC_SPECIAL_TWO)) { + curUser = hero; + Invisibility.dispel(); + doSpecial2(); + } else if (action.equals(AC_SPECIAL_THREE)) { + curUser = hero; + Invisibility.dispel(); + doSpecial3(); + } else if (action.equals(AC_SPECIAL_FOUR)) { + curUser = hero; + Invisibility.dispel(); + doSpecial4(); + } else { + super.execute(hero, action); + } + } + + abstract public void doSpecial(); + + abstract public void doSpecial2(); + + abstract public void doSpecial3(); + + abstract public void doSpecial4(); + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + @Override + public int price() { + return 0; + } + + @Override + public String info() { + String info = desc(); + info += "\n\n" + Messages.get(ClassSkill.class, "charge",charge); + return info; + } + + @Override + public String status() { + return Messages.format("%d", charge); + } + + protected class SkillCharger extends Buff { + + @Override + public boolean attachTo( Char target ) { + super.attachTo( target ); + return true; + } + + @Override + public boolean act() { + if (charge > 0) + gainCharge(); + + if (colddown >= 20 && charge > 0) { + colddown=0; + charge--; + updateQuickslot(); + } + spend( TICK ); + + return true; + } + + private void gainCharge(){ + colddown+= hero.energybase(); + } + + } + +} diff --git a/java/com/hmdzl/spspd/items/skills/FollowerSkill.java b/java/com/hmdzl/spspd/items/skills/FollowerSkill.java new file mode 100644 index 00000000..e9b4f2ac --- /dev/null +++ b/java/com/hmdzl/spspd/items/skills/FollowerSkill.java @@ -0,0 +1,137 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.skills; + +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.actors.buffs.Blindness; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Haste; +import com.hmdzl.spspd.actors.buffs.ParyAttack; +import com.hmdzl.spspd.actors.buffs.Terror; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.actors.mobs.npcs.NPC; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.scrolls.ScrollOfUpgrade; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.CharSprite; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.windows.WndBag; +import com.watabou.utils.Callback; +import com.watabou.noosa.audio.Sample; +import com.hmdzl.spspd.effects.particles.ElmoParticle; + +import java.util.HashMap; + + +public class FollowerSkill extends ClassSkill { + private static final String TXT_VALUE = "%+d"; + private static int SKILL_TIME = 1; + { + //name = "follower cape"; + image = ItemSpriteSheet.ARMOR_FOLLOWER; + } + + private HashMap targets = new HashMap(); + + @Override + public void doSpecial() { + curUser.spend(SKILL_TIME); + curUser.sprite.operate(curUser.pos); + curUser.busy(); + curUser.sprite.centerEmitter().start(ElmoParticle.FACTORY, 0.15f, 4); + Sample.INSTANCE.play(Assets.SND_READ); + FollowerSkill.charge += 15; + Buff.affect(curUser, ParyAttack.class); + } + + @Override + public void doSpecial2() { + + curUser.spend(SKILL_TIME); + curUser.sprite.operate(curUser.pos); + curUser.busy(); + curUser.sprite.centerEmitter().start(ElmoParticle.FACTORY, 0.15f, 4); + Sample.INSTANCE.play(Assets.SND_READ); + FollowerSkill.charge += 20; + int people = 0; + for (Mob mob : Dungeon.level.mobs) { + mob.beckon(curUser.pos); + if (mob instanceof Mob && !(mob instanceof NPC)){ + people++; + } + } + int goldearn = (int)(people*(Dungeon.hero.lvl/10+100)); + Dungeon.gold+= goldearn; + Dungeon.hero.sprite.showStatus(CharSprite.NEUTRAL, TXT_VALUE, goldearn); + } + + @Override + public void doSpecial3() { + + for (Mob mob : Dungeon.level.mobs) { + if (Level.fieldOfView[mob.pos] && (Dungeon.level.distance(curUser.pos, mob.pos) <= 10)) { + Buff.affect(mob, Terror.class, 10f).object = curUser.id(); + Buff.prolong(mob, Blindness.class, 10f); + } + } + Buff.affect(curUser, Haste.class,20f); + curUser.spend(SKILL_TIME); + curUser.sprite.operate(curUser.pos); + curUser.busy(); + curUser.sprite.centerEmitter().start(ElmoParticle.FACTORY, 0.15f, 4); + Sample.INSTANCE.play(Assets.SND_READ); + FollowerSkill.charge += 10; + } + + @Override + public void doSpecial4() { + GameScene.selectItem(itemSelector, WndBag.Mode.UPGRADEABLE, Messages.get(ScrollOfUpgrade.class,"prompt")); + + } + + private final WndBag.Listener itemSelector = new WndBag.Listener() { + @Override + public void onSelect(Item item) { + if (item != null) { + FollowerSkill.this.upgrade(item); + FollowerSkill.charge += 15; + } + } + }; + private void upgrade(Item item) { + + GLog.w(Messages.get(ScrollOfUpgrade.class,"looks_better", item.name())); + + item.upgrade(1); + item.uncurse(); + + curUser.sprite.operate(curUser.pos); + curUser.sprite.emitter().start(Speck.factory(Speck.UP), 0.2f, 3); + Badges.validateItemLevelAquired(item); + + curUser.spend(1f); + curUser.busy(); + + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/skills/HuntressSkill.java b/java/com/hmdzl/spspd/items/skills/HuntressSkill.java new file mode 100644 index 00000000..7360615a --- /dev/null +++ b/java/com/hmdzl/spspd/items/skills/HuntressSkill.java @@ -0,0 +1,187 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.skills; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.buffs.FireImbue; +import com.hmdzl.spspd.actors.buffs.GrowSeed; +import com.hmdzl.spspd.actors.buffs.Needling; +import com.hmdzl.spspd.actors.buffs.Roots; +import com.hmdzl.spspd.actors.buffs.TargetShoot; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.EarthImbue; +import com.hmdzl.spspd.actors.buffs.Awareness; +import com.hmdzl.spspd.actors.buffs.BerryRegeneration; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.actors.mobs.npcs.Mtree; +import com.hmdzl.spspd.items.summon.FairyCard; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.effects.particles.ElmoParticle; +import com.watabou.utils.PathFinder; +import com.watabou.utils.Random; +import com.watabou.noosa.audio.Sample; + +public class HuntressSkill extends ClassSkill { + private static int SKILL_TIME = 1; + { + //name = "huntress cloak"; + image = ItemSpriteSheet.ARMOR_HUNTRESS; + } + + @Override + public void doSpecial() { + + /*Item proto = new Shuriken(); + + for (Mob mob : Dungeon.level.mobs) { + if (Level.fieldOfView[mob.pos]) { + + Callback callback = new Callback() { + @Override + public void call() { + curUser.attack(targets.get(this)); + targets.remove(this); + if (targets.isEmpty()) { + curUser.spendAndNext(curUser.attackDelay()); + } + } + }; + + ((MissileSprite) curUser.sprite.parent + .recycle(MissileSprite.class)).reset(curUser.pos, + mob.pos, proto, callback); + + targets.put(callback, mob); + } + } + + if (targets.size() == 0) { + GLog.w(TXT_NO_ENEMIES); + return; + }*/ + + //curUser.HP -= (curUser.HP / 2); + + HuntressSkill.charge +=10; + + curUser.spend(SKILL_TIME); + curUser.sprite.operate(curUser.pos); + curUser.busy(); + + curUser.sprite.centerEmitter().start(ElmoParticle.FACTORY, 0.15f, 4); + Sample.INSTANCE.play(Assets.SND_READ); + + switch(Random.Int(4)){ + case 0: + Buff.affect(curUser, FireImbue.class).set(30f); + break; + case 1: + Buff.affect(curUser, EarthImbue.class,30); + break; + case 2: + Buff.affect(curUser, Awareness.class,10); + break; + case 3: + Buff.affect(curUser, BerryRegeneration.class).level(curUser.HP/2); + break; + } + } + + @Override + public void doSpecial2() { + + HuntressSkill.charge +=10; + + curUser.spend(SKILL_TIME); + curUser.sprite.operate(curUser.pos); + curUser.busy(); + + curUser.sprite.centerEmitter().start(ElmoParticle.FACTORY, 0.15f, 4); + Sample.INSTANCE.play(Assets.SND_READ); + + Buff.affect(curUser, TargetShoot.class,20f); + + Buff.affect(curUser, Needling.class,20f); + + } + + @Override + public void doSpecial3() { + + curUser.spend(SKILL_TIME); + curUser.sprite.operate(curUser.pos); + curUser.busy(); + + curUser.sprite.centerEmitter().start(ElmoParticle.FACTORY, 0.15f, 4); + Sample.INSTANCE.play(Assets.SND_READ); + + ArrayList spawnPoints = new ArrayList(); + for (int i = 0; i < PathFinder.NEIGHBOURS8.length; i++) { + int p = curUser.pos + PathFinder.NEIGHBOURS8[i]; + if (Actor.findChar(p) == null && (Level.passable[p] || Level.avoid[p])) { + spawnPoints.add(p); + } + } + + if (spawnPoints.size() > 0) { + FairyCard.Fairy fairy = new FairyCard.Fairy(); + fairy.pos = Random.element(spawnPoints); + GameScene.add(fairy); + HuntressSkill.charge +=15; + } else { + GLog.i( Messages.get(this, "no_space") ); + } + } + @Override + public void doSpecial4() { + + for (Mob mob : Dungeon.level.mobs) { + if (Level.fieldOfView[mob.pos] && (Dungeon.level.distance(curUser.pos, mob.pos) <= 10)) { + Buff.prolong(mob, Roots.class, 8); + Buff.affect(mob, GrowSeed.class); + } + } + for (int i = 0; i < (Dungeon.hero.lvl)/15; i++){ + Mtree tree = new Mtree(); + tree.state = tree.WANDERING; + tree.pos = Dungeon.level.randomRespawnCellFish(); + GameScene.add(tree); + tree.beckon(Dungeon.hero.pos); + } + + + HuntressSkill.charge += 15; + + curUser.spend(SKILL_TIME); + curUser.sprite.operate(curUser.pos); + curUser.busy(); + + curUser.sprite.centerEmitter().start(ElmoParticle.FACTORY, 0.15f, 4); + Sample.INSTANCE.play(Assets.SND_READ); + + } + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/skills/MageSkill.java b/java/com/hmdzl/spspd/items/skills/MageSkill.java new file mode 100644 index 00000000..18272769 --- /dev/null +++ b/java/com/hmdzl/spspd/items/skills/MageSkill.java @@ -0,0 +1,146 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.skills; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Burning; +import com.hmdzl.spspd.actors.buffs.CountDown; +import com.hmdzl.spspd.actors.buffs.Frost; +import com.hmdzl.spspd.actors.buffs.Recharging; +import com.hmdzl.spspd.actors.buffs.Shocked; +import com.hmdzl.spspd.actors.buffs.Slow; +import com.hmdzl.spspd.actors.buffs.Ooze; +import com.hmdzl.spspd.actors.buffs.Roots; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.particles.ElmoParticle; +import com.hmdzl.spspd.effects.particles.SmokeParticle; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.Terrain; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.noosa.audio.Sample; + +public class MageSkill extends ClassSkill { + private static int SKILL_TIME = 1; + { + //name = "mage robe"; + image = ItemSpriteSheet.ARMOR_MAGE; + } + + @Override + public void doSpecial() { + + for (Mob mob : Dungeon.level.mobs) { + if (Level.fieldOfView[mob.pos] && (Dungeon.level.distance(curUser.pos, mob.pos) <= 10)) { + Buff.affect(mob, Burning.class).reignite(mob); + Buff.affect(mob, Ooze.class); + Buff.affect(mob, Slow.class, 8); + Buff.prolong(mob, Roots.class, 3); + } + } + + MageSkill.charge += 15; + + curUser.spend(SKILL_TIME); + curUser.sprite.operate(curUser.pos); + curUser.busy(); + + curUser.sprite.centerEmitter().start(ElmoParticle.FACTORY, 0.15f, 4); + Sample.INSTANCE.play(Assets.SND_READ); + + } + + @Override + public void doSpecial2() { + for (Mob mob : Dungeon.level.mobs) { + if (Level.fieldOfView[mob.pos] && (Dungeon.level.distance(curUser.pos, mob.pos) <= 10)) { + Buff.affect(mob, CountDown.class); + for (int n : Level.NEIGHBOURS4) { + int c = mob.pos + n; + if (c >= 0 && c < Level.getLength()) { + if (Dungeon.visible[c]) { + CellEmitter.get(c).burst(SmokeParticle.FACTORY, 2); + } + if (Dungeon.level.map[c] == Terrain.WALL && Level.insideMap(c)) { + Level.set(c, Terrain.EMPTY); + GameScene.updateMap(c); + Dungeon.observe(); + } + } + } + } + } + + MageSkill.charge += 15; + + curUser.spend(SKILL_TIME); + curUser.sprite.operate(curUser.pos); + curUser.busy(); + + curUser.sprite.centerEmitter().start(ElmoParticle.FACTORY, 0.15f, 4); + Sample.INSTANCE.play(Assets.SND_READ); + + } + + @Override + public void doSpecial3() { + + for (Mob mob : Dungeon.level.mobs) { + if (Level.fieldOfView[mob.pos] && (Dungeon.level.distance(curUser.pos, mob.pos) <= 10)) { + int dmg = (int) (Dungeon.hero.lvl * (1 + 0.1 * Dungeon.hero.magicSkill())) ; + mob.damage(Math.min(mob.HP-10,mob.HT/10 + dmg), this ); + Buff.prolong(mob, Frost.class, 8); + } + } + + MageSkill.charge += 15; + + curUser.spend(SKILL_TIME); + curUser.sprite.operate(curUser.pos); + curUser.busy(); + + curUser.sprite.centerEmitter().start(ElmoParticle.FACTORY, 0.15f, 4); + Sample.INSTANCE.play(Assets.SND_READ); + + } + + @Override + public void doSpecial4() { + for (Mob mob : Dungeon.level.mobs) { + if (Level.fieldOfView[mob.pos] && (Dungeon.level.distance(curUser.pos, mob.pos) <= 4)) { + Buff.prolong(mob, Shocked.class, 8); + } + } + + Buff.affect(curUser, Recharging.class, 30); + MageSkill.charge += 9; + + curUser.spend(SKILL_TIME); + curUser.sprite.operate(curUser.pos); + curUser.busy(); + + curUser.sprite.centerEmitter().start(ElmoParticle.FACTORY, 0.15f, 4); + Sample.INSTANCE.play(Assets.SND_READ); + + } + + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/skills/PerformerSkill.java b/java/com/hmdzl/spspd/items/skills/PerformerSkill.java new file mode 100644 index 00000000..ba0e3a4b --- /dev/null +++ b/java/com/hmdzl/spspd/items/skills/PerformerSkill.java @@ -0,0 +1,253 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.skills; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.actors.buffs.Amok; +import com.hmdzl.spspd.actors.buffs.ArmorBreak; +import com.hmdzl.spspd.actors.buffs.AttackUp; +import com.hmdzl.spspd.actors.buffs.Blindness; +import com.hmdzl.spspd.actors.buffs.Charm; +import com.hmdzl.spspd.actors.buffs.DefenceUp; +import com.hmdzl.spspd.actors.buffs.Haste; +import com.hmdzl.spspd.actors.buffs.HighVoice; +import com.hmdzl.spspd.actors.buffs.Rhythm; +import com.hmdzl.spspd.actors.buffs.Rhythm2; +import com.hmdzl.spspd.actors.buffs.Slow; +import com.hmdzl.spspd.actors.buffs.WarGroove; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.armor.Armor; +import com.hmdzl.spspd.items.artifacts.Artifact; +import com.hmdzl.spspd.items.rings.Ring; +import com.hmdzl.spspd.items.wands.Wand; +import com.hmdzl.spspd.items.weapon.melee.MeleeWeapon; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.windows.WndBag; +import com.hmdzl.spspd.effects.particles.ElmoParticle; +import com.watabou.noosa.audio.Sample; + +public class PerformerSkill extends ClassSkill { + private static int SKILL_TIME = 1; + { + //name = "performer cloak"; + image = ItemSpriteSheet.ARMOR_PERFORMER; + } + + @Override + public void doSpecial() { + + for (Mob mob : Dungeon.level.mobs) { + if (Level.fieldOfView[mob.pos]) { + Buff.affect(mob, Charm.class,Charm.durationFactor(mob)*5f).object = curUser.id(); + mob.sprite.centerEmitter().start(Speck.factory(Speck.HEART),0.2f, 5); + Buff.affect(mob, Amok.class, 10f); + Buff.prolong(mob, Haste.class, 5f); + Buff.prolong(mob, ArmorBreak.class, 20f).level(50); + } + } + PerformerSkill.charge += 20; + Buff.affect(curUser, DefenceUp.class,10).level(25); + Buff.affect(curUser, AttackUp.class,10).level(25); + curUser.spend(SKILL_TIME); + curUser.sprite.operate(curUser.pos); + curUser.busy(); + + curUser.sprite.centerEmitter().start(ElmoParticle.FACTORY, 0.15f, 4); + Sample.INSTANCE.play(Assets.SND_READ); + } + + @Override + public void doSpecial2() { + + for (Mob mob : Dungeon.level.mobs) { + if (Level.fieldOfView[mob.pos]) { + mob.sprite.centerEmitter().start(Speck.factory(Speck.HEART),0.2f, 5); + Buff.prolong(mob, Blindness.class, 10f); + Buff.prolong(mob, Slow.class, 10f); + } + } + PerformerSkill.charge += 5; + + curUser.spend(SKILL_TIME); + curUser.sprite.operate(curUser.pos); + curUser.busy(); + curUser.sprite.centerEmitter().start(ElmoParticle.FACTORY, 0.15f, 4); + Sample.INSTANCE.play(Assets.SND_READ); + } + + @Override + public void doSpecial3() { + GameScene.selectItem(itemSelector, WndBag.Mode.TRANMSUTABLE, Messages.get(PerformerSkill.class, "prompt")); + } + + @Override + public void doSpecial4() { + + PerformerSkill.charge +=10; + + Buff.affect(curUser, HighVoice.class,100); + curUser.spend(SKILL_TIME); + curUser.sprite.operate(curUser.pos); + curUser.busy(); + + curUser.sprite.centerEmitter().start(ElmoParticle.FACTORY, 0.15f, 4); + Sample.INSTANCE.play(Assets.SND_READ); + } + + private final WndBag.Listener itemSelector = new WndBag.Listener() { + @Override + public void onSelect(Item item) { + curUser = Dungeon.hero; + Item result; + if (item != null) { + if (item instanceof MeleeWeapon) { + result = changeWeapon((MeleeWeapon) item); + } else if (item instanceof Armor) { + result = changeArmor((Armor) item); + } else if (item instanceof Ring) { + result = changeRing((Ring) item); + } else if (item instanceof Wand) { + result = changeWand((Wand) item); + } else if (item instanceof Artifact) { + result = changeArtifact((Artifact) item); + } else { + result = null; + } + item.detach(Dungeon.hero.belongings.backpack); + Dungeon.level.drop(result, Dungeon.hero.pos).sprite.drop(); + PerformerSkill.charge += 20; + } + } + }; + private MeleeWeapon changeWeapon(MeleeWeapon w) { + + MeleeWeapon n; + do { + n = (MeleeWeapon) Generator.random(Generator.Category.MELEEWEAPON); + } while (n.getClass() == w.getClass()); + + n.level = 0; + + int level = w.level; + if (level > 0) { + n.upgrade(level); + } else if (level < 0) { + n.degrade(-level); + } + + n.enchantment = w.enchantment; + n.reinforced = w.reinforced; + n.levelKnown = w.levelKnown; + n.cursedKnown = w.cursedKnown; + n.cursed = w.cursed; + + return n; + + } + + private Armor changeArmor(Armor r) { + Armor n; + do { + n = (Armor) Generator.random(Generator.Category.ARMOR); + } 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.glyph = r.glyph; + n.reinforced = r.reinforced; + n.levelKnown = r.levelKnown; + n.cursedKnown = r.cursedKnown; + n.cursed = r.cursed; + + return n; + } + + + private Ring changeRing(Ring r) { + Ring n; + do { + n = (Ring) Generator.random(Generator.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.reinforced = r.reinforced; + n.levelKnown = r.levelKnown; + n.cursedKnown = r.cursedKnown; + n.cursed = r.cursed; + + return n; + } + + private Artifact changeArtifact(Artifact a) { + Artifact n; + do { + n = (Artifact) Generator.random(Generator.Category.ARTIFACT); + } while (n.getClass() == a.getClass()); + + if (n != null) { + n.cursedKnown = a.cursedKnown; + n.cursed = a.cursed; + n.levelKnown = a.levelKnown; + n.transferUpgrade(a.visiblyUpgraded()); + } + + return n; + } + + private Wand changeWand(Wand w) { + + Wand n; + do { + n = (Wand) Generator.random(Generator.Category.WAND); + } while (n.getClass() == w.getClass()); + + n.level = 0; + n.updateLevel(); + n.upgrade(w.level); + + n.reinforced = w.reinforced; + n.levelKnown = w.levelKnown; + n.cursedKnown = w.cursedKnown; + n.cursed = w.cursed; + + return n; + } + +} + diff --git a/java/com/hmdzl/spspd/items/skills/RogueSkill.java b/java/com/hmdzl/spspd/items/skills/RogueSkill.java new file mode 100644 index 00000000..ad8ed9d3 --- /dev/null +++ b/java/com/hmdzl/spspd/items/skills/RogueSkill.java @@ -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 + */ +package com.hmdzl.spspd.items.skills; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.buffs.ArmorBreak; +import com.hmdzl.spspd.actors.buffs.AttackUp; +import com.hmdzl.spspd.actors.buffs.Blindness; +import com.hmdzl.spspd.actors.buffs.Disarm; +import com.hmdzl.spspd.actors.buffs.GoldTouch; +import com.hmdzl.spspd.actors.buffs.HighAttack; +import com.hmdzl.spspd.actors.buffs.Silent; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Strength; +import com.hmdzl.spspd.actors.buffs.Haste; +import com.hmdzl.spspd.actors.buffs.Invisibility; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.noosa.audio.Sample; +import com.hmdzl.spspd.effects.particles.ElmoParticle; +import com.watabou.utils.Random; + +public class RogueSkill extends ClassSkill { + private static int SKILL_TIME = 1; + { + //name = "rogue garb"; + image = ItemSpriteSheet.ARMOR_ROGUE; + } + + @Override + public void doSpecial() { + //GameScene.selectCell(teleporter); + RogueSkill.charge += 10; + + curUser.spend(SKILL_TIME); + curUser.sprite.operate(curUser.pos); + curUser.busy(); + + curUser.sprite.centerEmitter().start(ElmoParticle.FACTORY, 0.15f, 4); + Sample.INSTANCE.play(Assets.SND_READ); + Buff.affect(curUser, Invisibility.class,20); + + switch (Random.Int(3)){ + case 0: + Buff.affect(curUser, Strength.class); + break; + case 1: + Buff.affect(curUser, Haste.class,15); + break; + case 2: + Buff.affect(curUser, AttackUp.class,15).level(50); + break; + case 3: + break; + } + } + + @Override + public void doSpecial2() { + RogueSkill.charge += 20; + + curUser.spend(SKILL_TIME); + curUser.sprite.operate(curUser.pos); + curUser.busy(); + + curUser.sprite.centerEmitter().start(ElmoParticle.FACTORY, 0.15f, 4); + Sample.INSTANCE.play(Assets.SND_READ); + Buff.affect(curUser, GoldTouch.class,15f); + } + + @Override + public void doSpecial3() { + + for (Mob mob : Dungeon.level.mobs) { + if (Level.fieldOfView[mob.pos] && (Dungeon.level.distance(curUser.pos, mob.pos) <= 10)) { + Buff.affect(mob, Silent.class,9999f); + Buff.affect(mob, Disarm.class,5f); + Buff.affect(mob, ArmorBreak.class, 10f).level(50); + Buff.prolong(mob, Blindness.class, 3f); + } + } + + RogueSkill.charge += 20; + + curUser.spend(SKILL_TIME); + curUser.sprite.operate(curUser.pos); + curUser.busy(); + + curUser.sprite.centerEmitter().start(ElmoParticle.FACTORY, 0.15f, 4); + Sample.INSTANCE.play(Assets.SND_READ); + } + + @Override + public void doSpecial4() { + RogueSkill.charge += 20; + + curUser.spend(SKILL_TIME); + curUser.sprite.operate(curUser.pos); + curUser.busy(); + + curUser.sprite.centerEmitter().start(ElmoParticle.FACTORY, 0.15f, 4); + Sample.INSTANCE.play(Assets.SND_READ); + Buff.affect(curUser, HighAttack.class); + } + + /*protected static CellSelector.Listener teleporter = new CellSelector.Listener() { + + @Override + public void onSelect(Integer target) { + if (target != null) { + + if (!Level.fieldOfView[target] + || !(Level.passable[target] || Level.avoid[target]) + || Actor.findChar(target) != null) { + + GLog.w(TXT_FOV); + return; + } + + curUser.HP -= (curUser.HP / 5); + + ScrollOfTeleportation.appear(curUser, target); + CellEmitter.get(target).burst(Speck.factory(Speck.WOOL), 10); + Sample.INSTANCE.play(Assets.SND_PUFF); + Dungeon.level.press(target, curUser); + Dungeon.observe(); + + curUser.spendAndNext(SKILL_TIME); + } + } + + @Override + public String prompt() { + return "Choose a location to jump to"; + } + };*/ +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/skills/SoldierSkill.java b/java/com/hmdzl/spspd/items/skills/SoldierSkill.java new file mode 100644 index 00000000..f43a58e9 --- /dev/null +++ b/java/com/hmdzl/spspd/items/skills/SoldierSkill.java @@ -0,0 +1,316 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.skills; + +import java.util.ArrayList; +import java.util.HashSet; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.ToxicGas; +import com.hmdzl.spspd.actors.buffs.Bless; +import com.hmdzl.spspd.actors.buffs.Burning; +import com.hmdzl.spspd.actors.buffs.Chill; +import com.hmdzl.spspd.actors.buffs.Cripple; +import com.hmdzl.spspd.actors.buffs.MechArmor; +import com.hmdzl.spspd.actors.buffs.Ooze; +import com.hmdzl.spspd.actors.buffs.Poison; +import com.hmdzl.spspd.actors.buffs.ShieldArmor; +import com.hmdzl.spspd.actors.buffs.Terror; +import com.hmdzl.spspd.actors.buffs.Weakness; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Awareness; +import com.hmdzl.spspd.actors.hero.HeroSubClass; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.actors.mobs.npcs.MirrorImage; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.items.bombs.DungeonBomb; +import com.hmdzl.spspd.items.scrolls.ScrollOfTeleportation; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.sprites.SeekingBombSprite; +import com.hmdzl.spspd.sprites.SeekingClusterBombSprite; +import com.hmdzl.spspd.effects.particles.ElmoParticle; +import com.watabou.utils.Random; +import com.watabou.noosa.audio.Sample; + +public class SoldierSkill extends ClassSkill { + private static int SKILL_TIME = 1; + { + image = ItemSpriteSheet.ARMOR_SOLDIER; + } + + @Override + public void doSpecial() { + + ArrayList respawnPoints = new ArrayList(); + + for (int i = 0; i < Level.NEIGHBOURS8.length; i++) { + int p = curUser.pos + Level.NEIGHBOURS8[i]; + if (Actor.findChar(p) == null + && (Level.passable[p] || Level.avoid[p])) { + respawnPoints.add(p); + } + } + + int nImages = 4; + while (nImages > 0 && respawnPoints.size() > 0) { + int index = Random.index(respawnPoints); + + MirrorImage mob = new MirrorImage(); + mob.duplicate(curUser); + GameScene.add(mob); + ScrollOfTeleportation.appear(mob, respawnPoints.get(index)); + + respawnPoints.remove(index); + nImages--; + } + SoldierSkill.charge += 12; + Buff.detach(curUser, Poison.class); + Buff.detach(curUser, Cripple.class); + Buff.detach(curUser, Weakness.class); + Buff.detach(curUser, Burning.class); + Buff.detach(curUser, Ooze.class); + Buff.detach(curUser, Chill.class); + Buff.affect(curUser, Bless.class, 5f); + curUser.spend(SKILL_TIME); + curUser.sprite.operate(curUser.pos); + curUser.busy(); + + curUser.sprite.centerEmitter().start(ElmoParticle.FACTORY, 0.15f, 4); + Sample.INSTANCE.play(Assets.SND_READ); + } + + @Override + public void doSpecial2() { + SoldierSkill.charge += 25; + Buff.affect(curUser, MechArmor.class).level(250); + Buff.affect(curUser, ShieldArmor.class).level(Dungeon.hero.lvl*3); + curUser.spend(SKILL_TIME); + curUser.sprite.operate(curUser.pos); + curUser.busy(); + + curUser.sprite.centerEmitter().start(ElmoParticle.FACTORY, 0.15f, 4); + Sample.INSTANCE.play(Assets.SND_READ); + } + @Override + public void doSpecial3() { + + ArrayList respawnPoints = new ArrayList(); + + for (int i = 0; i < Level.NEIGHBOURS8.length; i++) { + int p = curUser.pos + Level.NEIGHBOURS8[i]; + if (Actor.findChar(p) == null + && (Level.passable[p] || Level.avoid[p])) { + respawnPoints.add(p); + } + } + + int nImages = 2; + while (nImages > 0 && respawnPoints.size() > 0) { + int index = Random.index(respawnPoints); + SeekingBomb mob = new SeekingBomb(); + SeekingHugeBomb mob2 = new SeekingHugeBomb(); + if (Dungeon.hero.subClass == HeroSubClass.LEADER) { + GameScene.add(mob2); + ScrollOfTeleportation.appear(mob2, respawnPoints.get(index)); + respawnPoints.remove(index); + nImages--; + }else { + GameScene.add(mob); + ScrollOfTeleportation.appear(mob, respawnPoints.get(index)); + respawnPoints.remove(index); + nImages--; + } + } + SoldierSkill.charge += 5; + curUser.spend(SKILL_TIME); + curUser.sprite.operate(curUser.pos); + curUser.busy(); + curUser.sprite.centerEmitter().start(ElmoParticle.FACTORY, 0.15f, 4); + Sample.INSTANCE.play(Assets.SND_READ); + } + + @Override + public void doSpecial4() { + SoldierSkill.charge += 20; + + int cell = Dungeon.level.randomRespawnCell(); + + if (cell != -1) { + Dungeon.level.spdrop(Generator.random(Generator.Category.HIGHFOOD), cell); + Dungeon.level.spdrop(Generator.random(Generator.Category.RANGEWEAPON), cell); + } else { + Dungeon.level.spdrop(Generator.random(Generator.Category.HIGHFOOD), curUser.pos); + Dungeon.level.spdrop(Generator.random(Generator.Category.RANGEWEAPON), curUser.pos); + } + Buff.affect( curUser, Awareness.class, 2f); + curUser.spend(SKILL_TIME); + curUser.sprite.operate(curUser.pos); + curUser.busy(); + curUser.sprite.centerEmitter().start(ElmoParticle.FACTORY, 0.15f, 4); + Sample.INSTANCE.play(Assets.SND_READ); + } + + public static class SeekingBomb extends Mob { + { + spriteClass = SeekingBombSprite.class; + hostile = false; + state = HUNTING; + HP = HT = 1; + evadeSkill = 20; + ally=true; + + properties.add(Property.MECH); + } + @Override + public int attackProc(Char enemy, int damage) { + int dmg = super.attackProc(enemy, damage); + DungeonBomb bomb = new DungeonBomb(); + bomb.explode(pos); + yell("KA-BOOM!!!"); + destroy(); + sprite.die(); + return dmg; + } + + @Override + protected Char chooseEnemy() { + + if (enemy == null || !enemy.isAlive()) { + HashSet enemies = new HashSet(); + for (Mob mob : Dungeon.level.mobs) { + if (mob.hostile && Level.fieldOfView[mob.pos]) { + enemies.add(mob); + } + } + + enemy = enemies.size() > 0 ? Random.element(enemies) : null; + } + + return enemy; + } + + public static SeekingBomb spawnAt(int pos) { + + SeekingBomb b = new SeekingBomb(); + + b.pos = pos; + b.state = b.HUNTING; + GameScene.add(b, 1f); + + return b; + + } + + + @Override + public void die(Object cause) { + DungeonBomb bomb = new DungeonBomb(); + bomb.explode(pos); + super.die(cause); + } + + private static final HashSet> IMMUNITIES = new HashSet>(); + static { + IMMUNITIES.add(Terror.class); + IMMUNITIES.add(ToxicGas.class); + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } + } + public static class SeekingHugeBomb extends Mob { + { + spriteClass = SeekingClusterBombSprite.class; + hostile = false; + state = HUNTING; + HP = HT = 1; + evadeSkill = 20; + ally=true; + + properties.add(Property.MECH); + } + @Override + public int attackProc(Char enemy, int damage) { + int dmg = super.attackProc(enemy, damage); + DungeonBomb bomb = new DungeonBomb(); + bomb.explode(pos); + bomb.explode(pos); + yell("KA-BOOM!!!"); + destroy(); + sprite.die(); + return dmg; + } + + @Override + protected Char chooseEnemy() { + + if (enemy == null || !enemy.isAlive()) { + HashSet enemies = new HashSet(); + for (Mob mob : Dungeon.level.mobs) { + if (mob.hostile && Level.fieldOfView[mob.pos]) { + enemies.add(mob); + } + } + + enemy = enemies.size() > 0 ? Random.element(enemies) : null; + } + + return enemy; + } + + public static SeekingHugeBomb spawnAt(int pos) { + + SeekingHugeBomb b = new SeekingHugeBomb(); + + b.pos = pos; + b.state = b.HUNTING; + GameScene.add(b, 1f); + + return b; + + } + + + @Override + public void die(Object cause) { + DungeonBomb bomb = new DungeonBomb(); + bomb.explode(pos); + bomb.explode(pos); + super.die(cause); + } + + private static final HashSet> IMMUNITIES = new HashSet>(); + static { + IMMUNITIES.add(Terror.class); + IMMUNITIES.add(ToxicGas.class); + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } + } +} + diff --git a/java/com/hmdzl/spspd/items/skills/WarriorSkill.java b/java/com/hmdzl/spspd/items/skills/WarriorSkill.java new file mode 100644 index 00000000..6fac52b1 --- /dev/null +++ b/java/com/hmdzl/spspd/items/skills/WarriorSkill.java @@ -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 + */ +package com.hmdzl.spspd.items.skills; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.AttackUp; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.DefenceUp; +import com.hmdzl.spspd.actors.buffs.Disarm; +import com.hmdzl.spspd.actors.buffs.BloodImbue; +import com.hmdzl.spspd.actors.buffs.ShieldArmor; +import com.hmdzl.spspd.actors.buffs.Silent; +import com.hmdzl.spspd.actors.buffs.SpAttack; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.actors.mobs.pets.PET; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.utils.Callback; +import com.watabou.noosa.audio.Sample; +import com.hmdzl.spspd.effects.particles.ElmoParticle; +import com.watabou.utils.PathFinder; + +import java.util.HashMap; + + +public class WarriorSkill extends ClassSkill { + private static int SKILL_TIME = 1; + { + //name = "warrior suit of armor"; + image = ItemSpriteSheet.ARMOR_WARRIOR; + } + + private HashMap targets = new HashMap(); + + @Override + public void doSpecial() { + curUser.spend(SKILL_TIME); + curUser.sprite.operate(curUser.pos); + curUser.busy(); + curUser.sprite.centerEmitter().start(ElmoParticle.FACTORY, 0.15f, 4); + Sample.INSTANCE.play(Assets.SND_READ); + Buff.prolong(curUser, BloodImbue.class,30f); + WarriorSkill.charge += 10; + } + + @Override + public void doSpecial2() { + + for (Mob mob : Dungeon.level.mobs) { + if (Level.fieldOfView[mob.pos]) { + if (Dungeon.level.distance(curUser.pos, mob.pos) <= 3){ + Buff.affect(mob, AttackUp.class).level(10); + } else { + Buff.affect(mob, Disarm.class, curUser.STR); + Buff.affect(mob, Silent.class, curUser.STR); + } + } + } + WarriorSkill.charge += 15; + curUser.spend(SKILL_TIME); + curUser.sprite.operate(curUser.pos); + curUser.busy(); + curUser.sprite.centerEmitter().start(ElmoParticle.FACTORY, 0.15f, 4); + Sample.INSTANCE.play(Assets.SND_READ); + Buff.prolong(curUser, DefenceUp.class,targets.size()*5f).level(50); + } + + @Override + public void doSpecial3() { + + for (Mob mob : Dungeon.level.mobs) { + if (mob instanceof PET) { + mob.HP += (int)mob.HT/2; + } + } + Buff.affect(curUser,ShieldArmor.class).level(curUser.HT/2); + for (int i = 0; i < PathFinder.NEIGHBOURS8.length; i++) { + Char mob = Actor.findChar(curUser.pos + + Level.NEIGHBOURS8[i]); + if (mob != null && mob != curUser && !(mob instanceof PET ) ) { + mob.damage((int)curUser.HT/2, this); + } + + } + + WarriorSkill.charge += 25; + curUser.spend(SKILL_TIME); + curUser.sprite.operate(curUser.pos); + curUser.busy(); + curUser.sprite.centerEmitter().start(ElmoParticle.FACTORY, 0.15f, 4); + Sample.INSTANCE.play(Assets.SND_READ); + Buff.prolong(curUser, DefenceUp.class,targets.size()*5f).level(50); + } + + @Override + public void doSpecial4() { + curUser.spend(SKILL_TIME); + curUser.sprite.operate(curUser.pos); + curUser.busy(); + curUser.sprite.centerEmitter().start(ElmoParticle.FACTORY, 0.15f, 4); + Sample.INSTANCE.play(Assets.SND_READ); + Buff.prolong(curUser, SpAttack.class,30f); + WarriorSkill.charge += 8; + } + + /*protected static CellSelector.Listener leaper = new CellSelector.Listener() { + + @Override + public void onSelect(Integer target) { + if (target != null && target != curUser.pos) { + + int cell = Ballistica.cast(curUser.pos, target, false, true); + if (Actor.findChar(cell) != null && cell != curUser.pos) { + cell = Ballistica.trace[Ballistica.distance - 2]; + } + + curUser.HP -= (curUser.HP / 3); + if (curUser.subClass == HeroSubClass.BERSERKER + && curUser.HP <= curUser.HT * Fury.LEVEL) { + Buff.affect(curUser, Fury.class); + } + + final int dest = cell; + curUser.busy(); + curUser.sprite.jump(curUser.pos, cell, new Callback() { + @Override + public void call() { + curUser.move(dest); + Dungeon.level.press(dest, curUser); + Dungeon.observe(); + + for (int i = 0; i < Level.NEIGHBOURS8.length; i++) { + Char mob = Actor.findChar(curUser.pos + + Level.NEIGHBOURS8[i]); + if (mob != null && mob != curUser) { + Buff.prolong(mob, EnchantmentEnergy.class, SHOCK_TIME); + } + } + + CellEmitter.center(dest).burst( + Speck.factory(Speck.DUST), 10); + Camera.main.shake(2, 0.5f); + + curUser.spendAndNext(LEAP_TIME); + } + }); + } + } + + @Override + public String prompt() { + return "Choose direction to leap"; + } + };*/ +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/summon/ActiveMrDestructo.java b/java/com/hmdzl/spspd/items/summon/ActiveMrDestructo.java new file mode 100644 index 00000000..e4239a33 --- /dev/null +++ b/java/com/hmdzl/spspd/items/summon/ActiveMrDestructo.java @@ -0,0 +1,464 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 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 + */ +package com.hmdzl.spspd.items.summon; + +import java.util.ArrayList; +import java.util.HashSet; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.ResultDescriptions; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.ToxicGas; +import com.hmdzl.spspd.actors.buffs.Terror; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.hero.HeroSubClass; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.particles.PurpleParticle; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.weapon.enchantments.EnchantmentDark; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.CharSprite; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.sprites.MrDestructo2dot0Sprite; +import com.hmdzl.spspd.sprites.MrDestructoSprite; +import com.watabou.utils.Random; + +public class ActiveMrDestructo extends Item { + + { + //name = "mr destructo"; + image = ItemSpriteSheet.ACTIVEMRD; + defaultAction = AC_ACTIVE; + stackable = true; + } + + + private static boolean activate = false; + + private static final String AC_ACTIVE = "ACTIVE"; + + + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + actions.add(AC_ACTIVE); + return actions; + } + + @Override + public void execute(Hero hero, String action) { + if (action.equals(AC_ACTIVE)) { + activate = true; + action = AC_THROW; + } else + activate = false; + + super.execute(hero, action); + } + + @Override + protected void onThrow(int cell) { + + if (Actor.findChar(cell) != null) { + ArrayList candidates = new ArrayList<>(); + for (int i : Level.NEIGHBOURS8) + if (Level.passable[cell + i]) + candidates.add(cell + i); + int newCell = candidates.isEmpty() ? cell : Random + .element(candidates); + + if (!Level.pit[newCell] && activate) { + if (Dungeon.hero.subClass == HeroSubClass.LEADER){ + MrDestructo2dot0.spawnAt(newCell); + } else MrDestructo.spawnAt(newCell); + } else { + Dungeon.level.drop(this, newCell).sprite.drop(cell); + } + + } else if (!Level.pit[cell] && activate) { + if (Dungeon.hero.subClass == HeroSubClass.LEADER){ + MrDestructo2dot0.spawnAt(cell); + } else + MrDestructo.spawnAt(cell); + } else { + + super.onThrow(cell); + } + + } + + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + @Override + public int price() { + return 100 * quantity; + } + + public static class MrDestructo extends Mob { + + { + spriteClass = MrDestructoSprite.class; + hostile = false; + state = HUNTING; + HP = HT= 100; + evadeSkill = 3; + ally=true; + + properties.add(Property.MECH); + } + + private Ballistica beam; + + private static final float SPAWN_DELAY = 0.1f; + + @Override + public int drRoll() { + return 0; + } + + + @Override + protected boolean act() { + + for (int n : Level.NEIGHBOURS8DIST2) { + int c = pos + n; + if (c0){ + Char ch = Actor.findChar(c); + } + } + //Level.fieldOfView[Dungeon.hero.pos] && + + boolean result = super.act(); + return result; + } + + @Override + public void move(int step) { + } + + @Override + protected Char chooseEnemy() { + + if (enemy == null || !enemy.isAlive()) { + HashSet enemies = new HashSet(); + for (Mob mob : Dungeon.level.mobs) { + if (mob.hostile && Level.fieldOfView[mob.pos]) { + enemies.add(mob); + } + } + + enemy = enemies.size() > 0 ? Random.element(enemies) : null; + } + + return enemy; + } + + + + public static MrDestructo spawnAt(int pos) { + + MrDestructo b = new MrDestructo(); + + b.pos = pos; + b.state = b.HUNTING; + GameScene.add(b, SPAWN_DELAY); + + return b; + + } + + private int hitCell; + + @Override + protected boolean canAttack(Char enemy) { + + beam = new Ballistica( pos, enemy.pos, Ballistica.STOP_TERRAIN); + + return beam.subPath(1, beam.dist).contains(enemy.pos); + } + + @Override + public int hitSkill(Char target) { + return 20+(Dungeon.depth); + } + + @Override + protected boolean doAttack(Char enemy) { + + spend(attackDelay()); + + boolean rayVisible = false; + + for (int i : beam.subPath(0, beam.dist)) { + if (Dungeon.visible[i]) { + rayVisible = true; + } + } + + if (rayVisible) { + sprite.attack(beam.collisionPos ); + return false; + } else { + attack(enemy); + return true; + } + } + + @Override + public boolean attack(Char enemy) { + + for (int pos : beam.subPath(1, beam.dist)) { + + Char ch = Actor.findChar(pos); + if (ch == null) { + continue; + } + + if (hit(this, ch, true)) { + ch.damage(Random.NormalIntRange(Dungeon.depth, Dungeon.depth+12), this); + damage(Random.NormalIntRange(5, 10), 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(Messages.format(ResultDescriptions.MOB)); + //GLog.n(Messages.get(this, "kill")); + } + } else { + ch.sprite.showStatus(CharSprite.NEUTRAL, ch.defenseVerb()); + } + } + + return true; + } + + @Override + public void beckon(int cell) { + } + + private static final HashSet> RESISTANCES = new HashSet>(); + static { + RESISTANCES.add(EnchantmentDark.class); + + } + + @Override + public HashSet> resistances() { + return RESISTANCES; + } + + private static final HashSet> IMMUNITIES = new HashSet>(); + static { + IMMUNITIES.add(Terror.class); + IMMUNITIES.add(ToxicGas.class); + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } + } + public static class MrDestructo2dot0 extends Mob { + + { + spriteClass = MrDestructo2dot0Sprite.class; + hostile = false; + state = HUNTING; + HP = HT= 200; + evadeSkill = 35; + ally=true; + + properties.add(Property.MECH); + } + + private Ballistica beam; + + private static final float SPAWN_DELAY = 1f; + + @Override + public int drRoll() { + return 0; + } + + + @Override + protected boolean act() { + + for (int n : Level.NEIGHBOURS8DIST2) { + int c = pos + n; + if (c0){ + Char ch = Actor.findChar(c); + } + } + //Level.fieldOfView[Dungeon.hero.pos] && + + boolean result = super.act(); + return result; + } + + @Override + public void move(int step) { + } + + @Override + protected Char chooseEnemy() { + + if (enemy == null || !enemy.isAlive()) { + HashSet enemies = new HashSet(); + for (Mob mob : Dungeon.level.mobs) { + if (mob.hostile && Level.fieldOfView[mob.pos]) { + enemies.add(mob); + } + } + + enemy = enemies.size() > 0 ? Random.element(enemies) : null; + } + + return enemy; + } + + + + public static MrDestructo2dot0 spawnAt(int pos) { + + MrDestructo2dot0 b = new MrDestructo2dot0(); + + b.pos = pos; + b.state = b.HUNTING; + GameScene.add(b, SPAWN_DELAY); + + return b; + + } + + private int hitCell; + + @Override + protected boolean canAttack(Char enemy) { + + beam = new Ballistica( pos, enemy.pos, Ballistica.STOP_TERRAIN); + + return beam.subPath(1, beam.dist).contains(enemy.pos); + } + + @Override + public int hitSkill(Char target) { + return 30+(Dungeon.depth); + } + + @Override + protected boolean doAttack(Char enemy) { + + spend(attackDelay()); + + boolean rayVisible = false; + + for (int i : beam.subPath(0, beam.dist)) { + if (Dungeon.visible[i]) { + rayVisible = true; + } + } + + if (rayVisible) { + sprite.attack( beam.collisionPos ); + return false; + } else { + attack(enemy); + return true; + } + } + + @Override + public boolean attack(Char enemy) { + + for (int pos : beam.subPath(1, beam.dist)) { + + Char ch = Actor.findChar( pos ); + if (ch == null) { + continue; + } + + if (hit(this, ch, true)) { + ch.damage(Random.NormalIntRange(Dungeon.depth+20, Dungeon.depth+32), this); + damage(Random.NormalIntRange(5, 10), 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(Messages.format(ResultDescriptions.MOB)); + //GLog.n(Messages.get(this, "kill")); + } + } else { + ch.sprite.showStatus(CharSprite.NEUTRAL, ch.defenseVerb()); + } + } + + return true; + } + + @Override + public void beckon(int cell) { + } + + private static final HashSet> RESISTANCES = new HashSet>(); + static { + RESISTANCES.add(EnchantmentDark.class); + + } + + @Override + public HashSet> resistances() { + return RESISTANCES; + } + + private static final HashSet> IMMUNITIES = new HashSet>(); + static { + IMMUNITIES.add(Terror.class); + IMMUNITIES.add(ToxicGas.class); + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } + } + +} diff --git a/java/com/hmdzl/spspd/items/summon/CallCoconut.java b/java/com/hmdzl/spspd/items/summon/CallCoconut.java new file mode 100644 index 00000000..4336626c --- /dev/null +++ b/java/com/hmdzl/spspd/items/summon/CallCoconut.java @@ -0,0 +1,298 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 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 + */ +package com.hmdzl.spspd.items.summon; + +import java.util.ArrayList; +import java.util.HashSet; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.hero.HeroSubClass; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.bombs.BuildBomb; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.CoconutSprite; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.utils.Random; + +public class CallCoconut extends Item { + + { + //name = "call coconut"; + image = ItemSpriteSheet.ANCIENTKEY; + defaultAction = AC_ACTIVE; + stackable = true; + } + + + private static boolean activate = false; + + private static final String AC_ACTIVE = "ACTIVE"; + + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + actions.add(AC_ACTIVE); + return actions; + } + + @Override + public void execute(Hero hero, String action) { + if (action.equals(AC_ACTIVE)) { + activate = true; + action = AC_THROW; + } else + activate = false; + + super.execute(hero, action); + } + + @Override + protected void onThrow(int cell) { + + if (Actor.findChar(cell) != null) { + ArrayList candidates = new ArrayList<>(); + for (int i : Level.NEIGHBOURS8) + if (Level.passable[cell + i]) + candidates.add(cell + i); + int newCell = candidates.isEmpty() ? cell : Random + .element(candidates); + + if (!Level.pit[newCell] && activate) { + if (Dungeon.hero.subClass == HeroSubClass.LEADER) { + EXcococat.spawnAt(newCell); + } else Scococat.spawnAt(newCell); + } else { + Dungeon.level.drop(this, newCell).sprite.drop(cell); + } + + } else if (!Level.pit[cell] && activate) { + if (Dungeon.hero.subClass == HeroSubClass.LEADER) { + EXcococat.spawnAt(cell); + } else + Scococat.spawnAt(cell); + } else { + + super.onThrow(cell); + } + + } + + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + @Override + public int price() { + return 100 * quantity; + } + + public static class Scococat extends Mob { + + { + spriteClass = CoconutSprite.class; + hostile = false; + state = HUNTING; + HP = HT = 200; + evadeSkill = 0; + ally=true; + properties.add(Property.BEAST); + } + + private static final float SPAWN_DELAY = 1f; + + @Override + public int drRoll() { + return 0; + } + + @Override + protected boolean act() { + damage(1, this); + + return super.act(); + } + + @Override + protected Char chooseEnemy() { + + if (enemy == null || !enemy.isAlive()) { + HashSet enemies = new HashSet(); + for (Mob mob : Dungeon.level.mobs) { + if (mob.hostile && Level.fieldOfView[mob.pos]) { + enemies.add(mob); + } + } + + enemy = enemies.size() > 0 ? Random.element(enemies) : null; + } + + return enemy; + } + + + public static Scococat spawnAt(int pos) { + + Scococat b = new Scococat(); + + b.pos = pos; + b.state = b.HUNTING; + GameScene.add(b, SPAWN_DELAY); + + return b; + + } + + @Override + protected boolean canAttack(Char enemy) { + + return Dungeon.level.distance(pos, enemy.pos) <= 4; + + } + + @Override + public int hitSkill(Char target) { + return 40 + (Dungeon.depth); + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(Dungeon.depth + 10, Dungeon.depth + 16); + } + + @Override + public int attackProc(Char enemy, int damage) { + if (Random.Int(10) == 1) { + BuildBomb bomb = new BuildBomb(); + bomb.explode(enemy.pos); + } + + return damage; + } + + @Override + public void add(Buff buff) { + //in other words, can't be directly affected by buffs/debuffs. + } + + } + + public static class EXcococat extends Mob { + + { + spriteClass = CoconutSprite.class; + hostile = false; + state = HUNTING; + HP = HT = 400; + evadeSkill = 20; + ally=true; + + properties.add(Property.BEAST); + } + + private static final float SPAWN_DELAY = 1f; + + @Override + public int drRoll() { + return 0; + } + + @Override + protected boolean act() { + damage(1, this); + + return super.act(); + } + + @Override + protected Char chooseEnemy() { + + if (enemy == null || !enemy.isAlive()) { + HashSet enemies = new HashSet(); + for (Mob mob : Dungeon.level.mobs) { + if (mob.hostile && Level.fieldOfView[mob.pos]) { + enemies.add(mob); + } + } + + enemy = enemies.size() > 0 ? Random.element(enemies) : null; + } + + return enemy; + } + + + public static EXcococat spawnAt(int pos) { + + EXcococat b = new EXcococat(); + + b.pos = pos; + b.state = b.HUNTING; + GameScene.add(b, SPAWN_DELAY); + + return b; + + } + + @Override + protected boolean canAttack(Char enemy) { + + return Dungeon.level.distance(pos, enemy.pos) <= 4; + + } + + @Override + public int hitSkill(Char target) { + return 60 + (Dungeon.depth); + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(Dungeon.depth + 20, Dungeon.depth + 32); + } + + + @Override + public int attackProc(Char enemy, int damage) { + if (Random.Int(5) == 1) { + BuildBomb bomb = new BuildBomb(); + bomb.explode(enemy.pos); + } + + return damage; + } + + @Override + public void add(Buff buff) { + //in other words, can't be directly affected by buffs/debuffs. + } + } +} diff --git a/java/com/hmdzl/spspd/items/summon/FairyCard.java b/java/com/hmdzl/spspd/items/summon/FairyCard.java new file mode 100644 index 00000000..7804f8cd --- /dev/null +++ b/java/com/hmdzl/spspd/items/summon/FairyCard.java @@ -0,0 +1,281 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 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 + */ +package com.hmdzl.spspd.items.summon; + +import java.util.ArrayList; +import java.util.HashSet; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.hero.HeroSubClass; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.CharSprite; +import com.hmdzl.spspd.sprites.FairySprite; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.sprites.SugarplumFairySprite; +import com.watabou.utils.Random; + +public class FairyCard extends Item { + + { + //name = "FairyCard"; + image = ItemSpriteSheet.FAIRYCARD; + defaultAction = AC_ACTIVE; + stackable = true; + } + + + private static boolean activate = false; + + private static final String AC_ACTIVE = "ACTIVE"; + + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + actions.add(AC_ACTIVE); + return actions; + } + + @Override + public void execute(Hero hero, String action) { + if (action.equals(AC_ACTIVE)) { + activate = true; + action = AC_THROW; + } else + activate = false; + + super.execute(hero, action); + } + + @Override + protected void onThrow(int cell) { + + if (Actor.findChar(cell) != null) { + ArrayList candidates = new ArrayList<>(); + for (int i : Level.NEIGHBOURS8) + if (Level.passable[cell + i]) + candidates.add(cell + i); + int newCell = candidates.isEmpty() ? cell : Random + .element(candidates); + + if (!Level.pit[newCell] && activate) { + if (Dungeon.hero.subClass == HeroSubClass.LEADER) { + SugarplumFairy.spawnAt(newCell); + } else Fairy.spawnAt(newCell); + } else { + Dungeon.level.drop(this, newCell).sprite.drop(cell); + } + + } else if (!Level.pit[cell] && activate) { + if (Dungeon.hero.subClass == HeroSubClass.LEADER) { + SugarplumFairy.spawnAt(cell); + } else + Fairy.spawnAt(cell); + } else { + + super.onThrow(cell); + } + + } + + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + @Override + public int price() { + return 100 * quantity; + } + + public static class Fairy extends Mob { + + { + spriteClass = FairySprite.class; + hostile = false; + state = HUNTING; + HP = HT = 200; + evadeSkill = 0; + ally=true; + properties.add(Property.BEAST); + } + + private static final float SPAWN_DELAY = 1f; + + @Override + public int drRoll() { + return 0; + } + + @Override + protected boolean act() { + damage(1, this); + + if (Level.adjacent(pos, Dungeon.hero.pos)){ + + int bless = 5; + + Dungeon.hero.sprite.emitter().start(Speck.factory(Speck.HEALING), 0.4f, 1); + Dungeon.hero.sprite.showStatus(CharSprite.POSITIVE,Integer.toString(bless)); + + Dungeon.hero.HP = Math.min(Dungeon.hero.HT, Dungeon.hero.HP+bless); + } + + return super.act(); + } + + @Override + protected boolean getCloser(int target) { + return super.getCloser(Dungeon.hero.pos); + } + + @Override + protected Char chooseEnemy() { + return null; + } + + + public static Fairy spawnAt(int pos) { + + Fairy b = new Fairy(); + + b.pos = pos; + b.state = b.HUNTING; + GameScene.add(b, SPAWN_DELAY); + + return b; + + } + + @Override + public void add(Buff buff) { + //in other words, can't be directly affected by buffs/debuffs. + } + + } + + public static class SugarplumFairy extends Mob { + + { + spriteClass = SugarplumFairySprite.class; + hostile = false; + state = HUNTING; + HP = HT = 400; + evadeSkill = 20; + ally=true; + + properties.add(Property.BEAST); + } + + private static final float SPAWN_DELAY = 1f; + + @Override + public int drRoll() { + return 0; + } + + @Override + protected boolean act() { + damage(1, this); + if (Level.adjacent(pos, Dungeon.hero.pos)){ + + int bless = 5; + + Dungeon.hero.sprite.emitter().start(Speck.factory(Speck.HEALING), 0.4f, 1); + Dungeon.hero.sprite.showStatus(CharSprite.POSITIVE,Integer.toString(bless)); + + Dungeon.hero.HP = Math.min(Dungeon.hero.HT*2, Dungeon.hero.HP+bless); + } + return super.act(); + } + + @Override + protected boolean getCloser(int target) { + if (state == WANDERING + || Level.distance(target, Dungeon.hero.pos) > 6) + this.target = target = Dungeon.hero.pos; + return super.getCloser(target); + } + + @Override + protected Char chooseEnemy() { + + if (enemy == null || !enemy.isAlive()) { + HashSet enemies = new HashSet(); + for (Mob mob : Dungeon.level.mobs) { + if (mob.hostile && Level.fieldOfView[mob.pos]) { + enemies.add(mob); + } + } + + enemy = enemies.size() > 0 ? Random.element(enemies) : null; + } + + return enemy; + } + + + public static SugarplumFairy spawnAt(int pos) { + + SugarplumFairy b = new SugarplumFairy(); + + b.pos = pos; + b.state = b.HUNTING; + GameScene.add(b, SPAWN_DELAY); + + return b; + + } + + @Override + protected boolean canAttack(Char enemy) { + + return Dungeon.level.distance(pos, enemy.pos) <= 4; + + } + + @Override + public int hitSkill(Char target) { + return 60 + (Dungeon.depth); + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(Dungeon.depth + 12, Dungeon.depth + 25); + } + + @Override + public void add(Buff buff) { + //in other words, can't be directly affected by buffs/debuffs. + } + } +} diff --git a/java/com/hmdzl/spspd/items/summon/Honeypot.java b/java/com/hmdzl/spspd/items/summon/Honeypot.java new file mode 100644 index 00000000..a33098ad --- /dev/null +++ b/java/com/hmdzl/spspd/items/summon/Honeypot.java @@ -0,0 +1,482 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 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 + */ +package com.hmdzl.spspd.items.summon; + +import java.util.ArrayList; +import java.util.HashSet; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.Statistics; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Amok; +import com.hmdzl.spspd.actors.buffs.Poison; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.hero.HeroSubClass; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.actors.mobs.npcs.NPC; +import com.hmdzl.spspd.effects.Pushing; +import com.hmdzl.spspd.effects.Splash; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.BeeSprite; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.sprites.SteelBeeSprite; +import com.watabou.noosa.audio.Sample; +import com.watabou.noosa.tweeners.AlphaTweener; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public class Honeypot extends Item { + + public static final String AC_SHATTER = "SHATTER"; + + { + //name = "honeypot"; + image = ItemSpriteSheet.HONEYPOT; + defaultAction = AC_THROW; + stackable = true; + } + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + actions.add(AC_SHATTER); + return actions; + } + + @Override + public void execute(final Hero hero, String action) { + if (action.equals(AC_SHATTER)) { + + hero.sprite.zap(hero.pos); + + detach(hero.belongings.backpack); + + shatter(hero, hero.pos).collect(); + + hero.next(); + + } else { + super.execute(hero, action); + } + } + + @Override + protected void onThrow(int cell) { + if (Level.pit[cell]) { + super.onThrow(cell); + } else { + Dungeon.level.drop(shatter(null, cell), cell); + } + } + + public Item shatter(Char owner, int pos) { + + if (Dungeon.visible[pos]) { + Sample.INSTANCE.play(Assets.SND_SHATTER); + Splash.at(pos, 0xffd500, 5); + } + + int newPos = pos; + if (Actor.findChar(pos) != null) { + ArrayList candidates = new ArrayList(); + boolean[] passable = Level.passable; + + for (int n : Level.NEIGHBOURS4) { + int c = pos + n; + if (passable[c] && Actor.findChar(c) == null) { + candidates.add(c); + } + } + + newPos = candidates.size() > 0 ? Random.element(candidates) : -1; + } + + if (newPos != -1 ) { + if (Dungeon.hero.subClass == HeroSubClass.LEADER ){ + SteelBee bee = new SteelBee(); + bee.spawn(Dungeon.depth); + bee.HP = bee.HT; + bee.pos = newPos; + + GameScene.add(bee); + Actor.addDelayed(new Pushing(bee, pos, newPos), -1f); + + bee.sprite.alpha(0); + bee.sprite.parent.add(new AlphaTweener(bee.sprite, 1, 0.15f)); + + Sample.INSTANCE.play(Assets.SND_BEE); + return new ShatteredPot(); + } else { + Bee bee = new Bee(); + bee.spawn(Dungeon.depth); + bee.setPotInfo(pos, owner); + bee.HP = bee.HT; + bee.pos = newPos; + + GameScene.add(bee); + Actor.addDelayed(new Pushing(bee, pos, newPos), -1f); + + bee.sprite.alpha(0); + bee.sprite.parent.add(new AlphaTweener(bee.sprite, 1, 0.15f)); + + Sample.INSTANCE.play(Assets.SND_BEE); + return new ShatteredPot().setBee(bee); + } + } else { + return this; + } + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + @Override + public int price() { + return 30 * quantity; + } + + // The bee's broken 'home', all this item does is let its bee know where it + // is, and who owns it (if anyone). + public static class ShatteredPot extends Item { + + { + //name = "shattered honeypot"; + image = ItemSpriteSheet.SHATTPOT; + stackable = false; + } + + private int myBee; + private int beeDepth; + + public Item setBee(Char bee) { + myBee = bee.id(); + beeDepth = Dungeon.depth; + return this; + } + + @Override + public boolean doPickUp(Hero hero) { + if (super.doPickUp(hero)) { + setHolder(hero); + return true; + } else + return false; + } + + @Override + public void doDrop(Hero hero) { + super.doDrop(hero); + updateBee(hero.pos, null); + } + + @Override + protected void onThrow(int cell) { + super.onThrow(cell); + updateBee(cell, null); + } + + public void setHolder(Char holder) { + updateBee(holder.pos, holder); + } + + public void goAway() { + updateBee(-1, null); + } + + private void updateBee(int cell, Char holder) { + // important, as ids are not unique between depths. + if (Dungeon.depth != beeDepth) + return; + + Bee bee = (Bee) Actor.findById(myBee); + if (bee != null) + bee.setPotInfo(cell, holder); + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + private static final String MYBEE = "mybee"; + private static final String BEEDEPTH = "beedepth"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(MYBEE, myBee); + bundle.put(BEEDEPTH, beeDepth); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + myBee = bundle.getInt(MYBEE); + beeDepth = bundle.getInt(BEEDEPTH); + } + } + public static class Bee extends Mob { + + { + spriteClass = BeeSprite.class; + + viewDistance = 4; + + flying = true; + state = WANDERING; + + properties.add(Property.BEAST); + } + + private int level; + + // -1 refers to a pot that has gone missing. + private int potPos; + // -1 for no owner + private int potHolder; + + private static final String LEVEL = "level"; + private static final String POTPOS = "potpos"; + private static final String POTHOLDER = "potholder"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(LEVEL, level); + bundle.put(POTPOS, potPos); + bundle.put(POTHOLDER, potHolder); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + spawn(bundle.getInt(LEVEL)); + potPos = bundle.getInt(POTPOS); + potHolder = bundle.getInt(POTHOLDER); + } + + public void spawn(int level) { + this.level = Math.min(level,Statistics.deepestFloor); + + HT = (20 + level) * 4; + evadeSkill = 9 + level; + } + + public void setPotInfo(int potPos, Char potHolder) { + this.potPos = potPos; + if (potHolder == null) + this.potHolder = -1; + else + this.potHolder = potHolder.id(); + } + + @Override + public int hitSkill(Char target) { + return evadeSkill; + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(HT / 10, HT / 4); + } + + @Override + public int attackProc(Char enemy, int damage) { + if (enemy instanceof Mob) { + ((Mob) enemy).aggro(this); + } + return damage; + } + + @Override + protected Char chooseEnemy() { + // if the pot is no longer present, target the hero + if (potHolder == -1 && potPos == -1) + return Dungeon.hero; + + // if something is holding the pot, target that + else if (Actor.findById(potHolder) != null) + return (Char) Actor.findById(potHolder); + + // if the pot is on the ground + else { + + // if already targeting something, and that thing is still alive and + // near the pot, keeping targeting it. + if (enemy != null && enemy.isAlive() + && Level.distance(enemy.pos, potPos) <= 3) + return enemy; + + // find all mobs near the pot + HashSet enemies = new HashSet(); + for (Mob mob : Dungeon.level.mobs) + if (!(mob instanceof Bee) + && Level.distance(mob.pos, potPos) <= 3 + && (mob.hostile || mob.ally)) + enemies.add(mob); + + // pick one, if there are none, check if the hero is near the pot, + // go for them, otherwise go for nothing. + if (enemies.size() > 0) + return Random.element(enemies); + else + return (Level.distance(Dungeon.hero.pos, potPos) <= 3) ? Dungeon.hero + : null; + } + } + + @Override + protected boolean getCloser(int target) { + if (enemy != null && Actor.findById(potHolder) == enemy) { + target = enemy.pos; + } else if (potPos != -1 + && (state == WANDERING || Level.distance(target, potPos) > 3)) + this.target = target = potPos; + return super.getCloser(target); + } + + private static final HashSet> IMMUNITIES = new HashSet>(); + static { + IMMUNITIES.add(Poison.class); + IMMUNITIES.add(Amok.class); + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } + } + public static class SteelBee extends NPC { + + { + //name = "golden bee"; + spriteClass = SteelBeeSprite.class; + + viewDistance = 6; + ally=true; + flying = true; + state = WANDERING; + } + + private 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); + spawn(bundle.getInt(LEVEL)); + } + + public void spawn(int level) { + this.level = Math.min(level,Statistics.deepestFloor); + HT = (50 + level) * 4; + evadeSkill = 15 + level; + } + @Override + public int hitSkill(Char target) { + return evadeSkill*2; + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(HT / 8, HT / 2); + } + + @Override + protected boolean canAttack(Char enemy) { + return super.canAttack(enemy); + } + + @Override + protected boolean getCloser(int target) { + if (state == WANDERING + || Level.distance(target, Dungeon.hero.pos) > 6) + this.target = target = Dungeon.hero.pos; + return super.getCloser(target); + } + @Override + protected Char chooseEnemy() { + if (enemy == null || !enemy.isAlive() || state == WANDERING) { + + HashSet enemies = new HashSet(); + for (Mob mob : Dungeon.level.mobs) { + if (mob.hostile && Level.fieldOfView[mob.pos] + && mob.state != mob.PASSIVE) { + enemies.add(mob); + } + } + enemy = enemies.size() > 0 ? Random.element(enemies) : null; + } + return enemy; + } + + @Override + public boolean interact() { + if (Dungeon.level.passable[pos] || Dungeon.hero.flying) { + int curPos = pos; + + moveSprite(pos, Dungeon.hero.pos); + move(Dungeon.hero.pos); + + Dungeon.hero.sprite.move(Dungeon.hero.pos, curPos); + Dungeon.hero.move(curPos); + + Dungeon.hero.spend(1 / Dungeon.hero.speed()); + Dungeon.hero.busy(); + return true; + } else { + return false; + } + } + + private static final HashSet> IMMUNITIES = new HashSet>(); + + static { + IMMUNITIES.add(Poison.class); + } + + @Override + public HashSet> immunities() { + return IMMUNITIES; + } + + } +} diff --git a/java/com/hmdzl/spspd/items/summon/Mobile.java b/java/com/hmdzl/spspd/items/summon/Mobile.java new file mode 100644 index 00000000..7ed28c79 --- /dev/null +++ b/java/com/hmdzl/spspd/items/summon/Mobile.java @@ -0,0 +1,302 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 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 + */ +package com.hmdzl.spspd.items.summon; + +import java.util.ArrayList; +import java.util.HashSet; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.hero.HeroSubClass; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ExMobileSprite; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.sprites.MobileSprite; +import com.watabou.utils.Random; + +public class Mobile extends Item { + + { + //name = "mobile key"; + image = ItemSpriteSheet.MOBS; + defaultAction = AC_ACTIVE; + stackable = true; + } + + + private static boolean activate = false; + + private static final String AC_ACTIVE = "ACTIVE"; + + + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + actions.add(AC_ACTIVE); + return actions; + } + + @Override + public void execute(Hero hero, String action) { + if (action.equals(AC_ACTIVE)) { + activate = true; + action = AC_THROW; + } else + activate = false; + + super.execute(hero, action); + } + + @Override + protected void onThrow(int cell) { + + if (Actor.findChar(cell) != null) { + ArrayList candidates = new ArrayList<>(); + for (int i : Level.NEIGHBOURS8) + if (Level.passable[cell + i]) + candidates.add(cell + i); + int newCell = candidates.isEmpty() ? cell : Random + .element(candidates); + + if (!Level.pit[newCell] && activate) { + if (Dungeon.hero.subClass == HeroSubClass.LEADER){ + EXMobileSatellite.spawnAt(newCell); + } else MobileSatellite.spawnAt(newCell); + } else { + Dungeon.level.drop(this, newCell).sprite.drop(cell); + } + + } else if (!Level.pit[cell] && activate) { + if (Dungeon.hero.subClass == HeroSubClass.LEADER){ + EXMobileSatellite.spawnAt(cell); + } else MobileSatellite.spawnAt(cell); + } else { + + super.onThrow(cell); + } + + } + + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + @Override + public int price() { + return 100 * quantity; + } + + public static class MobileSatellite extends Mob { + + { + spriteClass = MobileSprite.class; + hostile = false; + state = HUNTING; + HP = HT= 100; + evadeSkill = 0; + ally=true; + properties.add(Property.MECH); + } + + private static final float SPAWN_DELAY = 1f; + + @Override + protected float attackDelay() { + return 0.33f; + } + + @Override + public int drRoll() { + return 0; + } + + + @Override + protected boolean act() { + damage(1, this); + return super.act(); + } + + @Override + protected boolean getCloser(int target) { + if (state == WANDERING + || Level.distance(target, Dungeon.hero.pos) > 6) + this.target = target = Dungeon.hero.pos; + return super.getCloser(target); + } + + + @Override + protected Char chooseEnemy() { + + if (enemy == null || !enemy.isAlive()) { + HashSet enemies = new HashSet(); + for (Mob mob : Dungeon.level.mobs) { + if (mob.hostile && Level.fieldOfView[mob.pos]) { + enemies.add(mob); + } + } + + enemy = enemies.size() > 0 ? Random.element(enemies) : null; + } + + return enemy; + } + + + + public static MobileSatellite spawnAt(int pos) { + + MobileSatellite b = new MobileSatellite(); + + b.pos = pos; + b.state = b.HUNTING; + GameScene.add(b, SPAWN_DELAY); + + return b; + + } + + + @Override + protected boolean canAttack(Char enemy) { + return Dungeon.level.distance( pos, enemy.pos ) <= 6 ; + } + + @Override + public int hitSkill(Char target) { + return 30+(Dungeon.depth); + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(HP/8+5, HP/2+10); + } + @Override + public void add( Buff buff ) { + //in other words, can't be directly affected by buffs/debuffs. + } + } + public static class EXMobileSatellite extends Mob { + + { + spriteClass = ExMobileSprite.class; + hostile = false; + state = HUNTING; + HP = HT = 300; + evadeSkill = 35; + ally=true; + properties.add(Property.MECH); + } + + private Ballistica beam; + + private static final float SPAWN_DELAY = 1f; + + @Override + protected float attackDelay() { + return 0.25f; + } + + @Override + public int drRoll() { + return 0; + } + + + @Override + protected boolean act() { + damage(1, this); + return super.act(); + } + + @Override + protected boolean getCloser(int target) { + if (state == WANDERING + || Level.distance(target, Dungeon.hero.pos) > 6) + this.target = target = Dungeon.hero.pos; + return super.getCloser(target); + } + + @Override + protected Char chooseEnemy() { + + if (enemy == null || !enemy.isAlive()) { + HashSet enemies = new HashSet(); + for (Mob mob : Dungeon.level.mobs) { + if (mob.hostile && Level.fieldOfView[mob.pos]) { + enemies.add(mob); + } + } + + enemy = enemies.size() > 0 ? Random.element(enemies) : null; + } + + return enemy; + } + + + public static EXMobileSatellite spawnAt(int pos) { + + EXMobileSatellite b = new EXMobileSatellite(); + + b.pos = pos; + b.state = b.HUNTING; + GameScene.add(b, SPAWN_DELAY); + + return b; + + } + + @Override + protected boolean canAttack(Char enemy) { + return Dungeon.level.distance(pos, enemy.pos) <= 6; + } + + @Override + public int hitSkill(Char target) { + return 60 + (Dungeon.depth); + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(HP / 6 + 10, HP / 2 + 20); + } + + @Override + public void add(Buff buff) { + //in other words, can't be directly affected by buffs/debuffs. + } + + } +} diff --git a/java/com/hmdzl/spspd/items/wands/CannonOfMage.java b/java/com/hmdzl/spspd/items/wands/CannonOfMage.java new file mode 100644 index 00000000..89619b04 --- /dev/null +++ b/java/com/hmdzl/spspd/items/wands/CannonOfMage.java @@ -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 + */ +package com.hmdzl.spspd.items.wands; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.ArmorBreak; +import com.hmdzl.spspd.actors.buffs.AttackDown; +import com.hmdzl.spspd.actors.buffs.Blindness; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Burning; +import com.hmdzl.spspd.actors.buffs.Frost; +import com.hmdzl.spspd.actors.buffs.Ooze; +import com.hmdzl.spspd.actors.buffs.Shocked; +import com.hmdzl.spspd.effects.MagicMissile; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; + +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Callback; +import com.watabou.utils.Random; + +public class CannonOfMage extends DamageWand { + + { + image = ItemSpriteSheet.CANNON_OF_MAGE; + collisionProperties = Ballistica.MAGIC_BOLT; + reinforced = true; + } + + public int min(int lvl){ + return 1+lvl; + } + + public int max(int lvl){ + return 5+2*lvl; + } + + @Override + protected void onZap( Ballistica bolt ) { + + Char ch = Actor.findChar(bolt.collisionPos); + if (ch != null) { + + + + if (ch.isAlive()){ + switch (Random.Int(7)) { + case 0: + ch.damage((int) (damageRoll() * (1 + 0.3 * Dungeon.hero.magicSkill())), this); + break; + case 1: + Buff.affect(ch, Burning.class).reignite(ch); + break; + case 2: + Buff.affect(ch, Shocked.class, 5f); + break; + case 3: + Buff.affect(ch, Ooze.class); + break; + case 4: + Buff.affect(ch, Frost.class, 5f); + break; + case 5: + Buff.affect(ch, AttackDown.class, 10f).level(30); + Buff.affect(ch, ArmorBreak.class, 10f).level(30); + break; + case 6: + Buff.prolong(ch, Blindness.class, 5f); + break; + default: + GLog.i("nothing happened"); + break; + } + processSoulMark(ch, chargesPerCast()); + ch.damage((int) (damageRoll() * (1 + 0.5 * Dungeon.hero.magicSkill())), this); + } + } + } + + @Override + protected int initialCharges() { + return 7; + } + + @Override + public Item upgrade() { + + super.upgrade(); + maxCharges = 7; + updateQuickslot(); + return this; + } + + @Override + protected void fx(Ballistica bolt, Callback callback) { + MagicMissile.rainbow(curUser.sprite.parent, curUser.pos, bolt.collisionPos, + callback); + Sample.INSTANCE.play(Assets.SND_ZAP); + } +} diff --git a/java/com/hmdzl/spspd/items/wands/DamageWand.java b/java/com/hmdzl/spspd/items/wands/DamageWand.java new file mode 100644 index 00000000..ffb664f1 --- /dev/null +++ b/java/com/hmdzl/spspd/items/wands/DamageWand.java @@ -0,0 +1,76 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2017 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ + +package com.hmdzl.spspd.items.wands; + +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Recharging; +import com.hmdzl.spspd.actors.hero.HeroClass; +import com.hmdzl.spspd.actors.hero.HeroSubClass; +import com.hmdzl.spspd.items.rings.RingOfMagic; +import com.hmdzl.spspd.messages.Messages; +import com.watabou.utils.Random; + +//for wands that directly damage a target +//wands with AOE effects count here (e.g. fireblast), but wands with indrect damage do not (e.g. venom, transfusion) +public abstract class DamageWand extends Wand{ + + //public int magicLevel = 0; + /*{ + for (Buff buff : curUser.buffs(RingOfMagic.Magic.class)) + magicLevel += Math.min(30,((RingOfMagic.Magic) buff).level); + if (curUser.subClass == HeroSubClass.BATTLEMAGE) + magicLevel += 5; + if (curUser.heroClass == HeroClass.MAGE) + magicLevel += 3; + if (curUser.buff(Recharging.class)!= null) + magicLevel += 10; + }*/ + + + public int min(){ + return min(level()); + } + + public abstract int min(int lvl); + + public int max(){ + return max(level()); + } + + public abstract int max(int lvl); + + public int damageRoll(){ + return Random.NormalIntRange(min(), max()); + } + + public int damageRoll(int lvl){ + return Random.NormalIntRange(min(lvl), max(lvl)); + } + + @Override + public String statsDesc() { + if (levelKnown) + return Messages.get(this, "stats_desc", min(), max()); + else + return Messages.get(this, "stats_desc", min(0), max(0)); + } +} diff --git a/java/com/hmdzl/spspd/items/wands/Wand.java b/java/com/hmdzl/spspd/items/wands/Wand.java new file mode 100644 index 00000000..caf4d933 --- /dev/null +++ b/java/com/hmdzl/spspd/items/wands/Wand.java @@ -0,0 +1,451 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2015 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.items.wands; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Challenges; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.buffs.Recharging; +import com.hmdzl.spspd.actors.buffs.Silent; +import com.hmdzl.spspd.actors.buffs.SoulMark; +import com.hmdzl.spspd.actors.hero.HeroClass; +import com.hmdzl.spspd.actors.hero.HeroSubClass; +import com.hmdzl.spspd.items.misc.GnollMark; +import com.hmdzl.spspd.items.rings.Ring; +import com.hmdzl.spspd.items.rings.RingOfEnergy; +import com.hmdzl.spspd.messages.Messages; +import com.watabou.noosa.audio.Sample; +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Invisibility; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.MagicMissile; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.bags.Bag; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.scenes.CellSelector; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.ui.QuickSlotButton; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Bundle; +import com.watabou.utils.Callback; +import com.watabou.utils.Random; + +public abstract class Wand extends Item { + + private static final int USAGES_TO_KNOW = 20; + + public static final String AC_ZAP = "ZAP"; + + private static final float TIME_TO_ZAP = 1f; + + public int maxCharges = initialCharges(); + public int curCharges = maxCharges; + public float partialCharge = 0f; + + protected Charger charger; + + private boolean curChargeKnown = false; + + protected boolean hitChars = true; + + protected int usagesToKnow = USAGES_TO_KNOW; + + protected int collisionProperties = Ballistica.MAGIC_BOLT; + + { + defaultAction = AC_ZAP; + usesTargeting = true; + } + + @Override + public ArrayList actions( Hero hero ) { + ArrayList actions = super.actions( hero ); + if (curCharges > 0 || !curChargeKnown) { + actions.add( AC_ZAP ); + } + + return actions; + } + + @Override + public void execute( Hero hero, String action ) { + if (action.equals( AC_ZAP )) { + if (hero.buff(Silent.class) != null) { + GLog.w(Messages.get(Wand.class, "silent")); + } else { + curUser = hero; + curItem = this; + GameScene.selectCell( zapper ); + } + + } else { + + super.execute( hero, action ); + + } + } + + protected abstract void onZap( Ballistica attack ); + + @Override + public boolean collect( Bag container ) { + if (super.collect( container )) { + if (container.owner != null) { + charge( container.owner ); + } + return true; + } else { + return false; + } + } + + public void charge( Char owner ) { + if (charger == null) charger = new Charger(); + charger.attachTo( owner ); + } + + public void charge( Char owner, float chargeScaleFactor ){ + charge( owner ); + charger.setScaleFactor( chargeScaleFactor ); + } + + protected void processSoulMark(Char target, int chargesUsed){ + if (target != Dungeon.hero && + Dungeon.hero.subClass == HeroSubClass.WARLOCK && + Random.Float() < .15f + (level*chargesUsed*0.03f)){ + SoulMark.prolong(target, SoulMark.class, SoulMark.DURATION + level); + } + } + + @Override + public void onDetach( ) { + stopCharging(); + } + + public void stopCharging() { + if (charger != null) { + charger.detach(); + charger = null; + } + } + + public int level() { + + return level; + } + + @Override + public Item identify() { + + curChargeKnown = true; + super.identify(); + + updateQuickslot(); + + return this; + } + + @Override + public String toString() { + + StringBuilder sb = new StringBuilder( super.toString() ); + + String status = status(); + if (status != null) { + sb.append( " (" + status + ")" ); + } + + return sb.toString(); + } + + @Override + public String info() { + String desc = desc(); + + desc += "\n\n" + statsDesc(); + + if (cursed && cursedKnown) + desc += "\n\n" + Messages.get(Wand.class, "cursed"); + + if(reinforced){ + desc += "\n\n" + Messages.get(Item.class, "reinforced"); + } + + return desc; + } + + public String statsDesc(){ + return Messages.get(this, "stats_desc"); + }; + + @Override + public boolean isIdentified() { + return super.isIdentified() && curChargeKnown; + } + + @Override + public String status() { + if (levelKnown) { + return (curChargeKnown ? curCharges : "?") + "/" + maxCharges; + } else { + return null; + } + } + + @Override + public Item upgrade() { + + super.upgrade(); + + updateLevel(); + curCharges = Math.min( curCharges + 1, maxCharges ); + updateQuickslot(); + + return this; + } + + @Override + public Item degrade() { + super.degrade(); + + updateLevel(); + updateQuickslot(); + + return this; + } + + public void updateLevel() { + maxCharges = + Dungeon.isChallenged(Challenges.ENERGY_LOST)? Math.min( initialCharges() + level, 4 ) : Math.min( initialCharges() + level, 10 ); + curCharges = Math.min( curCharges, maxCharges ); + } + + protected int initialCharges() { + return 2; + } + + protected int chargesPerCast() { + return 1; + } + + protected void fx( Ballistica bolt, Callback callback ) { + MagicMissile.whiteLight( curUser.sprite.parent, bolt.sourcePos, bolt.collisionPos, callback ); + Sample.INSTANCE.play( Assets.SND_ZAP ); + } + + protected void wandUsed() { + curCharges -= chargesPerCast(); + //if (!isIdentified() && usagesToKnow <= 0) { + // identify(); + // GLog.w( Messages.get(Wand.class, "identify", name()) ); + //} else { + if (curUser.heroClass == HeroClass.MAGE) levelKnown = true; + updateQuickslot(); + // } + + if (Dungeon.hero.heroClass == HeroClass.MAGE && Dungeon.hero.subClass == HeroSubClass.BATTLEMAGE){ + curUser.spendAndNext(TIME_TO_ZAP/3); + } else if (Dungeon.hero.heroClass == HeroClass.MAGE ){ + curUser.spendAndNext(TIME_TO_ZAP*2/3); + } else curUser.spendAndNext(TIME_TO_ZAP); + + GnollMark gnollmark = curUser.belongings.getItem(GnollMark.class); + if (gnollmark!=null && gnollmark.charge 0) { + price *= (level + 1); + } else if (level < 0) { + price /= (1 - level); + } + } + if (price < 1) { + price = 1; + } + return price; + } + + private static final String UNFAMILIRIARITY = "unfamiliarity"; + private static final String CUR_CHARGES = "curCharges"; + private static final String CUR_CHARGE_KNOWN = "curChargeKnown"; + private static final String PARTIALCHARGE = "partialCharge"; + + @Override + public void storeInBundle( Bundle bundle ) { + super.storeInBundle( bundle ); + bundle.put( UNFAMILIRIARITY, usagesToKnow ); + bundle.put( CUR_CHARGES, curCharges ); + bundle.put( CUR_CHARGE_KNOWN, curChargeKnown ); + bundle.put( PARTIALCHARGE , partialCharge ); + } + + @Override + public void restoreFromBundle( Bundle bundle ) { + super.restoreFromBundle( bundle ); + if ((usagesToKnow = bundle.getInt( UNFAMILIRIARITY )) == 0) { + usagesToKnow = USAGES_TO_KNOW; + } + curCharges = bundle.getInt( CUR_CHARGES ); + curChargeKnown = bundle.getBoolean( CUR_CHARGE_KNOWN ); + partialCharge = bundle.getFloat( PARTIALCHARGE ); + } + + protected static CellSelector.Listener zapper = new CellSelector.Listener() { + + @Override + public void onSelect( Integer target ) { + + if (target != null) { + + final Wand curWand = (Wand)Wand.curItem; + + final Ballistica shot = new Ballistica( curUser.pos, target, curWand.collisionProperties); + int cell = shot.collisionPos; + + if (target == curUser.pos || cell == curUser.pos) { + GLog.i( Messages.get(Wand.class, "self_target") ); + return; + } + + curUser.sprite.zap(cell); + + //attempts to target the cell aimed at if something is there, otherwise targets the collision pos. + if (Actor.findChar(target) != null) + QuickSlotButton.target(Actor.findChar(target)); + else + QuickSlotButton.target(Actor.findChar(cell)); + + if (curWand.curCharges >= 1) { + + curUser.busy(); + + curWand.fx(shot, new Callback() { + @Override + public void call() { + curWand.onZap(shot); + curWand.wandUsed(); + } + }); + + Invisibility.dispel(); + + } else { + + GLog.w( Messages.get(Wand.class, "fizzles") ); + + } + + } + } + + @Override + public String prompt() { + return Messages.get(Wand.class, "prompt"); + } + }; + + protected class Charger extends Buff { + + private static final float BASE_CHARGE_DELAY = 10f; + private static final float SCALING_CHARGE_ADDITION = 50f; + private static final float NORMAL_SCALE_FACTOR = 0.95f; + + private static final float CHARGE_BUFF_BONUS = 0.25f; + + float scalingFactor = NORMAL_SCALE_FACTOR; + + @Override + public boolean attachTo( Char target ) { + super.attachTo( target ); + + return true; + } + + @Override + public boolean act() { + if (curCharges < maxCharges) + gainCharge(); + + if (partialCharge >= 1 && curCharges < maxCharges) { + partialCharge--; + curCharges++; + updateQuickslot(); + } + + spend( TICK ); + + return true; + } + + private void gainCharge(){ + int missingCharges = maxCharges - curCharges; + + missingCharges += Ring.getBonus(target, RingOfEnergy.Energy.class); + missingCharges = Math.max(0, missingCharges); + if (Dungeon.hero.heroClass==HeroClass.MAGE && Dungeon.skins==2){ + missingCharges+=2; + } + float turnsToCharge = (float) (BASE_CHARGE_DELAY + + (SCALING_CHARGE_ADDITION * Math.pow(scalingFactor, missingCharges))); + partialCharge += 1f/turnsToCharge; + Recharging bonus = target.buff(Recharging.class); + if (bonus != null && bonus.remainder() > 0f){ + partialCharge += CHARGE_BUFF_BONUS * bonus.remainder(); + } + } + + private void setScaleFactor(float value){ + this.scalingFactor = value; + } + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/wands/WandOfAcid.java b/java/com/hmdzl/spspd/items/wands/WandOfAcid.java new file mode 100644 index 00000000..f8db0a57 --- /dev/null +++ b/java/com/hmdzl/spspd/items/wands/WandOfAcid.java @@ -0,0 +1,78 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.wands; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Ooze; +import com.hmdzl.spspd.effects.MagicMissile; +import com.hmdzl.spspd.items.Heap; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Callback; +import com.watabou.utils.Random; + +import static com.hmdzl.spspd.Dungeon.hero; + +public class WandOfAcid extends DamageWand { + + { + image = ItemSpriteSheet.WAND_ACID; + collisionProperties = Ballistica.PROJECTILE; + } + + public int min(int lvl){ + return 2+lvl; + } + + public int max(int lvl){ + return 6+4*lvl; + } + + @Override + protected void onZap( Ballistica bolt ) { + + Heap heap = Dungeon.level.heaps.get(bolt.collisionPos); + if (heap != null) { + heap.poison(); + } + + Char ch = Actor.findChar(bolt.collisionPos); + if (ch != null) { + + processSoulMark(ch, chargesPerCast()); + if (ch.isAlive() && Random.Int(2) == 0){ + Buff.affect(ch, Ooze.class); + } + ch.damage((int)( damageRoll() * (1 + 0.1 * hero.magicSkill())), this); + + + } + } + + @Override + protected void fx(Ballistica bolt, Callback callback) { + MagicMissile.foliage(curUser.sprite.parent, curUser.pos, bolt.collisionPos, + callback); + Sample.INSTANCE.play(Assets.SND_ZAP); + } +} diff --git a/java/com/hmdzl/spspd/items/wands/WandOfBlood.java b/java/com/hmdzl/spspd/items/wands/WandOfBlood.java new file mode 100644 index 00000000..af9803f7 --- /dev/null +++ b/java/com/hmdzl/spspd/items/wands/WandOfBlood.java @@ -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 + */ +package com.hmdzl.spspd.items.wands; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.effects.MagicMissile; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Callback; +import com.watabou.utils.Random; + +public class WandOfBlood extends DamageWand { + + { + image = ItemSpriteSheet.WAND_BLOOD; + collisionProperties = Ballistica.PROJECTILE; + } + + public int min(int lvl){ + return lvl; + } + + public int max(int lvl){ + return 6+2*lvl; + } + + @Override + protected void onZap(Ballistica bolt) { + Char ch = Actor.findChar(bolt.collisionPos); + if (ch != null) { + + processSoulMark(ch, chargesPerCast()); + + ch.damage((int)( damageRoll() * (1 + 0.1 * Dungeon.hero.magicSkill())), this); + if (curUser.HP < curUser.HT){ + curUser.HP += Math.min(Random.Int(0,damageRoll()),(curUser.HT - curUser.HP));} + } + + } + + + @Override + protected void fx(Ballistica bolt, Callback callback) { + MagicMissile.shadow(curUser.sprite.parent, curUser.pos, bolt.collisionPos, + callback); + Sample.INSTANCE.play(Assets.SND_ZAP); + } + + /*public static void appear(Char ch, int pos) { + + ch.sprite.interruptMotion(); + + ch.move(pos); + ch.sprite.place(pos); + + if (ch.invisible == 0) { + ch.sprite.alpha(0); + ch.sprite.parent.add(new AlphaTweener(ch.sprite, 1, 0.4f)); + } + + ch.sprite.emitter().start(Speck.factory(Speck.LIGHT), 0.2f, 3); + Sample.INSTANCE.play(Assets.SND_TELEPORT); + }*/ +} diff --git a/java/com/hmdzl/spspd/items/wands/WandOfCharm.java b/java/com/hmdzl/spspd/items/wands/WandOfCharm.java new file mode 100644 index 00000000..b7e86723 --- /dev/null +++ b/java/com/hmdzl/spspd/items/wands/WandOfCharm.java @@ -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 + */ +package com.hmdzl.spspd.items.wands; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Amok; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Charm; +import com.hmdzl.spspd.actors.buffs.Vertigo; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.effects.MagicMissile; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Callback; +import com.watabou.utils.Random; + +public class WandOfCharm extends Wand { + + { + image = ItemSpriteSheet.WAND_CHARM; + collisionProperties = Ballistica.PROJECTILE; + } + + @Override + protected void onZap(Ballistica bolt) { + Char ch = Actor.findChar(bolt.collisionPos); + if (ch != null) { + + processSoulMark(ch, chargesPerCast()); + + if (ch == Dungeon.hero) { + Buff.affect(ch, Vertigo.class, Vertigo.duration(ch)); + } else { + Buff.affect(ch, Amok.class, chargesPerCast() + level()); + Buff.affect(ch, Charm.class, Charm.durationFactor(ch) + * Random.IntRange(chargesPerCast(), 3*level())).object = curUser.id(); + ch.sprite.centerEmitter().start(Speck.factory(Speck.HEART), + 0.2f, 5); + Sample.INSTANCE.play(Assets.SND_CHARMS); + } + } + } + + @Override + protected int initialCharges() { + return 1; + } + + @Override + protected int chargesPerCast() { + return Math.max(1, (int)Math.ceil(curCharges*0.5f)); + } + + @Override + protected void fx(Ballistica bolt, Callback callback) { + MagicMissile.purpleLight(curUser.sprite.parent, curUser.pos, bolt.collisionPos, + callback); + Sample.INSTANCE.play(Assets.SND_ZAP); + } +} diff --git a/java/com/hmdzl/spspd/items/wands/WandOfDisintegration.java b/java/com/hmdzl/spspd/items/wands/WandOfDisintegration.java new file mode 100644 index 00000000..ad5b25b7 --- /dev/null +++ b/java/com/hmdzl/spspd/items/wands/WandOfDisintegration.java @@ -0,0 +1,107 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.wands; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.DungeonTilemap; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.effects.Beam; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.particles.PurpleParticle; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.utils.Callback; +import com.watabou.utils.Random; + +public class WandOfDisintegration extends DamageWand { + + { + + image = ItemSpriteSheet.WAND_DISINTEGRATION; + + collisionProperties = Ballistica.WONT_STOP; + } + + public int min(int lvl){ + return 2+lvl; + } + + public int max(int lvl){ + return 8+4*lvl; + } + + @Override + protected void onZap( Ballistica beam) { + + boolean terrainAffected = false; + + int level = level(); + + int maxDistance = Math.min(distance(), beam.dist); + + ArrayList chars = new ArrayList<>(); + + int terrainPassed = 2, terrainBonus = 0; + for (int c : beam.subPath(1, maxDistance)) { + + Char ch; + if ((ch = Actor.findChar( c )) != null) { + + //we don't want to count passed terrain after the last enemy hit. That would be a lot of bonus levels. + //terrainPassed starts at 2, equivalent of rounding up when /3 for integer arithmetic. + terrainBonus += terrainPassed/3; + terrainPassed = terrainPassed%3; + + chars.add( ch ); + } + + if (Level.solid[c]) + terrainPassed++; + + CellEmitter.center( c ).burst( PurpleParticle.BURST, Random.IntRange( 1, 2 ) ); + } + + if (terrainAffected) { + Dungeon.observe(); + } + + int lvl = Math.max(level - chars.size() , 1); + for (Char ch : chars) { + processSoulMark(ch, chargesPerCast()); + ch.damage( (int)( damageRoll(lvl) * (1 + 0.1 * Dungeon.hero.magicSkill())), this ); + ch.sprite.centerEmitter().burst( PurpleParticle.BURST, Random.IntRange( 1, 2 ) ); + ch.sprite.flash(); + } + } + + private int distance() { + return Math.min(8,level() + 2); + } + + @Override + protected void fx( Ballistica beam, Callback callback ) { + + int cell = beam.path.get(Math.min(beam.dist, distance())); + curUser.sprite.parent.add(new Beam.DeathRay(curUser.sprite.center(), DungeonTilemap.tileCenterToWorld( cell ))); + callback.call(); + } +} diff --git a/java/com/hmdzl/spspd/items/wands/WandOfError.java b/java/com/hmdzl/spspd/items/wands/WandOfError.java new file mode 100644 index 00000000..8c85abe6 --- /dev/null +++ b/java/com/hmdzl/spspd/items/wands/WandOfError.java @@ -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 + */ +package com.hmdzl.spspd.items.wands; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.Blob; +import com.hmdzl.spspd.actors.blobs.ConfusionGas; +import com.hmdzl.spspd.actors.blobs.ParalyticGas; +import com.hmdzl.spspd.actors.blobs.Regrowth; +import com.hmdzl.spspd.actors.blobs.ToxicGas; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Burning; +import com.hmdzl.spspd.actors.buffs.Frost; +import com.hmdzl.spspd.actors.buffs.Recharging; +import com.hmdzl.spspd.actors.mobs.npcs.NPC; +import com.hmdzl.spspd.effects.MagicMissile; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.effects.SpellSprite; +import com.hmdzl.spspd.items.bombs.Bomb; +import com.hmdzl.spspd.items.scrolls.ScrollOfRecharging; +import com.hmdzl.spspd.items.scrolls.ScrollOfTeleportation; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.Terrain; +import com.hmdzl.spspd.levels.traps.LightningTrap; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Callback; +import com.watabou.utils.Random; +import com.hmdzl.spspd.actors.buffs.Slow; +import com.hmdzl.spspd.actors.buffs.Strength; +import com.watabou.noosa.tweeners.AlphaTweener; + +public class WandOfError extends Wand { + + { + image = ItemSpriteSheet.ERROR_WAND; + + } + + protected void onZap(Ballistica bolt) { + Char ch = Actor.findChar(bolt.collisionPos); + switch (Random.Int(10)){ + case 0: + if (ch == curUser) { + ScrollOfTeleportation.teleportHero(curUser); + + } else if (ch != null && !(ch instanceof NPC)) { + + int count = 10; + int pos; + do { + pos = Dungeon.level.randomRespawnCell(); + if (count-- <= 0) { + break; + } + } while (pos == -1); + + if (pos == -1) { + + GLog.w("In a blink of an eye you were teleported to another location of the level."); + + } else { + + ch.pos = pos; + ch.sprite.place(ch.pos); + ch.sprite.visible = Dungeon.visible[pos]; + GLog.i(curUser.name + " teleported " + ch.name + + " to somewhere");} + } + break; + case 1: + if (ch != null) { + int damage = (ch.HT/4) ; + if (Dungeon.hero.buff(Strength.class) != null) + {damage *= (int) 4f; Buff.detach(Dungeon.hero, Strength.class);} + ch.damage(damage, this); + } + break; + case 2: + if (ch != null) {Buff.affect(ch, Slow.class,10);} + break; + case 3: + if (Ballistica.distance > 9) { + bolt.sourcePos = Ballistica.trace[8]; + } else if (Actor.findChar(bolt.sourcePos) != null && Ballistica.distance > 1) { + bolt.sourcePos = Ballistica.trace[Ballistica.distance - 2]; + } + curUser.sprite.visible = true; + appear(Dungeon.hero, bolt.sourcePos); + Dungeon.observe(); + break; + case 4: + for (int i = 1; i < Ballistica.distance - 1; i++) { + int p = Ballistica.trace[i]; + int c = Dungeon.level.map[p]; + if (c == Terrain.EMPTY || c == Terrain.EMBERS + || c == Terrain.EMPTY_DECO) { + + Level.set(p, Terrain.GRASS); + + } + } + int c = Dungeon.level.map[bolt.collisionPos]; + if (c == Terrain.EMPTY || c == Terrain.EMBERS + || c == Terrain.EMPTY_DECO || c == Terrain.GRASS + || c == Terrain.HIGH_GRASS) { + GameScene.add(Blob.seed(bolt.collisionPos, (level() + 2) * 20, Regrowth.class)); + } + break; + case 5: + switch (Random.Int(3)) { + case 0: + GameScene.add( Blob.seed( bolt.collisionPos, 800, ConfusionGas.class ) ); + break; + case 1: + GameScene.add( Blob.seed( bolt.collisionPos, 500, ToxicGas.class ) ); + break; + case 2: + GameScene.add( Blob.seed( bolt.collisionPos, 200, ParalyticGas.class ) ); + break; + } + break; + case 6: + new Bomb().explode(bolt.collisionPos); + break; + case 7: + new LightningTrap().set( curUser.pos ).activate(curUser); + Buff.prolong(curUser, Recharging.class, 20f); + ScrollOfRecharging.charge(curUser); + SpellSprite.show(curUser, SpellSprite.CHARGE); + break; + case 8: + switch (Random.Int(2)){ + case 0: + if (ch != null) + Buff.affect(ch, Burning.class).reignite(ch); + break; + case 1: + if (ch!= null) + Buff.affect(ch, Frost.class, Frost.duration(ch) * Random.Float(3f, 5f)); + break; + } + break; + default: + GLog.i("nothing happened"); + break; + } + } + + public static void appear(Char ch, int pos) { + + ch.sprite.interruptMotion(); + + ch.move(pos); + ch.sprite.place(pos); + + if (ch.invisible == 0) { + ch.sprite.alpha(0); + ch.sprite.parent.add(new AlphaTweener(ch.sprite, 1, 0.4f)); + } + + ch.sprite.emitter().start(Speck.factory(Speck.LIGHT), 0.2f, 3); + Sample.INSTANCE.play(Assets.SND_TELEPORT); + } + + @Override + protected void fx(Ballistica bolt, Callback callback) { + MagicMissile.rainbow(curUser.sprite.parent, bolt.sourcePos, bolt.collisionPos, callback); + Sample.INSTANCE.play(Assets.SND_ZAP); + } + +} diff --git a/java/com/hmdzl/spspd/items/wands/WandOfFirebolt.java b/java/com/hmdzl/spspd/items/wands/WandOfFirebolt.java new file mode 100644 index 00000000..40dfec73 --- /dev/null +++ b/java/com/hmdzl/spspd/items/wands/WandOfFirebolt.java @@ -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 + */ +package com.hmdzl.spspd.items.wands; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.Blob; +import com.hmdzl.spspd.actors.blobs.Fire; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Burning; +import com.hmdzl.spspd.effects.MagicMissile; +import com.hmdzl.spspd.effects.particles.FlameParticle; +import com.hmdzl.spspd.items.Heap; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.scenes.GameScene; + +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Callback; + +public class WandOfFirebolt extends DamageWand { + + { + image = ItemSpriteSheet.WAND_FIREBOLT; + collisionProperties = Ballistica.PROJECTILE; + } + + public int min(int lvl){ + return lvl; + } + + public int max(int lvl){ + return 10+6*lvl; + } + + @Override + protected void onZap( Ballistica bolt) { + + Heap heap = Dungeon.level.heaps.get(bolt.collisionPos); + if (heap != null) { + heap.burn(); + } + + Char ch = Actor.findChar(bolt.collisionPos); + if (ch != null) { + + processSoulMark(ch, chargesPerCast()); + + ch.damage((int)( damageRoll() * (1 + 0.1 * Dungeon.hero.magicSkill())), this); + + + Buff.affect(ch, Burning.class).reignite(ch); + + ch.sprite.emitter().burst(FlameParticle.FACTORY, 5); + + } + + GameScene.add( Blob.seed(bolt.collisionPos, 1, Fire.class ) ); + + + } + + /*public void explode(int cell, int damage) { + // We're blowing up, so no need for a fuse anymore. + + Sample.INSTANCE.play(Assets.SND_BLAST, 2); + + if (Dungeon.visible[cell]) { + CellEmitter.center(cell).burst(BlastParticle.FACTORY, 30); + } + + boolean terrainAffected = false; + for (int n : Level.NEIGHBOURS9) { + int c = cell + n; + if (c >= 0 && c < Level.getLength()) { + if (Dungeon.visible[c]) { + CellEmitter.get(c).burst(SmokeParticle.FACTORY, 4); + } + + if (Level.flamable[c]) { + Level.set(c, Terrain.EMBERS); + GameScene.updateMap(c); + terrainAffected = true; + } + + // destroys items / triggers bombs caught in the blast. + Heap heap = Dungeon.level.heaps.get(c); + if (heap != null) + heap.explode(); + + Char ch = Actor.findChar(c); + if (ch != null) { + // those not at the center of the blast take damage less + // consistently. + int minDamage = c == cell ? Math.round(damage/10) : 1; + int maxDamage = c == cell ? Math.round(damage/4) : Math.round(damage/10); + + int dmg = Random.NormalIntRange(minDamage, maxDamage) + - Math.max(ch.drRoll(),0); + if (dmg > 0) { + ch.damage(dmg, this); + } + + if (ch == Dungeon.hero && !ch.isAlive()) + // constant is used here in the rare instance a player + // is killed by a double bomb. + Dungeon.fail(Messages.format(ResultDescriptions.ITEM,"wand of firebolt")); + } + } + } + + if (terrainAffected) { + Dungeon.observe(); + } + }*/ + + @Override + protected void fx(Ballistica bolt, Callback callback) { + MagicMissile.fire(curUser.sprite.parent, curUser.pos, bolt.collisionPos, callback); + Sample.INSTANCE.play(Assets.SND_ZAP); + } +} diff --git a/java/com/hmdzl/spspd/items/wands/WandOfFlock.java b/java/com/hmdzl/spspd/items/wands/WandOfFlock.java new file mode 100644 index 00000000..8a50f5db --- /dev/null +++ b/java/com/hmdzl/spspd/items/wands/WandOfFlock.java @@ -0,0 +1,243 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.wands; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.hero.HeroSubClass; +import com.hmdzl.spspd.actors.mobs.FlyingProtector; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.actors.mobs.npcs.NPC; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.MagicMissile; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.Heap; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.BaBaSprite; +import com.hmdzl.spspd.sprites.SheepSprite; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.BArray; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Callback; +import com.watabou.utils.PathFinder; +import com.watabou.utils.Random; + +import java.util.HashSet; + +public class WandOfFlock extends Wand { + + { + image = ItemSpriteSheet.WAND_FLOCK; + collisionProperties = Ballistica.PROJECTILE; + } + + @Override + protected void onZap(Ballistica bolt) { + + int level = level(); + + int n = 1; + + if (Actor.findChar( bolt.collisionPos) != null && Ballistica.distance > 2) { + bolt.sourcePos = Ballistica.trace[Ballistica.distance - 2]; + } + + boolean[] passable = BArray.or(Level.passable, Level.avoid, null); + for (Actor actor : Actor.all()) { + if (actor instanceof Char) { + passable[((Char) actor).pos] = false; + } + } + + PathFinder.buildDistanceMap(bolt.collisionPos, passable, n); + int dist = 0; + + if (Actor.findChar(bolt.collisionPos) != null) { + PathFinder.distance[bolt.collisionPos] = Integer.MAX_VALUE; + dist = 1; + } + + float lifespan = 2 + level; + + sheepLabel: for (int i = 0; i < n; i++) { + do { + for (int j = 0; j < Level.getLength(); j++) { + if (PathFinder.distance[j] == dist) { + + if (Dungeon.hero.subClass == HeroSubClass.LEADER && (Dungeon.depth < 51 || Dungeon.depth > 54)){ + MagicBombSheep bsheep = new MagicBombSheep(); + bsheep.pos = j; + GameScene.add(bsheep); + } else { + MagicSheep sheep = new MagicSheep(); + sheep.lifespan = lifespan; + sheep.pos = j; + GameScene.add(sheep); + Dungeon.level.mobPress(sheep); + } + + + CellEmitter.get(j).burst(Speck.factory(Speck.WOOL), 4); + + PathFinder.distance[j] = Integer.MAX_VALUE; + + continue sheepLabel; + } + } + dist++; + } while (dist < n); + } + + if (Dungeon.depth>50 && Dungeon.depth<55){ + int spawnCell = Dungeon.level.randomRespawnCellMob(); + if (spawnCell>0){ + FlyingProtector.spawnAt(spawnCell); + //GLog.w("How dare you violate the magic of this place! "); + GLog.w(Messages.get(this,"guard")); + } + } + + Heap heap = Dungeon.level.heaps.get(bolt.collisionPos); + if (heap != null) {heap.summon();} + } + + @Override + protected void fx(Ballistica bolt, Callback callback) { + MagicMissile.wool(curUser.sprite.parent, curUser.pos, bolt.collisionPos, callback); + Sample.INSTANCE.play(Assets.SND_ZAP); + } + + public static class MagicSheep extends NPC { + + { + spriteClass = SheepSprite.class; + properties.add(Property.UNKNOW); + flying = true; + ally=true; + } + + public float lifespan; + + private boolean initialized = false; + + @Override + protected boolean act() { + if (initialized) { + HP = 0; + + destroy(); + sprite.die(); + + } else { + initialized = true; + /*for (int n : Level.NEIGHBOURS8DIST2) { + Char ch = Actor.findChar(n); + if (ch != null && ch != this && ch.isAlive()) { + Buff.affect(ch, Taunt.class,2f).object = id(); + } + }*/ + spend( lifespan + Random.Float(2) ); + } + return true; + } + + @Override + public void damage( int dmg, Object src ) { + } + + @Override + public boolean interact() { + return false; + } + } + public static class MagicBombSheep extends NPC { + + { + spriteClass = BaBaSprite.class; + HP = HT = 20; + state = HUNTING; + properties.add(Property.UNKNOW); + evadeSkill = 10; + ally=true; + } + + @Override + protected boolean act() { + damage(1,this); + return super.act(); + } + + @Override + public int hitSkill(Char target) { + return 100; + } + + + @Override + public int damageRoll() { + return Random.NormalIntRange(Dungeon.depth+10, Dungeon.depth+20); + } + + @Override + protected Char chooseEnemy() { + + if (enemy == null || !enemy.isAlive()) { + HashSet enemies = new HashSet(); + for (Mob mob : Dungeon.level.mobs) { + if (mob.hostile && Level.fieldOfView[mob.pos]) { + enemies.add(mob); + } + } + + enemy = enemies.size() > 0 ? Random.element(enemies) : null; + } + + return enemy; + } + + @Override + public boolean interact() { + + if (state == SLEEPING) { + state = HUNTING; + } + + int curPos = pos; + + moveSprite(pos, Dungeon.hero.pos); + move(Dungeon.hero.pos); + + Dungeon.hero.sprite.move(Dungeon.hero.pos, curPos); + Dungeon.hero.move(curPos); + + Dungeon.hero.spend(1 / Dungeon.hero.speed()); + Dungeon.hero.busy(); + return true; + } + } + public void add( Buff buff ) { + //in other words, can't be directly affected by buffs/debuffs. + } +} diff --git a/java/com/hmdzl/spspd/items/wands/WandOfFlow.java b/java/com/hmdzl/spspd/items/wands/WandOfFlow.java new file mode 100644 index 00000000..8a3af5f9 --- /dev/null +++ b/java/com/hmdzl/spspd/items/wands/WandOfFlow.java @@ -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 + */ +package com.hmdzl.spspd.items.wands; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.DungeonTilemap; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Paralysis; +import com.hmdzl.spspd.actors.buffs.Wet; +import com.hmdzl.spspd.actors.mobs.npcs.NPC; +import com.hmdzl.spspd.actors.mobs.npcs.SheepSokoban; +import com.hmdzl.spspd.actors.mobs.npcs.SheepSokobanBlack; +import com.hmdzl.spspd.actors.mobs.npcs.SheepSokobanCorner; +import com.hmdzl.spspd.actors.mobs.npcs.SheepSokobanStop; +import com.hmdzl.spspd.actors.mobs.npcs.SheepSokobanSwitch; +import com.hmdzl.spspd.effects.Beam; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.effects.Pushing; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.watabou.utils.Callback; +import com.watabou.utils.Random; + +import java.util.ArrayList; + +import static com.hmdzl.spspd.Dungeon.hero; + +public class WandOfFlow extends DamageWand { + + { + image = ItemSpriteSheet.WAND_FLOW; + collisionProperties = Ballistica.PROJECTILE; + } + + public int min(int lvl){ + return 1+lvl; + } + + public int max(int lvl){ + return 5+3*lvl; + } + + @Override + protected void onZap(Ballistica beam) { + + ArrayList chars = new ArrayList<>(); + + int damage = (int)( damageRoll() * (1 + 0.1 * hero.magicSkill())); + + Char ch = Actor.findChar(beam.collisionPos); + if (ch != null){ + processSoulMark(ch, chargesPerCast()); + ch.damage(damage, this); + Buff.affect(ch,Wet.class,5f); + if (ch.isAlive() && beam.path.size() > beam.dist+1) { + Ballistica trajectory = new Ballistica(ch.pos, beam.path.get(beam.dist + 1), Ballistica.MAGIC_BOLT); + int strength = Math.min( level() + 3, 5 ); + throwChar(ch, trajectory, strength); + } + } + } + + public static void throwChar(final Char ch, final Ballistica trajectory, int power){ + int dist = Math.min(trajectory.dist, power); + + if (ch.properties().contains(Char.Property.BOSS)) + dist /= 2; + + if (dist == 0 ) return; + + if (Actor.findChar(trajectory.path.get(dist)) != null){ + dist--; + } + if (ch instanceof SheepSokoban || + ch instanceof SheepSokobanCorner || + ch instanceof SheepSokobanStop || + ch instanceof SheepSokobanSwitch || + ch instanceof SheepSokobanBlack) { + dist=1; + } + final int newPos = trajectory.path.get(dist); + + if (newPos == ch.pos) return; + + final int finalDist = dist; + final int initialpos = ch.pos; + + Actor.addDelayed(new Pushing(ch, ch.pos, newPos, new Callback() { + public void call() { + if (initialpos != ch.pos) { + //something cased movement before pushing resolved, cancel to be safe. + ch.sprite.place(ch.pos); + return; + } + ch.pos = newPos; + if (ch instanceof SheepSokoban || + ch instanceof SheepSokobanCorner || + ch instanceof SheepSokobanStop || + ch instanceof SheepSokobanSwitch || + ch instanceof SheepSokobanBlack) { + Dungeon.level.mobPress((NPC) ch); + } else {if (ch.pos == trajectory.collisionPos) { + ch.damage(Random.NormalIntRange((finalDist + 1) / 2, finalDist), this); + Paralysis.prolong(ch, Paralysis.class, Random.NormalIntRange((finalDist + 1) / 2, finalDist)); + } Dungeon.level.press(ch.pos, ch);} + if (ch == hero){ + Dungeon.observe(); + } + } + }), -1); + } + + /*Char ch; + + for (int i = 1; i < Ballistica.distance; i++) { + + int c = Ballistica.trace[i]; + + int before = Dungeon.level.map[c]; + + if ((ch = Actor.findChar(c)) != null) { + + if (i == Ballistica.distance - 1) { + + int level = level(); + int damage= Random.Int(level+3, 6 + level * 3); + Buff.prolong(ch, Wet.class, 5f); + if (Dungeon.hero.buff(Strength.class) != null){ damage *= (int) 4f; Buff.detach(Dungeon.hero, Strength.class);} + ch.damage(damage, this); + + } else { + + int next = Ballistica.trace[i + 1]; + if ((Level.passable[next] || Level.avoid[next]) + && Actor.findChar(next) == null + + && !(ch instanceof SheepSokoban || + ch instanceof SheepSokobanCorner || + ch instanceof SheepSokobanStop || + ch instanceof SheepSokobanSwitch || + ch instanceof SheepSokobanBlack) + + ) { + + if ((ch instanceof SheepSokoban || + ch instanceof SheepSokobanCorner || + ch instanceof SheepSokobanStop || + ch instanceof SheepSokobanSwitch || + ch instanceof SheepSokobanBlack) + && (Dungeon.level.map[next]==Terrain.FLEECING_TRAP || + Dungeon.level.map[next]==Terrain.CHANGE_SHEEP_TRAP)){ + + } else { + processSoulMark(ch, chargesPerCast()); + Buff.prolong(ch, Wet.class, 5f); + Actor.addDelayed(new Pushing(ch, ch.pos, next), -1); + } + + ch.pos = next; + Actor.freeCell(next); + + if (ch instanceof Shopkeeper) + ch.damage(0, this); + + // FIXME + + if (ch instanceof SheepSokoban || + ch instanceof SheepSokobanCorner || + ch instanceof SheepSokobanStop || + ch instanceof SheepSokobanSwitch || + ch instanceof SheepSokobanBlack){ + Dungeon.level.mobPress((NPC) ch); + } else if (ch instanceof Mob && !(ch.properties().contains(Char.Property.IMMOVABLE))){ + Dungeon.level.mobPress((Mob) ch); + + } else { + Dungeon.level.press(ch.pos, ch); + } + + } else { + int level = level(); + int damage= Random.Int(level+3, 6 + level * 3); + Buff.prolong(ch, Wet.class, 5f); + if (Dungeon.hero.buff(Strength.class) != null){ damage *= (int) 4f; Buff.detach(Dungeon.hero, Strength.class);} + ch.damage(damage, this); + + } + } + } + + } + + }*/ + + + @Override + protected void fx( Ballistica beam, Callback callback ) { + + curUser.sprite.parent.add(new Beam.WaterRay(curUser.sprite.center(), DungeonTilemap.tileCenterToWorld(beam.collisionPos ))); + callback.call(); + } + +} diff --git a/java/com/hmdzl/spspd/items/wands/WandOfFreeze.java b/java/com/hmdzl/spspd/items/wands/WandOfFreeze.java new file mode 100644 index 00000000..bd07907e --- /dev/null +++ b/java/com/hmdzl/spspd/items/wands/WandOfFreeze.java @@ -0,0 +1,100 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.wands; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Chill; +import com.hmdzl.spspd.actors.buffs.Frost; +import com.hmdzl.spspd.effects.MagicMissile; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Callback; +import com.watabou.utils.Random; +import com.hmdzl.spspd.items.Heap; + +public class WandOfFreeze extends DamageWand { + + { + image = ItemSpriteSheet.WAND_FREEZE; + collisionProperties = Ballistica.PROJECTILE; + } + + public int min(int lvl){ + return 5+lvl*2; + } + + public int max(int lvl){ + return 10+lvl*4; + } + + @Override + protected void onZap(Ballistica bolt) { + + Char ch = Actor.findChar(bolt.collisionPos); + if (ch != null) { + + int damage = damageRoll(); + + if (ch.buff(Frost.class) != null){ + return; //do nothing, can't affect a frozen target + } + if (ch.buff(Chill.class) != null){ + float chill = ch.buff(Chill.class).cooldown(); + damage = (int)(Math.round(damage * Math.pow(0.9f, chill)) * (1 + 0.1 * Dungeon.hero.magicSkill())); + } else { + ch.sprite.burst( 0xFF99CCFF, level() / 2 + 2 ); + } + + processSoulMark(ch, chargesPerCast()); + ch.damage(damage, this); + + if (ch.isAlive()){ + if (Level.water[ch.pos]){ + //20+(10*level)% chance + if (Random.Int(10) >= 8-level() ) + Buff.affect(ch, Frost.class, Frost.duration(ch)*Random.Float(2f, 4f)); + else + Buff.prolong(ch, Chill.class, 6+level()); + } else { + Buff.prolong(ch, Chill.class, 4+level()); + } + } + + } + + Heap heap = Dungeon.level.heaps.get(bolt.collisionPos); + if (heap != null) { + heap.freeze(); + } + + } + + @Override + protected void fx(Ballistica bolt, Callback callback) { + MagicMissile.coldLight(curUser.sprite.parent, curUser.pos, bolt.collisionPos, + callback); + Sample.INSTANCE.play(Assets.SND_ZAP); + } + +} diff --git a/java/com/hmdzl/spspd/items/wands/WandOfLight.java b/java/com/hmdzl/spspd/items/wands/WandOfLight.java new file mode 100644 index 00000000..dd7fa571 --- /dev/null +++ b/java/com/hmdzl/spspd/items/wands/WandOfLight.java @@ -0,0 +1,103 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2014 Oleg Dolya + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.items.wands; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.DungeonTilemap; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Blindness; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Light; +import com.hmdzl.spspd.effects.Beam; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.effects.particles.RainbowParticle; +import com.hmdzl.spspd.effects.particles.ShadowParticle; +import com.hmdzl.spspd.items.Heap; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Callback; +import com.watabou.utils.Random; + +public class WandOfLight extends DamageWand { + + { + image = ItemSpriteSheet.WAND_REGROWTH; + collisionProperties = Ballistica.PROJECTILE; + } + + public int min(int lvl){ + return 3+lvl; + } + + public int max(int lvl){ + return 6+4*lvl; + } + + @Override + protected void onZap(Ballistica beam) { + Char ch = Actor.findChar(beam.collisionPos); + if (ch != null) { + + processSoulMark(ch, chargesPerCast()); + affectTarget(ch); + + if (Random.Int(5+level()) >= 3) { + Buff.prolong(ch, Blindness.class, 2f + (level() * 0.34f)); + ch.sprite.emitter().burst(Speck.factory(Speck.LIGHT), 6 ); + } + Buff.prolong( curUser, Light.class, 5f+level()); + } + + Heap heap = Dungeon.level.heaps.get(beam.collisionPos); + if (heap != null) {heap.light();} + } + + private void affectTarget(Char ch){ + int dmg = (int)( damageRoll() * (1 + 0.1 * Dungeon.hero.magicSkill())); + + //three in (5+lvl) chance of failing + if (Random.Int(5+level()) >= 3) { + Buff.prolong(ch, Blindness.class, 2f + (level() * 0.333f)); + ch.sprite.emitter().burst(Speck.factory(Speck.LIGHT), 6 ); + } + + if (ch.properties().contains(Char.Property.DEMONIC) || ch.properties().contains(Char.Property.UNDEAD)){ + ch.sprite.emitter().start( ShadowParticle.UP, 0.05f, 10+level() ); + Sample.INSTANCE.play(Assets.SND_BURNING); + + ch.damage(Math.round(dmg*1.333f), this); + } else { + ch.sprite.centerEmitter().burst( RainbowParticle.BURST, 10+level() ); + + ch.damage(dmg, this); + } + + } + + @Override + protected void fx(Ballistica beam, Callback callback) { + curUser.sprite.parent.add( + new Beam.LightRay(curUser.sprite.center(), DungeonTilemap.tileCenterToWorld(beam.collisionPos))); + callback.call(); + Sample.INSTANCE.play(Assets.SND_ZAP); + } + +} diff --git a/java/com/hmdzl/spspd/items/wands/WandOfLightning.java b/java/com/hmdzl/spspd/items/wands/WandOfLightning.java new file mode 100644 index 00000000..a5302465 --- /dev/null +++ b/java/com/hmdzl/spspd/items/wands/WandOfLightning.java @@ -0,0 +1,136 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.wands; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.ResultDescriptions; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.Lightning; +import com.hmdzl.spspd.effects.particles.SparkParticle; +import com.hmdzl.spspd.items.Heap; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +import com.watabou.noosa.Camera; +import com.watabou.utils.Callback; +import com.watabou.utils.Random; + +public class WandOfLightning extends DamageWand { + + { + image = ItemSpriteSheet.WAND_LIGHTNING; + collisionProperties = Ballistica.PROJECTILE; + } + + private ArrayList affected = new ArrayList<>(); + + ArrayList arcs = new ArrayList<>(); + + public int min(int lvl){ + return 5+lvl; + } + + public int max(int lvl){ + return Math.round(10 + (lvl * lvl / 4f)); + } + + @Override + protected void onZap( Ballistica bolt ) { + + float multipler = 0.4f + (0.6f/affected.size()); + if (Level.water[bolt.collisionPos]) multipler *= 1.5f; + + int min = 5+level(); + int max = Math.round(10 + (level() * level() / 4f)); + + for (Char ch : affected){ + processSoulMark(ch, chargesPerCast()); + ch.damage((int)((1 + 0.1 * Dungeon.hero.magicSkill()) * Math.round(Random.NormalIntRange(min, max) * multipler)), this); + + if (ch == Dungeon.hero) Camera.main.shake( 2, 0.3f ); + ch.sprite.centerEmitter().burst( SparkParticle.FACTORY, 3 ); + ch.sprite.flash(); + } + // Everything is processed in fx() method + if (!curUser.isAlive()) { + Dungeon.fail(Messages.format(ResultDescriptions.ITEM)); + //GLog.n("You killed yourself with your own Wand of Lightning..."); + } + + + Heap heap = Dungeon.level.heaps.get(bolt.collisionPos); + if (heap != null) {heap.lit();} + } + + private void arc( Char ch ) { + + affected.add( ch ); + + for (int i : Level.NEIGHBOURS8) { + int cell = ch.pos + i; + + Char n = Actor.findChar( cell ); + if (n != null && !affected.contains( n )) { + arcs.add(new Lightning.Arc(ch.pos, n.pos)); + arc(n); + } + } + + if (Level.water[ch.pos] && !ch.flying){ + for (int i : Level.NEIGHBOURS8DIST2) { + int cell = ch.pos + i; + //player can only be hit by lightning from an adjacent enemy. + if (!Level.insideMap(cell) || Actor.findChar(cell) == Dungeon.hero) continue; + + Char n = Actor.findChar( ch.pos + i ); + if (n != null && !affected.contains( n )) { + arcs.add(new Lightning.Arc(ch.pos, n.pos)); + arc(n); + } + } + } + } + + @Override + protected void fx( Ballistica bolt, Callback callback ) { + + affected.clear(); + arcs.clear(); + arcs.add( new Lightning.Arc(bolt.sourcePos, bolt.collisionPos)); + + int cell = bolt.collisionPos; + + Char ch = Actor.findChar( cell ); + if (ch != null) { + arc(ch); + } else { + CellEmitter.center( cell ).burst( SparkParticle.FACTORY, 3 ); + } + + //don't want to wait for the effect before processing damage. + curUser.sprite.parent.add( new Lightning( arcs, null ) ); + callback.call(); + } + +} diff --git a/java/com/hmdzl/spspd/items/wands/WandOfMagicMissile.java b/java/com/hmdzl/spspd/items/wands/WandOfMagicMissile.java new file mode 100644 index 00000000..0dcb65a7 --- /dev/null +++ b/java/com/hmdzl/spspd/items/wands/WandOfMagicMissile.java @@ -0,0 +1,168 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.wands; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class WandOfMagicMissile extends DamageWand { + + public static final String AC_DISENCHANT = "DISENCHANT"; + + private static final String TXT_SELECT_WAND = "Select a wand to upgrade"; + + private static final String TXT_DISENCHANTED = "you disenchanted the Wand of Magic Missile and used its essence to upgrade your %s"; + + private static final float TIME_TO_DISENCHANT = 2f; + + private boolean disenchantEquipped; + + private float upgradeChance = 0.5f; + + { + image = ItemSpriteSheet.WAND_MAGIC_MISSILE; + collisionProperties = Ballistica.MAGIC_BOLT; + } + + //@Override + //public ArrayList actions(Hero hero) { + // ArrayList actions = super.actions(hero); + // if (level > 0) { + // actions.add(AC_DISENCHANT); + // } + // return actions; + //} + + public int min(int lvl){ + return 2+lvl; + } + + public int max(int lvl){ + return 6+5*lvl; + } + + @Override + protected void onZap( Ballistica bolt ) { + + Char ch = Actor.findChar( bolt.collisionPos ); + if (ch != null) { + + processSoulMark(ch, chargesPerCast()); + ch.damage((int)( damageRoll() * (1 + 0.1 * Dungeon.hero.magicSkill())), this); + + ch.sprite.burst(0xFF99CCFF, 2); + + } + } + + //@Override + //public void execute(Hero hero, String action) { + // if (action.equals(AC_DISENCHANT)) { + + // if (hero.belongings.weapon == this) { + // disenchantEquipped = true; + // hero.belongings.weapon = null; + // updateQuickslot(); + // } else { + // detach(hero.belongings.backpack); + // } + + // curUser = hero; + // GameScene.selectItem(itemSelector, WndBag.Mode.WAND, + // TXT_SELECT_WAND); + + // } else { + + // super.execute(hero, action); + + // } + //} + + @Override + protected int initialCharges() { + return 3; + } + + /*@Override + public String statsDesc() { + /*if (levelKnown) + return Messages.get(this, "stats_desc", min(), max()); + else + return Messages.get(this, "stats_desc", min(0), max(0)); + return Messages.get(this,"stats_desc"); + }*/ + //private final WndBag.Listener itemSelector = new WndBag.Listener() { + // @Override + // public void onSelect(Item item) { + // if (item != null) { + + // Sample.INSTANCE.play(Assets.SND_EVOKE); + // ScrollOfUpgrade.upgrade(curUser); + // evoke(curUser); + + // GLog.w(TXT_DISENCHANTED, item.name()); + + // Dungeon.quickslot.clearItem(WandOfMagicMissile.this); + // WandOfMagicMissile.this.updateQuickslot(); + + // DarkGold gold = Dungeon.hero.belongings.getItem(DarkGold.class); + // if (gold!=null){ + // upgradeChance = (upgradeChance + (gold.quantity()*0.01f)); + // } + + // int i=0; + // while(i + */ +package com.hmdzl.spspd.items.wands; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.ResultDescriptions; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Paralysis; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.MagicMissile; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.effects.particles.SmokeParticle; +import com.hmdzl.spspd.items.Heap; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.Terrain; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +import com.watabou.noosa.Camera; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Callback; +import com.watabou.utils.Random; + +public class WandOfMeteorite extends DamageWand { + + { + image = ItemSpriteSheet.WAND_METEORITE; + collisionProperties = Ballistica.PROJECTILE; + } + + public int min(int lvl){ + return lvl; + } + + public int max(int lvl){ + return 12+6*lvl; + } + + + @Override + protected void onZap(Ballistica bolt) { + + Heap heap = Dungeon.level.heaps.get(bolt.collisionPos); + if (heap != null) { + heap.burn(); + } + + Sample.INSTANCE.play(Assets.SND_ROCKS); + + int level = level(); + + Char ch = Actor.findChar(bolt.collisionPos); + if (ch != null) { + + ch.sprite.flash(); + + processSoulMark(ch, chargesPerCast()); + + int damage = (int) (damageRoll() * (1 + 0.1 * Dungeon.hero.magicSkill())); + + ch.damage(damage, this); + + if (ch.isAlive() && Random.Int(2) == 0) { + Buff.prolong(ch, Paralysis.class, Random.IntRange(5, level)); + } + CellEmitter.get(bolt.collisionPos).start(Speck.factory(Speck.ROCK), 0.07f, 5); + Camera.main.shake(3, 0.07f * 3); + } + + + for (int n : Level.NEIGHBOURS9) { + int c = bolt.collisionPos + n; + if (c >= 0 && c < Level.getLength()) { + if (Dungeon.visible[c]) { + CellEmitter.get(c).burst(SmokeParticle.FACTORY, 2); + } + + if (Level.flamable[c]) { + Level.set(c, Terrain.EMBERS); + GameScene.updateMap(c); + } + + // destroys items / triggers bombs caught in the blast. + Char ch2 = Actor.findChar(c); + if (ch2 != null) { + int dmg = (int) (damageRoll() * (1 + 0.1 * Dungeon.hero.magicSkill())* chargesPerCast()/9) ; + if (dmg > 0) { + ch2.damage(dmg, this); + } + } + } + + + if (!curUser.isAlive()) { + Dungeon.fail(Messages.format(ResultDescriptions.ITEM)); + //GLog.n("You killed yourself with your own Wand of Avalanche..."); + } + } + } + + @Override + protected int initialCharges() { + return 1; + } + + @Override + protected int chargesPerCast() { + return Math.max(1, curCharges); + } + + @Override + protected void fx(Ballistica bolt, Callback callback) { + MagicMissile.earth(curUser.sprite.parent, curUser.pos, bolt.collisionPos, callback); + Sample.INSTANCE.play(Assets.SND_ZAP); + } +} diff --git a/java/com/hmdzl/spspd/items/wands/WandOfPoison.java b/java/com/hmdzl/spspd/items/wands/WandOfPoison.java new file mode 100644 index 00000000..6d13e543 --- /dev/null +++ b/java/com/hmdzl/spspd/items/wands/WandOfPoison.java @@ -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 + */ +package com.hmdzl.spspd.items.wands; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Poison; +import com.hmdzl.spspd.effects.MagicMissile; +import com.hmdzl.spspd.items.Heap; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Callback; + +public class WandOfPoison extends Wand { + + { + image = ItemSpriteSheet.WAND_POISON; + collisionProperties = Ballistica.MAGIC_BOLT; + } + + + + @Override + protected void onZap(Ballistica bolt) { + + Char ch = Actor.findChar(bolt.collisionPos); + if (ch != null) { + + processSoulMark(ch, chargesPerCast()); + + int poisonbase=5; + + Buff.affect(ch, Poison.class).set( + Poison.durationFactor(ch) * (poisonbase + level()*2)); + + } + + Heap heap = Dungeon.level.heaps.get(bolt.collisionPos); + if (heap != null) { + heap.poison(); + } + } + + @Override + protected void fx(Ballistica bolt, Callback callback) { + MagicMissile.poison(curUser.sprite.parent, curUser.pos, bolt.collisionPos, callback); + Sample.INSTANCE.play(Assets.SND_ZAP); + } + +} diff --git a/java/com/hmdzl/spspd/items/wands/WandOfTCloud.java b/java/com/hmdzl/spspd/items/wands/WandOfTCloud.java new file mode 100644 index 00000000..1b26ad70 --- /dev/null +++ b/java/com/hmdzl/spspd/items/wands/WandOfTCloud.java @@ -0,0 +1,511 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.wands; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.ResultDescriptions; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.Blob; +import com.hmdzl.spspd.actors.blobs.ElectriShock; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.MagicalSleep; +import com.hmdzl.spspd.actors.buffs.Paralysis; +import com.hmdzl.spspd.actors.hero.HeroSubClass; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.actors.mobs.npcs.NPC; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.MagicMissile; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.effects.particles.EnergyParticle; +import com.hmdzl.spspd.effects.particles.SparkParticle; +import com.hmdzl.spspd.items.Heap; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.CharSprite; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.sprites.KeKeSprite; +import com.hmdzl.spspd.sprites.TCloudSprite; +import com.hmdzl.spspd.utils.BArray; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.noosa.Camera; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Bundle; +import com.watabou.utils.Callback; +import com.watabou.utils.PathFinder; +import com.watabou.utils.Random; + +import java.util.HashSet; + +public class WandOfTCloud extends Wand { + + { + image = ItemSpriteSheet.WAND_TCLOUD; + collisionProperties = Ballistica.PROJECTILE; + } + + @Override + protected void onZap(Ballistica bolt) { + + int level = level(); + + int n = 1; + + if (Actor.findChar(bolt.collisionPos) != null && Ballistica.distance > 2) { + bolt.sourcePos = Ballistica.trace[Ballistica.distance - 2]; + } + + boolean[] passable = BArray.or(Level.passable, Level.avoid, null); + for (Actor actor : Actor.all()) { + if (actor instanceof Char) { + passable[((Char) actor).pos] = false; + } + } + + PathFinder.buildDistanceMap(bolt.collisionPos, passable, n); + int dist = 0; + + if (Actor.findChar(bolt.collisionPos) != null) { + PathFinder.distance[bolt.collisionPos] = Integer.MAX_VALUE; + dist = 1; + } + + if ( curCharges > 9 ){ + cloudLabel: for (int i = 0; i < n; i++) { + do { + for (int j = 0; j < Level.getLength(); j++) { + if (PathFinder.distance[j] == dist) { + + if (Dungeon.hero.subClass == HeroSubClass.LEADER ){ + STCloud scloud = new STCloud(); + scloud.pos = j; + scloud.lvl = level; + GameScene.add(scloud); + } else { + + TCloud cloud = new TCloud(); + cloud.pos = j; + cloud.lvl = level; + //cloud.lifespan = chargesPerCast(); + GameScene.add(cloud); + } + CellEmitter.get(j).burst(Speck.factory(Speck.WOOL), 4); + PathFinder.distance[j] = Integer.MAX_VALUE; + continue cloudLabel; + } + } + dist++; + } while (dist < n); + } + } else { + GLog.w(Messages.get(this, "more_charge")); + for (int i : Level.NEIGHBOURS9) { + int c = bolt.collisionPos + i; + if (c >= 0 && c < Level.getLength()) { + GameScene.add(Blob.seed(c, curCharges, ElectriShock.class)); + CellEmitter.get(c).burst(EnergyParticle.FACTORY, 5); + } + } + } + Heap heap = Dungeon.level.heaps.get(bolt.collisionPos); + if (heap != null) {heap.lit();} + } + + @Override + protected int initialCharges() { + return 1; + } + + @Override + protected int chargesPerCast() { + return Math.max(1, curCharges); + } + + @Override + protected void fx(Ballistica bolt, Callback callback) { + MagicMissile.wool(curUser.sprite.parent, curUser.pos, bolt.collisionPos, callback); + Sample.INSTANCE.play(Assets.SND_ZAP); + } + + public static class TCloud extends NPC implements Callback { + + private static final float TIME_TO_ZAP = 1f; + private static final int BOMB_DELAY = 20; + private int timeToBomb = BOMB_DELAY; + + { + //name = "TCloud"; + + spriteClass = TCloudSprite.class; + HP = HT = 200; + state = HUNTING; + flying = true; + ally=true; + + viewDistance = 6; + properties.add(Property.ELEMENT); + + } + + public int lvl; + public int lifespan; + + private static final String LVL = "lvl"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(LVL, lvl); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + lvl = bundle.getInt(LVL); + } + + @Override + protected boolean act() { + timeToBomb --; + if (timeToBomb == 0){ + destroy(); + sprite.die(); + } + + return super.act(); + } + + @Override + public void move(int step) { + } + + @Override + protected Char chooseEnemy() { + + if (enemy == null || !enemy.isAlive()) { + HashSet enemies = new HashSet(); + for (Mob mob : Dungeon.level.mobs) { + if (mob.hostile && Level.fieldOfView[mob.pos]) { + enemies.add(mob); + } + } + + enemy = enemies.size() > 0 ? Random.element(enemies) : null; + } + + return enemy; + } + + @Override + public int hitSkill(Char target) { + return 500; + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(10 + lvl, 15 + 3*lvl); + } + + @Override + protected float attackDelay() { + return 0.5f; + } + + @Override + protected boolean canAttack(Char enemy) { + return new Ballistica( pos, enemy.pos, Ballistica.MAGIC_BOLT).collisionPos == 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) { + ((TCloudSprite) sprite).zap(enemy.pos); + } + + spend(TIME_TO_ZAP); + + if (hit(this, enemy, true)) { + int dmg = Random.Int(6 + lvl, 20 + 3*lvl); + if (Level.water[enemy.pos] && !enemy.flying) { + dmg *= 1.5f; + } + enemy.damage(dmg, this); + //Buff.affect(enemy, Taunt.class,2f).object = id(); + enemy.sprite.centerEmitter().burst(SparkParticle.FACTORY, 3); + enemy.sprite.flash(); + damage(Random.NormalIntRange(10 + lvl, 15 + 3*lvl), this); + if (enemy == Dungeon.hero) { + + Camera.main.shake(2, 0.3f); + + if (!enemy.isAlive()) { + Dungeon.fail( Messages.format(ResultDescriptions.MOB)); + //GLog.n(Messages.get(this, "zap_kill")); + } + } + } else { + enemy.sprite + .showStatus(CharSprite.NEUTRAL, enemy.defenseVerb()); + } + + return !visible; + } + } + + @Override + public void call() { + next(); + } + + @Override + public int attackProc(Char enemy, int damage) { + int dmg = super.attackProc(enemy, damage); + if(HP < 1){ + destroy(); + sprite.die(); + } + + return dmg; + } + + @Override + public int drRoll() { + return 0; + } + + @Override + public boolean interact() { + + if (this.buff(MagicalSleep.class) != null) { + Buff.detach(this, MagicalSleep.class); + } + + if (state == SLEEPING) { + state = HUNTING; + } + if (buff(Paralysis.class) != null) { + Buff.detach(this, Paralysis.class); + } + + int curPos = pos; + + moveSprite(pos, Dungeon.hero.pos); + move(Dungeon.hero.pos); + + Dungeon.hero.sprite.move(Dungeon.hero.pos, curPos); + Dungeon.hero.move(curPos); + + Dungeon.hero.spend(1 / Dungeon.hero.speed()); + Dungeon.hero.busy(); + return true; + } + + @Override + public void add( Buff buff ) { + //in other words, can't be directly affected by buffs/debuffs. + } + +} + + public static class STCloud extends NPC implements Callback { + + private static final float TIME_TO_ZAP = 1f; + private static final int BOMB_DELAY = 40; + private int timeToBomb = BOMB_DELAY; + + { + //name = "TCloud"; + + spriteClass = KeKeSprite.class; + HP = HT = 100; + state = HUNTING; + flying = true; + ally=true; + + viewDistance = 6; + properties.add(Property.ELEMENT); + + } + + public int lvl; + public int lifespan; + + private static final String LVL = "lvl"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(LVL, lvl); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + lvl = bundle.getInt(LVL); + } + + @Override + protected boolean act() { + timeToBomb --; + if (timeToBomb == 0){ + destroy(); + sprite.die(); + } + + return super.act(); + } + + + @Override + protected Char chooseEnemy() { + + if (enemy == null || !enemy.isAlive()) { + HashSet enemies = new HashSet(); + for (Mob mob : Dungeon.level.mobs) { + if (mob.hostile && Level.fieldOfView[mob.pos]) { + enemies.add(mob); + } + } + + enemy = enemies.size() > 0 ? Random.element(enemies) : null; + } + + return enemy; + } + + @Override + public int hitSkill(Char target) { + return 500; + } + + @Override + public int damageRoll() { + return Random.NormalIntRange(20 + lvl, 30 + 5*lvl); + } + + @Override + protected float attackDelay() { + return 0.5f; + } + + @Override + protected boolean canAttack(Char enemy) { + return new Ballistica( pos, enemy.pos, Ballistica.MAGIC_BOLT).collisionPos == 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) { + ((KeKeSprite) sprite).zap(enemy.pos); + } + + spend(TIME_TO_ZAP); + + if (hit(this, enemy, true)) { + int dmg = Random.Int(4 + lvl, 12 + 3*lvl); + if (Level.water[enemy.pos] && !enemy.flying) { + dmg *= 1.5f; + } + enemy.damage(dmg, this); + //Buff.affect(enemy, Taunt.class,2f).object = id(); + enemy.sprite.centerEmitter().burst(SparkParticle.FACTORY, 3); + enemy.sprite.flash(); + damage(Random.NormalIntRange(20 + lvl, 30 + 5*lvl), this); + if (enemy == Dungeon.hero) { + + Camera.main.shake(2, 0.3f); + + if (!enemy.isAlive()) { + Dungeon.fail( Messages.format(ResultDescriptions.MOB)); + //GLog.n(Messages.get(this, "zap_kill")); + } + } + } else { + enemy.sprite + .showStatus(CharSprite.NEUTRAL, enemy.defenseVerb()); + } + + return !visible; + } + } + + @Override + public void call() { + next(); + } + + @Override + public int drRoll() { + return 0; + } + + @Override + public boolean interact() { + + if (this.buff(MagicalSleep.class) != null) { + Buff.detach(this, MagicalSleep.class); + } + + if (state == SLEEPING) { + state = HUNTING; + } + if (buff(Paralysis.class) != null) { + Buff.detach(this, Paralysis.class); + } + + int curPos = pos; + + moveSprite(pos, Dungeon.hero.pos); + move(Dungeon.hero.pos); + + Dungeon.hero.sprite.move(Dungeon.hero.pos, curPos); + Dungeon.hero.move(curPos); + + Dungeon.hero.spend(1 / Dungeon.hero.speed()); + Dungeon.hero.busy(); + return true; + } + + @Override + public void add( Buff buff ) { + //in other words, can't be directly affected by buffs/debuffs. + } + +} +} diff --git a/java/com/hmdzl/spspd/items/weapon/Weapon.java b/java/com/hmdzl/spspd/items/weapon/Weapon.java new file mode 100644 index 00000000..1a1d1bfc --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/Weapon.java @@ -0,0 +1,500 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.weapon; + +import com.hmdzl.spspd.Challenges; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.MechArmor; +import com.hmdzl.spspd.actors.buffs.TargetShoot; +import com.hmdzl.spspd.actors.hero.HeroSubClass; +import com.hmdzl.spspd.items.rings.RingOfAccuracy; +import com.hmdzl.spspd.items.weapon.enchantments.EnchantmentDark; +import com.hmdzl.spspd.items.weapon.enchantments.EnchantmentDark2; +import com.hmdzl.spspd.items.weapon.enchantments.EnchantmentEarth; +import com.hmdzl.spspd.items.weapon.enchantments.EnchantmentEarth2; +import com.hmdzl.spspd.items.weapon.enchantments.EnchantmentEnergy; +import com.hmdzl.spspd.items.weapon.enchantments.EnchantmentEnergy2; +import com.hmdzl.spspd.items.weapon.enchantments.EnchantmentFire; +import com.hmdzl.spspd.items.weapon.enchantments.EnchantmentFire2; +import com.hmdzl.spspd.items.weapon.enchantments.EnchantmentIce; +import com.hmdzl.spspd.items.weapon.enchantments.EnchantmentIce2; +import com.hmdzl.spspd.items.weapon.enchantments.EnchantmentLight; +import com.hmdzl.spspd.items.weapon.enchantments.EnchantmentLight2; +import com.hmdzl.spspd.items.weapon.enchantments.EnchantmentShock; +import com.hmdzl.spspd.items.weapon.enchantments.EnchantmentShock2; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.hero.HeroClass; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.KindOfWeapon; +import com.hmdzl.spspd.items.rings.RingOfFuror; +import com.hmdzl.spspd.items.rings.RingOfSharpshooting; +import com.hmdzl.spspd.items.weapon.enchantments.AresLeech; +import com.hmdzl.spspd.items.weapon.enchantments.BuzzSaw; +import com.hmdzl.spspd.items.weapon.enchantments.CromLuck; +import com.hmdzl.spspd.items.weapon.enchantments.JupitersHorror; +import com.hmdzl.spspd.items.weapon.enchantments.LokisPoison; +import com.hmdzl.spspd.items.weapon.enchantments.NeptuneShock; +import com.hmdzl.spspd.items.weapon.melee.MeleeWeapon; +import com.hmdzl.spspd.items.weapon.melee.relic.RelicMeleeWeapon; +import com.hmdzl.spspd.items.weapon.missiles.MissileWeapon; +import com.hmdzl.spspd.sprites.ItemSprite; + +import com.watabou.utils.Bundlable; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public class Weapon extends KindOfWeapon { + + private static final String TXT_IDENTIFY = "You are now familiar enough with your %s to identify it. It is %s."; + //private static final String TXT_INCOMPATIBLE = "Interaction of different types of magic has negated the enchantment on this weapon!"; + private static final String TXT_TO_STRING = "%s :%d"; + //private static final int HITS_TO_KNOW = 5; + public int STR = 10; + public float ACU = 1f; // Accuracy modifier + public float DLY = 1f; // Speed modifier + public int RCH = 1; // Reach modifier + //public int DUR = 10; // durable modifier + + public int durable = 100; + + public Enchantment enchantment; + //private int hitsToKnow = HITS_TO_KNOW; + + //@Override + public void proc(Char attacker, Char defender, int damage) { + + + if (enchantment != null) { + enchantment.proc(this, attacker, defender, damage); + } + + /*if (!levelKnown) { + if (--hitsToKnow <= 0) { + levelKnown = true; + GLog.i( Messages.get(Weapon.class, "identify", name(), toString()) ); + Badges.validateItemLevelAquired( this ); + } + }*/ + } + + private static final String ENCHANTMENT = "enchantment"; + + public int STR() + { + if(Dungeon.hero != null && (this instanceof MeleeWeapon || this instanceof RelicMeleeWeapon ) && + Dungeon.hero.belongings.weapon == this && STR > 2 && + (Dungeon.hero.heroClass == HeroClass.ROGUE || Dungeon.hero.subClass == HeroSubClass.ARTISAN)) + return STR - 2; + else return STR; + } + + public boolean durable(){ + return Dungeon.isChallenged(Challenges.ABRASION); + } + + private static final String DURABLE= "durable"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(ENCHANTMENT, enchantment); + bundle.put(DURABLE, durable); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + enchantment = (Enchantment) bundle.get(ENCHANTMENT); + durable = bundle.getInt(DURABLE); + } + + @Override + public float acuracyFactor(Hero hero) { + + int encumbrance = STR() - hero.STR(); + + float ACU = this.ACU; + + if (this instanceof MissileWeapon) { + switch (hero.heroClass) { + //case WARRIOR: + //encumbrance += 3; + //break; + //case HUNTRESS: + //encumbrance -= 2; + // break; + default: + } + int bonus = 0; + for (Buff buff : hero.buffs(RingOfSharpshooting.Aim.class)) { + bonus += ((RingOfSharpshooting.Aim) buff).level; + } + ACU *= (float) (Math.pow(1.1, bonus)); + } + + return encumbrance > 0 ? (float) (ACU / Math.pow(1.5, encumbrance)) + : ACU; + } + + + @Override + public float speedFactor(Hero hero) { + + int encumrance = STR() - hero.STR(); + if (this instanceof MissileWeapon + && hero.heroClass == HeroClass.HUNTRESS) { + encumrance -= 2; + } + + float DLY = this.DLY; + int bonus = 0; + for (Buff buff : hero.buffs(RingOfFuror.Furor.class)) { + bonus += ((RingOfFuror.Furor) buff).level; + } + + DLY = (float)( DLY / Math.min( 4, 1 + bonus * 1.00 / 10) ); + + return (encumrance > 0 ? (float) (DLY * Math.pow(1.2, encumrance)) + : DLY); + } + + @Override + public int reachFactor(Hero hero) { + //return RCH; + + int RCH = this.RCH; + + int bonus = 0; + for (Buff buff : hero.buffs(RingOfAccuracy.Accuracy.class)) { + bonus += ((RingOfAccuracy.Accuracy) buff).level; + } + if (Dungeon.hero.subClass == HeroSubClass.JOKER){ + bonus += 10; + } + if (hero.buff(MechArmor.class) != null){ + bonus += 10; + } + RCH += (int)(bonus/10); + return RCH; + } + + @Override + public int damageRoll(Hero hero) { + + int damage = super.damageRoll(hero); + + int exStr = hero.STR() - STR(); + if (exStr > 0) { + damage += exStr; + } + + if (this instanceof MissileWeapon) { + float bonus = 0; + for (Buff buff : hero.buffs(RingOfSharpshooting.Aim.class)) { + bonus += ((RingOfSharpshooting.Aim) buff).level; + } + if (Dungeon.hero.buff(TargetShoot.class)!= null) + bonus += 10; + damage = (int)(damage*(1 + 0.05*bonus)); + } + + return Math.round(damage); + } + + public Item upgrade(boolean enchant) { + + if (enchant){ + if (enchantment != null) { + enchantAdv(); + } else { + enchant(); + } + } + + return super.upgrade(); + } + + @Override + public String toString() { + return levelKnown ? Messages.format(TXT_TO_STRING, super.toString(), STR()) + : super.toString(); + } + + @Override + public String name() { + return enchantment == null ? super.name() : enchantment.name(super.name()); + } + + @Override + public Item random() { + if (Random.Float() < 0.4) { + int n = 1; + if (Random.Int(3) == 0) { + n++; + if (Random.Int(3) == 0) { + n++; + } + } + if (Random.Int(2) == 0) { + upgrade(n); + } else { + degrade(n); + cursed = true; + } + } + return this; + } + + public Weapon enchant(Enchantment ench) { + enchantment = ench; + return this; + } + + + public Weapon enchant() { + + Class oldEnchantment = enchantment != null ? enchantment.getClass() : null; + Enchantment ench = Enchantment.random(); + while (ench.getClass() == oldEnchantment) { + ench = Enchantment.random(); + } + + return enchant(ench); + } + + public Weapon enchantAdv() { + + Class oldEnchantment = enchantment != null ? enchantment.getClass() : null; + Enchantment ench = Enchantment.randomAdv(); + while (ench.getClass() == oldEnchantment) { + ench = Enchantment.randomAdv(); + } + + return enchant(ench); + } + + public Weapon enchantLow() { + + Class oldEnchantment = enchantment != null ? enchantment.getClass() : null; + Enchantment ench = Enchantment.randomLow(); + while (ench.getClass() == oldEnchantment) { + ench = Enchantment.randomLow(); + } + + return enchant(ench); + } + + public Weapon enchantLuck() { + + Enchantment ench = Enchantment.randomLuck(); + return enchant(ench); + } + + public Weapon enchantBuzz() { + + Enchantment ench = Enchantment.randomBuzz(); + return enchant(ench); + } + + public Weapon enchantNeptune() { + + Enchantment ench = Enchantment.randomNeptune(); + return enchant(ench); + } + + public Weapon enchantAres() { + + Enchantment ench = Enchantment.Ares(); + return enchant(ench); + } + + + public Weapon enchantJupiter() { + + Enchantment ench = Enchantment.Jupiter(); + return enchant(ench); + } + public Weapon enchantLoki() { + + Enchantment ench = Enchantment.Loki(); + return enchant(ench); + } + + public boolean isEnchanted() { + return enchantment != null; + } + + @Override + public ItemSprite.Glowing glowing() { + return enchantment != null ? enchantment.glowing() : null; + } + + public static abstract class Enchantment implements Bundlable { + + private static final Class[] enchants = new Class[] { EnchantmentFire.class, + EnchantmentEarth.class, EnchantmentDark.class, EnchantmentEnergy.class, + EnchantmentIce.class, EnchantmentShock.class, EnchantmentLight.class, + EnchantmentFire2.class, + EnchantmentEarth2.class, EnchantmentDark2.class, EnchantmentEnergy2.class, + EnchantmentIce2.class, EnchantmentShock2.class, EnchantmentLight2.class, + BuzzSaw.class}; + private static final float[] chances = new float[] { 5, 5, 5, 5, 5,5, + 5, 5, 5, 5, 5, 5, + 5, 5, 0}; + + private static final float[] chancesLow = new float[] { 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, + 3, 3, 0 }; + + private static final float[] chancesAdv = new float[] { 2, 2, 2, 2, 2,2, + 2, 2, 2, 2, 2, 2, + 2, 2, 0 }; + + private static final float[] chancesBuzz = new float[] { 0, 0,0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0 , 10 }; + + private static final Class[] relicenchants = new Class[] { NeptuneShock.class, + CromLuck.class, AresLeech.class, JupitersHorror.class, LokisPoison.class}; + + private static final float[] chancesAres = new float[] { 0, 0, 1, 0, 0 }; + private static final float[] chancesNeptune = new float[] { 1, 0, 0, 0, 0 }; + private static final float[] chancesLuck = new float[] { 0, 1, 0, 0, 0 }; + private static final float[] chancesJupiter = new float[] { 0, 0, 0, 1, 0 }; + private static final float[] chancesLoki = new float[] { 0, 0, 0, 0, 1 }; + + public abstract boolean proc(Weapon weapon, Char attacker, + Char defender, int damage); + + + public abstract boolean proc(RelicMeleeWeapon weapon, Char attacker, + Char defender, int damage); + + public String name( String weaponName ) { + return Messages.get(this, "name", weaponName); + } + + public String desc() { + return Messages.get(this, "desc"); + } + + + @Override + public void restoreFromBundle(Bundle bundle) { + } + + @Override + public void storeInBundle(Bundle bundle) { + } + + public ItemSprite.Glowing glowing() { + return ItemSprite.Glowing.WHITE; + } + + @SuppressWarnings("unchecked") + public static Enchantment random() { + try { + return ((Class) enchants[Random.chances(chances)]) + .newInstance(); + } catch (Exception e) { + return null; + } + } + @SuppressWarnings("unchecked") + public static Enchantment randomAdv() { + try { + return ((Class) enchants[Random.chances(chancesAdv)]) + .newInstance(); + } catch (Exception e) { + return null; + } + } + @SuppressWarnings("unchecked") + public static Enchantment randomLow() { + try { + return ((Class) enchants[Random.chances(chancesLow)]) + .newInstance(); + } catch (Exception e) { + return null; + } + } + @SuppressWarnings("unchecked") + public static Enchantment randomBuzz() { + try { + return ((Class) enchants[Random.chances(chancesBuzz)]) + .newInstance(); + } catch (Exception e) { + return null; + } + } + + @SuppressWarnings("unchecked") + public static Enchantment randomLuck() { + try { + return ((Class) enchants[Random.chances(chancesLuck)]) + .newInstance(); + } catch (Exception e) { + return null; + } + } + + @SuppressWarnings("unchecked") + public static Enchantment Ares() { + try { + return ((Class) relicenchants[Random.chances(chancesAres)]) + .newInstance(); + } catch (Exception e) { + return null; + } + } + + @SuppressWarnings("unchecked") + public static Enchantment Jupiter() { + try { + return ((Class) relicenchants[Random.chances(chancesJupiter)]) + .newInstance(); + } catch (Exception e) { + return null; + } + } + + @SuppressWarnings("unchecked") + public static Enchantment Loki() { + try { + return ((Class) relicenchants[Random.chances(chancesLoki)]) + .newInstance(); + } catch (Exception e) { + return null; + } + } + + + @SuppressWarnings("unchecked") + public static Enchantment randomNeptune() { + try { + return ((Class) enchants[Random.chances(chancesNeptune)]) + .newInstance(); + } catch (Exception e) { + return null; + } + } + } +} diff --git a/java/com/hmdzl/spspd/items/weapon/enchantments/AresLeech.java b/java/com/hmdzl/spspd/items/weapon/enchantments/AresLeech.java new file mode 100644 index 00000000..58cc387e --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/enchantments/AresLeech.java @@ -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 + */ +package com.hmdzl.spspd.items.weapon.enchantments; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.items.weapon.Weapon; +import com.hmdzl.spspd.items.weapon.melee.relic.RelicMeleeWeapon; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.sprites.ItemSprite.Glowing; +import com.hmdzl.spspd.ui.BuffIndicator; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public class AresLeech extends Weapon.Enchantment { + + private static ItemSprite.Glowing PURPLE = new ItemSprite.Glowing(0x660066); + + @Override + public boolean proc(Weapon weapon, Char attacker, Char defender, int damage) { + return false; + } + + @Override + public boolean proc(RelicMeleeWeapon weapon, Char attacker, Char defender, int damage) { + + int level = Math.max(0, weapon.level); + int distance = 3; + int maxValue = damage * (level + 2) / (level + 6); + int effValue = Math.min(Random.IntRange(0, maxValue), attacker.HT - attacker.HP); + + for (Mob mob : Dungeon.level.mobs) { + + if (Level.distance(attacker.pos, mob.pos) < distance && mob.isAlive() ){ + if(effValue 0) { + + HealDamage spbuff = attacker.buff(HealDamage.class); + if (spbuff == null) { + spbuff = new HealDamage(); + spbuff.attachTo(attacker); + } + spbuff.prolong(damage); + return true; + } else { + return false; + } + + + } + + @Override + public Glowing glowing() { + return PURPLE; + } + + public static class HealDamage extends Buff { + + protected int damage = 0; + + private static final String DAMAGE = "damage"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(DAMAGE, damage); + + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + damage = bundle.getInt(DAMAGE); + } + + @Override + public boolean attachTo(Char target) { + if (super.attachTo(target)) { + postpone(TICK); + return true; + } else { + return false; + } + } + + public void prolong(int damage) { + this.damage = damage; + }; + + @Override + public int icon() { + return BuffIndicator.DEFERRED; + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public boolean act() { + if (target.isAlive()) { + + int damageThisTick = Math.max(1, (int)(damage*0.1f)) + ; + if (target.HP= target.HT) { + detach(); + } + + } else { + + detach(); + + } + + return true; + } + @Override + public String desc() { + return Messages.get(this, "desc", damage); + } + + } +} + + + diff --git a/java/com/hmdzl/spspd/items/weapon/enchantments/BuzzSaw.java b/java/com/hmdzl/spspd/items/weapon/enchantments/BuzzSaw.java new file mode 100644 index 00000000..afa1b4fa --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/enchantments/BuzzSaw.java @@ -0,0 +1,87 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.weapon.enchantments; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.items.DewVial; +import com.hmdzl.spspd.items.weapon.Weapon; +import com.hmdzl.spspd.items.weapon.melee.special.Handcannon; +import com.hmdzl.spspd.items.weapon.melee.relic.RelicMeleeWeapon; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.sprites.ItemSprite.Glowing; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Random; + +public class BuzzSaw extends Weapon.Enchantment { + + private static ItemSprite.Glowing OLIVE = new ItemSprite.Glowing(0x999900); + + @Override + public boolean proc(RelicMeleeWeapon weapon, Char attacker, Char defender, int damage) { + return false; + } + + @Override + public boolean proc(Weapon weapon, Char attacker, Char defender, int damage) { + + //int level = Math.max(0, weapon.level); + + + DewVial vial = Dungeon.hero.belongings.getItem(DewVial.class); + Handcannon saw = Dungeon.hero.belongings.getItem(Handcannon.class); + + if (vial != null) { + + int hits = Random.Int(Math.round(vial.checkVol()/10)); + int dmg; + + for (int i = 1; i <= hits + 1; i++) { + if (vial.checkVol()>0 && saw.turnedOn){ + vial.sip(); + dmg = Math.max(1, (attacker.damageRoll()- i)*2); + defender.damage(dmg, this); + GLog.h("Vrrrrrr!"); + } else if (vial.checkVol()==0 && saw.turnedOn){ + //defender.damage(Random.Int(level), this); + GLog.n(Messages.get(this, "fuel")); + break; + } else if (vial.checkVol()>0 && !saw.turnedOn){ + //defender.damage(Random.Int(level), this); + GLog.n(Messages.get(this, "off")); + break; + } else { + //defender.damage(Random.Int(level), this); + //GLog.n("Handcannon is out of fuel!"); + break; + } + if(!defender.isAlive()){break;} + } + + } + + return true; + + } + + @Override + public Glowing glowing() { + return OLIVE; + } +} diff --git a/java/com/hmdzl/spspd/items/weapon/enchantments/CromLuck.java b/java/com/hmdzl/spspd/items/weapon/enchantments/CromLuck.java new file mode 100644 index 00000000..4bd8d313 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/enchantments/CromLuck.java @@ -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 + */ +package com.hmdzl.spspd.items.weapon.enchantments; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.items.weapon.Weapon; +import com.hmdzl.spspd.items.weapon.melee.relic.RelicMeleeWeapon; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.sprites.ItemSprite.Glowing; + +public class CromLuck extends Weapon.Enchantment { + + private static ItemSprite.Glowing RED = new ItemSprite.Glowing(0x800000); + + @Override + public boolean proc(RelicMeleeWeapon weapon, Char attacker, Char defender, int damage) { + return false; + } + + @Override + public boolean proc(Weapon weapon, Char attacker, Char defender, int damage) { + int level = Math.max(0, weapon.level); + + int dmg = damage; + for (int i = 1; i <= level + 1; i++) { + dmg = Math.max(dmg, attacker.damageRoll()); + } + + if (dmg > damage) { + defender.damage(dmg - damage, weapon); + return true; + } else { + return false; + } + } + + @Override + public Glowing glowing() { + return RED; + } +} diff --git a/java/com/hmdzl/spspd/items/weapon/enchantments/EnchantmentDark.java b/java/com/hmdzl/spspd/items/weapon/enchantments/EnchantmentDark.java new file mode 100644 index 00000000..58e9b9b4 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/enchantments/EnchantmentDark.java @@ -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 + */ +package com.hmdzl.spspd.items.weapon.enchantments; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Terror; +import com.hmdzl.spspd.effects.particles.ShadowParticle; +import com.hmdzl.spspd.items.misc.FourClover; +import com.hmdzl.spspd.items.weapon.Weapon; +import com.hmdzl.spspd.items.weapon.melee.relic.RelicMeleeWeapon; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.sprites.ItemSprite.Glowing; +import com.watabou.utils.Random; + +public class EnchantmentDark extends Weapon.Enchantment { + + private static ItemSprite.Glowing BLACK = new ItemSprite.Glowing( 0x000000 ); + + @Override + public boolean proc(RelicMeleeWeapon weapon, Char attacker, Char defender, int damage) { + return false; + } + + @Override + public boolean proc(Weapon weapon, Char attacker, Char defender, int damage) { + // lvl 0 - 8% + // lvl 1 ~ 9% + // lvl 2 ~ 10% + FourClover.FourCloverBless fcb = attacker.buff(FourClover.FourCloverBless.class); + int level = Math.max(0, weapon.level); + int dmg = damage; + defender.damage(Random.Int(dmg/6), this); + if(fcb != null && Random.Int(2) == 1){ + defender.damage(Random.Int(dmg/6), this); + } + if (Random.Int(level + 15) >= 15) { + Buff.prolong(defender, Terror.class,5f); + defender.sprite.emitter().burst(ShadowParticle.UP, 5); + return true; + } else { + return false; + } + } + + @Override + public Glowing glowing() { + return BLACK; + } +} diff --git a/java/com/hmdzl/spspd/items/weapon/enchantments/EnchantmentDark2.java b/java/com/hmdzl/spspd/items/weapon/enchantments/EnchantmentDark2.java new file mode 100644 index 00000000..c6fedcd3 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/enchantments/EnchantmentDark2.java @@ -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 + */ +package com.hmdzl.spspd.items.weapon.enchantments; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.AttackDown; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.effects.particles.ShadowParticle; +import com.hmdzl.spspd.items.misc.FourClover; +import com.hmdzl.spspd.items.weapon.Weapon; +import com.hmdzl.spspd.items.weapon.melee.relic.RelicMeleeWeapon; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.sprites.ItemSprite.Glowing; +import com.watabou.utils.Random; + +public class EnchantmentDark2 extends Weapon.Enchantment { + + private static ItemSprite.Glowing BLACK = new ItemSprite.Glowing( 0x000000 ); + + @Override + public boolean proc(RelicMeleeWeapon weapon, Char attacker, Char defender, int damage) { + return false; + } + + @Override + public boolean proc(Weapon weapon, Char attacker, Char defender, int damage) { + // lvl 0 - 8% + // lvl 1 ~ 9% + // lvl 2 ~ 10% + FourClover.FourCloverBless fcb = attacker.buff(FourClover.FourCloverBless.class); + int lvl = Math.max(0, weapon.level); + Buff.prolong(defender, AttackDown.class,5f).level(Math.min(50,lvl+5)); + if(fcb != null && Random.Int(2) == 1){ + defender.damage(Random.Int(damage/6), this); + } + defender.sprite.emitter().burst(ShadowParticle.UP, 5); + return true; + + } + + @Override + public Glowing glowing() { + return BLACK; + } +} diff --git a/java/com/hmdzl/spspd/items/weapon/enchantments/EnchantmentEarth.java b/java/com/hmdzl/spspd/items/weapon/enchantments/EnchantmentEarth.java new file mode 100644 index 00000000..6af22bba --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/enchantments/EnchantmentEarth.java @@ -0,0 +1,72 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.weapon.enchantments; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.GrowSeed; +import com.hmdzl.spspd.actors.buffs.Roots; +import com.hmdzl.spspd.actors.buffs.Weakness; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.particles.EarthParticle; +import com.hmdzl.spspd.effects.particles.ShadowParticle; +import com.hmdzl.spspd.items.misc.FourClover; +import com.hmdzl.spspd.items.weapon.Weapon; +import com.hmdzl.spspd.items.weapon.melee.relic.RelicMeleeWeapon; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.sprites.ItemSprite.Glowing; +import com.watabou.utils.Random; + +public class EnchantmentEarth extends Weapon.Enchantment { + + private static ItemSprite.Glowing BROWN = new ItemSprite.Glowing( 0x996600 ); + + @Override + public boolean proc(RelicMeleeWeapon weapon, Char attacker, Char defender, int damage) { + return false; + } + + @Override + public boolean proc(Weapon weapon, Char attacker, Char defender, int damage) { + // lvl 0 - 33% + // lvl 1 - 50% + // lvl 2 - 60% + FourClover.FourCloverBless fcb = attacker.buff(FourClover.FourCloverBless.class); + int level = Math.max(0, weapon.level); + + int dmg = damage; + defender.damage(Random.Int(dmg/6), this); + if(fcb != null && Random.Int(2) == 1){ + defender.damage(Random.Int(dmg/6), this); + } + + if (Random.Int(level + 15) >= 30) { + Buff.affect(defender, GrowSeed.class).reignite(defender); + CellEmitter.bottom(defender.pos).start(EarthParticle.FACTORY, 0.05f, 8); + return true; + } else { + return false; + } + } + + @Override + public Glowing glowing() { + return BROWN; + } + +} diff --git a/java/com/hmdzl/spspd/items/weapon/enchantments/EnchantmentEarth2.java b/java/com/hmdzl/spspd/items/weapon/enchantments/EnchantmentEarth2.java new file mode 100644 index 00000000..4332cd5e --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/enchantments/EnchantmentEarth2.java @@ -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 + */ +package com.hmdzl.spspd.items.weapon.enchantments; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Ooze; +import com.hmdzl.spspd.actors.buffs.Roots; +import com.hmdzl.spspd.actors.buffs.Weakness; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.particles.EarthParticle; +import com.hmdzl.spspd.effects.particles.ShadowParticle; +import com.hmdzl.spspd.items.misc.FourClover; +import com.hmdzl.spspd.items.weapon.Weapon; +import com.hmdzl.spspd.items.weapon.melee.relic.RelicMeleeWeapon; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.sprites.ItemSprite.Glowing; +import com.watabou.utils.Random; + +public class EnchantmentEarth2 extends Weapon.Enchantment { + + private static ItemSprite.Glowing BROWN = new ItemSprite.Glowing( 0x996600 ); + + @Override + public boolean proc(RelicMeleeWeapon weapon, Char attacker, Char defender, int damage) { + return false; + } + + @Override + public boolean proc(Weapon weapon, Char attacker, Char defender, int damage) { + // lvl 0 - 33% + // lvl 1 - 50% + // lvl 2 - 60% + FourClover.FourCloverBless fcb = attacker.buff(FourClover.FourCloverBless.class); + int level = Math.max(0, weapon.level); + if ((Random.Int(level + 15) >= 15 || (fcb != null && Random.Int(level + 15) >= 10) )&& defender.isAlive()) { + Buff.prolong(defender, Roots.class,5f); + Buff.affect(defender, Ooze.class); + CellEmitter.bottom(defender.pos).start(EarthParticle.FACTORY, 0.05f, 8); + return true; + } else { + return false; + } + } + + @Override + public Glowing glowing() { + return BROWN; + } + +} diff --git a/java/com/hmdzl/spspd/items/weapon/enchantments/EnchantmentEnergy.java b/java/com/hmdzl/spspd/items/weapon/enchantments/EnchantmentEnergy.java new file mode 100644 index 00000000..a1682022 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/enchantments/EnchantmentEnergy.java @@ -0,0 +1,71 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2014 Oleg Dolya + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.items.weapon.enchantments; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.AttackUp; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Weakness; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.effects.particles.ShadowParticle; +import com.hmdzl.spspd.items.misc.FourClover; +import com.hmdzl.spspd.items.weapon.Weapon; +import com.hmdzl.spspd.items.weapon.melee.relic.RelicMeleeWeapon; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.sprites.ItemSprite.Glowing; +import com.watabou.utils.Random; + +public class EnchantmentEnergy extends Weapon.Enchantment { + + private static ItemSprite.Glowing GRAY = new ItemSprite.Glowing( 0x888888 ); + + @Override + public boolean proc(RelicMeleeWeapon weapon, Char attacker, Char defender, int damage) { + return false; + } + + @Override + public boolean proc(Weapon weapon, Char attacker, Char defender, int damage) { + // lvl 0 - 13% + // lvl 1 - 22% + // lvl 2 - 30% + FourClover.FourCloverBless fcb = attacker.buff(FourClover.FourCloverBless.class); + int level = Math.max(0, weapon.level); + + int dmg = damage; + defender.damage(Random.Int(dmg/6), this); + if(fcb != null && Random.Int(2) == 1){ + defender.damage(Random.Int(dmg/6), this); + } + + if (Random.Int(level + 15) >= 15) { + Buff.prolong(attacker, AttackUp.class,10f).level(15); + attacker.sprite.emitter().start(Speck.factory(Speck.UP), 0.2f, 3); + return true; + } else { + return false; + } + } + + @Override + public Glowing glowing() { + return GRAY; + } + +} diff --git a/java/com/hmdzl/spspd/items/weapon/enchantments/EnchantmentEnergy2.java b/java/com/hmdzl/spspd/items/weapon/enchantments/EnchantmentEnergy2.java new file mode 100644 index 00000000..16d20615 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/enchantments/EnchantmentEnergy2.java @@ -0,0 +1,72 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.weapon.enchantments; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.AttackUp; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.DefenceUp; +import com.hmdzl.spspd.actors.buffs.Weakness; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.effects.particles.ShadowParticle; +import com.hmdzl.spspd.items.misc.FourClover; +import com.hmdzl.spspd.items.weapon.Weapon; +import com.hmdzl.spspd.items.weapon.melee.relic.RelicMeleeWeapon; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.sprites.ItemSprite.Glowing; +import com.watabou.utils.Random; + +public class EnchantmentEnergy2 extends Weapon.Enchantment { + + private static ItemSprite.Glowing GRAY = new ItemSprite.Glowing( 0x888888 ); + + @Override + public boolean proc(RelicMeleeWeapon weapon, Char attacker, Char defender, int damage) { + return false; + } + + @Override + public boolean proc(Weapon weapon, Char attacker, Char defender, int damage) { + // lvl 0 - 13% + // lvl 1 - 22% + // lvl 2 - 30% + FourClover.FourCloverBless fcb = attacker.buff(FourClover.FourCloverBless.class); + int lvl = Math.max(0, weapon.level); + + //int dmg = damage; + //defender.damage(Random.Int(dmg/6), this); + + //if (Random.Int(level + 15) >= 15) { + if(fcb != null && Random.Int(2) == 1){ + defender.damage(Random.Int(damage/6), this); + } + Buff.prolong(attacker, DefenceUp.class,5f).level(Math.min(30,lvl+1)); + attacker.sprite.emitter().start(Speck.factory(Speck.UP), 0.2f, 3); + return true; + //} else { + //return false; + //} + } + + @Override + public Glowing glowing() { + return GRAY; + } + +} diff --git a/java/com/hmdzl/spspd/items/weapon/enchantments/EnchantmentFire.java b/java/com/hmdzl/spspd/items/weapon/enchantments/EnchantmentFire.java new file mode 100644 index 00000000..c5332dc0 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/enchantments/EnchantmentFire.java @@ -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 + */ +package com.hmdzl.spspd.items.weapon.enchantments; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Burning; +import com.hmdzl.spspd.actors.buffs.Weakness; +import com.hmdzl.spspd.effects.particles.FlameParticle; +import com.hmdzl.spspd.effects.particles.ShadowParticle; +import com.hmdzl.spspd.items.misc.FourClover; +import com.hmdzl.spspd.items.weapon.Weapon; +import com.hmdzl.spspd.items.weapon.melee.relic.RelicMeleeWeapon; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.sprites.ItemSprite.Glowing; +import com.watabou.utils.Random; + +public class EnchantmentFire extends Weapon.Enchantment { + + private static ItemSprite.Glowing RED = new ItemSprite.Glowing( 0xCC0000 ); + + @Override + public boolean proc(RelicMeleeWeapon weapon, Char attacker, Char defender, int damage) { + return false; + } + + @Override + public boolean proc(Weapon weapon, Char attacker, Char defender, int damage) { + // lvl 0 - 33% + // lvl 1 - 50% + // lvl 2 - 60% + FourClover.FourCloverBless fcb = attacker.buff(FourClover.FourCloverBless.class); + int level = Math.max(0, weapon.level); + + int dmg = damage; + defender.damage(Random.Int(dmg/6), this); + if(fcb != null && Random.Int(2) == 1){ + defender.damage(Random.Int(dmg/6), this); + } + + if (Random.Int(level + 15) >= 15) { + Buff.affect(defender, Burning.class).reignite( defender ); + defender.sprite.emitter().burst(FlameParticle.FACTORY, 5); + return true; + } else { + return false; + } + } + + @Override + public Glowing glowing() { + return RED; + } +} diff --git a/java/com/hmdzl/spspd/items/weapon/enchantments/EnchantmentFire2.java b/java/com/hmdzl/spspd/items/weapon/enchantments/EnchantmentFire2.java new file mode 100644 index 00000000..e719eee9 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/enchantments/EnchantmentFire2.java @@ -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 + */ +package com.hmdzl.spspd.items.weapon.enchantments; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Burning; +import com.hmdzl.spspd.actors.buffs.Hot; +import com.hmdzl.spspd.actors.buffs.Tar; +import com.hmdzl.spspd.actors.buffs.Weakness; +import com.hmdzl.spspd.effects.particles.FlameParticle; +import com.hmdzl.spspd.effects.particles.ShadowParticle; +import com.hmdzl.spspd.items.misc.FourClover; +import com.hmdzl.spspd.items.weapon.Weapon; +import com.hmdzl.spspd.items.weapon.melee.relic.RelicMeleeWeapon; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.sprites.ItemSprite.Glowing; +import com.watabou.utils.Random; + +public class EnchantmentFire2 extends Weapon.Enchantment { + + private static ItemSprite.Glowing RED = new ItemSprite.Glowing( 0xCC0000 ); + + @Override + public boolean proc(RelicMeleeWeapon weapon, Char attacker, Char defender, int damage) { + return false; + } + + @Override + public boolean proc(Weapon weapon, Char attacker, Char defender, int damage) { + // lvl 0 - 33% + // lvl 1 - 50% + // lvl 2 - 60% + FourClover.FourCloverBless fcb = attacker.buff(FourClover.FourCloverBless.class); + int lvl = Math.max(0, weapon.level); + if(fcb != null && Random.Int(2) == 1){ + defender.damage(Random.Int(damage/6), this); + } + if (defender.isAlive()){ + Buff.prolong(defender, Hot.class,Math.min(30,lvl+1)); + Buff.affect(defender, Tar.class); + defender.sprite.emitter().burst(FlameParticle.FACTORY, 5); + return true; + } else { + return false; + } + + } + + @Override + public Glowing glowing() { + return RED; + } +} diff --git a/java/com/hmdzl/spspd/items/weapon/enchantments/EnchantmentIce.java b/java/com/hmdzl/spspd/items/weapon/enchantments/EnchantmentIce.java new file mode 100644 index 00000000..677a0b0a --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/enchantments/EnchantmentIce.java @@ -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 + */ +package com.hmdzl.spspd.items.weapon.enchantments; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Chill; +import com.hmdzl.spspd.actors.buffs.Frost; +import com.hmdzl.spspd.actors.buffs.Weakness; +import com.hmdzl.spspd.effects.particles.ShadowParticle; +import com.hmdzl.spspd.effects.particles.SnowParticle; +import com.hmdzl.spspd.items.misc.FourClover; +import com.hmdzl.spspd.items.weapon.Weapon; +import com.hmdzl.spspd.items.weapon.melee.relic.RelicMeleeWeapon; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.sprites.ItemSprite.Glowing; +import com.watabou.utils.Random; + +public class EnchantmentIce extends Weapon.Enchantment { + + private static ItemSprite.Glowing BLUE = new ItemSprite.Glowing(0x0044FF); + + @Override + public boolean proc(RelicMeleeWeapon weapon, Char attacker, Char defender, int damage) { + return false; + } + + @Override + public boolean proc(Weapon weapon, Char attacker, Char defender, int damage) { + // lvl 0 - 25% + // lvl 1 - 40% + // lvl 2 - 50% + FourClover.FourCloverBless fcb = attacker.buff(FourClover.FourCloverBless.class); + int level = Math.max(0, weapon.level); + int dmg = damage; + defender.damage(Random.Int(dmg/6), this); + if(fcb != null && Random.Int(2) == 1){ + defender.damage(Random.Int(dmg/6), this); + } + if (Random.Int(level + 15) >= 15) { + Buff.affect(defender, Frost.class, Frost.duration(defender)*Random.Float(2f, 4f)); + defender.sprite.emitter().burst(SnowParticle.FACTORY, 5); + return true; + } else { + return false; + } + } + + @Override + public Glowing glowing() { + return BLUE; + } + +} diff --git a/java/com/hmdzl/spspd/items/weapon/enchantments/EnchantmentIce2.java b/java/com/hmdzl/spspd/items/weapon/enchantments/EnchantmentIce2.java new file mode 100644 index 00000000..6a95d7db --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/enchantments/EnchantmentIce2.java @@ -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 + */ +package com.hmdzl.spspd.items.weapon.enchantments; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Chill; +import com.hmdzl.spspd.actors.buffs.Cold; +import com.hmdzl.spspd.actors.buffs.Frost; +import com.hmdzl.spspd.actors.buffs.Weakness; +import com.hmdzl.spspd.actors.buffs.Wet; +import com.hmdzl.spspd.effects.particles.ShadowParticle; +import com.hmdzl.spspd.effects.particles.SnowParticle; +import com.hmdzl.spspd.items.misc.FourClover; +import com.hmdzl.spspd.items.weapon.Weapon; +import com.hmdzl.spspd.items.weapon.melee.relic.RelicMeleeWeapon; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.sprites.ItemSprite.Glowing; +import com.watabou.utils.Random; + +public class EnchantmentIce2 extends Weapon.Enchantment { + + private static ItemSprite.Glowing BLUE = new ItemSprite.Glowing(0x0044FF); + + @Override + public boolean proc(RelicMeleeWeapon weapon, Char attacker, Char defender, int damage) { + return false; + } + + @Override + public boolean proc(Weapon weapon, Char attacker, Char defender, int damage) { + // lvl 0 - 25% + // lvl 1 - 40% + // lvl 2 - 50% + FourClover.FourCloverBless fcb = attacker.buff(FourClover.FourCloverBless.class); + int lvl = Math.max(0, weapon.level); + if(fcb != null && Random.Int(2) == 1){ + defender.damage(Random.Int(damage/6), this); + } + Buff.prolong(defender, Wet.class, Math.min(30,lvl+2)); + Buff.prolong(defender, Cold.class, Math.min(30,lvl+2)); + defender.sprite.emitter().burst(SnowParticle.FACTORY, 5); + + return true; + + } + + @Override + public Glowing glowing() { + return BLUE; + } + +} diff --git a/java/com/hmdzl/spspd/items/weapon/enchantments/EnchantmentLight.java b/java/com/hmdzl/spspd/items/weapon/enchantments/EnchantmentLight.java new file mode 100644 index 00000000..7cb6724f --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/enchantments/EnchantmentLight.java @@ -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 + */ +package com.hmdzl.spspd.items.weapon.enchantments; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.items.misc.FourClover; +import com.hmdzl.spspd.items.weapon.Weapon; +import com.hmdzl.spspd.items.weapon.melee.relic.RelicMeleeWeapon; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.sprites.ItemSprite.Glowing; +import com.watabou.utils.Random; + +public class EnchantmentLight extends Weapon.Enchantment { + +private static ItemSprite.Glowing YELLOW = new ItemSprite.Glowing( 0xFFFF44 ); + + @Override + public boolean proc(RelicMeleeWeapon weapon, Char attacker, Char defender, int damage) { + return false; + } + + @Override + public boolean proc(Weapon weapon, Char attacker, Char defender, int damage) { + // lvl 0 - 20% + // lvl 1 - 33% + // lvl 2 - 43% + FourClover.FourCloverBless fcb = attacker.buff(FourClover.FourCloverBless.class); + int level = Math.max(0, weapon.level); + + int dmg = damage; + defender.damage(Random.Int(dmg/6), this); + if(fcb != null && Random.Int(2) == 1){ + defender.damage(Random.Int(dmg/6), this); + } + if (Random.Int(level + 15) >= 30) { + if (defender.properties().contains(Char.Property.DEMONIC) || defender.properties().contains(Char.Property.UNDEAD)){ + defender.damage((int)(damage*0.5),this); + } + } + + //if (Random.Int(level + 15) >= 15) { + //Buff.prolong(defender, Blindness.class,5f); + //defender.sprite.emitter().burst(Speck.factory(Speck.LIGHT), 6); + return true; + //} else { + //return false; + //} + } + + @Override + public Glowing glowing() { + return YELLOW; + } +} diff --git a/java/com/hmdzl/spspd/items/weapon/enchantments/EnchantmentLight2.java b/java/com/hmdzl/spspd/items/weapon/enchantments/EnchantmentLight2.java new file mode 100644 index 00000000..0ff6ffab --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/enchantments/EnchantmentLight2.java @@ -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 + */ +package com.hmdzl.spspd.items.weapon.enchantments; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Blindness; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.misc.FourClover; +import com.hmdzl.spspd.items.weapon.Weapon; +import com.hmdzl.spspd.items.weapon.melee.relic.RelicMeleeWeapon; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.sprites.ItemSprite.Glowing; +import com.watabou.utils.Random; + +public class EnchantmentLight2 extends Weapon.Enchantment { + +private static ItemSprite.Glowing YELLOW = new ItemSprite.Glowing( 0xFFFF44 ); + + @Override + public boolean proc(RelicMeleeWeapon weapon, Char attacker, Char defender, int damage) { + return false; + } + + @Override + public boolean proc(Weapon weapon, Char attacker, Char defender, int damage) { + // lvl 0 - 20% + // lvl 1 - 33% + // lvl 2 - 43% + FourClover.FourCloverBless fcb = attacker.buff(FourClover.FourCloverBless.class); + int lvl = Math.max(0, weapon.level); + Buff.prolong(defender, Blindness.class,Math.min(50,lvl+5)); + if(fcb != null && Random.Int(2) == 1){ + defender.damage(Random.Int(damage/6), this); + } + defender.sprite.emitter().burst(Speck.factory(Speck.LIGHT), 6); + return true; + + } + + @Override + public Glowing glowing() { + return YELLOW; + } +} diff --git a/java/com/hmdzl/spspd/items/weapon/enchantments/EnchantmentShock.java b/java/com/hmdzl/spspd/items/weapon/enchantments/EnchantmentShock.java new file mode 100644 index 00000000..202101a6 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/enchantments/EnchantmentShock.java @@ -0,0 +1,115 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 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 + */ +package com.hmdzl.spspd.items.weapon.enchantments; + +import java.util.ArrayList; +import java.util.HashSet; + +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.effects.Lightning; +import com.hmdzl.spspd.effects.particles.SparkParticle; +import com.hmdzl.spspd.items.misc.FourClover; +import com.hmdzl.spspd.items.weapon.Weapon; +import com.hmdzl.spspd.items.weapon.melee.relic.RelicMeleeWeapon; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.traps.LightningTrap; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.sprites.ItemSprite.Glowing; +import com.watabou.utils.Random; + +public class EnchantmentShock extends Weapon.Enchantment { + + private static ItemSprite.Glowing GREEN = new ItemSprite.Glowing( 0x00FF00 ); + @Override + public boolean proc(RelicMeleeWeapon weapon, Char attacker, Char defender, int damage) { + return false; + } + + @Override + public boolean proc(Weapon weapon, Char attacker, Char defender, int damage) { + // lvl 0 - 25% + // lvl 1 - 40% + // lvl 2 - 50% + FourClover.FourCloverBless fcb = attacker.buff(FourClover.FourCloverBless.class); + int level = Math.max(0, weapon.level); + + if (Random.Int(level + 4) >= 3) { + + points[0] = attacker.pos; + nPoints = 1; + + affected.clear(); + affected.add(attacker); + + hit(defender, Random.Int(1, damage / 2)); + + if(fcb != null && Random.Int(2) == 1){ + hit(defender, Random.Int(1, damage / 2)); + } + + attacker.sprite.parent.add(new Lightning( attacker.pos, defender.pos, null )); + + return true; + + } else { + + return false; + + } + } + + private ArrayList affected = new ArrayList(); + + private int[] points = new int[20]; + private int nPoints; + + private void hit(Char ch, int damage) { + + if (damage < 1) { + return; + } + + affected.add(ch); + ch.damage(Level.water[ch.pos] && !ch.flying ? (int) (damage * 2) + : damage, this); + + ch.sprite.centerEmitter().burst(SparkParticle.FACTORY, 3); + ch.sprite.flash(); + + points[nPoints++] = ch.pos; + + HashSet ns = new HashSet(); + for (int i = 0; i < Level.NEIGHBOURS8.length; i++) { + Char n = Actor.findChar(ch.pos + Level.NEIGHBOURS8[i]); + if (n != null && !affected.contains(n)) { + ns.add(n); + } + } + + if (ns.size() > 0) { + hit(Random.element(ns), Random.Int(damage / 2, damage)); + } + } + + @Override + public Glowing glowing() { + return GREEN; + } +} + diff --git a/java/com/hmdzl/spspd/items/weapon/enchantments/EnchantmentShock2.java b/java/com/hmdzl/spspd/items/weapon/enchantments/EnchantmentShock2.java new file mode 100644 index 00000000..468adea0 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/enchantments/EnchantmentShock2.java @@ -0,0 +1,67 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 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 + */ +package com.hmdzl.spspd.items.weapon.enchantments; + +import java.util.ArrayList; +import java.util.HashSet; + +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Paralysis; +import com.hmdzl.spspd.actors.buffs.Shocked; +import com.hmdzl.spspd.effects.Lightning; +import com.hmdzl.spspd.effects.particles.SparkParticle; +import com.hmdzl.spspd.items.misc.FourClover; +import com.hmdzl.spspd.items.weapon.Weapon; +import com.hmdzl.spspd.items.weapon.melee.relic.RelicMeleeWeapon; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.traps.LightningTrap; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.sprites.ItemSprite.Glowing; +import com.watabou.utils.Random; + +public class EnchantmentShock2 extends Weapon.Enchantment { + +private static ItemSprite.Glowing GREEN = new ItemSprite.Glowing( 0x00FF00 ); + @Override + public boolean proc(RelicMeleeWeapon weapon, Char attacker, Char defender, int damage) { + return false; + } + + @Override + public boolean proc(Weapon weapon, Char attacker, Char defender, int damage) { + // lvl 0 - 25% + // lvl 1 - 40% + // lvl 2 - 50% + FourClover.FourCloverBless fcb = attacker.buff(FourClover.FourCloverBless.class); + int level = Math.max(0, weapon.level); + + if (Random.Int(level + 15) >= 15 || (fcb != null && Random.Int(level + 15) >= 10)) { + Buff.prolong(defender, Shocked.class,2f); + return true; + } else { + return false; + } + } + @Override + public Glowing glowing() { + return GREEN; + } +} + diff --git a/java/com/hmdzl/spspd/items/weapon/enchantments/JupitersHorror.java b/java/com/hmdzl/spspd/items/weapon/enchantments/JupitersHorror.java new file mode 100644 index 00000000..7d73d798 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/enchantments/JupitersHorror.java @@ -0,0 +1,104 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.weapon.enchantments; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Paralysis; +import com.hmdzl.spspd.actors.buffs.Terror; +import com.hmdzl.spspd.actors.buffs.Vertigo; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.weapon.Weapon; +import com.hmdzl.spspd.items.weapon.melee.relic.RelicMeleeWeapon; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.sprites.ItemSprite.Glowing; +import com.watabou.noosa.Camera; +import com.watabou.utils.Random; + +public class JupitersHorror extends Weapon.Enchantment { + + private static ItemSprite.Glowing GREY = new ItemSprite.Glowing(0x222222); + + @Override + public boolean proc(RelicMeleeWeapon weapon, Char attacker, Char defender, int damage) { + return false; + } + + @Override + public boolean proc(Weapon weapon, Char attacker, Char defender, int damage) { + // lvl 0 - 20% + // lvl 1 - 33% + // lvl 2 - 43% + int level = Math.max(0, weapon.level); + + if (Random.Int(level + 5) >= 4) { + + if (defender == Dungeon.hero) { + Buff.affect(defender, Vertigo.class, Vertigo.duration(defender)); + } else { + Buff.affect(defender, Terror.class, Terror.DURATION).object = attacker + .id(); + if (Random.Int(level + 11) >= 10){ + //doExplode(defender.pos); + } + } + + return true; + } else { + return false; + } + } + + public void doExplode(int cell) { + + Camera.main.shake(3, 0.7f); + + if (Dungeon.visible[cell] && Level.passable[cell]) { + CellEmitter.center(cell).start(Speck.factory(Speck.ROCK), 0.07f, 10); + } + + Char ch = Actor.findChar(cell); + if (ch != null && ch!=Dungeon.hero) { + // those not at the center of the blast take damage less + // consistently. + int minDamage = Dungeon.depth + 5; + int maxDamage = 10 + Dungeon.depth * 3; + + + int dmg = Random.NormalIntRange(minDamage, maxDamage) - Math.max(ch.drRoll(),0); + + + if (dmg > 0) { + ch.damage(dmg, this); + if(Random.Int(15)==1){Buff.prolong(ch, Paralysis.class, 1);} + } + + } + + } + + + @Override + public Glowing glowing() { + return GREY; + } +} diff --git a/java/com/hmdzl/spspd/items/weapon/enchantments/LokisPoison.java b/java/com/hmdzl/spspd/items/weapon/enchantments/LokisPoison.java new file mode 100644 index 00000000..793c8ff1 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/enchantments/LokisPoison.java @@ -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 + */ +package com.hmdzl.spspd.items.weapon.enchantments; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.items.weapon.Weapon; +import com.hmdzl.spspd.items.weapon.melee.relic.RelicMeleeWeapon; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.sprites.ItemSprite.Glowing; +import com.watabou.utils.Random; + +public class LokisPoison extends Weapon.Enchantment { + + private static ItemSprite.Glowing PURPLE = new ItemSprite.Glowing(0x4400AA); + + @Override + public boolean proc(RelicMeleeWeapon weapon, Char attacker, Char defender, int damage) { + return false; + } + + @Override + public boolean proc(Weapon weapon, Char attacker, Char defender, int damage) { + // lvl 0 - 33% + // lvl 1 - 50% + // lvl 2 - 60% + int level = Math.max(0, weapon.level); + int distance = 1 + level*2; + + if (Random.Int(level + 3) >= 2) { + + Buff.affect( + defender, + com.hmdzl.spspd.actors.buffs.LokisPoison.class) + .set(com.hmdzl.spspd.actors.buffs.LokisPoison + .durationFactor(defender) * (level + 1)); + return true; + } else { + return false; + } + } + + @Override + public Glowing glowing() { + return PURPLE; + } +} diff --git a/java/com/hmdzl/spspd/items/weapon/enchantments/NeptuneShock.java b/java/com/hmdzl/spspd/items/weapon/enchantments/NeptuneShock.java new file mode 100644 index 00000000..5133db70 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/enchantments/NeptuneShock.java @@ -0,0 +1,110 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 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 + */ +package com.hmdzl.spspd.items.weapon.enchantments; + +import java.util.ArrayList; +import java.util.HashSet; + +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.effects.Lightning; +import com.hmdzl.spspd.effects.particles.SparkParticle; +import com.hmdzl.spspd.items.weapon.Weapon; +import com.hmdzl.spspd.items.weapon.melee.relic.RelicMeleeWeapon; +import com.hmdzl.spspd.levels.Level; +import com.watabou.utils.Random; + +public class NeptuneShock extends Weapon.Enchantment { + + private int cost = 10; + + @Override + public boolean proc(Weapon weapon, Char attacker, Char defender, int damage) { + + return false; + } + + @Override + public boolean proc(RelicMeleeWeapon weapon, Char attacker, Char defender, int damage) { + // lvl 0 - 25% + // lvl 1 - 40% + // lvl 2 - 50% + + + if (weapon.charge>=cost){ + weapon.charge-=cost; + } else { + return false; + } + + int level = Math.max(0, weapon.level); + + if (Random.Int(level + 4) >= 3) { + + points[0] = attacker.pos; + nPoints = 1; + + affected.clear(); + affected.add(attacker); + + hit(defender, Random.Int(damage / 3, damage / 2)); + + attacker.sprite.parent.add(new Lightning( attacker.pos, defender.pos, null )); + + return true; + + } else { + + return false; + + } + } + + private ArrayList affected = new ArrayList(); + + private int[] points = new int[20]; + private int nPoints; + + private void hit(Char ch, int damage) { + + if (damage < 1) { + return; + } + + affected.add(ch); + ch.damage(Level.water[ch.pos] && !ch.flying ? (int) (damage * 2) + : damage, this); + + ch.sprite.centerEmitter().burst(SparkParticle.FACTORY, 3); + ch.sprite.flash(); + + points[nPoints++] = ch.pos; + + HashSet ns = new HashSet(); + for (int i = 0; i < Level.NEIGHBOURS8.length; i++) { + Char n = Actor.findChar(ch.pos + Level.NEIGHBOURS8[i]); + if (n != null && !affected.contains(n)) { + ns.add(n); + } + } + + if (ns.size() > 0) { + hit(Random.element(ns), Random.Int(damage / 2, damage)); + } + } +} diff --git a/java/com/hmdzl/spspd/items/weapon/guns/GunA.java b/java/com/hmdzl/spspd/items/weapon/guns/GunA.java new file mode 100644 index 00000000..76ac6266 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/guns/GunA.java @@ -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 + */ +package com.hmdzl.spspd.items.weapon.guns; + +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class GunA extends GunWeapon { + + { + //name = "GunA"; + image = ItemSpriteSheet.GUN_A; + } + + public GunA() { + super(1,4); + } + +} diff --git a/java/com/hmdzl/spspd/items/weapon/guns/GunB.java b/java/com/hmdzl/spspd/items/weapon/guns/GunB.java new file mode 100644 index 00000000..b074deb9 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/guns/GunB.java @@ -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 + */ +package com.hmdzl.spspd.items.weapon.guns; + +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class GunB extends GunWeapon { + + { + //name = "GunB"; + image = ItemSpriteSheet.GUN_B; + } + + public GunB() { + super(2,4); + } + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/weapon/guns/GunC.java b/java/com/hmdzl/spspd/items/weapon/guns/GunC.java new file mode 100644 index 00000000..35932c1a --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/guns/GunC.java @@ -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 + */ +package com.hmdzl.spspd.items.weapon.guns; + +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class GunC extends GunWeapon { + + { + //name = "GunC"; + image = ItemSpriteSheet.GUN_C; + } + + public GunC() { + super(3,5); + } + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/weapon/guns/GunD.java b/java/com/hmdzl/spspd/items/weapon/guns/GunD.java new file mode 100644 index 00000000..f043b2b2 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/guns/GunD.java @@ -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 + */ +package com.hmdzl.spspd.items.weapon.guns; + +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class GunD extends GunWeapon { + + { + //name = "GunD"; + image = ItemSpriteSheet.GUN_D; + } + + public GunD() { + super(4,5); + } + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/weapon/guns/GunE.java b/java/com/hmdzl/spspd/items/weapon/guns/GunE.java new file mode 100644 index 00000000..5354d144 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/guns/GunE.java @@ -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 + */ +package com.hmdzl.spspd.items.weapon.guns; + +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class GunE extends GunWeapon { + + { + //name = "GunE"; + image = ItemSpriteSheet.GUN_E; + } + + public GunE() { + super(5,6); + } + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/weapon/guns/GunWeapon.java b/java/com/hmdzl/spspd/items/weapon/guns/GunWeapon.java new file mode 100644 index 00000000..48d09916 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/guns/GunWeapon.java @@ -0,0 +1,368 @@ +package com.hmdzl.spspd.items.weapon.guns; + + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.MechArmor; +import com.hmdzl.spspd.actors.buffs.TargetShoot; +import com.hmdzl.spspd.actors.buffs.Vertigo; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.hero.HeroSubClass; +import com.hmdzl.spspd.effects.Splash; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.rings.RingOfSharpshooting; +import com.hmdzl.spspd.items.wands.WandOfFlow; +import com.hmdzl.spspd.items.weapon.Weapon; +import com.hmdzl.spspd.items.weapon.missiles.MissileWeapon; +import com.hmdzl.spspd.items.weapon.spammo.SpAmmo; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.CellSelector; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.CharSprite; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; +import com.hmdzl.spspd.windows.WndBag; +import com.hmdzl.spspd.windows.WndOptions; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +import java.util.ArrayList; + +public class GunWeapon extends Weapon { + + public static final String AC_SHOOT = "SHOOT"; + public static final String AC_RELOAD = "RELOAD"; + public static final String AC_AMMO = "AMMO"; + + private int tier; + private int fullcharge; + // private Ammo ammo = null; + + private SpAmmo spammo; + + public int charge = 0; + public int maxcharge = fullcharge; + public int maxammo = 100; + + + + public GunWeapon(int tier /*int ammo*/ ,int fullcharge) { + super(); + + this.tier = tier; + + //AMMO = ammo + spammo = null; + this.fullcharge = fullcharge; + + STR = typicalSTR(); + + MIN = min(); + MAX = max(); + } + + private static final String SPAMMO = "spammo"; + private static final String CHARGE = "charge"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + if (spammo != null) bundle.put( SPAMMO, spammo ); + bundle.put( CHARGE, charge ); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + if (bundle.contains(SPAMMO)) spammo = (SpAmmo) bundle.get( SPAMMO ); + charge = bundle.getInt( CHARGE ); + } + + public GunWeapon(SpAmmo spammo) { + this.spammo = spammo; + } + + + private int min() { + return tier + 3; + } + + private int max() { + return (int) (tier * tier - tier + 8); + } + + public int typicalSTR() { + return 8 + tier * 2; + } + + public Item upgrade() { + MIN += 2; + MAX += 2 + tier/2; + maxammo += 10; + + return super.upgrade(); + } + + @Override + public int price() { + int price = 100 ; + if (enchantment != null) { + price *= 1.5; + } + if (cursed && cursedKnown) { + price /= 2; + } + if (levelKnown) { + if (level > 0) { + price *= (level + 1); + } else if (level < 0) { + price /= (1 - level); + } + } + if (price < 1) { + price = 1; + } + return price; + } + + { + image = ItemSpriteSheet.AMMO; + + defaultAction = AC_SHOOT; + usesTargeting = true; + } + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + //actions.remove(AC_EQUIP); + if (isEquipped(hero) || Dungeon.hero.subClass != HeroSubClass.AGENT){ + actions.add(AC_SHOOT); + } + actions.add(AC_RELOAD); + actions.add(AC_AMMO); + return actions; + } + + @Override + public void execute(Hero hero, String action) { + super.execute(hero, action); + if (action.equals(AC_SHOOT)) { + if (!isEquipped( hero ) && Dungeon.hero.subClass != HeroSubClass.AGENT) + GLog.i( Messages.get(ToyGun.class, "need_to_equip") ); + else if (charge<1){ + if ( maxammo < 1 ){ + GLog.n(Messages.get(ToyGun.class, "empty")); + } else { + if (durable() && maxammo > 0){ + maxammo = Math.max( maxammo - ( fullcharge - charge),0); + } + charge = Math.min(fullcharge,maxammo); + hero.sprite.showStatus(CharSprite.DEFAULT, Messages.get(this, "reloading")); + if (Dungeon.hero.subClass == HeroSubClass.AGENT){ hero.spendAndNext(1/2 * 1f);} + else hero.spendAndNext(fullcharge/2 * 1f); + } + } else GameScene.selectCell( shooter ); + } else if(action.equals(AC_RELOAD)){ + if (charge == fullcharge){ + GLog.n(Messages.get(ToyGun.class,"full")); + } else if ( maxammo < 1 ){ + GLog.n(Messages.get(ToyGun.class, "empty")); + } else { + if (durable() && maxammo > 0) { + maxammo = Math.max(maxammo - (fullcharge - charge), 0); + } + float reloadtime = (Dungeon.hero.subClass == HeroSubClass.AGENT ) ? 1/2 : (fullcharge - charge) / 2; + hero.spendAndNext(reloadtime * 1f); + hero.sprite.showStatus(CharSprite.DEFAULT, Messages.get(this, "reloading")); + charge = Math.min(fullcharge, maxammo); + } + } else if (action.equals(AC_AMMO)) { + curUser = hero; + GameScene.selectItem(itemSelector, WndBag.Mode.AMMO ,Messages.get(this, "prompt2")); + } + } + + @Override + public int damageRoll(Hero owner) { + return 0; + } + + public int damageRoll2(Hero owner) { + int damage = Random.Int(MIN, MAX); + + float bonus = 0; + for (Buff buff : owner.buffs(RingOfSharpshooting.Aim.class)) { + bonus += ((RingOfSharpshooting.Aim) buff).level; + } + if (Dungeon.hero.buff(TargetShoot.class)!= null) + bonus += 10; + if (Dungeon.hero.buff(MechArmor.class)!= null) + bonus += 10; + damage = (int)(damage*(1 + 0.05*bonus)); + return Math.round(damage); + } + + @Override + public void proc(Char attacker, Char defender, int damage) { + + int oppositeDefender = defender.pos + (defender.pos - attacker.pos); + Ballistica trajectory = new Ballistica(defender.pos, oppositeDefender, Ballistica.MAGIC_BOLT); + WandOfFlow.throwChar(defender, trajectory, 1); + Buff.prolong(defender, Vertigo.class,3f); + } + + @Override + public String info() { + String info = desc(); + + + info += "\n\n" + Messages.get(ToyGun.class, "stats_known", tier, MIN, MAX, STR); + + String stats_desc = Messages.get(this, "stats_desc"); + if (!stats_desc.equals("")) info+= "\n\n" + stats_desc; + //Messages.get(MeleeWeapon.class, "stats_known", tier, MIN, MAX,STR,ACU,DLY,RCH ) + + if (spammo != null){ + info += "\n" + Messages.get(GunWeapon.class, "ammo_add") + Messages.get(spammo,"name") ; + } + + if (reinforced) { + info += "\n" + Messages.get(Item.class, "reinforced"); + } + + info += "\n " + Messages.get(ToyGun.class, "charge", charge, fullcharge); + + return info; + } + + + @Override + public String status() { + if (levelKnown) { + return charge + "/" + fullcharge; + } else { + return null; + } + } + + public Item addSpAmmo(SpAmmo spammo, Char owner){ + + this.spammo = null; + + //GLog.p( Messages.get(this, "imbue", spammo.name())); + + this.spammo= spammo; + spammo.identify(); + spammo.cursed = false; + //name = Messages.get(spammo, "spammo_name"); + + updateQuickslot(); + + return this; + } + + private final WndBag.Listener itemSelector = new WndBag.Listener() { + @Override + public void onSelect( final Item item ) { + if (item != null) { + + GameScene.show( + new WndOptions("", + Messages.get(GunWeapon.class, "warning"), + Messages.get(GunWeapon.class, "yes"), + Messages.get(GunWeapon.class, "no")) { + @Override + protected void onSelect(int index) { + if (index == 0) { + Sample.INSTANCE.play(Assets.SND_EVOKE); + item.detach(curUser.belongings.backpack); + + addSpAmmo((SpAmmo) item, curUser); + + curUser.spendAndNext(2f); + + updateQuickslot(); + } + } + } + ); + } + } + }; + + private int targetPos; + + + + @Override + public boolean isUpgradable() { + return true; + } + + public NormalAmmo Ammo(){ + return new NormalAmmo(); + } + + public class NormalAmmo extends MissileWeapon { + + { + image = ItemSpriteSheet.AMMO; + STR = Math.max(typicalSTR(),Dungeon.hero.STR); + } + + public int damageRoll(Hero owner) { + return GunWeapon.this.damageRoll2(owner); + } + + @Override + protected void onThrow( int cell ) { + Char enemy = Actor.findChar( cell ); + if (enemy == null || enemy == curUser) { + parent = null; + Splash.at( cell, 0xCC99FFFF, 1 ); + } else { + if (!curUser.shoot( enemy, this )) { + Splash.at(cell, 0xCC99FFFF, 1); + } + } + } + + @Override + public void proc(Char attacker, Char defender, int damage) { + if (spammo != null) { + spammo.onHit(GunWeapon.this, attacker, defender, damage); + } + super.proc(attacker, defender, damage); + } + + int flurryCount = -1; + + @Override + public void cast(final Hero user, final int dst) { + final int cell = throwPos( user, dst ); + GunWeapon.this.targetPos = cell; + charge--; + super.cast(user, dst); + } + + } + + private CellSelector.Listener shooter = new CellSelector.Listener() { + @Override + public void onSelect( Integer target ) { + if (target != null) { + Ammo().cast(curUser, target); + } + } + @Override + public String prompt() { + return Messages.get(GunWeapon.class, "prompt"); + } + }; +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/weapon/guns/Sling.java b/java/com/hmdzl/spspd/items/weapon/guns/Sling.java new file mode 100644 index 00000000..59e9d34c --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/guns/Sling.java @@ -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 + */ +package com.hmdzl.spspd.items.weapon.guns; + +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.items.Item; +import com.watabou.utils.Random; + +public class Sling extends GunWeapon { + + { + //name = "Sling"; + image = ItemSpriteSheet.SLING; + } + + public Sling() { + super(0, 1); + STR = 8; + MIN = 3; + MAX = 7; + } + + public Item upgrade() { + MIN++; + MAX += 2; + return super.upgrade(); + } + + @Override + public int damageRoll(Hero owner) { + return Random.Int(MIN, MAX) / 2; + } +} + + + diff --git a/java/com/hmdzl/spspd/items/weapon/guns/ToyGun.java b/java/com/hmdzl/spspd/items/weapon/guns/ToyGun.java new file mode 100644 index 00000000..c56e1538 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/guns/ToyGun.java @@ -0,0 +1,293 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.weapon.guns; + +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.Splash; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.wands.WandOfFlow; +import com.hmdzl.spspd.items.weapon.Weapon; +import com.hmdzl.spspd.items.weapon.missiles.MissileWeapon; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.scenes.CellSelector; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.CharSprite; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; +import com.hmdzl.spspd.messages.Messages; + +import java.util.ArrayList; + +public class ToyGun extends Weapon { + + /*{ + //name = "ToyGun"; + + } + + public ToyGun() { + super(1); + }*/ + + public static final String AC_SHOOT = "SHOOT"; + public static final String AC_RELOAD = "RELOAD"; + + private int tier = 1; + + public int charge = 0; + public int maxammo = 100; + public int fullcharge = 10; + + public ToyGun() { + super(); + + this.tier = tier; + + //AMMO = ammo + + STR = typicalSTR(); + + MIN = min(); + MAX = max(); + + reinforced = true; + } + + + private int min() { + return 1; + } + + private int max() { + return 10; + } + + public int typicalSTR() { + return 10; + } + + public Item upgrade() { + MIN += 1; + MAX += 3; + maxammo += 10; + + return super.upgrade(); + } + + @Override + public int price() { + int price = 100 ; + if (enchantment != null) { + price *= 1.5; + } + if (cursed && cursedKnown) { + price /= 2; + } + if (levelKnown) { + if (level > 0) { + price *= (level + 1); + } else if (level < 0) { + price /= (1 - level); + } + } + if (price < 1) { + price = 1; + } + return price; + } + + { + image = ItemSpriteSheet.TOYGUN; + + defaultAction = AC_SHOOT; + usesTargeting = true; + + + } + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + //actions.remove(AC_EQUIP); + if (isEquipped(hero)){ + actions.add(AC_SHOOT); + actions.add(AC_RELOAD); + } + return actions; + } + + @Override + public void execute(Hero hero, String action) { + super.execute(hero, action); + if (action.equals(AC_SHOOT)) { + if (!isEquipped( hero )) + GLog.i( Messages.get(ToyGun.class, "need_to_equip") ); + else if (charge<1){ + if ( maxammo < 1 ){ + GLog.n(Messages.get(ToyGun.class, "empty")); + } else { + if (durable() && maxammo > 0){ + maxammo = Math.max( maxammo - ( fullcharge - charge),0); + } + charge = Math.min(fullcharge,maxammo); + hero.sprite.showStatus(CharSprite.DEFAULT, Messages.get(this, "reloading")); + hero.spendAndNext(3f); + } + } else GameScene.selectCell( shooter ); + } else if(action.equals(AC_RELOAD)){ + if (!isEquipped( hero )) + GLog.i( Messages.get(ToyGun.class, "need_to_equip") ); + else if (charge == fullcharge){ + GLog.n(Messages.get(ToyGun.class,"full")); + } else if ( maxammo < 1 ){ + GLog.n(Messages.get(ToyGun.class, "empty")); + } else { + if (durable() && maxammo > 0){ + maxammo = Math.max( maxammo - ( fullcharge - charge),0); + } + float reloadtime = (fullcharge - charge)/2; + hero.spendAndNext(reloadtime*1f); + hero.sprite.showStatus(CharSprite.DEFAULT, Messages.get(this, "reloading")); + charge = Math.min(fullcharge,maxammo); + + } + } + } + + private static final String CHARGE = "charge"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put( CHARGE, charge ); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + charge = bundle.getInt( CHARGE ); + } + + @Override + public int damageRoll(Hero owner) { + return 0; + } + + public int damageRoll2(Hero owner) { + return Random.Int(MAX,MIN); + } + + @Override + public void proc(Char attacker, Char defender, int damage) { + + int oppositeDefender = defender.pos + (defender.pos - attacker.pos); + Ballistica trajectory = new Ballistica(defender.pos, oppositeDefender, Ballistica.MAGIC_BOLT); + WandOfFlow.throwChar(defender, trajectory, 1); + } + + @Override + public String info() { + String info = desc(); + + + info += "\n\n" + Messages.get(ToyGun.class, "stats_known", tier, MIN, MAX, STR); + + String stats_desc = Messages.get(this, "stats_desc"); + if (!stats_desc.equals("")) info+= "\n\n" + stats_desc; + //Messages.get(MeleeWeapon.class, "stats_known", tier, MIN, MAX,STR,ACU,DLY,RCH ) + + if (reinforced) { + info += "\n" + Messages.get(Item.class, "reinforced"); + } + + info += "\n " + Messages.get(ToyGun.class, "charge", charge, fullcharge); + + return info; + } + + @Override + public String status() { + if (levelKnown) { + return charge + "/" + fullcharge; + } else { + return null; + } + } + + private int targetPos; + + @Override + public boolean isUpgradable() { + return true; + } + + public ToyAmmo Ammo(){ + return new ToyAmmo(); + } + + public class ToyAmmo extends MissileWeapon { + + { + image = ItemSpriteSheet.AMMO; + } + + public int damageRoll(Hero owner) { + return ToyGun.this.damageRoll2(owner); + } + + @Override + protected void onThrow( int cell ) { + Char enemy = Actor.findChar( cell ); + if (enemy == null || enemy == curUser) { + parent = null; + Splash.at( cell, 0xCC99FFFF, 1 ); + } else { + if (!curUser.shoot( enemy, this )) { + Splash.at(cell, 0xCC99FFFF, 1); + } + } + } + + int flurryCount = -1; + + @Override + public void cast(final Hero user, final int dst) { + final int cell = throwPos( user, dst ); + ToyGun.this.targetPos = cell; + charge--; + super.cast(user, dst); + } + } + + private CellSelector.Listener shooter = new CellSelector.Listener() { + @Override + public void onSelect( Integer target ) { + if (target != null) { + Ammo().cast(curUser, target); + } + } + @Override + public String prompt() { + return Messages.get(ToyGun.class, "prompt"); + } + }; +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/weapon/melee/AssassinsBlade.java b/java/com/hmdzl/spspd/items/weapon/melee/AssassinsBlade.java new file mode 100644 index 00000000..a28d3cce --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/melee/AssassinsBlade.java @@ -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 + */ +package com.hmdzl.spspd.items.weapon.melee; + +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Random; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.items.KindOfWeapon; +import com.hmdzl.spspd.messages.Messages; + +public class AssassinsBlade extends MeleeWeapon { + + { + //name = "AssassinsBlade"; + image = ItemSpriteSheet.ASSASSINSBLADE; + } + + public AssassinsBlade() { + super(4, 1f, 1f, 1); + } + + @Override + public Item upgrade(boolean enchant) { + MIN+=3; + MAX+=1; + return super.upgrade(enchant); + } + + @Override + public void proc(Char attacker, Char defender, int damage) { + int DMG = damage; + if (Random.Int(100) < 50 ){ + defender.damage(Random.Int(DMG/4,DMG/2), this); + } + if (enchantment != null) { + enchantment.proc(this, attacker, defender, damage); + } + if (durable() && attacker == Dungeon.hero){ + durable --; + if (durable == 10){ + GLog.n(Messages.get(KindOfWeapon.class,"almost_destory")); + } + if (durable == 0){ + Dungeon.hero.belongings.weapon = null; + GLog.n(Messages.get(KindOfWeapon.class,"destory")); + } + } + } +} diff --git a/java/com/hmdzl/spspd/items/weapon/melee/BattleAxe.java b/java/com/hmdzl/spspd/items/weapon/melee/BattleAxe.java new file mode 100644 index 00000000..d100bdc1 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/melee/BattleAxe.java @@ -0,0 +1,80 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.weapon.melee; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.KindOfWeapon; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Random; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Bleeding; + + +public class BattleAxe extends MeleeWeapon { + + { + //name = "battle axe"; + image = ItemSpriteSheet.BATTLE_AXE; + } + + public BattleAxe() { + super(4, 1f, 1f, 1); + } + + @Override + public Item upgrade(boolean enchant) { + + if (ACU < 1.2f){ + ACU+=0.05f; + } + + if (ACU > 1.2f && DLY > 0.9f) { + DLY-=0.05f; + } + + MAX+=6; + + return super.upgrade(enchant); + } + + @Override + public void proc(Char attacker, Char defender, int damage) { + + int DMG = damage; + if (Random.Int(100) < 20) { + Buff.affect(defender, Bleeding.class).set(Random.Int(4,DMG)); + } + if (enchantment != null) { + enchantment.proc(this, attacker, defender, damage); + } + if (durable() && attacker == Dungeon.hero){ + durable --; + if (durable == 10){ + GLog.n(Messages.get(KindOfWeapon.class,"almost_destory")); + } + if (durable == 0){ + Dungeon.hero.belongings.weapon = null; + GLog.n(Messages.get(KindOfWeapon.class,"destory")); + } + } + } +} diff --git a/java/com/hmdzl/spspd/items/weapon/melee/Club.java b/java/com/hmdzl/spspd/items/weapon/melee/Club.java new file mode 100644 index 00000000..e6e0fba1 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/melee/Club.java @@ -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 + */ +package com.hmdzl.spspd.items.weapon.melee; + +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Random; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Paralysis; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.items.KindOfWeapon; +import com.hmdzl.spspd.messages.Messages; + +public class Club extends MeleeWeapon { + + { + //name = "Club"; + image = ItemSpriteSheet.CLUB; + } + + public Club() { + super(4, 1f, 1f, 1); + } + + @Override + public Item upgrade(boolean enchant) { + + if (ACU < 1.50f){ + ACU+=0.05f; + } + + MIN+=3; + MAX+=1; + + return super.upgrade(enchant); + } + + @Override + public void proc(Char attacker, Char defender, int damage) { + + if (Random.Int(100) < 15) { + Buff.prolong(defender, Paralysis.class, 2); + } + + if (enchantment != null) { + enchantment.proc(this, attacker, defender, damage); + } + if (durable() && attacker == Dungeon.hero){ + durable --; + if (durable == 10){ + GLog.n(Messages.get(KindOfWeapon.class,"almost_destory")); + } + if (durable == 0){ + Dungeon.hero.belongings.weapon = null; + GLog.n(Messages.get(KindOfWeapon.class,"destory")); + } + } + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/weapon/melee/Dagger.java b/java/com/hmdzl/spspd/items/weapon/melee/Dagger.java new file mode 100644 index 00000000..8058b708 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/melee/Dagger.java @@ -0,0 +1,74 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.weapon.melee; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.items.KindOfWeapon; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Random; + +public class Dagger extends MeleeWeapon { + + { + //name = "dagger"; + image = ItemSpriteSheet.DAGGER; + } + + public Dagger() { + super(1, 1f, 1f, 1); + MIN = 1; + MAX = 10; + } + + @Override + public Item upgrade(boolean enchant) { + + if (ACU < 4f) { + ACU+=0.2f; + } + + MIN+=1; + MAX+=1; + + return super.upgrade(enchant); + } + + @Override + public void proc(Char attacker, Char defender, int damage) { + + int DMG = damage; + defender.damage(Random.Int(DMG/2,DMG/4*3), this); + if (enchantment != null) { + enchantment.proc(this, attacker, defender, damage); + } + if (durable() && attacker == Dungeon.hero){ + durable --; + if (durable == 10){ + GLog.n(Messages.get(KindOfWeapon.class,"almost_destory")); + } + if (durable == 0){ + Dungeon.hero.belongings.weapon = null; + GLog.n(Messages.get(KindOfWeapon.class,"destory")); + } + } + } +} diff --git a/java/com/hmdzl/spspd/items/weapon/melee/Dualknive.java b/java/com/hmdzl/spspd/items/weapon/melee/Dualknive.java new file mode 100644 index 00000000..8eca20b7 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/melee/Dualknive.java @@ -0,0 +1,84 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.weapon.melee; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.items.KindOfWeapon; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Random; + + +public class Dualknive extends MeleeWeapon { + + { + //name = "Dual Knive"; + image = ItemSpriteSheet.DKNIVE; + } + + public Dualknive(){ + super(2, 1f, 1f, 1); + } + + @Override + public Item upgrade(boolean enchant) { + + if (ACU < 1.2f) { + ACU+=0.05f; + } + + if (ACU > 1.2f && DLY > 0.8f){ + DLY-=0.05f; + } + + if (DLY < 0.8f && RCH < 2){ + RCH++; + } + + MIN+=2; + MAX+=1; + + return super.upgrade(enchant); + } + + @Override + public void proc(Char attacker, Char defender, int damage) { + + int DMG = damage; + + defender.damage(Random.Int(DMG/4,DMG/2), this); + + if (enchantment != null) { + enchantment.proc(this, attacker, defender, damage); + } + if (durable() && attacker == Dungeon.hero){ + durable --; + if (durable == 10){ + GLog.n(Messages.get(KindOfWeapon.class,"almost_destory")); + } + if (durable == 0){ + Dungeon.hero.belongings.weapon = null; + GLog.n(Messages.get(KindOfWeapon.class,"destory")); + } + } + } + +} diff --git a/java/com/hmdzl/spspd/items/weapon/melee/FightGloves.java b/java/com/hmdzl/spspd/items/weapon/melee/FightGloves.java new file mode 100644 index 00000000..de17b544 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/melee/FightGloves.java @@ -0,0 +1,81 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.weapon.melee; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.buffs.Paralysis; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.KindOfWeapon; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Random; + +public class FightGloves extends MeleeWeapon { + + { + //name = "FightGloves"; + image = ItemSpriteSheet.FIGHTGLOVES; + } + + public FightGloves() { + super(2, 1f, 1f, 1); + } + + @Override + public Item upgrade(boolean enchant) { + + if (ACU < 1.50f){ + ACU+=0.1f; + } + if (ACU > 1.45f && DLY> 0.55f){ + DLY-=0.1f; + } + if (DLY < 0.55f && RCH < 2){ + RCH ++; + } + MIN+=1; + MAX+=1; + + return super.upgrade(enchant); + } + + @Override + public void proc(Char attacker, Char defender, int damage) { + + if (Random.Int(100) < 40) { + Buff.prolong(defender, Paralysis.class, 2); + } + if (enchantment != null) { + enchantment.proc(this, attacker, defender, damage); + } + if (durable() && attacker == Dungeon.hero){ + durable --; + if (durable == 10){ + GLog.n(Messages.get(KindOfWeapon.class,"almost_destory")); + } + if (durable == 0){ + Dungeon.hero.belongings.weapon = null; + GLog.n(Messages.get(KindOfWeapon.class,"destory")); + } + } + } + +} diff --git a/java/com/hmdzl/spspd/items/weapon/melee/Flute.java b/java/com/hmdzl/spspd/items/weapon/melee/Flute.java new file mode 100644 index 00000000..e2b04bfa --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/melee/Flute.java @@ -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 + */ +package com.hmdzl.spspd.items.weapon.melee; + +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.KindOfWeapon; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.actors.Char; +import com.watabou.utils.Random; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.utils.GLog; + +public class Flute extends MeleeWeapon { + + { + //name = "Flute"; + image = ItemSpriteSheet.FLUTE; + } + + public Flute() { + super(2, 1f, 1f, 2); + } + + + @Override + public Item upgrade(boolean enchant) { + + if (ACU < 1.1f) { + ACU+=0.05f; + } + + if (ACU > 1.1f && DLY > 0.9f){ + DLY-=0.05f; + } + + if (DLY < 0.9f && RCH < 3){ + RCH++; + } + + MAX+=4; + return super.upgrade(enchant); + } + + @Override + public void proc(Char attacker, Char defender, int damage) { + + int p = defender.pos; + for (int n : Level.NEIGHBOURS8) { + Char ch = Actor.findChar(n+p); + if (ch != null && ch != defender && ch != attacker && ch.isAlive()) { + + int dr = Random.IntRange( 0, 1 ); + int dmg = Random.Int( MIN, MAX ); + int effectiveDamage = Math.max( dmg - dr, 0 ); + + ch.damage( effectiveDamage/2, attacker ); + } + } + + + if (enchantment != null) { + enchantment.proc(this, attacker, defender, damage); + } + + if (durable() && attacker == Dungeon.hero){ + durable --; + if (durable == 10){ + GLog.n(Messages.get(KindOfWeapon.class,"almost_destory")); + } + if (durable == 0){ + Dungeon.hero.belongings.weapon = null; + GLog.n(Messages.get(KindOfWeapon.class,"destory")); + } + } + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/weapon/melee/Glaive.java b/java/com/hmdzl/spspd/items/weapon/melee/Glaive.java new file mode 100644 index 00000000..e86e991b --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/melee/Glaive.java @@ -0,0 +1,74 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.weapon.melee; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.items.KindOfWeapon; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Cripple; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Random; + +public class Glaive extends MeleeWeapon { + + { + //name = "glaive"; + image = ItemSpriteSheet.GLAIVE; + } + + public Glaive() { + super(4, 1f, 1.75f, 2); + } + + @Override + public Item upgrade(boolean enchant) { + + if (DLY > 1.4f) { + DLY -=0.05f; + } + MIN += 1; + MAX += 6; + return super.upgrade(enchant); + } + + @Override + public void proc(Char attacker, Char defender, int damage) { + + if (Random.Int(100) < 20) { + Buff.affect(defender, Cripple.class, 3); + } + if (enchantment != null) { + enchantment.proc(this, attacker, defender, damage); + } + + if (durable() && attacker == Dungeon.hero){ + durable --; + if (durable == 10){ + GLog.n(Messages.get(KindOfWeapon.class,"almost_destory")); + } + if (durable == 0){ + Dungeon.hero.belongings.weapon = null; + GLog.n(Messages.get(KindOfWeapon.class,"destory")); + } + } + } +} diff --git a/java/com/hmdzl/spspd/items/weapon/melee/Gsword.java b/java/com/hmdzl/spspd/items/weapon/melee/Gsword.java new file mode 100644 index 00000000..89aabc14 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/melee/Gsword.java @@ -0,0 +1,73 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.weapon.melee; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.items.KindOfWeapon; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Random; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Bleeding; + + +public class Gsword extends MeleeWeapon { + + { + //name = "great sword"; + image = ItemSpriteSheet.GSWORD; + } + + public Gsword() { + super(5, 1f, 1f ,1); + } + + @Override + public Item upgrade(boolean enchant) { + MIN +=3; + MAX +=1; + return super.upgrade(enchant); + } + + @Override + public void proc(Char attacker, Char defender, int damage) { + + int DMG = damage; + if (Random.Int(100) < 10) { + Buff.affect(defender, Bleeding.class).set(Random.Int(5,DMG)); + } + if (enchantment != null) { + enchantment.proc(this, attacker, defender, damage); + } + + if (durable() && attacker == Dungeon.hero){ + durable --; + if (durable == 10){ + GLog.n(Messages.get(KindOfWeapon.class,"almost_destory")); + } + if (durable == 0){ + Dungeon.hero.belongings.weapon = null; + GLog.n(Messages.get(KindOfWeapon.class,"destory")); + } + } + } + +} diff --git a/java/com/hmdzl/spspd/items/weapon/melee/Halberd.java b/java/com/hmdzl/spspd/items/weapon/melee/Halberd.java new file mode 100644 index 00000000..5c01e290 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/melee/Halberd.java @@ -0,0 +1,74 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.weapon.melee; + +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Cripple; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Random; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.items.KindOfWeapon; +import com.hmdzl.spspd.messages.Messages; + +public class Halberd extends MeleeWeapon { + + { + //name = "halberd"; + image = ItemSpriteSheet.HALBERD; + } + + public Halberd() { + super(5, 1f, 2f ,2); + } + + @Override + public Item upgrade(boolean enchant) { + + if (DLY > 1.50f){ + DLY-=0.05f; + } + MAX+=5; + return super.upgrade(enchant); + } + + @Override + public void proc(Char attacker, Char defender, int damage) { + + if (Random.Int(100) < 10) { + Buff.affect(defender, Cripple.class, 3); + } + if (enchantment != null) { + enchantment.proc(this, attacker, defender, damage); + } + + if (durable() && attacker == Dungeon.hero){ + durable --; + if (durable == 10){ + GLog.n(Messages.get(KindOfWeapon.class,"almost_destory")); + } + if (durable == 0){ + Dungeon.hero.belongings.weapon = null; + GLog.n(Messages.get(KindOfWeapon.class,"destory")); + } + } + + } +} diff --git a/java/com/hmdzl/spspd/items/weapon/melee/Handaxe.java b/java/com/hmdzl/spspd/items/weapon/melee/Handaxe.java new file mode 100644 index 00000000..3f705d58 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/melee/Handaxe.java @@ -0,0 +1,80 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.weapon.melee; + +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Bleeding; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Random; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.items.KindOfWeapon; +import com.hmdzl.spspd.messages.Messages; + +public class Handaxe extends MeleeWeapon { + + { + //name = "hand axe"; + image = ItemSpriteSheet.HANDAXE; + } + + public Handaxe() { + super(2, 1f, 1f, 1); + } + + @Override + public Item upgrade(boolean enchant) { + + if (ACU < 1.5f){ + ACU+=0.1f; + } + + if (ACU > 1.4f && STR > 10) { + STR--; + } + + MIN+=2; + MAX+=3; + + return super.upgrade(enchant); + } + + @Override + public void proc(Char attacker, Char defender, int damage) { + + int DMG = damage; + if (Random.Int(100) < 40) { + Buff.affect(defender, Bleeding.class).set(Random.Int(2,DMG)); + } + if (enchantment != null) { + enchantment.proc(this, attacker, defender, damage); + } + if (durable() && attacker == Dungeon.hero){ + durable --; + if (durable == 10){ + GLog.n(Messages.get(KindOfWeapon.class,"almost_destory")); + } + if (durable == 0){ + Dungeon.hero.belongings.weapon = null; + GLog.n(Messages.get(KindOfWeapon.class,"destory")); + } + } + } +} diff --git a/java/com/hmdzl/spspd/items/weapon/melee/Harp.java b/java/com/hmdzl/spspd/items/weapon/melee/Harp.java new file mode 100644 index 00000000..7465a512 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/melee/Harp.java @@ -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 + */ +package com.hmdzl.spspd.items.weapon.melee; + +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.actors.Char; +import com.watabou.utils.Random; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.utils.GLog; +import com.hmdzl.spspd.items.KindOfWeapon; +import com.hmdzl.spspd.messages.Messages; + +public class Harp extends MeleeWeapon { + + { + //name = "Harp"; + image = ItemSpriteSheet.HARP; + } + + public Harp() { + super(5, 1f, 1f, 2); + } + + + @Override + public Item upgrade(boolean enchant) { + MIN+=4; + return super.upgrade(enchant); + } + + @Override + public void proc(Char attacker, Char defender, int damage) { + + int p = defender.pos; + for (int n : Level.NEIGHBOURS8) { + Char ch = Actor.findChar(n+p); + if (ch != null && ch != defender && ch != attacker && ch.isAlive()) { + + int dr = Random.IntRange( 0, 1 ); + int dmg = Random.Int( MIN, MAX ); + int effectiveDamage = Math.max( dmg - dr, 0 ); + + ch.damage( effectiveDamage/4, attacker ); + } + } + + if (enchantment != null) { + enchantment.proc(this, attacker, defender, damage); + } + if (durable() && attacker == Dungeon.hero){ + durable --; + if (durable == 10){ + GLog.n(Messages.get(KindOfWeapon.class,"almost_destory")); + } + if (durable == 0){ + Dungeon.hero.belongings.weapon = null; + GLog.n(Messages.get(KindOfWeapon.class,"destory")); + } + } + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/weapon/melee/HolyWater.java b/java/com/hmdzl/spspd/items/weapon/melee/HolyWater.java new file mode 100644 index 00000000..6ce97ad9 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/melee/HolyWater.java @@ -0,0 +1,111 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.weapon.melee; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.weapon.Weapon; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Bundle; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.items.KindOfWeapon; +import com.hmdzl.spspd.messages.Messages; + +public class HolyWater extends MeleeWeapon { + + { + //name = "holywater"; + image = ItemSpriteSheet.HOLY_WATER; + + + } + + public HolyWater() { + super(3, 0.8f, 1f, 1); + } + + public static int charge = 0; + private static final String CHARGE = "charge"; + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(CHARGE, charge); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + charge = bundle.getInt(CHARGE); + } + + + + @Override + public Item upgrade(boolean enchant) { + if (ACU < 1.2f) { + ACU+=0.05f; + } + + if (ACU > 1.2f && DLY > 0.8f){ + DLY-=0.05f; + } + + MIN+=2; + MAX+=1; + + return super.upgrade(enchant); + } + + + @Override + public void proc(Char attacker, Char defender, int damage) { + + int DMG = damage; + + if (charge >= 14) { + defender.damage(5*damage ,this); + attacker.HP += damage; + charge = 0; + } + + if (enchantment != null) { + enchantment.proc(this, attacker, defender, damage); + } + + charge++; + if (durable() && attacker == Dungeon.hero){ + durable --; + if (durable == 10){ + GLog.n(Messages.get(KindOfWeapon.class,"almost_destory")); + } + if (durable == 0){ + Dungeon.hero.belongings.weapon = null; + GLog.n(Messages.get(KindOfWeapon.class,"destory")); + } + } + } + + @Override + public String desc() { + String info = super.desc(); + + info += "\n\n" + Messages.get(Weapon.class, "charge",charge,14); + return info; + } +} diff --git a/java/com/hmdzl/spspd/items/weapon/melee/Knuckles.java b/java/com/hmdzl/spspd/items/weapon/melee/Knuckles.java new file mode 100644 index 00000000..fd462074 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/melee/Knuckles.java @@ -0,0 +1,77 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.weapon.melee; + +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Cripple; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Random; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.items.KindOfWeapon; +import com.hmdzl.spspd.messages.Messages; + +public class Knuckles extends MeleeWeapon { + + { + //name = "knuckleduster"; + image = ItemSpriteSheet.KNUCKLEDUSTER; + } + + public Knuckles() { + super(1, 1f, 1f, 1); + } + + @Override + public Item upgrade(boolean enchant) { + + if (DLY > 0.40f){ + DLY-=0.05f; + } + if (DLY < 0.45f && RCH < 2){ + RCH ++; + } + MIN+=1; + MAX+=1; + + return super.upgrade(enchant); + } + + @Override + public void proc(Char attacker, Char defender, int damage) { + + if (Random.Int(100) < 70) { + Buff.affect(defender, Cripple.class, 3); + } + if (enchantment != null) { + enchantment.proc(this, attacker, defender, damage); + } + if (durable() && attacker == Dungeon.hero){ + durable --; + if (durable == 10){ + GLog.n(Messages.get(KindOfWeapon.class,"almost_destory")); + } + if (durable == 0){ + Dungeon.hero.belongings.weapon = null; + GLog.n(Messages.get(KindOfWeapon.class,"destory")); + } + } + } +} diff --git a/java/com/hmdzl/spspd/items/weapon/melee/Lance.java b/java/com/hmdzl/spspd/items/weapon/melee/Lance.java new file mode 100644 index 00000000..f54c22a8 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/melee/Lance.java @@ -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 + */ +package com.hmdzl.spspd.items.weapon.melee; + +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Random; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.items.KindOfWeapon; +import com.hmdzl.spspd.messages.Messages; + +public class Lance extends MeleeWeapon { + + { + //name = "Lance"; + image = ItemSpriteSheet.LANCE; + } + + public Lance() { + super(5, 1f, 1f, 1); + } + + @Override + public Item upgrade(boolean enchant) { + MIN+=1; + MAX+=3; + return super.upgrade(enchant); + } + + @Override + public void proc(Char attacker, Char defender, int damage) { + + int DMG = damage; + if (Random.Int(4) == 0 ){ + defender.damage(Random.Int(DMG/4,DMG/2), this); + } + if (enchantment != null) { + enchantment.proc(this, attacker, defender, damage); + } + if (durable() && attacker == Dungeon.hero){ + durable --; + if (durable == 10){ + GLog.n(Messages.get(KindOfWeapon.class,"almost_destory")); + } + if (durable == 0){ + Dungeon.hero.belongings.weapon = null; + GLog.n(Messages.get(KindOfWeapon.class,"destory")); + } + } + + } +} diff --git a/java/com/hmdzl/spspd/items/weapon/melee/Mace.java b/java/com/hmdzl/spspd/items/weapon/melee/Mace.java new file mode 100644 index 00000000..dacdc446 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/melee/Mace.java @@ -0,0 +1,113 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.weapon.melee; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.weapon.Weapon; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Bundle; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.items.KindOfWeapon; +import com.hmdzl.spspd.messages.Messages; + +public class Mace extends MeleeWeapon { + + { + //name = "mace"; + image = ItemSpriteSheet.MACE; + + + } + + public Mace() { + super(2, 0.8f, 1f, 1); + } + + public static int charge = 0; + private static final String CHARGE = "charge"; + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(CHARGE, charge); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + charge = bundle.getInt(CHARGE); + } + + + + @Override + public Item upgrade(boolean enchant) { + if (ACU < 1.2f) { + ACU+=0.05f; + } + + if (ACU > 1.2f && DLY > 0.8f){ + DLY-=0.05f; + } + + if (DLY < 0.8f && RCH < 2){ + RCH++; + } + + MIN+=2; + MAX+=1; + return super.upgrade(enchant); + } + + + @Override + public void proc(Char attacker, Char defender, int damage) { + + int DMG = damage; + + if (charge >= 11) { + defender.damage(5*damage ,this); + charge = 0; + } + + if (enchantment != null) { + enchantment.proc(this, attacker, defender, damage); + } + + charge++; + if (durable() && attacker == Dungeon.hero){ + durable --; + if (durable == 10){ + GLog.n(Messages.get(KindOfWeapon.class,"almost_destory")); + } + if (durable == 0){ + Dungeon.hero.belongings.weapon = null; + GLog.n(Messages.get(KindOfWeapon.class,"destory")); + } + } + } + + @Override + public String desc() { + String info = super.desc(); + + info += "\n\n" + Messages.get(Weapon.class, "charge",charge,11); + return info; + } +} diff --git a/java/com/hmdzl/spspd/items/weapon/melee/MageBook.java b/java/com/hmdzl/spspd/items/weapon/melee/MageBook.java new file mode 100644 index 00000000..8c48df61 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/melee/MageBook.java @@ -0,0 +1,85 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.weapon.melee; + +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Paralysis; +import com.watabou.utils.Random; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.utils.GLog; +import com.hmdzl.spspd.items.KindOfWeapon; +import com.hmdzl.spspd.messages.Messages; + +public class MageBook extends MeleeWeapon { + + { + //name = "Mage Book"; + image = ItemSpriteSheet.MAGEBOOK; + + usesTargeting = true; + } + + public MageBook() { + super(1, 1f, 1f, 1); + MIN = 1; + MAX = 10; + } + + + @Override + public Item upgrade(boolean enchant) { + + if (STR > 1) { + STR --; + } + if (STR < 3 && RCH < 3 ) { + RCH ++; + } + MIN+=1; + MAX+=2; + return super.upgrade(enchant); + } + + @Override + public void proc(Char attacker, Char defender, int damage) { + /*if (wand != null && Dungeon.hero.subClass == HeroSubClass.BATTLEMAGE) { + if (wand.curCharges < wand.maxCharges) wand.curCharge += 0.33f; + ScrollOfRecharging.charge((Hero)attacker); + wand.onHit(this, attacker, defender, damage); + }*/ + if (Random.Int(100) < 50) { + Buff.prolong(defender, Paralysis.class, 2); + } + if (enchantment != null) { + enchantment.proc(this, attacker, defender, damage); + } + if (durable() && attacker == Dungeon.hero){ + durable --; + if (durable == 10){ + GLog.n(Messages.get(KindOfWeapon.class,"almost_destory")); + } + if (durable == 0){ + Dungeon.hero.belongings.weapon = null; + GLog.n(Messages.get(KindOfWeapon.class,"destory")); + } + } + } +} diff --git a/java/com/hmdzl/spspd/items/weapon/melee/MeleeWeapon.java b/java/com/hmdzl/spspd/items/weapon/melee/MeleeWeapon.java new file mode 100644 index 00000000..f1104871 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/melee/MeleeWeapon.java @@ -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 + */ +package com.hmdzl.spspd.items.weapon.melee; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.weapon.Weapon; +import com.hmdzl.spspd.messages.Messages; + +import com.watabou.utils.Random; + +import java.text.DecimalFormat; + +public class MeleeWeapon extends Weapon { + + private int tier; + + + public MeleeWeapon(int tier, float acu, float dly, int rch /*, int dur*/) { + super(); + + this.tier = tier; + + ACU = acu; + DLY = dly; + RCH = rch; + //DUR = 10; + + STR = typicalSTR(); + + MIN = min(); + MAX = max(); + } + + private int min() { + return tier; + } + + private int max() { + return (int) (((tier * tier - tier + 10) / ACU * DLY )/ (0.8 + 0.2*RCH) ); + } + + /*@Override + public void proc(Char attacker, Char defender, int damage) { + + if (enchantment != null) { + enchantment.proc(this, attacker, defender, damage); + } + + }*/ + + @Override + public Item upgrade() { + return upgrade(false); + } + + + public Item upgrade(boolean enchant) { + MIN++; + MAX += tier; + durable += 10; + + return super.upgrade(enchant); + } + + + public Item safeUpgrade() { + return upgrade(enchantment != null); + } + + public Item destory() { + return Dungeon.hero.belongings.weapon = null; + } + + @Override + public Item degrade() { + return super.degrade(); + } + + public int typicalSTR() { + return 8 + tier * 2; + } + + @Override + public String info() { + String name = name(); + + String info = desc(); + + if (levelKnown) { + info += "\n\n" + Messages.get(MeleeWeapon.class, "stats_known", tier, MIN, MAX, STR); + info += "\n\n" + Messages.get(MeleeWeapon.class, "stats_known2",new DecimalFormat("#.##").format(ACU), new DecimalFormat("#.##").format(DLY), RCH); + if (Dungeon.hero.STR() > typicalSTR()){ + info += " " + Messages.get(MeleeWeapon.class, "excess_str", Dungeon.hero.STR() - typicalSTR()); + } + } else { + info += "\n" + Messages.get(MeleeWeapon.class, "stats_unknown", tier, min(), max(), typicalSTR()); + } + + String stats_desc = Messages.get(this, "stats_desc"); + if (!stats_desc.equals("")) info+= " " + stats_desc; + + //Messages.get(MeleeWeapon.class, "stats_known", tier, MIN, MAX,STR,ACU,DLY,RCH ) + + if (enchantment != null) { + info += "\n" + Messages.get(MeleeWeapon.class, "enchanted", enchantment.desc()); + } + + if (reinforced) { + info += "\n" + Messages.get(Item.class, "reinforced"); + } + + if (levelKnown && STR() > Dungeon.hero.STR()) { + info += "\n" + Messages.get(MeleeWeapon.class, "too_heavy"); + } + + if (cursed && isEquipped( Dungeon.hero )) { + info += "\n\n" + Messages.get(MeleeWeapon.class, "cursed_worn"); + } else if (cursedKnown && cursed) { + info += "\n\n" + Messages.get(MeleeWeapon.class, "cursed"); + } + + return info; + } + + @Override + public int price() { + int price = 100 ; + if (enchantment != null) { + price *= 1.5; + } + if (cursed && cursedKnown) { + price /= 2; + } + if (levelKnown) { + if (level > 0) { + price *= (level + 1); + } else if (level < 0) { + price /= (1 - level); + } + } + if (price < 1) { + price = 1; + } + return price; + } + + @Override + public Item random() { + super.random(); + + if (Random.Int(10 + level) == 0) { + enchant(); + } + + return this; + } +} diff --git a/java/com/hmdzl/spspd/items/weapon/melee/Nunchakus.java b/java/com/hmdzl/spspd/items/weapon/melee/Nunchakus.java new file mode 100644 index 00000000..ef5ff36d --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/melee/Nunchakus.java @@ -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 + */ +package com.hmdzl.spspd.items.weapon.melee; + +import com.hmdzl.spspd.actors.buffs.Shieldblock; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Random; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.items.KindOfWeapon; +import com.hmdzl.spspd.messages.Messages; + +public class Nunchakus extends MeleeWeapon { + + { + //name = "Nunchakus"; + image = ItemSpriteSheet.NUNCHAKUS; + } + + public Nunchakus() { + super(3, 1f, 1f, 1); + } + + @Override + public Item upgrade(boolean enchant) { + + if (DLY > 0.75f){ + DLY-=0.05f; + } + + MIN+=3; + MAX+=1; + + return super.upgrade(enchant); + } + + @Override + public void proc(Char attacker, Char defender, int damage) { + + if (Random.Int(100) < 20) { + Buff.prolong(defender, Shieldblock.class, 2); + } + + if (enchantment != null) { + enchantment.proc(this, attacker, defender, damage); + } + if (durable() && attacker == Dungeon.hero){ + durable --; + if (durable == 10){ + GLog.n(Messages.get(KindOfWeapon.class,"almost_destory")); + } + if (durable == 0){ + Dungeon.hero.belongings.weapon = null; + GLog.n(Messages.get(KindOfWeapon.class,"destory")); + } + } + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/weapon/melee/PrayerWheel.java b/java/com/hmdzl/spspd/items/weapon/melee/PrayerWheel.java new file mode 100644 index 00000000..054b26ab --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/melee/PrayerWheel.java @@ -0,0 +1,109 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.weapon.melee; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.weapon.Weapon; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Bundle; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.items.KindOfWeapon; +import com.hmdzl.spspd.messages.Messages; + +public class PrayerWheel extends MeleeWeapon { + + { + //name = "prayerwheel"; + image = ItemSpriteSheet.PRAYER_WHEEL; + + + } + + public PrayerWheel() { + super(4, 0.8f, 1f, 1); + } + + public static int charge = 0; + private static final String CHARGE = "charge"; + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(CHARGE, charge); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + charge = bundle.getInt(CHARGE); + } + + + + @Override + public Item upgrade(boolean enchant) { + if (ACU < 1.2f) { + ACU+=0.05f; + } + + if (ACU > 1.2f && DLY > 0.8f){ + DLY-=0.05f; + } + MIN+=2; + MAX+=2; + + return super.upgrade(enchant); + } + + + @Override + public void proc(Char attacker, Char defender, int damage) { + + int DMG = damage; + + if (charge >= 17) { + defender.damage(5*damage ,this); + charge = 0; + } + + if (enchantment != null) { + enchantment.proc(this, attacker, defender, damage); + } + + charge++; + if (durable() && attacker == Dungeon.hero){ + durable --; + if (durable == 10){ + GLog.n(Messages.get(KindOfWeapon.class,"almost_destory")); + } + if (durable == 0){ + Dungeon.hero.belongings.weapon = null; + GLog.n(Messages.get(KindOfWeapon.class,"destory")); + } + } + } + + @Override + public String desc() { + String info = super.desc(); + + info += "\n\n" + Messages.get(Weapon.class, "charge",charge,17); + return info; + } +} diff --git a/java/com/hmdzl/spspd/items/weapon/melee/Rapier.java b/java/com/hmdzl/spspd/items/weapon/melee/Rapier.java new file mode 100644 index 00000000..06dcc796 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/melee/Rapier.java @@ -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 + */ +package com.hmdzl.spspd.items.weapon.melee; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.effects.Pushing; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Random; +import com.hmdzl.spspd.items.KindOfWeapon; +import com.hmdzl.spspd.messages.Messages; + +public class Rapier extends MeleeWeapon { + + { + //name = "Rapier"; + image = ItemSpriteSheet.RAPIER; + } + + public Rapier() { + super(3, 1f, 1f, 2); + } + + @Override + public Item upgrade(boolean enchant) { + + MAX+=4; + return super.upgrade(enchant); + } + + @Override + public void proc(Char attacker, Char defender, int damage) { + + Ballistica route = new Ballistica(attacker.pos, defender.pos, Ballistica.PROJECTILE); + int cell = route.collisionPos; + int dist = Level.distance(attacker.pos, cell); + if (dist == 2) { + cell = route.path.get(route.dist - 1); + Actor.addDelayed(new Pushing(attacker, attacker.pos, cell), -1); + attacker.pos = cell; + if (attacker instanceof Mob) { + Dungeon.level.mobPress((Mob) attacker); + } else { + Dungeon.level.press(cell, attacker); + } + defender.damage(damage,this); + } + + int DMG = damage; + if (Random.Int(100) < 75) { + defender.damage(Random.Int(DMG / 4, DMG / 2), this); + } + + if (enchantment != null) { + enchantment.proc(this, attacker, defender, damage); + } + if (durable() && attacker == Dungeon.hero){ + durable --; + if (durable == 10){ + GLog.n(Messages.get(KindOfWeapon.class,"almost_destory")); + } + if (durable == 0){ + Dungeon.hero.belongings.weapon = null; + GLog.n(Messages.get(KindOfWeapon.class,"destory")); + } + } + } +} diff --git a/java/com/hmdzl/spspd/items/weapon/melee/Scimitar.java b/java/com/hmdzl/spspd/items/weapon/melee/Scimitar.java new file mode 100644 index 00000000..844a2c84 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/melee/Scimitar.java @@ -0,0 +1,81 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.weapon.melee; + +import com.hmdzl.spspd.actors.buffs.ArmorBreak; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Bleeding; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Random; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.items.KindOfWeapon; +import com.hmdzl.spspd.messages.Messages; + +public class Scimitar extends MeleeWeapon { + + { + //name = "Scimitar"; + image = ItemSpriteSheet.SCIMITAR; + } + + public Scimitar() { + super(3, 1f, 1f, 1); + } + + @Override + public Item upgrade(boolean enchant) { + + if (ACU < 1.5f){ + ACU+=0.025f; + } + + if (DLY > 0.8f){ + DLY-=0.05f; + } + + MIN += 1; + MAX += 4; + return super.upgrade(enchant); + } + + @Override + public void proc(Char attacker, Char defender, int damage) { + + int DMG = damage; + if (Random.Int(100) < 30) { + Buff.affect(defender, Bleeding.class).set(Random.Int(3,DMG)); + Buff.affect(defender,ArmorBreak.class, 5f).level(30); + } + if (enchantment != null) { + enchantment.proc(this, attacker, defender, damage); + } + if (durable() && attacker == Dungeon.hero){ + durable --; + if (durable == 10){ + GLog.n(Messages.get(KindOfWeapon.class,"almost_destory")); + } + if (durable == 0){ + Dungeon.hero.belongings.weapon = null; + GLog.n(Messages.get(KindOfWeapon.class,"destory")); + } + } + } +} diff --git a/java/com/hmdzl/spspd/items/weapon/melee/ShortSword.java b/java/com/hmdzl/spspd/items/weapon/melee/ShortSword.java new file mode 100644 index 00000000..e5d20a2f --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/melee/ShortSword.java @@ -0,0 +1,74 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.weapon.melee; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Random; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Bleeding; +import com.hmdzl.spspd.items.KindOfWeapon; +import com.hmdzl.spspd.messages.Messages; + +public class ShortSword extends MeleeWeapon { + + { + //name = "short sword"; + image = ItemSpriteSheet.SHORT_SWORD; + + + } + + public ShortSword() { + super(1, 1f, 1f, 1); + } + + @Override + public Item upgrade(boolean enchant) { + MIN+=3; + MAX+=3; + return super.upgrade(enchant); + } + + + @Override + public void proc(Char attacker, Char defender, int damage) { + + int DMG = damage; + if (Random.Int(100) < 50) { + Buff.affect(defender, Bleeding.class).set(Random.Int(1,DMG)); + } + + if (enchantment != null) { + enchantment.proc(this, attacker, defender, damage); + } + if (durable() && attacker == Dungeon.hero){ + durable --; + if (durable == 10){ + GLog.n(Messages.get(KindOfWeapon.class,"almost_destory")); + } + if (durable == 0){ + Dungeon.hero.belongings.weapon = null; + GLog.n(Messages.get(KindOfWeapon.class,"destory")); + } + } + } +} diff --git a/java/com/hmdzl/spspd/items/weapon/melee/Spear.java b/java/com/hmdzl/spspd/items/weapon/melee/Spear.java new file mode 100644 index 00000000..cee84dac --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/melee/Spear.java @@ -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 + */ +package com.hmdzl.spspd.items.weapon.melee; + +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Cripple; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Random; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.items.KindOfWeapon; +import com.hmdzl.spspd.messages.Messages; + +public class Spear extends MeleeWeapon { + + { + //name = "spear"; + image = ItemSpriteSheet.SPEAR; + } + + public Spear() { + super(2, 1f, 1.5f, 2); + } + + @Override + public Item upgrade(boolean enchant) { + + if (DLY > 1.2f) { + DLY -= 0.05f ; + } + + if (DLY < 1.2f && RCH < 3) { + RCH ++ ; + } + + MIN+=1; + MAX+=4; + + return super.upgrade(enchant); + } + + @Override + public void proc(Char attacker, Char defender, int damage) { + + if (Random.Int(100) < 40) { + Buff.affect(defender, Cripple.class, 3); + } + if (enchantment != null) { + enchantment.proc(this, attacker, defender, damage); + } + if (durable() && attacker == Dungeon.hero){ + durable --; + if (durable == 10){ + GLog.n(Messages.get(KindOfWeapon.class,"almost_destory")); + } + if (durable == 0){ + Dungeon.hero.belongings.weapon = null; + GLog.n(Messages.get(KindOfWeapon.class,"destory")); + } + } + } +} diff --git a/java/com/hmdzl/spspd/items/weapon/melee/StoneCross.java b/java/com/hmdzl/spspd/items/weapon/melee/StoneCross.java new file mode 100644 index 00000000..2ce99db9 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/melee/StoneCross.java @@ -0,0 +1,109 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.weapon.melee; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.weapon.Weapon; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Bundle; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.items.KindOfWeapon; +import com.hmdzl.spspd.messages.Messages; + +public class StoneCross extends MeleeWeapon { + + { + //name = "stonecross"; + image = ItemSpriteSheet.STONE_CROSS; + + + } + + public StoneCross() { + super(5, 0.8f, 1f, 1); + } + + public static int charge = 0; + private static final String CHARGE = "charge"; + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(CHARGE, charge); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + charge = bundle.getInt(CHARGE); + } + + + + @Override + public Item upgrade(boolean enchant) { + if (ACU < 1.2f) { + ACU+=0.05f; + } + + if (ACU > 1.2f && DLY > 0.8f){ + DLY-=0.05f; + } + MIN+=1; + MAX+=2; + + return super.upgrade(enchant); + } + + + @Override + public void proc(Char attacker, Char defender, int damage) { + + int DMG = damage; + + if (charge >= 20) { + defender.damage(5*damage ,this); + charge = 0; + } + + if (enchantment != null) { + enchantment.proc(this, attacker, defender, damage); + } + + charge++; + if (durable() && attacker == Dungeon.hero){ + durable --; + if (durable == 10){ + GLog.n(Messages.get(KindOfWeapon.class,"almost_destory")); + } + if (durable == 0){ + Dungeon.hero.belongings.weapon = null; + GLog.n(Messages.get(KindOfWeapon.class,"destory")); + } + } + } + + @Override + public String desc() { + String info = super.desc(); + + info += "\n\n" + Messages.get(Weapon.class, "charge",charge,20); + return info; + } +} diff --git a/java/com/hmdzl/spspd/items/weapon/melee/Triangolo.java b/java/com/hmdzl/spspd/items/weapon/melee/Triangolo.java new file mode 100644 index 00000000..c80d34f6 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/melee/Triangolo.java @@ -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 + */ +package com.hmdzl.spspd.items.weapon.melee; + +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.actors.Char; +import com.watabou.utils.Random; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.utils.GLog; +import com.hmdzl.spspd.items.KindOfWeapon; +import com.hmdzl.spspd.messages.Messages; + +public class Triangolo extends MeleeWeapon { + + { + //name = "Triangolo"; + image = ItemSpriteSheet.TRIANGOLO; + } + + public Triangolo() { + super(1, 1f, 1f, 1); + MIN = 1; + MAX = 10; + } + + + @Override + public Item upgrade(boolean enchant) { + if (RCH < 4) { + RCH ++ ; + } + MIN+=1; + MAX+=1; + return super.upgrade(enchant); + } + + @Override + public void proc(Char attacker, Char defender, int damage) { + int p = defender.pos; + for (int n : Level.NEIGHBOURS8) { + Char ch = Actor.findChar(n+p); + if (ch != null && ch != defender && ch != attacker && ch.isAlive()) { + + int dr = Random.IntRange( 0, 1 ); + int dmg = Random.Int( MIN, MAX ); + int effectiveDamage = Math.max( dmg - dr, 0 ); + + ch.damage( effectiveDamage, attacker ); + } + } + if (enchantment != null) { + enchantment.proc(this, attacker, defender, damage); + } + if (durable() && attacker == Dungeon.hero){ + durable --; + if (durable == 10){ + GLog.n(Messages.get(KindOfWeapon.class,"almost_destory")); + } + if (durable == 0){ + Dungeon.hero.belongings.weapon = null; + GLog.n(Messages.get(KindOfWeapon.class,"destory")); + } + } + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/weapon/melee/Trumpet.java b/java/com/hmdzl/spspd/items/weapon/melee/Trumpet.java new file mode 100644 index 00000000..003eb485 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/melee/Trumpet.java @@ -0,0 +1,80 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.weapon.melee; + +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.actors.Char; +import com.watabou.utils.Random; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.utils.GLog; +import com.hmdzl.spspd.items.KindOfWeapon; + +public class Trumpet extends MeleeWeapon { + + { + //name = "Trumpet"; + image = ItemSpriteSheet.TRUMPET; + } + + public Trumpet() { + super(4, 1f, 1f, 2); + } + + + @Override + public Item upgrade(boolean enchant) { + MAX+=4; + return super.upgrade(enchant); + } + + @Override + public void proc(Char attacker, Char defender, int damage) { + + int p = defender.pos; + for (int n : Level.NEIGHBOURS8) { + Char ch = Actor.findChar(n+p); + if (ch != null && ch != defender && ch != attacker && ch.isAlive()) { + + int dr = Random.IntRange( 0, 1 ); + int dmg = Random.Int( MIN, MAX ); + int effectiveDamage = Math.max( dmg - dr, 0 ); + + ch.damage( effectiveDamage/3, attacker ); + } + } + + + if (enchantment != null) { + enchantment.proc(this, attacker, defender, damage); + } + if (durable() && attacker == Dungeon.hero){ + durable --; + if (durable == 10){ + GLog.n(Messages.get(KindOfWeapon.class,"almost_destory")); + } + if (durable == 0){ + Dungeon.hero.belongings.weapon = null; + GLog.n(Messages.get(KindOfWeapon.class,"destory")); + } + } + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/weapon/melee/WarHammer.java b/java/com/hmdzl/spspd/items/weapon/melee/WarHammer.java new file mode 100644 index 00000000..ce7575c7 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/melee/WarHammer.java @@ -0,0 +1,73 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.weapon.melee; + +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Paralysis; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Random; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.items.KindOfWeapon; + +public class WarHammer extends MeleeWeapon { + + { + //name = "war hammer"; + image = ItemSpriteSheet.WAR_HAMMER; + } + + public WarHammer() { + super(5, 1f, 1f ,1); + } + + @Override + public Item upgrade(boolean enchant) { + + if (ACU < 2f) { + ACU+=0.10f; + } + MIN +=1; + MAX +=3; + return super.upgrade(enchant); + } + + @Override + public void proc(Char attacker, Char defender, int damage) { + + if (Random.Int(100) < 10) { + Buff.prolong(defender, Paralysis.class, 2); + } + if (enchantment != null) { + enchantment.proc(this, attacker, defender, damage); + } + if (durable() && attacker == Dungeon.hero){ + durable --; + if (durable == 10){ + GLog.n(Messages.get(KindOfWeapon.class,"almost_destory")); + } + if (durable == 0){ + Dungeon.hero.belongings.weapon = null; + GLog.n(Messages.get(KindOfWeapon.class,"destory")); + } + } + } +} diff --git a/java/com/hmdzl/spspd/items/weapon/melee/Wardurm.java b/java/com/hmdzl/spspd/items/weapon/melee/Wardurm.java new file mode 100644 index 00000000..d988b143 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/melee/Wardurm.java @@ -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 + */ +package com.hmdzl.spspd.items.weapon.melee; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.buffs.Vertigo; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.KindOfWeapon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.buffs.Terror; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.watabou.utils.Random; +import com.hmdzl.spspd.utils.GLog; + +public class Wardurm extends MeleeWeapon { + + { + //name = "Wardurm"; + image = ItemSpriteSheet.WARDURM; + } + + public Wardurm() { + super(3, 1f, 1f, 2); + } + + + @Override + public Item upgrade(boolean enchant) { + MIN+=1; + MAX+=2; + return super.upgrade(enchant); + } + + @Override + public void proc(Char attacker, Char defender, int damage) { + + + int p = defender.pos; + for (int n : Level.NEIGHBOURS8) { + Char ch = Actor.findChar(n+p); + if (ch != null && ch != defender && ch != attacker && ch.isAlive()) { + + int dr = Random.IntRange( 0, 1 ); + int dmg = Random.Int( MIN, MAX ); + int effectiveDamage = Math.max( dmg - dr, 0 ); + + ch.damage( effectiveDamage/2, attacker ); + + Buff.prolong(ch, Vertigo.class, 3f); + Buff.prolong(ch, Terror.class, 3f).object = attacker.id(); + } + } + + + if (enchantment != null) { + enchantment.proc(this, attacker, defender, damage); + } + + if (durable() && attacker == Dungeon.hero){ + durable --; + if (durable == 10){ + GLog.n(Messages.get(KindOfWeapon.class,"almost_destory")); + } + if (durable == 0){ + Dungeon.hero.belongings.weapon = null; + GLog.n(Messages.get(KindOfWeapon.class,"destory")); + } + } + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/weapon/melee/Whip.java b/java/com/hmdzl/spspd/items/weapon/melee/Whip.java new file mode 100644 index 00000000..e479feb9 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/melee/Whip.java @@ -0,0 +1,78 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.weapon.melee; + +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Random; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Roots; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.items.KindOfWeapon; + + +public class Whip extends MeleeWeapon { + + { + //name = "Whip"; + image = ItemSpriteSheet.WHIP; + } + + public Whip() { + super(3, 1f, 1f, 2); + } + + @Override + public Item upgrade(boolean enchant) { + if (ACU <1.3){ + ACU+= 0.05; + } + + if (RCH < 3 && ACU >1.3){ + RCH++; + } + MIN+=1; + MAX+=2; + + return super.upgrade(enchant); + } + + @Override + public void proc(Char attacker, Char defender, int damage) { + + if (Random.Int(100) < 30) { + Buff.affect(defender, Roots.class, 1); + } + if (enchantment != null) { + enchantment.proc(this, attacker, defender, damage); + } + if (durable() && attacker == Dungeon.hero){ + durable --; + if (durable == 10){ + GLog.n(Messages.get(KindOfWeapon.class,"almost_destory")); + } + if (durable == 0){ + Dungeon.hero.belongings.weapon = null; + GLog.n(Messages.get(KindOfWeapon.class,"destory")); + } + } + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/weapon/melee/WoodenStaff.java b/java/com/hmdzl/spspd/items/weapon/melee/WoodenStaff.java new file mode 100644 index 00000000..0d5c9222 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/melee/WoodenStaff.java @@ -0,0 +1,111 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.weapon.melee; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.weapon.Weapon; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Bundle; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.items.KindOfWeapon; +import com.hmdzl.spspd.messages.Messages; + +public class WoodenStaff extends MeleeWeapon { + + { + //name = "WoodenStaff"; + image = ItemSpriteSheet.WOODEN_STAFF; + + } + + public WoodenStaff() { + super(1, 0.8f, 1f, 1); + MIN = 1; + MAX = 10; + } + + public static int charge = 0; + private static final String CHARGE = "charge"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(CHARGE, charge); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + charge = bundle.getInt(CHARGE); + } + + + + @Override + public Item upgrade(boolean enchant) { + if (ACU < 1.2f) { + ACU+=0.05f; + } + + if (ACU > 1.2f && DLY > 0.8f){ + DLY-=0.05f; + } + + MIN+=1; + MAX+=1; + return super.upgrade(enchant); + } + + + @Override + public void proc(Char attacker, Char defender, int damage) { + + int DMG = damage; + + if (charge >= 8) { + defender.damage(5*damage ,this); + charge = 0; + } + + if (enchantment != null) { + enchantment.proc(this, attacker, defender, damage); + } + + charge++; + if (durable() && attacker == Dungeon.hero){ + durable --; + if (durable == 10){ + GLog.n(Messages.get(KindOfWeapon.class,"almost_destory")); + } + if (durable == 0){ + Dungeon.hero.belongings.weapon = null; + GLog.n(Messages.get(KindOfWeapon.class,"destory")); + } + } + } + + @Override + public String desc() { + String info = super.desc(); + + info += "\n\n" + Messages.get(Weapon.class, "charge",charge,8); + return info; + } +} diff --git a/java/com/hmdzl/spspd/items/weapon/melee/block/GoblinShield.java b/java/com/hmdzl/spspd/items/weapon/melee/block/GoblinShield.java new file mode 100644 index 00000000..58eb5d71 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/melee/block/GoblinShield.java @@ -0,0 +1,186 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.weapon.melee.block; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.blobs.Blob; +import com.hmdzl.spspd.actors.blobs.ConfusionGas; +import com.hmdzl.spspd.actors.blobs.ParalyticGas; +import com.hmdzl.spspd.actors.blobs.TarGas; +import com.hmdzl.spspd.actors.blobs.ToxicGas; +import com.hmdzl.spspd.actors.buffs.Amok; +import com.hmdzl.spspd.actors.buffs.Blindness; +import com.hmdzl.spspd.actors.buffs.Burning; +import com.hmdzl.spspd.actors.buffs.Cripple; +import com.hmdzl.spspd.actors.buffs.Drowsy; +import com.hmdzl.spspd.actors.buffs.Frost; +import com.hmdzl.spspd.actors.buffs.MirrorShield; +import com.hmdzl.spspd.actors.buffs.Paralysis; +import com.hmdzl.spspd.actors.buffs.Recharging; +import com.hmdzl.spspd.actors.buffs.ShieldArmor; +import com.hmdzl.spspd.actors.buffs.Terror; +import com.hmdzl.spspd.actors.buffs.Vertigo; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.particles.PurpleParticle; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.wands.Wand; +import com.hmdzl.spspd.items.weapon.melee.MeleeWeapon; +import com.hmdzl.spspd.items.weapon.missiles.Boomerang; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.plants.Plant; +import com.hmdzl.spspd.scenes.CellSelector; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.sprites.MissileSprite; +import com.hmdzl.spspd.ui.QuickSlotButton; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Bundle; +import com.watabou.utils.Callback; +import com.watabou.utils.Random; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Bleeding; +import com.hmdzl.spspd.messages.Messages; + +public class GoblinShield extends MeleeWeapon { + + { + //name = "GoblinShield"; + image = ItemSpriteSheet.GOBLIN_SHIELD; + } + + public GoblinShield() { + super(3, 1f, 1f, 1); + } + + @Override + public Item upgrade(boolean enchant) { + MIN += 1; + MAX += 1; + return super.upgrade(enchant); + } + + public int charge = 0; + private static final String CHARGE = "charge"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(CHARGE, charge); + } + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + charge = bundle.getInt(CHARGE); + } + + + + @Override + public void proc(Char attacker, Char defender, int damage) { + + int DMG = damage; + + if (attacker.buff(ShieldArmor.class) == null){ + Buff.affect(attacker, ShieldArmor.class).level((int)(attacker.HT/8)); + } + + charge ++; + + if (charge > 10) { + charge = 0; + switch (Random.Int(16)) { + case 0: + break; + case 1: + Buff.affect(defender, Burning.class).reignite(defender); + break; + case 2: + Buff.affect(defender, Frost.class, 3f); + break; + case 3: + GameScene.add(Blob.seed(defender.pos, 20, TarGas.class)); + break; + case 4: + GameScene.add(Blob.seed(defender.pos, 30, ConfusionGas.class)); + break; + case 5: + GameScene.add(Blob.seed(defender.pos, 30, ToxicGas.class)); + break; + case 6: + GameScene.add(Blob.seed(defender.pos, 20, ParalyticGas.class)); + break; + case 7: + Buff.prolong(defender, Amok.class, 5f); + break; + + case 8: + Buff.affect(defender, Drowsy.class); + break; + + case 9: + Buff.affect(defender, Terror.class, Terror.DURATION).object = attacker.id(); + break; + + case 10: + Buff.prolong(defender, Paralysis.class, 3f); + break; + + case 11: + Buff.prolong(defender, Blindness.class, 5f); + break; + + case 12: + Dungeon.level.plant((Plant.Seed) Generator.random(Generator.Category.SEED), defender.pos); + break; + + case 13: + attacker.HP += Math.min(attacker.HT, attacker.HP + damage); + break; + case 14: + Buff.prolong(attacker, Recharging.class, 20f); + break; + case 15: + level++; + break; + } + + } + + if (enchantment != null) { + enchantment.proc(this, attacker, defender, damage); + } + + } + + + @Override + public String desc() { + String info = super.desc(); + + info += "\n\n" + Messages.get(this, "charge",charge); + return info; + } + + +} diff --git a/java/com/hmdzl/spspd/items/weapon/melee/block/SpKnuckles.java b/java/com/hmdzl/spspd/items/weapon/melee/block/SpKnuckles.java new file mode 100644 index 00000000..e32039e9 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/melee/block/SpKnuckles.java @@ -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 + */ +package com.hmdzl.spspd.items.weapon.melee.block; + +import com.hmdzl.spspd.actors.buffs.Paralysis; +import com.hmdzl.spspd.actors.buffs.ShieldArmor; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.weapon.melee.MeleeWeapon; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Cripple; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Random; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.items.KindOfWeapon; +import com.hmdzl.spspd.messages.Messages; + +public class SpKnuckles extends MeleeWeapon { + + { + //name = "knuckleduster"; + image = ItemSpriteSheet.SP_KNUCKLE; + } + + public SpKnuckles() { + super(1, 2f, 0.5f, 2); + MIN=1; + MAX=10; + } + + @Override + public Item upgrade(boolean enchant) { + + MIN+=1; + MAX+=2; + + return super.upgrade(enchant); + } + + @Override + public void proc(Char attacker, Char defender, int damage) { + + int DMG = damage; + + if (Random.Int(100) < 50) { + Buff.prolong(defender, Paralysis.class, 2); + } + + if (attacker.buff(ShieldArmor.class) == null){ + Buff.affect(attacker, ShieldArmor.class).level((int)(attacker.HT/10)); + } + + + if (enchantment != null) { + enchantment.proc(this, attacker, defender, damage); + } + + } +} diff --git a/java/com/hmdzl/spspd/items/weapon/melee/block/TenguSword.java b/java/com/hmdzl/spspd/items/weapon/melee/block/TenguSword.java new file mode 100644 index 00000000..c6efd98b --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/melee/block/TenguSword.java @@ -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 + */ +package com.hmdzl.spspd.items.weapon.melee.block; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.buffs.Cripple; +import com.hmdzl.spspd.actors.buffs.MirrorShield; +import com.hmdzl.spspd.actors.buffs.Paralysis; +import com.hmdzl.spspd.actors.buffs.ShieldArmor; +import com.hmdzl.spspd.actors.buffs.Vertigo; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.particles.PurpleParticle; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.wands.Wand; +import com.hmdzl.spspd.items.weapon.melee.MeleeWeapon; +import com.hmdzl.spspd.items.weapon.missiles.Boomerang; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.scenes.CellSelector; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.sprites.MissileSprite; +import com.hmdzl.spspd.ui.QuickSlotButton; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Bundle; +import com.watabou.utils.Callback; +import com.watabou.utils.Random; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Bleeding; +import com.hmdzl.spspd.messages.Messages; + +public class TenguSword extends MeleeWeapon { + + { + //name = "TenguSword"; + image = ItemSpriteSheet.TENGU_SWORD; + } + + public TenguSword() { + super(2, 1.2f, 0.8f, 1); + } + + @Override + public Item upgrade(boolean enchant) { + MIN += 1; + MAX += 2; + return super.upgrade(enchant); + } + + + @Override + public void proc(Char attacker, Char defender, int damage) { + + int DMG = damage; + + if (Random.Int(100) < 30) { + Buff.affect(defender, Bleeding.class).set(Random.Int(2,DMG)); + } + + if (Random.Int(100) < 10 && attacker.buff(ShieldArmor.class) == null) { + Buff.affect(attacker, ShieldArmor.class).level(DMG); + } + + if (enchantment != null) { + enchantment.proc(this, attacker, defender, damage); + } + + } + +} diff --git a/java/com/hmdzl/spspd/items/weapon/melee/relic/AresSword.java b/java/com/hmdzl/spspd/items/weapon/melee/relic/AresSword.java new file mode 100644 index 00000000..a74e1c05 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/melee/relic/AresSword.java @@ -0,0 +1,116 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.weapon.melee.relic; + +import java.util.ArrayList; + +import com.hmdzl.spspd.actors.buffs.BerryRegeneration; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.ui.BuffIndicator; + +public class AresSword extends RelicMeleeWeapon { + + public AresSword() { + super(6, 1f, 1f, 1); + // TODO Auto-generated constructor stub + } + + + { + //name = "Ares Sword"; + image = ItemSpriteSheet.ARESSWORD; + + level = 0; + exp = 0; + levelCap = 15; + + charge = 0; + chargeCap = 1000; + + cooldown = 0; + + + } + + public static final String AC_REGEN = "REGEN"; + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + if (isEquipped(hero) && charge >= chargeCap) + actions.add(AC_REGEN); + return actions; + } + + @Override + public void execute(Hero hero, String action) { + if (action.equals(AC_REGEN)) { + charge = 0; + Buff.affect(hero, BerryRegeneration.class).level(level); + } else + super.execute(hero, action); + } + + + public class RegenCounter extends WeaponBuff { + + @Override + public boolean act() { + if (charge < chargeCap) { + charge+=Math.min(level, 10); + updateQuickslot(); + } + spend(TICK); + return true; + } + + @Override + public String toString() { + return "Regen"; + } + + @Override + public int icon() { + if (cooldown == 0) + return BuffIndicator.NONE; + else + return BuffIndicator.NONE; + } + + @Override + public void detach() { + cooldown = 0; + charge = 0; + super.detach(); + } + + } + + + + + @Override + protected WeaponBuff passiveBuff() { + return new RegenCounter(); + } + +} + + diff --git a/java/com/hmdzl/spspd/items/weapon/melee/relic/CromCruachAxe.java b/java/com/hmdzl/spspd/items/weapon/melee/relic/CromCruachAxe.java new file mode 100644 index 00000000..80f0d704 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/melee/relic/CromCruachAxe.java @@ -0,0 +1,115 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.weapon.melee.relic; + +import java.util.ArrayList; + +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.MagicImmunity; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.ui.BuffIndicator; + +public class CromCruachAxe extends RelicMeleeWeapon { + + public CromCruachAxe() { + super(6, 1.2f, 1f, 1); + // TODO Auto-generated constructor stub + } + + + { + image = ItemSpriteSheet.CROMAXE; + + level = 0; + exp = 0; + levelCap = 15; + + charge = 0; + chargeCap = 1000; + + cooldown = 0; + + + } + + public static final String AC_DISPEL = "DISPEL"; + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + if (isEquipped(hero) && charge >= chargeCap) + actions.add(AC_DISPEL); + return actions; + } + + @Override + public void execute(Hero hero, String action) { + if (action.equals(AC_DISPEL)) { + charge = 0; + Buff.prolong(hero, MagicImmunity.class, 2f*(level/10)); + } else + super.execute(hero, action); + } + + + public class DispelCounter extends WeaponBuff { + + @Override + public boolean act() { + if (charge < chargeCap) { + charge+=Math.min(level, 10); + updateQuickslot(); + } + spend(TICK); + return true; + } + + @Override + public String toString() { + return "Dispel"; + } + + @Override + public int icon() { + if (cooldown == 0) + return BuffIndicator.NONE; + else + return BuffIndicator.NONE; + } + + @Override + public void detach() { + cooldown = 0; + charge = 0; + super.detach(); + } + + } + + + + + @Override + protected WeaponBuff passiveBuff() { + return new DispelCounter(); + } + +} + + diff --git a/java/com/hmdzl/spspd/items/weapon/melee/relic/JupitersWraith.java b/java/com/hmdzl/spspd/items/weapon/melee/relic/JupitersWraith.java new file mode 100644 index 00000000..c9e5a38f --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/melee/relic/JupitersWraith.java @@ -0,0 +1,165 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.weapon.melee.relic; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Paralysis; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.ui.BuffIndicator; + +import com.watabou.noosa.Camera; +import com.watabou.utils.Random; + +public class JupitersWraith extends RelicMeleeWeapon { + + public JupitersWraith() { + super(6, 1f, 1f, 4); + // TODO Auto-generated constructor stub + } + + { + //name = "jupiter's wraith"; + image = ItemSpriteSheet.JUPITERSWRAITH; + + level = 0; + exp = 0; + levelCap = 15; + + charge = 0; + chargeCap = 1000; + + cooldown = 0; + + } + + public static final String AC_EXPLODE = "EXPLODE"; + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + if (isEquipped(hero) && charge >= chargeCap) + actions.add(AC_EXPLODE); + return actions; + } + + @Override + public void execute(Hero hero, String action) { + if (action.equals(AC_EXPLODE)) { + int distance=distance(); + explode(distance, hero); + } else + super.execute(hero, action); + } + + + private int distance(){ + return Math.round(level/3)+1; + } + + private void explode(int distance, Hero hero) { + charge = 0; + int length = Level.getLength(); + int width = Level.getWidth(); + for (int i = width; i < length - width; i++){ + int dist = Level.distance(hero.pos, i); + if (dist 0) { + ch.damage(dmg, this); + if(Random.Int(3)==1 && ch.isAlive()){Buff.prolong(ch, Paralysis.class, 1);} + } + + } + + } + + + + public class ExplodeCharge extends WeaponBuff { + + @Override + public boolean act() { + if (charge < chargeCap) { + charge+=Math.min(level, 10); + updateQuickslot(); + } + spend(TICK); + return true; + } + + + @Override + public String toString() { + return "Explode"; + } + + @Override + public int icon() { + if (cooldown == 0) + return BuffIndicator.NONE; + else + return BuffIndicator.NONE; + } + + @Override + public void detach() { + cooldown = 0; + charge = 0; + super.detach(); + } + + } + + protected WeaponBuff passiveBuff() { + return new ExplodeCharge(); + } + +} diff --git a/java/com/hmdzl/spspd/items/weapon/melee/relic/LokisFlail.java b/java/com/hmdzl/spspd/items/weapon/melee/relic/LokisFlail.java new file mode 100644 index 00000000..553b5803 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/melee/relic/LokisFlail.java @@ -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 + */ +package com.hmdzl.spspd.items.weapon.melee.relic; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Shadows; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.ui.BuffIndicator; + +import com.watabou.noosa.audio.Sample; + +public class LokisFlail extends RelicMeleeWeapon { + + public LokisFlail() { + super(6, 0.8f, 1.2f, 2); + // TODO Auto-generated constructor stub + } + + + { + //name = "Loki's Flail"; + image = ItemSpriteSheet.LOKISFLAIL; + + level = 0; + exp = 0; + levelCap = 15; + + charge = 0; + chargeCap = 1000; + + cooldown = 0; + + + } + + public static final String AC_STEALTH = "STEALTH"; + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + if (isEquipped(hero) && charge >= chargeCap) + actions.add(AC_STEALTH); + return actions; + } + + @Override + public void execute(Hero hero, String action) { + if (action.equals(AC_STEALTH)) { + charge = 0; + Buff.affect(hero, Shadows.class, 10f); + Sample.INSTANCE.play(Assets.SND_MELD); + + } else + super.execute(hero, action); + } + + + public class StealthCounter extends WeaponBuff { + + @Override + public boolean act() { + if (charge < chargeCap) { + charge+=Math.min(level, 10); + updateQuickslot(); + } + spend(TICK); + return true; + } + + @Override + public String toString() { + return "StealthCounter"; + } + + @Override + public int icon() { + if (cooldown == 0) + return BuffIndicator.NONE; + else + return BuffIndicator.NONE; + } + + @Override + public void detach() { + cooldown = 0; + charge = 0; + super.detach(); + } + + } + + + + + @Override + protected WeaponBuff passiveBuff() { + return new StealthCounter(); + } + +} + + diff --git a/java/com/hmdzl/spspd/items/weapon/melee/relic/NeptunusTrident.java b/java/com/hmdzl/spspd/items/weapon/melee/relic/NeptunusTrident.java new file mode 100644 index 00000000..9be42546 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/melee/relic/NeptunusTrident.java @@ -0,0 +1,197 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.weapon.melee.relic; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Slow; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.Terrain; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.ui.BuffIndicator; + +public class NeptunusTrident extends RelicMeleeWeapon { + + public NeptunusTrident() { + super(6, 1f, 1f, 2); + // TODO Auto-generated constructor stub + } + + + { + //name = "Neptunus Trident"; + image = ItemSpriteSheet.TRIDENT; + + level = 0; + exp = 0; + levelCap = 15; + + charge = 0; + chargeCap = 1000; + + cooldown = 0; + + } + + + private int distance(){ + return Math.round(2); + } + + private void flood(int distance, Hero hero) { + charge = 0; + ArrayList affected = new ArrayList(); + + int length = Level.getLength(); + int width = Level.getWidth(); + for (int i = width; i < length - width; i++){ + int dist = Level.distance(hero.pos, i); + if (dist actions(Hero hero) { + ArrayList actions = super.actions(hero); + if (isEquipped(hero) && charge >= chargeCap) + actions.add(AC_FLOOD); + return actions; + } + + @Override + public void execute(Hero hero, String action) { + if (action.equals(AC_FLOOD)) { + int distance=distance(); + flood(distance, hero); + } else + super.execute(hero, action); + } + + + public class Flooding extends WeaponBuff { + + @Override + public boolean act() { + if (charge < chargeCap) { + charge+=Math.min(level, 10); + updateQuickslot(); + } + spend(TICK); + return true; + } + + + @Override + public String toString() { + return "Flooding"; + } + + @Override + public int icon() { + if (cooldown == 0) + return BuffIndicator.NONE; + else + return BuffIndicator.NONE; + } + + @Override + public void detach() { + cooldown = 0; + charge = 0; + super.detach(); + } + + } + + @Override + protected WeaponBuff passiveBuff() { + return new Flooding(); + } + +} + + diff --git a/java/com/hmdzl/spspd/items/weapon/melee/relic/RelicMeleeWeapon.java b/java/com/hmdzl/spspd/items/weapon/melee/relic/RelicMeleeWeapon.java new file mode 100644 index 00000000..6f81f1a3 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/melee/relic/RelicMeleeWeapon.java @@ -0,0 +1,273 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.weapon.melee.relic; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.weapon.Weapon; +import com.hmdzl.spspd.items.weapon.melee.MeleeWeapon; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.utils.GLog; + +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public class RelicMeleeWeapon extends Weapon { + + private int tier; + + private static final float TIME_TO_EQUIP = 1f; + + public Buff passiveBuff; + protected Buff activeBuff; + + // level is used internally to track upgrades to artifacts, size/logic + // varies per artifact. + // already inherited from item superclass + // exp is used to count progress towards levels for some artifacts + protected int exp = 0; + // levelCap is the artifact's maximum level + protected int levelCap = 0; + + // the current artifact charge + public int charge = 0; + + // the maximum charge, varies per artifact, not all artifacts use this. + public int chargeCap = 0; + + // used by some artifacts to keep track of duration of effects or cooldowns + // to use. + protected int cooldown = 0; + + public RelicMeleeWeapon(int tier, float acu, float dly, int rch) { + super(); + + this.tier = tier; + + ACU = acu; + DLY = dly; + RCH = rch; + + STR = typicalSTR(); + + MIN = min(); + MAX = max(); + reinforced = true; + + } + + private int min() { + return tier; + } + + private int max() { + return (int) (((tier * tier - tier + 10) / ACU * DLY)/(0.8+0.2*RCH)); + } + + @Override + public boolean doEquip(Hero hero) { + + activate(hero); + + return super.doEquip(hero); + + } + + + @Override + public void activate(Hero hero) { + passiveBuff = passiveBuff(); + passiveBuff.attachTo(hero); + } + + @Override + public boolean doUnequip(Hero hero, boolean collect, boolean single) { + + if (super.doUnequip(hero, collect, single)) { + + if (passiveBuff != null){ + passiveBuff.detach(); + passiveBuff = null; + } + + hero.belongings.weapon = null; + return true; + + } else { + + return false; + + } + } + + + protected WeaponBuff passiveBuff() { + return null; + } + + public class WeaponBuff extends Buff { + + public int level() { + return level; + } + + public boolean isCursed() { + return cursed; + } + + } + + @Override + public void proc(Char attacker, Char defender, int damage) { + + if (enchantment != null) { + enchantment.proc(this, attacker, defender, damage); + } + } + + + @Override + public Item upgrade() { + return upgrade(false); + } + + @Override + public Item upgrade(boolean enchant) { + + MIN+=2; + MAX+=5; + + if (enchant){ + GLog.i(Messages.get(this,"refuse")); + } + return super.upgrade(false); + + } + + public Item safeUpgrade() { + return upgrade(enchantment != null); + } + + + @Override + public Item degrade() { + MIN--; + MAX -= tier; + return super.degrade(); + } + + public int typicalSTR() { + return 8 + tier * 2; + } + + @Override + public String info() { + + String name = name(); + String info = desc(); + + if (levelKnown) { + info += "\n\n" + Messages.get(MeleeWeapon.class, "stats_known", tier, MIN, MAX, STR); + info += "\n\n" + Messages.get(MeleeWeapon.class, "stats_known2", ACU, DLY, RCH); +; if (Dungeon.hero.STR() > typicalSTR()){ + info += " " + Messages.get(MeleeWeapon.class, "excess_str", Dungeon.hero.STR() - typicalSTR()); + } + } else { + info += "\n\n" + Messages.get(MeleeWeapon.class, "stats_unknown", tier, min(), max(), typicalSTR()); + } + + String stats_desc = Messages.get(this, "stats_desc"); + if (!stats_desc.equals("")) info+= "\n\n" + stats_desc; + + //Messages.get(MeleeWeapon.class, "stats_known", tier, MIN, MAX,STR,ACU,DLY,RCH ) + + if (enchantment != null) { + info += "\n" + Messages.get(MeleeWeapon.class, "enchanted", enchantment.desc()); + } + + if (reinforced) { + info += "\n" + Messages.get(Item.class, "reinforced"); + } + + info += "\n " + Messages.get(Weapon.class, "charge", charge, chargeCap); + + if (levelKnown && STR() > Dungeon.hero.STR()) { + info += "\n" + Messages.get(MeleeWeapon.class, "too_heavy"); + } + + if (cursed && isEquipped( Dungeon.hero )) { + info += "\n\n" + Messages.get(MeleeWeapon.class, "cursed_worn"); + } else if (cursedKnown && cursed) { + info += "\n\n" + Messages.get(MeleeWeapon.class, "cursed"); + } + + return info; + } + + @Override + public int price() { + int price = 150; + if (enchantment != null) { + price *= 1.5; + } + if (cursed && cursedKnown) { + price /= 2; + } + if (levelKnown) { + if (level > 0) { + price *= (level + 1); + } else if (level < 0) { + price /= (1 - level); + } + } + if (price < 1) { + price = 1; + } + return price; + } + + @Override + public Item random() { + super.random(); + + if (Random.Int(10 + level) == 0) { + enchant(); + } + + return this; + } + + private static final String CHARGE = "charge"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(CHARGE, charge); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + charge = bundle.getInt(CHARGE); + } +} + + diff --git a/java/com/hmdzl/spspd/items/weapon/melee/special/Brick.java b/java/com/hmdzl/spspd/items/weapon/melee/special/Brick.java new file mode 100644 index 00000000..28604fa8 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/melee/special/Brick.java @@ -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 + */ +package com.hmdzl.spspd.items.weapon.melee.special; + +import com.hmdzl.spspd.actors.buffs.Shieldblock; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.items.KindOfWeapon; +import com.hmdzl.spspd.items.weapon.melee.MeleeWeapon; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.watabou.utils.Random; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.utils.GLog; + +public class Brick extends MeleeWeapon { + + { + //name = "Brick"; + image = ItemSpriteSheet.W_BRICK; + + usesTargeting = true; + } + + public Brick() { + super(1, 1f, 1f, 1); + MIN = 8; + MAX = 8; + } + + + @Override + public void proc(Char attacker, Char defender, int damage) { + + if (Random.Int(100) < 40) { + Buff.prolong(defender, Shieldblock.class, 2); + } + + if (enchantment != null) { + enchantment.proc(this, attacker, defender, damage); + } + if (Random.Int(80) ==1 ){ + + Dungeon.hero.belongings.weapon = null; + GLog.n(Messages.get(KindOfWeapon.class,"destory")); + Dungeon.level.drop(Generator.random(), defender.pos).sprite.drop(); + Dungeon.level.drop(Generator.random(), defender.pos).sprite.drop(); + Dungeon.level.drop(Generator.random(), defender.pos).sprite.drop(); + } + } + +} diff --git a/java/com/hmdzl/spspd/items/weapon/melee/special/DiamondPickaxe.java b/java/com/hmdzl/spspd/items/weapon/melee/special/DiamondPickaxe.java new file mode 100644 index 00000000..d5dc0917 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/melee/special/DiamondPickaxe.java @@ -0,0 +1,291 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.weapon.melee.special; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Hunger; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.effects.particles.ShadowParticle; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.weapon.melee.MeleeWeapon; +import com.hmdzl.spspd.items.weapon.missiles.buildblock.BookBlock; +import com.hmdzl.spspd.items.weapon.missiles.buildblock.DoorBlock; +import com.hmdzl.spspd.items.weapon.missiles.buildblock.StoneBlock; +import com.hmdzl.spspd.items.weapon.missiles.buildblock.WallBlock; +import com.hmdzl.spspd.items.weapon.missiles.buildblock.WoodenBlock; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.Terrain; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.ui.BuffIndicator; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Callback; +import com.watabou.utils.Random; + +public class DiamondPickaxe extends MeleeWeapon { + + public static final String AC_MINE = "MINE"; + + public static final float TIME_TO_MINE = 10; + + { + //name = "pickaxe"; + image = ItemSpriteSheet.DIAMOND_PICKAXE; + defaultAction = AC_MINE; + } + + public DiamondPickaxe() { + super(3, 2f, 0.5f, 2); + MIN = 2; + MAX = 8; + unique = true; + reinforced = true; + } + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + actions.add(AC_MINE); + return actions; + } + + @Override + public void execute(final Hero hero, String action) { + + if (action == AC_MINE) { + if (Random.Int(3) == 0) { + for (Mob mob : Dungeon.level.mobs.toArray(new Mob[0])) { + mob.beckon(hero.pos); + } + GLog.n(Messages.get(this,"noise")); + } + for (int i = 0; i < Level.NEIGHBOURS8.length; i++) { + + final int pos = hero.pos + Level.NEIGHBOURS8[i]; + if (Dungeon.level.map[pos] == Terrain.WALL && Level.insideMap(pos)) { + + hero.spend(TIME_TO_MINE); + hero.busy(); + + hero.sprite.attack(pos, new Callback() { + + @Override + public void call() { + + CellEmitter.center(pos).burst( + Speck.factory(Speck.STAR), 7); + Sample.INSTANCE.play(Assets.SND_EVOKE); + + Level.set(pos, Terrain.EMBERS); + GameScene.updateMap(pos); + + WallBlock wall = new WallBlock(); + + Dungeon.level.drop(wall, hero.pos).sprite.drop(); + + Hunger hunger = hero.buff(Hunger.class); + if (hunger != null && !hunger.isStarving()) { + hunger.satisfy(-10); + BuffIndicator.refreshHero(); + } + + hero.onOperateComplete(); + } + }); + + return; + } else if (Dungeon.level.map[pos] == Terrain.DOOR && Level.insideMap(pos)) { + + hero.spend(TIME_TO_MINE); + hero.busy(); + + hero.sprite.attack(pos, new Callback() { + + @Override + public void call() { + + CellEmitter.center(pos).burst( + Speck.factory(Speck.STAR), 7); + Sample.INSTANCE.play(Assets.SND_EVOKE); + + Level.set(pos, Terrain.EMBERS); + GameScene.updateMap(pos); + + DoorBlock door = new DoorBlock(); + + Dungeon.level.drop(door, hero.pos).sprite.drop(); + + Hunger hunger = hero.buff(Hunger.class); + if (hunger != null && !hunger.isStarving()) { + hunger.satisfy(-10); + BuffIndicator.refreshHero(); + } + + hero.onOperateComplete(); + } + }); + + return; + } else if (Dungeon.level.map[pos] == Terrain.BOOKSHELF && Level.insideMap(pos)) { + + hero.spend(TIME_TO_MINE); + hero.busy(); + + hero.sprite.attack(pos, new Callback() { + + @Override + public void call() { + + CellEmitter.center(pos).burst( + Speck.factory(Speck.STAR), 7); + Sample.INSTANCE.play(Assets.SND_EVOKE); + + Level.set(pos, Terrain.EMBERS); + GameScene.updateMap(pos); + + BookBlock book = new BookBlock(); + + Dungeon.level.drop(book, hero.pos).sprite.drop(); + + Hunger hunger = hero.buff(Hunger.class); + if (hunger != null && !hunger.isStarving()) { + hunger.satisfy(-10); + BuffIndicator.refreshHero(); + } + + hero.onOperateComplete(); + } + }); + + return; + } else if (Dungeon.level.map[pos] == Terrain.BARRICADE && Level.insideMap(pos)) { + + hero.spend(TIME_TO_MINE); + hero.busy(); + + hero.sprite.attack(pos, new Callback() { + + @Override + public void call() { + + CellEmitter.center(pos).burst( + Speck.factory(Speck.STAR), 7); + Sample.INSTANCE.play(Assets.SND_EVOKE); + + Level.set(pos, Terrain.EMBERS); + GameScene.updateMap(pos); + + WoodenBlock wooden = new WoodenBlock(); + + Dungeon.level.drop(wooden, hero.pos).sprite.drop(); + + Hunger hunger = hero.buff(Hunger.class); + if (hunger != null && !hunger.isStarving()) { + hunger.satisfy(-10); + BuffIndicator.refreshHero(); + } + + hero.onOperateComplete(); + } + }); + + return; + } else if (Dungeon.level.map[pos] == Terrain.STATUE && Level.insideMap(pos)) { + + hero.spend(TIME_TO_MINE); + hero.busy(); + + hero.sprite.attack(pos, new Callback() { + + @Override + public void call() { + + CellEmitter.center(pos).burst( + Speck.factory(Speck.STAR), 7); + Sample.INSTANCE.play(Assets.SND_EVOKE); + + Level.set(pos, Terrain.EMBERS); + GameScene.updateMap(pos); + + StoneBlock stone = new StoneBlock(); + + Dungeon.level.drop(stone, hero.pos).sprite.drop(); + + Hunger hunger = hero.buff(Hunger.class); + if (hunger != null && !hunger.isStarving()) { + hunger.satisfy(-10); + BuffIndicator.refreshHero(); + } + + hero.onOperateComplete(); + } + }); + + return; + } + } + GLog.w(Messages.get(this,"no_thing")); + } else { + + super.execute(hero, action); + + } + } + + public Item upgrade(boolean enchant) { + + MIN+=1; + MAX+=1; + super.upgrade(enchant); + return this; + } + + @Override + public void proc(Char attacker, Char defender, int damage) { + + if (Random.Int(10) < 1 && !(defender.properties().contains(Char.Property.BOSS)) && !(defender.properties().contains(Char.Property.MINIBOSS))) { + defender.damage(Random.Int(defender.HP/4, defender.HP/2), this); + defender.sprite.emitter().burst(ShadowParticle.UP, 5); + if (!defender.isAlive() && attacker instanceof Hero) { + Badges.validateGrimWeapon(); + } + } + if (enchantment != null) { + enchantment.proc(this, attacker, defender, damage); + } + if ( defender.HP <= damage && Random.Int(12) == 0) { + Dungeon.level.drop(Generator.random(), defender.pos).sprite.drop(); + } + } + + /*@Override + public String info() { + return "This is a large and sturdy tool for breaking rocks. Probably it can be used as a weapon."; + }*/ +} diff --git a/java/com/hmdzl/spspd/items/weapon/melee/special/ErrorW.java b/java/com/hmdzl/spspd/items/weapon/melee/special/ErrorW.java new file mode 100644 index 00000000..260749fb --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/melee/special/ErrorW.java @@ -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 + */ +package com.hmdzl.spspd.items.weapon.melee.special; + +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.particles.ShadowParticle; +import com.hmdzl.spspd.items.weapon.melee.MeleeWeapon; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Cripple; +import com.hmdzl.spspd.actors.buffs.Bleeding; +import com.hmdzl.spspd.actors.buffs.Terror; +import com.hmdzl.spspd.actors.buffs.Vertigo; +import com.hmdzl.spspd.actors.buffs.Paralysis; +import com.hmdzl.spspd.actors.buffs.Roots; +import com.hmdzl.spspd.actors.buffs.Ooze; +import com.hmdzl.spspd.actors.buffs.Charm; +import com.watabou.utils.Random; + +public class ErrorW extends MeleeWeapon { + + { + //name = "Error Weapon"; + image = ItemSpriteSheet.ERROR_WEAPON; + + STR = 0; + MIN = 0; + MAX = 0; + } + + public ErrorW() { + super(0, 1f, 1f, 1); + } + + @Override + public Item upgrade(boolean enchant) { + MIN --; + + if (Random.Int(10) > 4 || ACU < 0.5f ){ + ACU += 0.1f; + } else{ + ACU -= 0.1f; + } + + if (Random.Int(10) > 4 || DLY < 0.5f){ + DLY += 0.05f; + } else { + DLY -= 0.05f; + } + + return super.upgrade(enchant); + } + + @Override + public void proc(Char attacker, Char defender, int damage) { + + switch (Random.Int (10)) { + case 0 : + if (defender.properties().contains(Char.Property.BOSS) || defender.properties().contains(Char.Property.MINIBOSS)){ + defender.damage(Random.Int(defender.HT/8, defender.HT/4), this);} + else defender.damage(Random.Int(defender.HT, defender.HT * 2), this); + defender.sprite.emitter().burst(ShadowParticle.UP, 5); + if (!defender.isAlive() && attacker instanceof Hero) { + Badges.validateGrimWeapon(); + } + break; + case 1 : + Buff.affect(defender, Cripple.class, 3); + break; + case 2 : + Buff.affect(defender, Bleeding.class).set(5); + break; + case 3 : + Buff.affect(defender, Vertigo.class, Vertigo.duration(defender)); + Buff.affect(defender, Terror.class, Terror.DURATION).object = attacker.id(); + break; + case 4 : + Buff.affect(defender, Paralysis.class, 3); + break; + case 5 : + Buff.affect(defender, Roots.class, 3); + break; + case 6 : + if (attacker.HP < attacker.HT){ + attacker.HP += (int)((attacker.HT)/10); + attacker.sprite.emitter().start(Speck.factory(Speck.HEALING), 0.4f,1);} + break; + case 7 : + Buff.affect(defender, Ooze.class); + break; + case 8 : + Buff.affect(defender, Charm.class, 3 ).object = attacker.id(); + break; + default: + break; + } + + if (enchantment != null) { + enchantment.proc(this, attacker, defender, damage); + } + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/weapon/melee/special/FireCracker.java b/java/com/hmdzl/spspd/items/weapon/melee/special/FireCracker.java new file mode 100644 index 00000000..d294b753 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/melee/special/FireCracker.java @@ -0,0 +1,102 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.weapon.melee.special; + +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.buffs.Terror; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.actors.mobs.YearBeast; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.particles.SmokeParticle; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.weapon.melee.MeleeWeapon; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.watabou.utils.Random; +import com.hmdzl.spspd.Dungeon; + +public class FireCracker extends MeleeWeapon { + + { + //name = "FireCracker"; + image = ItemSpriteSheet.FIRECRACKER; + + usesTargeting = true; + } + + public FireCracker() { + super(1, 1f, 1f, 2); + MIN = 1; + MAX = 5; + } + + + @Override + public Item upgrade(boolean enchant) { + + return super.upgrade(enchant); + } + + @Override + public void proc(Char attacker, Char defender, int damage) { + + if (defender instanceof YearBeast) { + defender.damage(1,this); + } + + if (Random.Int(100)> 75) { + for (Mob mob : Dungeon.level.mobs.toArray(new Mob[0])) { + mob.beckon(attacker.pos); + } + } + + if (Random.Int(100)> 50 ){ + for (int n : Level.NEIGHBOURS9) { + int c = defender.pos + n; + if (c >= 0 && c < Level.getLength()) { + if (Dungeon.visible[c]) { + CellEmitter.get(c).burst(SmokeParticle.FACTORY, 4); + } + Char ch = Actor.findChar(c); + if (ch != null) { + // those not at the center of the blast take damage less + // consistently. + int minDamage = ch.HT/40; + int maxDamage = ch.HT/20; + + int dmg = Random.NormalIntRange(minDamage, maxDamage) + - Math.max(ch.drRoll(),0); + if (dmg > 0) { + ch.damage(dmg, this); + } + } + } + } + } + + if (Random.Int(100)> 70) { + Buff.affect(defender,Terror.class,5f).object = attacker.id(); + } + + if (enchantment != null) { + enchantment.proc(this, attacker, defender, damage); + } + } +} diff --git a/java/com/hmdzl/spspd/items/weapon/melee/special/Goei.java b/java/com/hmdzl/spspd/items/weapon/melee/special/Goei.java new file mode 100644 index 00000000..c6c909dc --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/melee/special/Goei.java @@ -0,0 +1,80 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.weapon.melee.special; + +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.weapon.Weapon; +import com.hmdzl.spspd.items.weapon.melee.MeleeWeapon; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.watabou.utils.Bundle; + +public class Goei extends MeleeWeapon { + public Buff passiveBuff; + { + //name = "goei"; + image = ItemSpriteSheet.GOEI; + + } + public Goei() { + super(3, 1f, 1f, 2); + MIN = 4; + MAX = 15; + } + + public int charge = 0; + private static final String CHARGE = "charge"; + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(CHARGE, charge); + } + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + charge = bundle.getInt(CHARGE); + } + + @Override + public Item upgrade(boolean enchant) { + return super.upgrade(enchant); + } + @Override + public void proc(Char attacker, Char defender, int damage) { + if (charge >= 5) { + defender.damage(damage ,this); + charge = 0; + } + if (defender.properties().contains(Char.Property.DEMONIC) || defender.properties().contains(Char.Property.UNDEAD)){ + defender.damage((int)(damage*0.35),this); + } + if (enchantment != null) { + enchantment.proc(this, attacker, defender, damage); + } + charge++; + } + @Override + public String desc() { + String info = super.desc(); + + info += "\n\n" + Messages.get(Weapon.class, "charge",charge,30); + return info; + } +} diff --git a/java/com/hmdzl/spspd/items/weapon/melee/special/Handcannon.java b/java/com/hmdzl/spspd/items/weapon/melee/special/Handcannon.java new file mode 100644 index 00000000..302cff77 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/melee/special/Handcannon.java @@ -0,0 +1,99 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.weapon.melee.special; + +import java.util.ArrayList; + +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.weapon.melee.MeleeWeapon; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Bundle; + +public class Handcannon extends MeleeWeapon { + + { + //name = "Handcannon"; + image = ItemSpriteSheet.HANDCANNON; + + } + + public Boolean turnedOn = false; + public static final String AC_ON = "ON"; + public static final String AC_OFF = "OFF"; + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + if(turnedOn){actions.add(AC_OFF);}else{actions.add(AC_ON);} + return actions; + } + + @Override + public void execute(final Hero hero, String action) { + if (action.equals(AC_ON)) { + turnedOn=true; + GLog.i(Messages.get(this, "power_on")); + hero.next(); + + } else if (action.equals(AC_OFF)) { + turnedOn=false; + GLog.i(Messages.get(this, "power_off")); + hero.next(); + } else { + super.execute(hero, action); + } + } + + + @Override + public Item upgrade() { + return upgrade(false); + } + + @Override + public Item upgrade(boolean enchant) { + + return super.upgrade(false); + } + + public Item safeUpgrade() { + return upgrade(enchantment != null); + } + + public Handcannon() { + super(4, 0.7f, 2f, 7); + } + + private static final String TURNEDON = "turnedOn"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(TURNEDON, turnedOn); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + turnedOn = bundle.getBoolean(TURNEDON); + } + +} diff --git a/java/com/hmdzl/spspd/items/weapon/melee/special/HookHam.java b/java/com/hmdzl/spspd/items/weapon/melee/special/HookHam.java new file mode 100644 index 00000000..21f49a42 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/melee/special/HookHam.java @@ -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 + */ +package com.hmdzl.spspd.items.weapon.melee.special; + +import com.hmdzl.spspd.actors.buffs.Bleeding; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.weapon.melee.MeleeWeapon; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.watabou.utils.Random; +import com.hmdzl.spspd.Dungeon; + +public class HookHam extends MeleeWeapon { + + { + //name = "hook&ham"; + image = ItemSpriteSheet.HOOK_HAM; + + usesTargeting = true; + } + + public HookHam() { + super(1, 1f, 1f, 1); + MIN = 1; + MAX = 5; + } + + + @Override + public Item upgrade(boolean enchant) { + + return super.upgrade(enchant); + } + + @Override + public void proc(Char attacker, Char defender, int damage) { + + int DMG = damage; + if (Random.Int(100)> 40){ + Buff.affect(defender, Bleeding.class).set(Random.Int(5,DMG)); + } + + if (Random.Int(100) < 20) { + if (attacker.HP < attacker.HT){ + attacker.HP += 10; + attacker.sprite.emitter().start(Speck.factory(Speck.HEALING), 0.4f,1);} + } + + if (Random.Int(100)==98){ + Dungeon.level.drop(Generator.random(), defender.pos).sprite.drop(); + } + + if (enchantment != null) { + enchantment.proc(this, attacker, defender, damage); + } + } +} diff --git a/java/com/hmdzl/spspd/items/weapon/melee/special/KeyWeapon.java b/java/com/hmdzl/spspd/items/weapon/melee/special/KeyWeapon.java new file mode 100644 index 00000000..534226f0 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/melee/special/KeyWeapon.java @@ -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 + */ +package com.hmdzl.spspd.items.weapon.melee.special; + +import com.hmdzl.spspd.actors.buffs.Amok; +import com.hmdzl.spspd.actors.buffs.Charm; +import com.hmdzl.spspd.actors.buffs.Terror; +import com.hmdzl.spspd.items.weapon.melee.MeleeWeapon; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Paralysis; +import com.watabou.utils.Random; + +public class KeyWeapon extends MeleeWeapon { + + { + //name = "keyweapon"; + image = ItemSpriteSheet.ANCIENTKEY; + + } + + public KeyWeapon() { + super(1, 1f, 1f, 1); + MIN = 1; + MAX = 10; + } + + + @Override + public void proc(Char attacker, Char defender, int damage) { + + if (Random.Int(100) < 40) { + Buff.prolong(defender, Paralysis.class, 2); + } + + int DMG = damage; + if (Random.Int(100) < 40) { + defender.damage(Random.Int(DMG/2,DMG/4*3), this); + } + + if (Random.Int(100) < 40) { + Buff.affect(defender, Charm.class,5f).object = attacker.id(); + Buff.affect(defender, Terror.class,5f).object = attacker.id(); + Buff.affect(defender, Amok.class,5f); + } + + if (enchantment != null) { + enchantment.proc(this, attacker, defender, damage); + } + + } + +} diff --git a/java/com/hmdzl/spspd/items/weapon/melee/special/LinkSword.java b/java/com/hmdzl/spspd/items/weapon/melee/special/LinkSword.java new file mode 100644 index 00000000..44dda0e5 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/melee/special/LinkSword.java @@ -0,0 +1,316 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.weapon.melee.special; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.buffs.Cripple; +import com.hmdzl.spspd.actors.buffs.MirrorShield; +import com.hmdzl.spspd.actors.buffs.Paralysis; +import com.hmdzl.spspd.actors.buffs.ShieldArmor; +import com.hmdzl.spspd.actors.buffs.Vertigo; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.particles.PurpleParticle; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.wands.Wand; +import com.hmdzl.spspd.items.weapon.melee.MeleeWeapon; +import com.hmdzl.spspd.items.weapon.missiles.Boomerang; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.scenes.CellSelector; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.sprites.MissileSprite; +import com.hmdzl.spspd.ui.QuickSlotButton; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Bundle; +import com.watabou.utils.Callback; +import com.watabou.utils.Random; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Bleeding; +import com.hmdzl.spspd.messages.Messages; + +public class LinkSword extends MeleeWeapon { + public Buff passiveBuff; + { + //name = "LinkSword"; + image = ItemSpriteSheet.S_AND_S; + defaultAction = AC_COURAGE; + usesTargeting = true; + } + + public LinkSword() { + super(1, 1f, 1f, 1); + unique = true; + reinforced = true; + } + + @Override + public Item upgrade(boolean enchant) { + MIN += 1; + MAX += 3; + return super.upgrade(enchant); + } + + public final int fullCharge = 30; + public int charge = 0; + private static final String CHARGE = "charge"; + + public static final String AC_POWER = "POWER"; + public static final String AC_WISDOM = "WISDOM"; + public static final String AC_COURAGE = "COURAGE"; + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + + actions.add(AC_COURAGE); + + if (charge > 20) { + actions.add(AC_WISDOM); + } + if (Dungeon.hero.STR - this.STR >2) { + actions.add(AC_POWER); + } + return actions; + } + + @Override + public void execute(Hero hero, String action) { + if (action == AC_POWER) { + curUser = hero; + STR +=2; + if (ACU < 1.6f){ + ACU+=0.1f; + } + if (DLY > 0.7f){ + DLY-=0.05; + } + MIN+=1; + MAX+=STR; + GLog.w(Messages.get(LinkSword.class,"power")); + curUser.sprite.operate(curUser.pos); + curUser.sprite.centerEmitter().start(PurpleParticle.BURST, 0.05f, 10); + curUser.spendAndNext(1f); + } else if (action == AC_WISDOM) { + curUser = hero; + Buff.affect(hero, MirrorShield.class,2f); + curUser.sprite.operate(curUser.pos); + curUser.spendAndNext(1f); + charge=0; + } else if (action == AC_COURAGE) { + curUser = hero; + curItem = this; + GameScene.selectCell( zapper ); + } else { + + super.execute(hero, action); + + } + } + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(CHARGE, charge); + } + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + charge = bundle.getInt(CHARGE); + } + protected LinkBuff passiveBuff() { + return new LinkCharge(); + } + public class LinkBuff extends Buff { + public int level() { + return level; + } + public boolean isCursed() { + return cursed; + } + } + @Override + public boolean doEquip(Hero hero) { + activate(hero); + return super.doEquip(hero); + } + @Override + public void activate(Hero hero) { + passiveBuff = passiveBuff(); + passiveBuff.attachTo(hero); + } + @Override + public boolean doUnequip(Hero hero, boolean collect, boolean single) { + if (super.doUnequip(hero, collect, single)) { + if (passiveBuff != null){ + passiveBuff.detach(); + passiveBuff = null; + } + hero.belongings.weapon = null; + return true; + } else { + return false; + } + } + public class LinkCharge extends LinkBuff { + @Override + public boolean act() { + if (charge < fullCharge) { + charge+=1; + } + if (Dungeon.hero.HP>=Dungeon.hero.HT){ + LinkSword.this.RCH = 4; + } else LinkSword.this.RCH = 1; + spend(TICK); + return true; + } + @Override + public String toString() { + return "LinkCharge"; + } + @Override + public void detach() { + charge = 0; + super.detach(); + } + } + + @Override + public void proc(Char attacker, Char defender, int damage) { + + int DMG = damage; + if (Random.Int(100) > 50) { + switch (Random.Int(7)) { + case 0: + defender.damage(Random.Int(DMG / 4, DMG / 2), this); + break; + case 1: + Buff.affect(defender, Bleeding.class).set(Random.Int(3, DMG)); + break; + case 2: + Buff.prolong(defender, Paralysis.class, 2); + break; + case 3: + Buff.affect(defender, Cripple.class, 3); + break; + case 4: + int p = attacker.pos; + for (int n : Level.NEIGHBOURS8) { + Char ch = Actor.findChar(n + p); + if (ch != null && ch != defender && ch != attacker && ch.isAlive()) { + + int dr = Random.IntRange(0, 1); + int dmg = Random.Int(MIN, MAX); + int effectiveDamage = Math.max(dmg - dr, 0); + + ch.damage(effectiveDamage / 2, this); + } + } + break; + case 5: + if (attacker.buff(ShieldArmor.class) == null){ + Buff.affect(attacker, ShieldArmor.class).level((int)(attacker.HT/10)); + } + break; + case 6: + if (charge > 25) { + charge -=15; + defender.damage(5*DMG, this); + } + break; + default: + break; + } + + if (enchantment != null) { + enchantment.proc(this, attacker, defender, damage); + } + if ( defender.HP <= damage && Random.Int(10) == 0) { + Dungeon.level.drop(Generator.random(Generator.Category.LINKDROP), defender.pos).sprite.drop(); + } + } + } + + @Override + public String desc() { + String info = super.desc(); + + info += "\n\n" + Messages.get(this, "charge",charge,fullCharge); + return info; + } + + protected static CellSelector.Listener zapper = new CellSelector.Listener() { + + @Override + public void onSelect(final Integer target ) { + Item proto = new Boomerang(); + if (target != null) { + + final LinkSword ls = (LinkSword) LinkSword.curItem; + + final Ballistica shot = new Ballistica( curUser.pos, target, Ballistica.MAGIC_BOLT); + int cell = shot.collisionPos; + + if (target == curUser.pos || cell == curUser.pos) { + GLog.i( Messages.get(Wand.class, "self_target") ); + return; + } + + curUser.sprite.zap(cell); + + //attempts to target the cell aimed at if something is there, otherwise targets the collision pos. + if (Actor.findChar(target) != null) + QuickSlotButton.target(Actor.findChar(target)); + else + QuickSlotButton.target(Actor.findChar(cell)); + + if (ls.charge >= 0) { + + curUser.busy(); + Callback callback = new Callback() { + @Override + public void call() { + Char ch = Actor.findChar(target); + if (ch != null) { + if (ch.isAlive() && Random.Int(2) == 0) { + Buff.affect(ch, Vertigo.class, 5f); + } + ch.damage((int) (ch.HT / 20), this); + } + } + }; + ((MissileSprite) curUser.sprite.parent.recycle(MissileSprite.class)).reset(curUser.pos, target, proto,callback); + Dungeon.hero.spendAndNext(1.5f); + } else { + GLog.w( Messages.get(Wand.class, "fizzles") ); + } + + } + } + + @Override + public String prompt() { + return Messages.get(Wand.class, "prompt"); + } + }; +} diff --git a/java/com/hmdzl/spspd/items/weapon/melee/special/Lollipop.java b/java/com/hmdzl/spspd/items/weapon/melee/special/Lollipop.java new file mode 100644 index 00000000..6778520c --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/melee/special/Lollipop.java @@ -0,0 +1,73 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.weapon.melee.special; + +import com.hmdzl.spspd.actors.buffs.Charm; +import com.hmdzl.spspd.actors.buffs.Shieldblock; +import com.hmdzl.spspd.actors.buffs.Tar; +import com.hmdzl.spspd.actors.buffs.Weakness; +import com.hmdzl.spspd.items.KindOfWeapon; +import com.hmdzl.spspd.items.weapon.melee.MeleeWeapon; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.watabou.utils.Random; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.utils.GLog; + +public class Lollipop extends MeleeWeapon { + + { + //name = "Lollipop"; + image = ItemSpriteSheet.LOLLIPOP; + + usesTargeting = true; + } + + public Lollipop() { + super(1, 1f, 1f, 1); + MIN = 50; + MAX = 50; + } + + + @Override + public void proc(Char attacker, Char defender, int damage) { + + if (Random.Int(100) < 40) { + Buff.affect(defender, Tar.class); + } + + if (Random.Int(100) < 60) { + Buff.affect(defender, Charm.class,5f).object = attacker.id(); + } + + if (enchantment != null) { + enchantment.proc(this, attacker, defender, damage); + } + if (Random.Int(50) == 1 ){ + Buff.prolong(attacker, Shieldblock.class, 5f); + Buff.prolong(attacker, Weakness.class, 20f); + attacker.HT -= Math.min(15,attacker.HT-1); + Dungeon.hero.belongings.weapon = null; + GLog.n(Messages.get(KindOfWeapon.class,"destory")); + } + } + +} diff --git a/java/com/hmdzl/spspd/items/weapon/melee/special/Pumpkin.java b/java/com/hmdzl/spspd/items/weapon/melee/special/Pumpkin.java new file mode 100644 index 00000000..0ca2828e --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/melee/special/Pumpkin.java @@ -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 + */ +package com.hmdzl.spspd.items.weapon.melee.special; + +import com.hmdzl.spspd.actors.buffs.Burning; +import com.hmdzl.spspd.actors.buffs.Light; +import com.hmdzl.spspd.actors.buffs.Terror; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.effects.particles.FlameParticle; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.weapon.melee.MeleeWeapon; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.watabou.utils.Random; + +public class Pumpkin extends MeleeWeapon { + + { + //name = "Pumpkin Lamp"; + image = ItemSpriteSheet.PUMPKIN; + + usesTargeting = true; + } + + public Pumpkin() { + super(1, 1f, 1f, 1); + MIN = 1; + MAX = 5; + } + + + @Override + public Item upgrade(boolean enchant) { + + return super.upgrade(enchant); + } + + @Override + public void proc(Char attacker, Char defender, int damage) { + + if (Random.Int(100) < 20) { + Buff.affect(defender, Burning.class).reignite(defender); + defender.damage(Random.Int(1, level + 2), this); + defender.sprite.emitter().burst(FlameParticle.FACTORY, level + 1); + } + if (Random.Int(100) < 20) { + Buff.affect(defender, Terror.class, 3); + } + if (Random.Int(100) < 20) { + if (attacker.HP < attacker.HT){ + attacker.HP += 10; + attacker.sprite.emitter().start(Speck.factory(Speck.HEALING), 0.4f,1);} + } + Buff.prolong(attacker, Light.class, 50f); + if (enchantment != null) { + enchantment.proc(this, attacker, defender, damage); + } + } +} diff --git a/java/com/hmdzl/spspd/items/weapon/melee/special/RunicBlade.java b/java/com/hmdzl/spspd/items/weapon/melee/special/RunicBlade.java new file mode 100644 index 00000000..6c15cd72 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/melee/special/RunicBlade.java @@ -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 + */ +package com.hmdzl.spspd.items.weapon.melee.special; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.scrolls.ScrollOfUpgrade; +import com.hmdzl.spspd.items.weapon.melee.MeleeWeapon; +import com.hmdzl.spspd.items.weapon.missiles.Boomerang; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; +import com.hmdzl.spspd.windows.WndBag; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Random; + +public class RunicBlade extends MeleeWeapon { + + public static final String AC_REFORGE = "REFORGE"; + + private static final String TXT_SELECT_WEAPON = "Select a weapon to upgrade"; + + private static final String TXT_REFORGED = "you reforged the short sword to upgrade your %s"; + private static final String TXT_NOT_BOOMERANG = "you can't upgrade a boomerang this way"; + + private static final float TIME_TO_REFORGE = 2f; + + private boolean equipped; + + private float upgradeChance = 0.9f; + + { + //name = "Runic Blade"; + image = ItemSpriteSheet.RUNICBLADE; + } + + public RunicBlade() { + super(5, 1f, 1f,1); + + MIN = 0; + MAX = 35; + + } + + @Override + public Item upgrade(boolean enchant) { + + if (STR > 1 ){ + STR--;} + MIN--; + MAX+=10; + + return super.upgrade(enchant); + } + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + if (level > 0) { + actions.add(AC_REFORGE); + } + return actions; + } + + @Override + public void execute(Hero hero, String action) { + if (action == AC_REFORGE) { + + if (hero.belongings.weapon == this) { + equipped = true; + hero.belongings.weapon = null; + } else { + equipped = false; + detach(hero.belongings.backpack); + } + + curUser = hero; + + GameScene.selectItem(itemSelector, WndBag.Mode.WEAPON, + Messages.get(RunicBlade.class, "choose")); + + } else { + + super.execute(hero, action); + + } + } + + private final WndBag.Listener itemSelector = new WndBag.Listener() { + @Override + public void onSelect(Item item) { + if (item != null && !(item instanceof Boomerang)) { + int i=0; + while(i + */ +package com.hmdzl.spspd.items.weapon.melee.special; + +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.buffs.Charm; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.effects.Pushing; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.weapon.melee.MeleeWeapon; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.CharSprite; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.watabou.utils.Random; +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.watabou.noosa.audio.Sample; + +public class SJRBMusic extends MeleeWeapon { + + { + //name = "SJRBMusic"; + image = ItemSpriteSheet.S_J_R_B_M; + + } + + public SJRBMusic() { + super(1, 1f, 1f, 2); + MIN = 3; + MAX = 6; + } + + + @Override + public void proc(Char attacker, Char defender, int damage) { + + if (Random.Int(100) < 40) { + Buff.affect(defender, Charm.class,5f).object = attacker.id(); + } + + if (Random.Int(100)> 60) { + for (Mob mob : Dungeon.level.mobs.toArray(new Mob[0])) { + mob.beckon(attacker.pos); + } + attacker.sprite.centerEmitter().start(Speck.factory(Speck.SCREAM), 0.3f, 3); + Sample.INSTANCE.play( Assets.SND_BEACON ); + attacker.sprite.showStatus(CharSprite.NEUTRAL, Messages.get(this, "rap")); + } + + Ballistica route = new Ballistica(attacker.pos, defender.pos, Ballistica.PROJECTILE); + int cell = route.collisionPos; + int dist = Level.distance(attacker.pos, cell); + if (dist == 2) { + cell = route.path.get(route.dist - 1); + Actor.addDelayed(new Pushing(attacker, attacker.pos, cell), -1); + attacker.pos = cell; + if (attacker instanceof Mob) { + Dungeon.level.mobPress((Mob) attacker); + } else { + Dungeon.level.press(cell, attacker); + } + defender.damage(damage,this); + } + + int p = defender.pos; + for (int n : Level.NEIGHBOURS8) { + Char ch = Actor.findChar(n+p); + if (ch != null && ch != defender && ch != attacker && ch.isAlive()) { + + int dr = Random.IntRange( 0, 1 ); + int dmg = Random.Int( MIN, MAX ); + int effectiveDamage = Math.max( dmg - dr, 0 ); + + ch.damage( effectiveDamage, attacker ); + } + } + + + if (enchantment != null) { + enchantment.proc(this, attacker, defender, damage); + } + } + +} diff --git a/java/com/hmdzl/spspd/items/weapon/melee/special/ShadowEater.java b/java/com/hmdzl/spspd/items/weapon/melee/special/ShadowEater.java new file mode 100644 index 00000000..11d025ca --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/melee/special/ShadowEater.java @@ -0,0 +1,152 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.weapon.melee.special; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.AttackUp; +import com.hmdzl.spspd.actors.buffs.Bleeding; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Cripple; +import com.hmdzl.spspd.actors.buffs.Locked; +import com.hmdzl.spspd.actors.buffs.Silent; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.weapon.melee.MeleeWeapon; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.CharSprite; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +import java.util.ArrayList; + +public class ShadowEater extends MeleeWeapon { + + { + //name = "ShadowEater"; + image = ItemSpriteSheet.SHADOW_EATER; + reinforced = true; + cursed = true; + } + + public ShadowEater() { + super(4, 1f, 1f, 1); + STR = 15; + } + + public static final String AC_AWAKE = "AWAKE"; + public static final String AC_UNCURSE = "UNCURSE"; + + public static int charge = 0; + private static final String CHARGE = "charge"; + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(CHARGE, charge); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + charge = bundle.getInt(CHARGE); + } + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + + if (charge >20) actions.add(AC_AWAKE); + actions.add(AC_UNCURSE); + + return actions; + } + + @Override + public Item uncurse(){ + //cursed=false; + return this; + } + + @Override + public void execute(Hero hero, String action) { + if (action == AC_AWAKE) { + curUser = hero; + this.cursed = true; + charge = 0 ; + GLog.i(Messages.get(this, "awake")); + Buff.affect(hero, AttackUp.class,30f).level(300); + Buff.affect(hero, Bleeding.class).set(hero.HT/2); + } else if (action == AC_UNCURSE) { + this.cursed = false; + } else { + + super.execute(hero, action); + + } + } + + @Override + public void proc(Char attacker, Char defender, int damage) { + + if (Random.Int(100)> 70) { + + damage*=1.5; + if (Random.Int(4) == 0 ) { + attacker.sprite.centerEmitter().start(Speck.factory(Speck.HEART), 0.3f, 3); + attacker.sprite.showStatus(CharSprite.NEUTRAL, Messages.get(this, "bleeding")); + Buff.affect(attacker, Bleeding.class).set(20); + } else if (Random.Int(3) == 0 ) { + attacker.sprite.centerEmitter().start(Speck.factory(Speck.HEART), 0.3f, 3); + attacker.sprite.showStatus(CharSprite.NEUTRAL, Messages.get(this, "locked")); + Buff.affect(attacker, Locked.class, 5f); + } else if (Random.Int(2) == 0 ) { + attacker.sprite.centerEmitter().start(Speck.factory(Speck.HEART), 0.3f, 3); + attacker.sprite.showStatus(CharSprite.NEUTRAL, Messages.get(this, "stand")); + Buff.affect(attacker, Cripple.class, 5f); + } else { + attacker.sprite.centerEmitter().start(Speck.factory(Speck.HEART), 0.3f, 3); + attacker.sprite.showStatus(CharSprite.NEUTRAL, Messages.get(this, "silent")); + Buff.affect(attacker, Silent.class, 5f); + } + } + + if ( defender.HP <= damage) { + charge++; + } + + if (enchantment != null) { + enchantment.proc(this, attacker, defender, damage); + } + } + + @Override + public String desc() { + String info = super.desc(); + + info += "\n\n" + Messages.get(this, "charge",charge); + return info; + } + +} diff --git a/java/com/hmdzl/spspd/items/weapon/melee/special/Spork.java b/java/com/hmdzl/spspd/items/weapon/melee/special/Spork.java new file mode 100644 index 00000000..b5d03a00 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/melee/special/Spork.java @@ -0,0 +1,57 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.weapon.melee.special; + +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.weapon.melee.MeleeWeapon; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.utils.Random; + +public class Spork extends MeleeWeapon { + + { + //name = "Royal Spork"; + image = ItemSpriteSheet.SPORK; + + } + + public Spork() { + super(3, 1.0f, 0.8f, 1); + } + + @Override + public Item upgrade(boolean enchant) { + MIN+=1; + return super.upgrade(enchant); + } + + + @Override + public void proc(Char attacker, Char defender, int damage) { + + if (attacker.HP < attacker.HT){ + attacker.HP += Random.Int((attacker.HT)/20); + attacker.sprite.emitter().start(Speck.factory(Speck.HEALING), 0.4f,1); + } + if (enchantment != null) { + enchantment.proc(this, attacker, defender, damage); + } + } +} diff --git a/java/com/hmdzl/spspd/items/weapon/melee/special/TekkoKagi.java b/java/com/hmdzl/spspd/items/weapon/melee/special/TekkoKagi.java new file mode 100644 index 00000000..7581fba6 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/melee/special/TekkoKagi.java @@ -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 + */ +package com.hmdzl.spspd.items.weapon.melee.special; + +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.items.weapon.melee.MeleeWeapon; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.effects.particles.ShadowParticle; +import com.hmdzl.spspd.actors.Char; +import com.watabou.utils.Random; + +public class TekkoKagi extends MeleeWeapon { + + { + //name = "Tekko-Kagi"; + image = ItemSpriteSheet.TEKKOKAGI; + } + + public TekkoKagi() { + super(1, 1f, 1f, 1); + } + + @Override + public Item upgrade(boolean enchant) { + + return super.upgrade(enchant); + } + + @Override + public void proc(Char attacker, Char defender, int damage) { + + if (Random.Int(100) < 20 ) { + defender.damage(Random.Int(defender.HT/4, defender.HT/2), this); + defender.sprite.emitter().burst(ShadowParticle.UP, 5); + if (!defender.isAlive() && attacker instanceof Hero) { + Badges.validateGrimWeapon(); + } + } + if (enchantment != null) { + enchantment.proc(this, attacker, defender, damage); + } + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/weapon/melee/special/TestWeapon.java b/java/com/hmdzl/spspd/items/weapon/melee/special/TestWeapon.java new file mode 100644 index 00000000..6909f993 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/melee/special/TestWeapon.java @@ -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 + */ +package com.hmdzl.spspd.items.weapon.melee.special; + +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.weapon.melee.MeleeWeapon; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class TestWeapon extends MeleeWeapon { + + { + //name = "TestWeapon"; + image = ItemSpriteSheet.ADAMANT_WEAPON; + + } + + public TestWeapon() { + super(1, 1f, 1f, 1); + MIN = 10; + MAX = 10; + } + + + @Override + public Item upgrade(boolean enchant) { + + return super.upgrade(enchant); + } + + /*@Override + public void proc(Char attacker, Char defender, int damage) { + + //Buff.affect(attacker,AttackUp.class,5).level(50); + //Buff.affect(attacker,DefenceUp.class,5).level(50); + + if (enchantment != null) { + enchantment.proc(this, attacker, defender, damage); + } + }*/ + +} diff --git a/java/com/hmdzl/spspd/items/weapon/melee/special/Tree.java b/java/com/hmdzl/spspd/items/weapon/melee/special/Tree.java new file mode 100644 index 00000000..2e56be1d --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/melee/special/Tree.java @@ -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 + */ +package com.hmdzl.spspd.items.weapon.melee.special; + +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.buffs.Dry; +import com.hmdzl.spspd.actors.buffs.Hot; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.weapon.melee.MeleeWeapon; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.watabou.utils.Random; +import com.hmdzl.spspd.Dungeon; + +public class Tree extends MeleeWeapon { + + { + //name = "Christmas tree"; + image = ItemSpriteSheet.TREE; + + //usesTargeting = true; + } + + public Tree() { + super(1, 1f, 1f, 1); + MIN = 1; + MAX = 5; + } + + + @Override + public Item upgrade(boolean enchant) { + + return super.upgrade(enchant); + } + + @Override + public void proc(Char attacker, Char defender, int damage) { + + if (Random.Int(100)> 40){ + Buff.affect(defender, Dry.class,10f); + } + + if (Random.Int(100)> 40){ + Buff.affect(defender, Hot.class,10f); + } + + if (Random.Int(100)==98){ + Dungeon.level.drop(Generator.random(), defender.pos).sprite.drop(); + } + + int p = defender.pos; + for (int n : Level.NEIGHBOURS8) { + Char ch = Actor.findChar(n+p); + if (ch != null && ch != defender && ch != attacker && ch.isAlive()) { + + int dr = Random.IntRange( 0, ch.drRoll() ); + int dmg = Random.Int( MIN, MAX ); + int effectiveDamage = Math.max( dmg - dr, 0 ); + + ch.damage( effectiveDamage, attacker ); + } + } + + + if (enchantment != null) { + enchantment.proc(this, attacker, defender, damage); + } + } +} diff --git a/java/com/hmdzl/spspd/items/weapon/melee/special/WraithBreath.java b/java/com/hmdzl/spspd/items/weapon/melee/special/WraithBreath.java new file mode 100644 index 00000000..e1448759 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/melee/special/WraithBreath.java @@ -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 + */ +package com.hmdzl.spspd.items.weapon.melee.special; + +import com.hmdzl.spspd.items.weapon.melee.MeleeWeapon; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Terror; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Vertigo; +import com.watabou.utils.Random; + +public class WraithBreath extends MeleeWeapon { + + { + //name = "Wraith Breath"; + image = ItemSpriteSheet.WRAITHBREATH; + } + + public WraithBreath() { + super(2, 0.75f, 1f, 4); + } + + @Override + public Item upgrade(boolean enchant) { + MAX+= 2; + MIN+= 2; + return super.upgrade(enchant); + } + + @Override + public void proc(Char attacker, Char defender, int damage) { + + if (Random.Int(100) < 50) { + Buff.affect(defender, Vertigo.class, Vertigo.duration(defender)); + Buff.affect(defender, Terror.class, Terror.DURATION).object = attacker.id(); + } + + if (enchantment != null) { + enchantment.proc(this, attacker, defender, damage); + } + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/weapon/melee/zero/Bamboo.java b/java/com/hmdzl/spspd/items/weapon/melee/zero/Bamboo.java new file mode 100644 index 00000000..39b676ef --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/melee/zero/Bamboo.java @@ -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 + */ +package com.hmdzl.spspd.items.weapon.melee.zero; + +import com.hmdzl.spspd.items.weapon.melee.MeleeWeapon; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.actors.Char; +import com.watabou.utils.Random; + +public class Bamboo extends MeleeWeapon { + + { + //name = "Bamboo"; + image = ItemSpriteSheet.DAGGER; + } + + public Bamboo() { + super(0, 1f, 1f, 1); + } + + @Override + public Item upgrade(boolean enchant) { + MAX+=1; + return super.upgrade(enchant); + } + + @Override + public void proc(Char attacker, Char defender, int damage) { + + int DMG = damage; + defender.damage(Random.Int(DMG,DMG/2*3), this); + if (enchantment != null) { + enchantment.proc(this, attacker, defender, damage); + } + } +} diff --git a/java/com/hmdzl/spspd/items/weapon/melee/zero/EmptyPotion.java b/java/com/hmdzl/spspd/items/weapon/melee/zero/EmptyPotion.java new file mode 100644 index 00000000..da157d9c --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/melee/zero/EmptyPotion.java @@ -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 + */ +package com.hmdzl.spspd.items.weapon.melee.zero; + +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.weapon.melee.MeleeWeapon; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.actors.Char; +import com.watabou.utils.Random; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.utils.GLog; +import com.hmdzl.spspd.items.KindOfWeapon; +import com.hmdzl.spspd.messages.Messages; + +public class EmptyPotion extends MeleeWeapon { + + { + //name = "EmptyPotion"; + image = ItemSpriteSheet.POTION; + } + + public EmptyPotion() { + super(0, 1f, 1f, 1); + } + + + @Override + public Item upgrade(boolean enchant) { + MAX+=1; + return super.upgrade(enchant); + } + + @Override + public void proc(Char attacker, Char defender, int damage) { + int p = defender.pos; + for (int n : Level.NEIGHBOURS8) { + Char ch = Actor.findChar(n+p); + if (ch != null && ch != defender && ch != attacker && ch.isAlive()) { + + int dr = Random.IntRange( 0, 1 ); + int dmg = Random.Int( MIN, MAX ); + int effectiveDamage = Math.max( dmg - dr, 0 ); + + ch.damage( effectiveDamage, this ); + } + } + if (enchantment != null) { + enchantment.proc(this, attacker, defender, damage); + } + if (attacker == Dungeon.hero){ + durable --; + if (durable == 10){ + GLog.n(Messages.get(KindOfWeapon.class,"almost_destory")); + } + if (durable == 0){ + Dungeon.hero.belongings.weapon = null; + defender.damage(2*damage, this); + GLog.n(Messages.get(KindOfWeapon.class,"destory")); + } + } + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/weapon/melee/zero/GlassBlade.java b/java/com/hmdzl/spspd/items/weapon/melee/zero/GlassBlade.java new file mode 100644 index 00000000..a3b7b186 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/melee/zero/GlassBlade.java @@ -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 + */ +package com.hmdzl.spspd.items.weapon.melee.zero; + +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.weapon.melee.MeleeWeapon; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.utils.Random; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Bleeding; + +public class GlassBlade extends MeleeWeapon { + + { + //name = "GlassBlade"; + image = ItemSpriteSheet.SHORT_SWORD; + + + } + + public GlassBlade() { + super(0, 1f, 1f, 1); + } + + @Override + public Item upgrade(boolean enchant) { + MAX+=1; + return super.upgrade(enchant); + } + + + @Override + public void proc(Char attacker, Char defender, int damage) { + + int DMG = damage; + if (Random.Int(100) < 75) { + Buff.affect(defender, Bleeding.class).set(Random.Int(1,DMG)); + } + + if (enchantment != null) { + enchantment.proc(this, attacker, defender, damage); + } + } +} diff --git a/java/com/hmdzl/spspd/items/weapon/melee/zero/Punch.java b/java/com/hmdzl/spspd/items/weapon/melee/zero/Punch.java new file mode 100644 index 00000000..6640049a --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/melee/zero/Punch.java @@ -0,0 +1,51 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.weapon.melee.zero; + +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.weapon.melee.MeleeWeapon; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Cripple; + +public class Punch extends MeleeWeapon { + + { + //name = "Punch"; + image = ItemSpriteSheet.KNUCKLEDUSTER; + } + + public Punch() { + super(0, 1f, 1f, 2); + } + + @Override + public Item upgrade(boolean enchant) { + MAX+=1; + return super.upgrade(enchant); + } + + @Override + public void proc(Char attacker, Char defender, int damage) { + Buff.affect(defender, Cripple.class, 3); + if (enchantment != null) { + enchantment.proc(this, attacker, defender, damage); + } + } +} diff --git a/java/com/hmdzl/spspd/items/weapon/melee/zero/WoodenHammer.java b/java/com/hmdzl/spspd/items/weapon/melee/zero/WoodenHammer.java new file mode 100644 index 00000000..44becd17 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/melee/zero/WoodenHammer.java @@ -0,0 +1,71 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2014 Oleg Dolya + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.items.weapon.melee.zero; + +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.weapon.melee.MeleeWeapon; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Paralysis; +import com.watabou.utils.Random; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.utils.GLog; +import com.hmdzl.spspd.items.KindOfWeapon; +import com.hmdzl.spspd.messages.Messages; + +public class WoodenHammer extends MeleeWeapon { + + { + //name = "WoodenHammer"; + image = ItemSpriteSheet.WOODEN_H; + + } + + public WoodenHammer() { + super(0, 1f, 1f, 1); + } + + + @Override + public Item upgrade(boolean enchant) { + MAX++; + return super.upgrade(enchant); + } + + @Override + public void proc(Char attacker, Char defender, int damage) { + if (Random.Int(100) < 75) { + Buff.prolong(defender, Paralysis.class, 2); + } + if (enchantment != null) { + enchantment.proc(this, attacker, defender, damage); + } + if (attacker == Dungeon.hero){ + durable --; + if (durable == 10){ + GLog.n(Messages.get(KindOfWeapon.class,"almost_destory")); + } + if (durable == 0){ + Dungeon.hero.belongings.weapon = null; + defender.damage(2*damage, this); + GLog.n(Messages.get(KindOfWeapon.class,"destory")); + } + } + } +} diff --git a/java/com/hmdzl/spspd/items/weapon/missiles/Boomerang.java b/java/com/hmdzl/spspd/items/weapon/missiles/Boomerang.java new file mode 100644 index 00000000..9ff6643b --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/missiles/Boomerang.java @@ -0,0 +1,218 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.weapon.missiles; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.weapon.guns.GunWeapon; +import com.hmdzl.spspd.items.weapon.spammo.SpAmmo; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.sprites.MissileSprite; +import com.hmdzl.spspd.windows.WndBag; +import com.hmdzl.spspd.windows.WndOptions; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Bundle; + +import java.util.ArrayList; + +public class Boomerang extends MissileWeapon { + + private SpAmmo spammo; + + public static final String AC_AMMO = "AMMO"; + { + //name = "boomerang"; + image = ItemSpriteSheet.BOOMERANG; + + STR = 10; + + MIN = 3; + MAX = 6; + + stackable = false; + unique = true; + reinforced = true; + + + } + + public Boomerang() { + spammo = null; + } + + public Boomerang(SpAmmo spammo) { + this.spammo = spammo; + } + + + + private static final String SPAMMO = "spammo"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + if (spammo != null) bundle.put( SPAMMO, spammo ); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + if (bundle.contains(SPAMMO)) spammo = (SpAmmo) bundle.get( SPAMMO ); + } + + + @Override + public boolean isUpgradable() { + return true; + } + + @Override + public Item upgrade() { + return upgrade(false); + } + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions( hero ); + actions.add(AC_AMMO); + return actions; + } + + @Override + public void execute(Hero hero, String action) { + super.execute(hero, action); + if (action.equals(AC_AMMO)) { + curUser = hero; + GameScene.selectItem(itemSelector, WndBag.Mode.AMMO ,Messages.get(this, "prompt")); + } + } + + @Override + public Item upgrade(boolean enchant) { + + MIN += 1; + MAX += 2; + super.upgrade(enchant); + + updateQuickslot(); + + return this; + } + + @Override + public Item degrade() { + + return super.degrade(); + } + + @Override + public void proc(Char attacker, Char defender, int damage) { + if (spammo != null) { + spammo.onHit(Boomerang.this, attacker, defender, damage); + } + super.proc(attacker, defender, damage); + if (attacker instanceof Hero && ((Hero) attacker).rangedWeapon == this) { + circleBack(defender.pos, (Hero) attacker); + } + } + + @Override + protected void miss(int cell) { + circleBack(cell, curUser); + } + + private void circleBack(int from, Hero owner) { + + ((MissileSprite) curUser.sprite.parent.recycle(MissileSprite.class)) + .reset(from, curUser.pos, curItem, null); + + if (!collect(curUser.belongings.backpack)) { + Dungeon.level.drop(this, owner.pos).sprite.drop(); + } + } + + @Override + public void cast(Hero user, int dst) { + super.cast(user, dst); + } + + @Override + public String desc() { + String info = super.desc(); + + if (spammo != null){ + info += "\n" + Messages.get(GunWeapon.class, "ammo_add") + Messages.get(spammo,"name") ; + } + + if(reinforced){ + info += "\n\n" + Messages.get(Item.class, "reinforced");; + } + + return info; + } + + public Item addSpAmmo(SpAmmo spammo, Char owner){ + + this.spammo = null; + + //GLog.p( Messages.get(this, "imbue", spammo.name())); + + this.spammo= spammo; + spammo.identify(); + spammo.cursed = false; + //name = Messages.get(spammo, "spammo_name"); + + updateQuickslot(); + + return this; + } + + private final WndBag.Listener itemSelector = new WndBag.Listener() { + @Override + public void onSelect( final Item item ) { + if (item != null) { + + GameScene.show( + new WndOptions("", + Messages.get(GunWeapon.class, "warning"), + Messages.get(GunWeapon.class, "yes"), + Messages.get(GunWeapon.class, "no")) { + @Override + protected void onSelect(int index) { + if (index == 0) { + Sample.INSTANCE.play(Assets.SND_EVOKE); + item.detach(curUser.belongings.backpack); + + addSpAmmo((SpAmmo) item, curUser); + + curUser.spendAndNext(2f); + + updateQuickslot(); + } + } + } + ); + } + } + }; +} diff --git a/java/com/hmdzl/spspd/items/weapon/missiles/EmpBola.java b/java/com/hmdzl/spspd/items/weapon/missiles/EmpBola.java new file mode 100644 index 00000000..7266af1a --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/missiles/EmpBola.java @@ -0,0 +1,71 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2014 Oleg Dolya + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.items.weapon.missiles; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Cripple; +import com.hmdzl.spspd.actors.buffs.ShieldArmor; +import com.hmdzl.spspd.actors.buffs.Shocked; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.utils.Random; + +public class EmpBola extends MissileWeapon { + + { + //name = "bola"; + image = ItemSpriteSheet.BOLA; + + STR = 10; + + MIN = 5; + MAX = 10; + } + + public EmpBola() { + this(1); + } + + public EmpBola(int number) { + super(); + quantity = number; + } + + @Override + public void proc(Char attacker, Char defender, int damage) { + super.proc(attacker, defender, damage); + Buff.prolong(defender, Cripple.class, Cripple.DURATION); + Buff.prolong(defender, Shocked.class, 5f); + Buff.detach(defender, ShieldArmor.class); + if(defender.properties().contains(Char.Property.MECH)){ + defender.damage(defender.HT/3,this); + } + } + + @Override + public Item random() { + quantity = Random.Int(2, 5); + return this; + } + + @Override + public int price() { + return 10 * quantity; + } +} diff --git a/java/com/hmdzl/spspd/items/weapon/missiles/ErrorAmmo.java b/java/com/hmdzl/spspd/items/weapon/missiles/ErrorAmmo.java new file mode 100644 index 00000000..4fa99cea --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/missiles/ErrorAmmo.java @@ -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 + */ +package com.hmdzl.spspd.items.weapon.missiles; + +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.utils.Random; + +public class ErrorAmmo extends MissileWeapon { + + { + //name = "error ammo"; + image = ItemSpriteSheet.ERROR_AMMO; + + STR = 0; + MIN = 10000; + MAX = 10000; + + // Finding them in bones would be semi-frequent and + // disappointing. + } + + public ErrorAmmo() { + this(1); + } + + public ErrorAmmo(int number) { + super(); + quantity = number; + } + + @Override + public Item random() { + quantity = Random.Int(5, 8); + return this; + } + @Override + public int price() { + return quantity * 0; + } +} diff --git a/java/com/hmdzl/spspd/items/weapon/missiles/EscapeKnive.java b/java/com/hmdzl/spspd/items/weapon/missiles/EscapeKnive.java new file mode 100644 index 00000000..47b832c5 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/missiles/EscapeKnive.java @@ -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 + */ +package com.hmdzl.spspd.items.weapon.missiles; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Shieldblock; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.utils.Random; + +public class EscapeKnive extends MissileWeapon { + + { + //name = "throwing knive"; + image = ItemSpriteSheet.KNIVE; + + STR = 10; + MIN = 5; + MAX = 10; + + // Finding them in bones would be semi-frequent and + // disappointing. + } + + public EscapeKnive() { + this(1); + } + + public EscapeKnive(int number) { + super(); + quantity = number; + } + + @Override + public void proc(Char attacker, Char defender, int damage) { + super.proc(attacker, defender, damage); + Buff.prolong(defender, Shieldblock.class, 4f); + } + + @Override + public Item random() { + quantity = Random.Int(2, 5); + return this; + } + + @Override + public int price() { + return quantity * 10; + } +} diff --git a/java/com/hmdzl/spspd/items/weapon/missiles/ForestDart.java b/java/com/hmdzl/spspd/items/weapon/missiles/ForestDart.java new file mode 100644 index 00000000..603c8255 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/missiles/ForestDart.java @@ -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 + */ +package com.hmdzl.spspd.items.weapon.missiles; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.mobs.Assassin; +import com.hmdzl.spspd.actors.mobs.Bat; +import com.hmdzl.spspd.actors.mobs.Brute; +import com.hmdzl.spspd.actors.mobs.Gnoll; +import com.hmdzl.spspd.actors.mobs.GoldThief; +import com.hmdzl.spspd.actors.mobs.Rat; +import com.hmdzl.spspd.actors.mobs.RatBoss; +import com.hmdzl.spspd.actors.mobs.GnollShaman; +import com.hmdzl.spspd.actors.mobs.Fiend; +import com.hmdzl.spspd.actors.mobs.Thief; +import com.hmdzl.spspd.actors.mobs.GnollArcher; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.sprites.ItemSprite.Glowing; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.utils.Random; + +public class ForestDart extends MissileWeapon { + + { + //name = "lucky throwing knive"; + image = ItemSpriteSheet.KNIVE; + + MIN = 6; + MAX = 14; + + // Finding them in bones would be semi-frequent and + // disappointing. + } + + public ForestDart() { + this(1); + } + + public ForestDart(int number) { + super(); + quantity = number; + } + + @Override + public void proc(Char attacker, Char defender, int damage) { + + + if ( defender.properties().contains(Char.Property.BOSS) + || defender.properties().contains(Char.Property.HUMAN) + //|| defender.properties().contains(Char.Property.GNOLL) + || defender.properties().contains(Char.Property.ORC) + || defender.properties().contains(Char.Property.BEAST) + || defender.properties().contains(Char.Property.PLANT) + ){ + defender.damage(Random.Int(damage*5,damage*8), this); + } else { + defender.damage(Random.Int(damage,damage*2), this); + } + + + } + + + @Override + public Item random() { + quantity = Random.Int(5, 15); + return this; + } + + @Override + public int price() { + return quantity * 2; + } + + private static final Glowing GREEN = new Glowing(0x00FF00); + + @Override + public Glowing glowing() { + return GREEN; + } +} diff --git a/java/com/hmdzl/spspd/items/weapon/missiles/HugeShuriken.java b/java/com/hmdzl/spspd/items/weapon/missiles/HugeShuriken.java new file mode 100644 index 00000000..483272c6 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/missiles/HugeShuriken.java @@ -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 + */ +package com.hmdzl.spspd.items.weapon.missiles; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.AttackDown; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.utils.Random; + +public class HugeShuriken extends MissileWeapon { + + { + //name = "Huge shuriken"; + image = ItemSpriteSheet.HUGESHURIKEN; + + STR = 13; + + MIN = 2; + MAX = 6; + } + + public HugeShuriken() { + this(1); + } + + public HugeShuriken(int number) { + super(); + quantity = number; + } + + @Override + public void proc(Char attacker, Char defender, int damage) { + Buff.affect(defender, AttackDown.class,10f).level(30); + super.proc(attacker, defender, damage); + } + @Override + public Item random() { + quantity = Random.Int(3, 7); + return this; + } + + @Override + public int price() { + return 10 * quantity; + } +} diff --git a/java/com/hmdzl/spspd/items/weapon/missiles/IncendiaryDart.java b/java/com/hmdzl/spspd/items/weapon/missiles/IncendiaryDart.java new file mode 100644 index 00000000..6a81040b --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/missiles/IncendiaryDart.java @@ -0,0 +1,80 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.weapon.missiles; + +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.Blob; +import com.hmdzl.spspd.actors.blobs.Fire; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Burning; +import com.hmdzl.spspd.actors.buffs.Tar; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.utils.Random; + +public class IncendiaryDart extends MissileWeapon { + + { + //name = "incendiary dart"; + image = ItemSpriteSheet.INCENDIARY_DART; + + STR = 10; + + MIN = 3; + MAX = 5; + } + + public IncendiaryDart() { + this(1); + } + + public IncendiaryDart(int number) { + super(); + quantity = number; + } + + @Override + protected void onThrow(int cell) { + Char enemy = Actor.findChar(cell); + if ((enemy == null || enemy == curUser) && Level.flamable[cell]) + GameScene.add(Blob.seed(cell, 4, Fire.class)); + else + super.onThrow(cell); + } + + @Override + public void proc(Char attacker, Char defender, int damage) { + Buff.affect(defender, Burning.class).reignite(defender); + Buff.affect(defender, Tar.class); + super.proc(attacker, defender, damage); + } + + @Override + public Item random() { + quantity = Random.Int(3, 6); + return this; + } + + @Override + public int price() { + return 10 * quantity; + } +} diff --git a/java/com/hmdzl/spspd/items/weapon/missiles/ManyKnive.java b/java/com/hmdzl/spspd/items/weapon/missiles/ManyKnive.java new file mode 100644 index 00000000..de0010a8 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/missiles/ManyKnive.java @@ -0,0 +1,296 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.weapon.missiles; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.buffs.MechArmor; +import com.hmdzl.spspd.actors.buffs.TargetShoot; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.Splash; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.rings.RingOfSharpshooting; +import com.hmdzl.spspd.items.weapon.Weapon; +import com.hmdzl.spspd.items.weapon.guns.GunWeapon; +import com.hmdzl.spspd.items.weapon.guns.ToyGun; +import com.hmdzl.spspd.items.weapon.spammo.SpAmmo; +import com.hmdzl.spspd.scenes.CellSelector; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.windows.WndBag; +import com.hmdzl.spspd.windows.WndOptions; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.messages.Messages; + +import java.util.ArrayList; + +public class ManyKnive extends Weapon { + + private SpAmmo spammo; + public static final String AC_SHOOT = "SHOOT"; + public static final String AC_AMMO = "AMMO"; + + { + //name = "ManyKnive"; + image = ItemSpriteSheet.MANY_KNIVE; + + STR = 10; + + MIN = 2; + MAX = 4; + + stackable = false; + unique = true; + + defaultAction = AC_SHOOT; + usesTargeting = true; + reinforced = true; + } + + + public ManyKnive() { + spammo = null; + } + + public ManyKnive(SpAmmo spammo) { + this.spammo = spammo; + } + + + private static final String SPAMMO = "spammo"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + if (spammo != null) bundle.put( SPAMMO, spammo ); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + if (bundle.contains(SPAMMO)) spammo = (SpAmmo) bundle.get( SPAMMO ); + } + + @Override + public boolean isUpgradable() { + return true; + } + + @Override + public Item upgrade() { + return upgrade(false); + } + + + @Override + public boolean isIdentified() { + return true; + } + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + actions.remove(AC_EQUIP); + actions.remove(AC_DROP); + actions.remove(AC_THROW); + actions.add(AC_SHOOT); + actions.add(AC_AMMO); + + return actions; + } + + @Override + public void execute(Hero hero, String action) { + super.execute(hero, action); + if (action.equals(AC_SHOOT)) { + GameScene.selectCell( shooter ); + } + if (action.equals(AC_AMMO)) { + curUser = hero; + GameScene.selectItem(itemSelector, WndBag.Mode.AMMO ,Messages.get(this, "prompt")); + } + } + + + @Override + public Item upgrade(boolean enchant) { + + MIN += 1; + MAX += 3; + super.upgrade(enchant); + + updateQuickslot(); + + return this; + } + + @Override + public Item degrade() { + return super.degrade(); + } + + public int damageRoll(Hero owner) { + int damage = Random.Int(MIN, MAX); + + float bonus = 0; + for (Buff buff : owner.buffs(RingOfSharpshooting.Aim.class)) { + bonus += ((RingOfSharpshooting.Aim) buff).level; + } + if (Dungeon.hero.buff(TargetShoot.class)!= null) + bonus += 10; + if (Dungeon.hero.buff(MechArmor.class)!= null) + bonus += 10; + damage = (int)(damage*(1 + 0.05*bonus)); + return Math.round(damage); + } + + + @Override + public String info() { + String info = desc(); + + if (spammo != null){ + info += "\n" + Messages.get(GunWeapon.class, "ammo_add") + Messages.get(spammo,"name") ; + } + + if (reinforced) { + info += "\n" + Messages.get(Item.class, "reinforced"); + } + info += "\n\n" + Messages.get(this, "damage",MIN,MAX); + + return info; + } + + + private int targetPos; + + + public Item addSpAmmo(SpAmmo spammo, Char owner){ + + this.spammo = null; + + //GLog.p( Messages.get(this, "imbue", spammo.name())); + + this.spammo= spammo; + spammo.identify(); + spammo.cursed = false; + //name = Messages.get(spammo, "spammo_name"); + + updateQuickslot(); + + return this; + } + + private final WndBag.Listener itemSelector = new WndBag.Listener() { + @Override + public void onSelect( final Item item ) { + if (item != null) { + + GameScene.show( + new WndOptions("", + Messages.get(GunWeapon.class, "warning"), + Messages.get(GunWeapon.class, "yes"), + Messages.get(GunWeapon.class, "no")) { + @Override + protected void onSelect(int index) { + if (index == 0) { + Sample.INSTANCE.play(Assets.SND_EVOKE); + item.detach(curUser.belongings.backpack); + + addSpAmmo((SpAmmo) item, curUser); + + curUser.spendAndNext(2f); + + updateQuickslot(); + } + } + } + ); + } + } + }; + + public KniveAmmo Ammo(){ + return new KniveAmmo(); + } + + public class KniveAmmo extends MissileWeapon { + + { + image = ItemSpriteSheet.KNIVE; + enchantment = ManyKnive.this.enchantment; + DLY = 0.25f; + } + + public int damageRoll(Hero owner) { + return ManyKnive.this.damageRoll(owner); + } + + @Override + protected void onThrow( int cell ) { + Char enemy = Actor.findChar( cell ); + if (enemy == null || enemy == curUser) { + parent = null; + Splash.at( cell, 0xCC99FFFF, 1 ); + } else { + if (!curUser.shoot( enemy, this )) { + Splash.at(cell, 0xCC99FFFF, 1); + } + } + } + + @Override + public void proc(Char attacker, Char defender, int damage) { + if (spammo != null) { + spammo.onHit(ManyKnive.this, attacker, defender, damage); + } + if (enchantment != null) { + enchantment.proc(ManyKnive.this, attacker, defender, damage); + } + if (Random.Int(50)== 0){ + Dungeon.level.drop(new EscapeKnive(1), defender.pos).sprite.drop(); + } + super.proc(attacker, defender, damage); + } + + @Override + public void cast(final Hero user, final int dst) { + final int cell = throwPos( user, dst ); + ManyKnive.this.targetPos = cell; + super.cast(user, dst); + } + } + + private CellSelector.Listener shooter = new CellSelector.Listener() { + @Override + public void onSelect( Integer target ) { + if (target != null) { + Ammo().cast(curUser, target); + } + } + @Override + public String prompt() { + return Messages.get(ToyGun.class, "prompt"); + } + }; +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/weapon/missiles/MiniMoai.java b/java/com/hmdzl/spspd/items/weapon/missiles/MiniMoai.java new file mode 100644 index 00000000..05a807a0 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/missiles/MiniMoai.java @@ -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 + */ +package com.hmdzl.spspd.items.weapon.missiles; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Charm; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.utils.Random; + +import java.util.ArrayList; + +public class MiniMoai extends MissileWeapon { + + { + //name = "MiniMoai"; + image = ItemSpriteSheet.MOAI; + + STR = 10; + + MIN = 1; + MAX = 10; + + stackable = false; + unique = true; + + + } + + @Override + public boolean isUpgradable() { + return true; + } + + @Override + public Item upgrade() { + return upgrade(false); + } + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions( hero ); + if (!isEquipped(hero)) actions.add(AC_EQUIP); + return actions; + } + + @Override + public Item upgrade(boolean enchant) { + + MIN += 1; + MAX += 1; + super.upgrade(enchant); + + updateQuickslot(); + + return this; + } + + @Override + public Item degrade() { + + return super.degrade(); + } + + @Override + public void proc(Char attacker, Char defender, int damage) { + if (Random.Int(10)> 7){ + Buff.prolong(defender, Charm.class, 3 ).object = attacker.id();} + super.proc(attacker, defender, damage); + } + + @Override + public String desc() { + String info = super.desc(); + + if(reinforced){ + info += "\n\n" + Messages.get(Item.class, "reinforced"); + } + + return info; + } + + @Override + public int price() { + return quantity * 100; + } +} diff --git a/java/com/hmdzl/spspd/items/weapon/missiles/MissileWeapon.java b/java/com/hmdzl/spspd/items/weapon/missiles/MissileWeapon.java new file mode 100644 index 00000000..74425a9c --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/missiles/MissileWeapon.java @@ -0,0 +1,149 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.weapon.missiles; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.hero.HeroClass; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.KindOfWeapon; +import com.hmdzl.spspd.items.rings.RingOfSharpshooting; +import com.hmdzl.spspd.items.weapon.Weapon; +import com.hmdzl.spspd.items.weapon.guns.GunWeapon; +import com.hmdzl.spspd.items.weapon.melee.MeleeWeapon; +import com.hmdzl.spspd.messages.Messages; +import com.watabou.utils.Random; + +public class MissileWeapon extends Weapon { + + { + levelKnown = true; + defaultAction = AC_THROW; + usesTargeting = true; + stackable = true; + } + + protected boolean sticky = true; + + protected static final float MAX_DURABILITY = 100; + protected float durability = MAX_DURABILITY; + + //used to reduce durability from the source weapon stack, rather than the one being thrown. + protected MissileWeapon parent; + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + actions.remove(AC_EQUIP); + actions.remove(AC_UNEQUIP); + return actions; + } + + @Override + protected void onThrow(int cell) { + Char enemy = Actor.findChar(cell); + if (enemy == null || enemy == curUser) { + if (this instanceof Boomerang ) + super.onThrow(cell); + else + miss(cell); + } else { + if (!curUser.shoot(enemy, this)) { + miss(cell); + } else if (this instanceof MiniMoai){ + Dungeon.level.drop( this, enemy.pos).sprite.drop(); + } else if (!(this instanceof Boomerang )) { + int bonus = 0; + for (Buff buff : curUser.buffs(RingOfSharpshooting.Aim.class)) + bonus += ((RingOfSharpshooting.Aim) buff).level; + + if (curUser.heroClass == HeroClass.HUNTRESS) + bonus += 3; + } + } + } + + protected void miss(int cell) { + int bonus = 0; + for (Buff buff : curUser.buffs(RingOfSharpshooting.Aim.class)) { + bonus += ((RingOfSharpshooting.Aim) buff).level; + } + + // degraded ring of sharpshooting will even make missed shots break. + if (Random.Float() < Math.pow(0.6, -bonus)) + super.onThrow(cell); + } + + @Override + public void proc(Char attacker, Char defender, int damage) { + super.proc(attacker, defender, damage); + KindOfWeapon wep = Dungeon.hero.belongings.weapon; + if (Dungeon.hero.heroClass== HeroClass.HUNTRESS && wep !=null && this instanceof MissileWeapon && !( this instanceof ManyKnive.KniveAmmo) && !(this instanceof TaurcenBow.TaurcenBowArrow)&& !(this instanceof GunWeapon.NormalAmmo)) { + defender.damage(Random.Int(wep.MAX,wep.MIN),this); + } + Hero hero = (Hero) attacker; + if (hero.rangedWeapon == null && stackable) { + if (quantity == 1) { + doUnequip(hero, false, false); + } else { + detach(null); + } + } + + } + + @Override + public Item random() { + return this; + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + @Override + public String info() { + + String info = desc(); + + info += "\n\n" + Messages.get( Weapon.class, "avg_dmg",MIN,MAX); + + if (STR > Dungeon.hero.STR()) { + info += Messages.get(Weapon.class, "too_heavy"); + } else { + info += " " + Messages.get(MeleeWeapon.class, "excess_str", Dungeon.hero.STR() - STR); + } + + if (enchantment != null) { + info += "\n" + Messages.get(MeleeWeapon.class, "enchanted", enchantment.desc()); + } + + return info; + } +} diff --git a/java/com/hmdzl/spspd/items/weapon/missiles/MoneyPack.java b/java/com/hmdzl/spspd/items/weapon/missiles/MoneyPack.java new file mode 100644 index 00000000..ed5e1b7a --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/missiles/MoneyPack.java @@ -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 + */ +package com.hmdzl.spspd.items.weapon.missiles; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.utils.Random; + +public class MoneyPack extends MissileWeapon { + + { + image = ItemSpriteSheet.MONEY_PACK; + + STR = 10; + MIN = 1; + MAX = 1; + + } + + public MoneyPack() { + this(1); + } + + public MoneyPack(int number) { + super(); + quantity = number; + } + + @Override + public void proc(Char attacker, Char defender, int damage) { + super.proc(attacker, defender, damage); + int moneyneed = defender.HP; + if (moneyneed < Dungeon.gold){ + defender.damage(moneyneed,this); + Dungeon.gold-=moneyneed; + } else { + defender.damage(Dungeon.gold,this); + Dungeon.gold=0; + } + + } + + @Override + public Item random() { + quantity = Random.Int(5, 10); + return this; + } + + @Override + public int price() { + return quantity * 100; + } +} diff --git a/java/com/hmdzl/spspd/items/weapon/missiles/NormalBomb.java b/java/com/hmdzl/spspd/items/weapon/missiles/NormalBomb.java new file mode 100644 index 00000000..033417d9 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/missiles/NormalBomb.java @@ -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 + */ +package com.hmdzl.spspd.items.weapon.missiles; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Paralysis; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.utils.Random; + +public class NormalBomb extends MissileWeapon { + + + { + //name = "Normal Bomb"; + image = ItemSpriteSheet.EMPTY_BOMB; + + STR = 10; + + MIN = 1; + MAX = 1; + } + + public NormalBomb() { + this(1); + } + + public NormalBomb(int number) { + super(); + quantity = number; + } + + private static ItemSprite.Glowing BROWN = new ItemSprite.Glowing(0xCC6600); + + @Override + public ItemSprite.Glowing glowing() { + return BROWN; + } + + @Override + public void proc(Char attacker, Char defender, int damage) { + super.proc(attacker, defender, damage); + if(defender.properties().contains(Char.Property.BOSS)){ + defender.damage(defender.HT/2,this); + } + } + + @Override + public Item random() { + quantity = Random.Int(1, 2); + return this; + } + + @Override + public int price() { + return 20 * quantity; + } +} diff --git a/java/com/hmdzl/spspd/items/weapon/missiles/PocketBall.java b/java/com/hmdzl/spspd/items/weapon/missiles/PocketBall.java new file mode 100644 index 00000000..38c36935 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/missiles/PocketBall.java @@ -0,0 +1,81 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 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 + */ +package com.hmdzl.spspd.items.weapon.missiles; + + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.mobs.pets.PET; +import com.hmdzl.spspd.items.PocketBallFull; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.noosa.audio.Sample; +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.effects.particles.ShadowParticle; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + + +public class PocketBall extends MissileWeapon { + + { + //name = "pocket ball"; + image = ItemSpriteSheet.POCKETBALL_EMPTY; + + STR = 10; + MIN = 1; + MAX = 10; + + stackable = true; + } + + public PocketBall() { + this( 1 ); + } + + public PocketBall(int number) { + super(); + quantity = number; + } + + + @Override + protected void onThrow( int cell ) { + if(Actor.findChar(cell) != null && Actor.findChar(cell) instanceof PET) { + Actor.findChar(cell).sprite.emitter().burst(ShadowParticle.CURSE, 6); + Sample.INSTANCE.play( Assets.SND_CURSED ); + PocketBallFull pbf = new PocketBallFull( + Dungeon.hero.petType, + Dungeon.hero.petHP, + Dungeon.hero.petLevel, + Dungeon.hero.petExperience + + ); + Dungeon.level.drop( pbf, cell ).sprite.drop(); + ((PET) Actor.findChar(cell)).sprite.killAndErase(); + ((PET) Actor.findChar(cell)).destroy(); + Dungeon.hero.haspet=false; + GLog.n(Messages.get(this, "get_pet")); + } else + miss(cell); + } + + @Override + public int price() { + return 100 * quantity; + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/weapon/missiles/PoisonDart.java b/java/com/hmdzl/spspd/items/weapon/missiles/PoisonDart.java new file mode 100644 index 00000000..03cfbb85 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/missiles/PoisonDart.java @@ -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 + */ +package com.hmdzl.spspd.items.weapon.missiles; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Paralysis; +import com.hmdzl.spspd.actors.buffs.Poison; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.utils.Random; + +public class PoisonDart extends MissileWeapon { + + public static final float DURATION = 3f; + + { + //name = "poison dart"; + image = ItemSpriteSheet.POSION_DART; + + STR = 10; + + MIN = 1; + MAX = 5; + } + + public PoisonDart() { + this(1); + } + + public PoisonDart(int number) { + super(); + quantity = number; + } + + @Override + public void proc(Char attacker, Char defender, int damage) { + Buff.affect(defender, Poison.class).set( + Poison.durationFactor(defender) * (10)); + super.proc(attacker, defender, damage); + } + + @Override + public Item random() { + quantity = Random.Int(2, 5); + return this; + } + + @Override + public int price() { + return 10 * quantity; + } +} diff --git a/java/com/hmdzl/spspd/items/weapon/missiles/RiceBall.java b/java/com/hmdzl/spspd/items/weapon/missiles/RiceBall.java new file mode 100644 index 00000000..160e327d --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/missiles/RiceBall.java @@ -0,0 +1,119 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.weapon.missiles; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Drowsy; +import com.hmdzl.spspd.actors.mobs.npcs.NPC; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.scrolls.ScrollOfTeleportation; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Random; + +public class RiceBall extends MissileWeapon { + + public static final float DURATION = 10f; + + { + //name = "rice dumpling"; + image = ItemSpriteSheet.DUST; + + MIN = 1; + MAX = 2; + + DLY = 0.25f; + + + } + + public RiceBall() { + this(1); + } + + public RiceBall(int number) { + super(); + quantity = number; + } + + + @Override + public void proc(Char attacker, Char defender, int damage) { + + if (defender != null + && !(defender instanceof NPC) + && !defender.properties().contains(Char.Property.UNDEAD) + && !defender.properties().contains(Char.Property.BOSS) + && !defender.properties().contains(Char.Property.DEMONIC) + && !defender.properties().contains(Char.Property.UNKNOW) + && !defender.properties().contains(Char.Property.ELEMENT) + && !defender.properties().contains(Char.Property.MECH) + ) { + + Buff.affect(defender, Drowsy.class); + defender.sprite.centerEmitter().start(Speck.factory(Speck.NOTE), 0.3f, 5); + + if (defender.HP/defender.HT > 0.01f){ + int count = 20; + int pos; + do { + pos = Dungeon.level.randomRespawnCell(); + if (count-- <= 0) { + break; + } + } while (pos == -1); + + if (pos == -1) { + + GLog.w(Messages.get(ScrollOfTeleportation.class, "tele")); + + } else { + + defender.pos = pos; + defender.sprite.place(defender.pos); + defender.sprite.visible = Dungeon.visible[pos]; + GLog.i(curUser.name + " teleported " + defender.name + + " to somewhere"); + + } + + } else { + + GLog.i("nothing happened"); + + } + } + + super.proc(attacker, defender, damage); + } + + @Override + public Item random() { + quantity = Random.Int(3, 5); + return this; + } + + @Override + public int price() { + return quantity * 10; + } +} diff --git a/java/com/hmdzl/spspd/items/weapon/missiles/ShatteredAmmo.java b/java/com/hmdzl/spspd/items/weapon/missiles/ShatteredAmmo.java new file mode 100644 index 00000000..02f23540 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/missiles/ShatteredAmmo.java @@ -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 + */ +package com.hmdzl.spspd.items.weapon.missiles; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.ArmorBreak; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.utils.Random; + +public class ShatteredAmmo extends MissileWeapon { + + { + image = ItemSpriteSheet.SHATTERED_AMMO; + + STR = 10; + MIN = 10; + MAX = 30; + + // Finding them in bones would be semi-frequent and + // disappointing. + } + + public ShatteredAmmo() { + this(1); + } + + public ShatteredAmmo(int number) { + super(); + quantity = number; + } + + @Override + public void proc(Char attacker, Char defender, int damage) { + super.proc(attacker, defender, damage); + Buff.affect(defender, ArmorBreak.class,10f).level(30); + } + + @Override + public Item random() { + quantity = Random.Int(3, 5); + return this; + } + + @Override + public int price() { + return quantity * 10; + } +} diff --git a/java/com/hmdzl/spspd/items/weapon/missiles/Skull.java b/java/com/hmdzl/spspd/items/weapon/missiles/Skull.java new file mode 100644 index 00000000..d4fb260b --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/missiles/Skull.java @@ -0,0 +1,64 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.weapon.missiles; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.SoulMark; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.utils.Random; + +public class Skull extends MissileWeapon { + + { + //name = "skull"; + image = ItemSpriteSheet.SKULLWEP; + + MIN = 1; + MAX = 4; + + + } + + public Skull() { + this(1); + } + + public Skull(int number) { + super(); + quantity = number; + } + + @Override + public void proc(Char attacker, Char defender, int damage) { + super.proc(attacker, defender, damage); + Buff.affect(defender, SoulMark.class,10f); + } + + @Override + public Item random() { + quantity = Random.Int(3, 5); + return this; + } + + @Override + public int price() { + return quantity * 10; + } +} diff --git a/java/com/hmdzl/spspd/items/weapon/missiles/Smoke.java b/java/com/hmdzl/spspd/items/weapon/missiles/Smoke.java new file mode 100644 index 00000000..47532413 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/missiles/Smoke.java @@ -0,0 +1,80 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.weapon.missiles; + +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.Blob; +import com.hmdzl.spspd.actors.blobs.DarkGas; +import com.hmdzl.spspd.actors.buffs.Blindness; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.utils.Random; + +public class Smoke extends MissileWeapon { + + { + //name = "shuriken"; + image = ItemSpriteSheet.SHURIKEN; + + STR = 10; + + MIN = 2; + MAX = 4; + + } + + public Smoke() { + this(1); + } + + public Smoke(int number) { + super(); + quantity = number; + } + + @Override + public Item random() { + quantity = Random.Int(3, 5); + return this; + } + + @Override + protected void onThrow(int cell) { + Char enemy = Actor.findChar(cell); + if (enemy == null || enemy == curUser) + //GameScene.add(Blob.seed(cell, 4, Fire.class)); + GameScene.add(Blob.seed(cell, 100, DarkGas.class)); + else + super.onThrow(cell); + } + + @Override + public void proc(Char attacker, Char defender, int damage) { + super.proc(attacker, defender, damage); + Buff.affect(defender, Blindness.class,3f); + GameScene.add(Blob.seed(defender.pos, 100, DarkGas.class)); + } + + @Override + public int price() { + return 10 * quantity; + } +} diff --git a/java/com/hmdzl/spspd/items/weapon/missiles/Tamahawk.java b/java/com/hmdzl/spspd/items/weapon/missiles/Tamahawk.java new file mode 100644 index 00000000..4d509fb0 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/missiles/Tamahawk.java @@ -0,0 +1,64 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.weapon.missiles; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Bleeding; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.utils.Random; + +public class Tamahawk extends MissileWeapon { + + { + //name = "tomahawk"; + image = ItemSpriteSheet.TOMAHAWK; + + STR = 16; + + MIN = 70; + MAX = 140; + } + + public Tamahawk() { + this(1); + } + + public Tamahawk(int number) { + super(); + quantity = number; + } + + @Override + public void proc(Char attacker, Char defender, int damage) { + super.proc(attacker, defender, damage); + Buff.affect(defender, Bleeding.class).set(damage); + } + + @Override + public Item random() { + quantity = Random.Int(4, 8); + return this; + } + + @Override + public int price() { + return 15 * quantity; + } +} diff --git a/java/com/hmdzl/spspd/items/weapon/missiles/TaurcenBow.java b/java/com/hmdzl/spspd/items/weapon/missiles/TaurcenBow.java new file mode 100644 index 00000000..14d9af00 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/missiles/TaurcenBow.java @@ -0,0 +1,309 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.weapon.missiles; + +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.buffs.ArmorBreak; +import com.hmdzl.spspd.actors.buffs.AttackUp; +import com.hmdzl.spspd.actors.buffs.Burning; +import com.hmdzl.spspd.actors.buffs.MechArmor; +import com.hmdzl.spspd.actors.buffs.Ooze; +import com.hmdzl.spspd.actors.buffs.Shocked; +import com.hmdzl.spspd.actors.buffs.Slow; +import com.hmdzl.spspd.actors.buffs.TargetShoot; +import com.hmdzl.spspd.actors.buffs.Wet; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.Splash; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.rings.RingOfSharpshooting; +import com.hmdzl.spspd.items.weapon.Weapon; +import com.hmdzl.spspd.items.weapon.guns.ToyGun; +import com.hmdzl.spspd.scenes.CellSelector; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.actors.Char; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.messages.Messages; + +import java.util.ArrayList; + +public class TaurcenBow extends Weapon { + + public static final String AC_SHOOT = "SHOOT"; + public static final String AC_BREAK = "BREAK"; + public static final String AC_FIRE = "FIRE"; + public static final String AC_ICE = "ICE"; + public static final String AC_POSION = "POSION"; + public static final String AC_ELE = "ELE"; + + { + //name = "TaurcenBow"; + image = ItemSpriteSheet.BOW; + + STR = 10; + + MIN = 4; + MAX = 8; + + stackable = false; + + unique = true; + + defaultAction = AC_SHOOT; + usesTargeting = true; + reinforced = true; + } + + public enum Arrow { + NONE, FIRE, ICE, POSION, ELE + } + + public Arrow arrow = Arrow.NONE; + + public static int charge = 0; + private static final String CHARGE = "charge"; + private static final String ARROW = "arrow"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put( ARROW, arrow ); + bundle.put(CHARGE, charge); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + arrow = bundle.getEnum( ARROW, Arrow.class ); + charge = bundle.getInt(CHARGE); + } + + @Override + public boolean isUpgradable() { + return true; + } + + @Override + public boolean isIdentified() { + return true; + } + + @Override + public Item upgrade() { + return upgrade(false); + } + + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + actions.remove(AC_EQUIP); + actions.remove(AC_DROP); + actions.remove(AC_THROW); + actions.add(AC_SHOOT); + actions.add(AC_BREAK); + actions.add(AC_FIRE); + actions.add(AC_ICE); + actions.add(AC_POSION); + actions.add(AC_ELE); + return actions; + } + + @Override + public void execute(Hero hero, String action) { + super.execute(hero, action); + if (action.equals(AC_SHOOT)) { + GameScene.selectCell( shooter ); + } + if (action.equals(AC_BREAK)) { + curUser = hero; + this.arrow = TaurcenBow.Arrow.NONE; + } + if (action.equals(AC_FIRE)) { + curUser = hero; + this.arrow = TaurcenBow.Arrow.FIRE; + } + if (action.equals(AC_ICE)) { + curUser = hero; + this.arrow = TaurcenBow.Arrow.ICE; + } + if (action.equals(AC_POSION)) { + curUser = hero; + this.arrow = TaurcenBow.Arrow.POSION; + } + if (action.equals(AC_ELE)) { + curUser = hero; + this.arrow = TaurcenBow.Arrow.ELE; + } + } + + + @Override + public Item upgrade(boolean enchant) { + + MIN += 3; + MAX += 5; + super.upgrade(enchant); + updateQuickslot(); + return this; + } + + @Override + public Item degrade() { + return super.degrade(); + } + + public int damageRoll(Hero owner) { + int damage = Random.Int(MIN, MAX); + + float bonus = 0; + for (Buff buff : owner.buffs(RingOfSharpshooting.Aim.class)) { + bonus += ((RingOfSharpshooting.Aim) buff).level; + } + if (Dungeon.hero.buff(TargetShoot.class)!= null) + bonus += 10; + if (Dungeon.hero.buff(MechArmor.class)!= null) + bonus += 10; + damage = (int)(damage*(1 + 0.05*bonus)); + return Math.round(damage); + } + + + @Override + public String info() { + String info = desc(); + + if (reinforced) { + info += "\n" + Messages.get(Item.class, "reinforced"); + } + info += "\n\n" + Messages.get(this, "damage",MIN,MAX); + info += "\n\n" + Messages.get(this, "charge",charge,8); + + return info; + } + + + @Override + public String status() { + if (levelKnown) { + //return charge + "/" + "8"; + return charge + "/8"; + } else { + return null; + } + } + + private int targetPos; + + public TaurcenBowArrow Arrow(){ + return new TaurcenBowArrow(); + } + + public class TaurcenBowArrow extends MissileWeapon { + + { + image = ItemSpriteSheet.POSION_DART; + enchantment = TaurcenBow.this.enchantment; + } + + + + public int damageRoll(Hero owner) { + return TaurcenBow.this.damageRoll(owner); + } + + @Override + protected void onThrow( int cell ) { + Char enemy = Actor.findChar( cell ); + if (enemy == null || enemy == curUser) { + parent = null; + Splash.at( cell, 0xCC99FFFF, 1 ); + } else { + if (!curUser.shoot( enemy, this )) { + Splash.at(cell, 0xCC99FFFF, 1); + } + } + } + + @Override + public void proc(Char attacker, Char defender, int damage) { + int DMG = damage; + if (TaurcenBow.charge > 7 ) { + if (arrow == Arrow.NONE) { + if (defender.isAlive()) Buff.affect(defender, ArmorBreak.class,5f).level(40); + defender.damage(DMG,this); + TaurcenBow.charge = 0; + } + if (arrow == Arrow.FIRE) { + if (defender.isAlive())Buff.affect(defender, Burning.class).reignite(defender); + defender.damage(DMG/2,this); + TaurcenBow.charge = 0; + } + if (arrow == Arrow.ICE) { + defender.damage(DMG/2,this); + if (defender.isAlive()) { + Buff.prolong(defender, Wet.class, 5f); + Buff.prolong(defender, Slow.class, 5f); + } + TaurcenBow.charge = 0; + } + if (arrow == Arrow.POSION) { + defender.damage(DMG/4,this); + if (defender.isAlive())Buff.affect(defender, Ooze.class); + TaurcenBow.charge = 0; + } + if (arrow == Arrow.ELE) { + if (defender.isAlive())Buff.affect(defender, Shocked.class,3f); + Buff.affect(attacker, AttackUp.class,10f).level(30); + defender.damage(DMG/3,this); + TaurcenBow.charge = 0; + } + + } + + if (enchantment != null) { + enchantment.proc(TaurcenBow.this, attacker, defender, damage); + } + TaurcenBow.charge++; + super.proc(attacker, defender, damage); + } + + @Override + public void cast(final Hero user, final int dst) { + final int cell = throwPos( user, dst ); + TaurcenBow.this.targetPos = cell; + super.cast(user, dst); + } + } + + private CellSelector.Listener shooter = new CellSelector.Listener() { + @Override + public void onSelect( Integer target ) { + if (target != null) { + Arrow().cast(curUser, target); + } + } + @Override + public String prompt() { + return Messages.get(ToyGun.class, "prompt"); + } + }; +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/weapon/missiles/Wave.java b/java/com/hmdzl/spspd/items/weapon/missiles/Wave.java new file mode 100644 index 00000000..b10c94c1 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/missiles/Wave.java @@ -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 + */ +package com.hmdzl.spspd.items.weapon.missiles; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Amok; +import com.hmdzl.spspd.actors.buffs.Blindness; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.utils.Random; + +public class Wave extends MissileWeapon { + + { + //name = "wave"; + image = ItemSpriteSheet.WAVE; + + STR = 10; + MIN = 1; + MAX = 3; + + // Finding them in bones would be semi-frequent and + // disappointing. + } + + public Wave() { + this(1); + } + + public Wave(int number) { + super(); + quantity = number; + } + + @Override + public void proc(Char attacker, Char defender, int damage) { + super.proc(attacker, defender, damage); + Buff.affect(defender, Amok.class,10f); + Buff.affect(defender, Blindness.class,2f); + } + + @Override + public Item random() { + quantity = Random.Int(2, 7); + return this; + } + + @Override + public int price() { + return quantity * 10; + } +} diff --git a/java/com/hmdzl/spspd/items/weapon/missiles/buildblock/BookBlock.java b/java/com/hmdzl/spspd/items/weapon/missiles/buildblock/BookBlock.java new file mode 100644 index 00000000..93e398e2 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/missiles/buildblock/BookBlock.java @@ -0,0 +1,73 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.weapon.missiles.buildblock; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.weapon.missiles.MissileWeapon; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.Terrain; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.utils.Random; + +public class BookBlock extends MissileWeapon { + + { + //name = "BookBlock"; + image = ItemSpriteSheet.BOOK_BLOCK; + + STR = 10; + + MIN = 1; + MAX = 1; + } + + public BookBlock() { + this(1); + } + + public BookBlock(int number) { + super(); + quantity = number; + } + + @Override + protected void onThrow(int cell) { + Char enemy = Actor.findChar(cell); + if ((enemy == null || enemy == curUser) && !(Dungeon.level.map[cell] == Terrain.WELL || Dungeon.level.map[cell] == Terrain.ENTRANCE || Dungeon.level.map[cell] == Terrain.EXIT )){ + Level.set(cell, Terrain.BOOKSHELF); + GameScene.updateMap(cell); + } + else + super.onThrow(cell); + } + + @Override + public Item random() { + quantity = Random.Int(1, 2); + return this; + } + + @Override + public int price() { + return 0; + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/weapon/missiles/buildblock/DoorBlock.java b/java/com/hmdzl/spspd/items/weapon/missiles/buildblock/DoorBlock.java new file mode 100644 index 00000000..282b522a --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/missiles/buildblock/DoorBlock.java @@ -0,0 +1,73 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.weapon.missiles.buildblock; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.weapon.missiles.MissileWeapon; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.Terrain; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.utils.Random; + +public class DoorBlock extends MissileWeapon { + + { + //name = "DoorBlock"; + image = ItemSpriteSheet.DOOR_BLOCK; + + STR = 10; + + MIN = 1; + MAX = 1; + } + + public DoorBlock() { + this(1); + } + + public DoorBlock(int number) { + super(); + quantity = number; + } + + @Override + protected void onThrow(int cell) { + Char enemy = Actor.findChar(cell); + if ((enemy == null || enemy == curUser) && !(Dungeon.level.map[cell] == Terrain.WELL || Dungeon.level.map[cell] == Terrain.ENTRANCE || Dungeon.level.map[cell] == Terrain.EXIT )){ + Level.set(cell, Terrain.DOOR); + GameScene.updateMap(cell); + } + else + super.onThrow(cell); + } + + @Override + public Item random() { + quantity = Random.Int(1, 2); + return this; + } + + @Override + public int price() { + return 0; + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/weapon/missiles/buildblock/StoneBlock.java b/java/com/hmdzl/spspd/items/weapon/missiles/buildblock/StoneBlock.java new file mode 100644 index 00000000..ac82e99f --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/missiles/buildblock/StoneBlock.java @@ -0,0 +1,73 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.weapon.missiles.buildblock; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.weapon.missiles.MissileWeapon; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.Terrain; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.utils.Random; + +public class StoneBlock extends MissileWeapon { + + { + //name = "StoneBlock"; + image = ItemSpriteSheet.STONE_BLOCK; + + STR = 10; + + MIN = 1; + MAX = 1; + } + + public StoneBlock() { + this(1); + } + + public StoneBlock(int number) { + super(); + quantity = number; + } + + @Override + protected void onThrow(int cell) { + Char enemy = Actor.findChar(cell); + if ((enemy == null || enemy == curUser) && !(Dungeon.level.map[cell] == Terrain.WELL || Dungeon.level.map[cell] == Terrain.ENTRANCE || Dungeon.level.map[cell] == Terrain.EXIT )){ + Level.set(cell, Terrain.STATUE); + GameScene.updateMap(cell); + } + else + super.onThrow(cell); + } + + @Override + public Item random() { + quantity = Random.Int(1, 2); + return this; + } + + @Override + public int price() { + return 0; + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/weapon/missiles/buildblock/WallBlock.java b/java/com/hmdzl/spspd/items/weapon/missiles/buildblock/WallBlock.java new file mode 100644 index 00000000..608100b5 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/missiles/buildblock/WallBlock.java @@ -0,0 +1,73 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.weapon.missiles.buildblock; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.weapon.missiles.MissileWeapon; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.Terrain; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.utils.Random; + +public class WallBlock extends MissileWeapon { + + { + //name = "WallBlock"; + image = ItemSpriteSheet.WALL_BLOCK; + + STR = 10; + + MIN = 1; + MAX = 1; + } + + public WallBlock() { + this(1); + } + + public WallBlock(int number) { + super(); + quantity = number; + } + + @Override + protected void onThrow(int cell) { + Char enemy = Actor.findChar(cell); + if ((enemy == null || enemy == curUser) && !(Dungeon.level.map[cell] == Terrain.WELL || Dungeon.level.map[cell] == Terrain.ENTRANCE || Dungeon.level.map[cell] == Terrain.EXIT )){ + Level.set(cell, Terrain.WALL); + GameScene.updateMap(cell); + } + else + super.onThrow(cell); + } + + @Override + public Item random() { + quantity = Random.Int(1, 2); + return this; + } + + @Override + public int price() { + return 0; + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/weapon/missiles/buildblock/WoodenBlock.java b/java/com/hmdzl/spspd/items/weapon/missiles/buildblock/WoodenBlock.java new file mode 100644 index 00000000..6cfdc3b8 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/missiles/buildblock/WoodenBlock.java @@ -0,0 +1,73 @@ +/* + * 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 + */ +package com.hmdzl.spspd.items.weapon.missiles.buildblock; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.weapon.missiles.MissileWeapon; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.Terrain; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.utils.Random; + +public class WoodenBlock extends MissileWeapon { + + { + //name = "WoodenBlock"; + image = ItemSpriteSheet.WOODEN_BLOCK; + + STR = 10; + + MIN = 1; + MAX = 1; + } + + public WoodenBlock() { + this(1); + } + + public WoodenBlock(int number) { + super(); + quantity = number; + } + + @Override + protected void onThrow(int cell) { + Char enemy = Actor.findChar(cell); + if ((enemy == null || enemy == curUser) && !(Dungeon.level.map[cell] == Terrain.WELL || Dungeon.level.map[cell] == Terrain.ENTRANCE || Dungeon.level.map[cell] == Terrain.EXIT )){ + Level.set(cell, Terrain.BARRICADE); + GameScene.updateMap(cell); + } + else + super.onThrow(cell); + } + + @Override + public Item random() { + quantity = Random.Int(1, 2); + return this; + } + + @Override + public int price() { + return 0; + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/weapon/spammo/BattleAmmo.java b/java/com/hmdzl/spspd/items/weapon/spammo/BattleAmmo.java new file mode 100644 index 00000000..5e4ed3c6 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/spammo/BattleAmmo.java @@ -0,0 +1,44 @@ +package com.hmdzl.spspd.items.weapon.spammo; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.AttackUp; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.DefenceUp; +import com.hmdzl.spspd.items.weapon.guns.GunWeapon; +import com.hmdzl.spspd.items.weapon.missiles.Boomerang; +import com.hmdzl.spspd.items.weapon.missiles.ManyKnive; +import com.hmdzl.spspd.sprites.ItemSprite.Glowing; +import com.hmdzl.spspd.sprites.ItemSprite; + + +public class BattleAmmo extends SpAmmo { + + private static Glowing DEEPGREEN = new ItemSprite.Glowing(0x006633); + + @Override + public Glowing glowing() { + return DEEPGREEN; + } + + @Override + public void onHit(GunWeapon gunweapon, Char attacker, Char defender, int damage) { + + defender.damage((int)(0.50*damage), attacker); + Buff.prolong(attacker, AttackUp.class,5f).level(35); + Buff.prolong(attacker, DefenceUp.class,5f).level(35); + } + @Override + public void onHit(Boomerang boomerang, Char attacker, Char defender, int damage) { + + defender.damage((int)(0.50*damage), attacker); + Buff.prolong(attacker, AttackUp.class,5f).level(35); + Buff.prolong(attacker, DefenceUp.class,5f).level(35); + } + @Override + public void onHit(ManyKnive manyknive, Char attacker, Char defender, int damage) { + + defender.damage((int)(0.50*damage), attacker); + Buff.prolong(attacker, AttackUp.class,5f).level(35); + Buff.prolong(attacker, DefenceUp.class,5f).level(35); + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/weapon/spammo/BlindAmmo.java b/java/com/hmdzl/spspd/items/weapon/spammo/BlindAmmo.java new file mode 100644 index 00000000..75fbeb46 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/spammo/BlindAmmo.java @@ -0,0 +1,63 @@ +package com.hmdzl.spspd.items.weapon.spammo; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Blindness; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Vertigo; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.weapon.guns.GunA; +import com.hmdzl.spspd.items.weapon.guns.GunB; +import com.hmdzl.spspd.items.weapon.guns.GunC; +import com.hmdzl.spspd.items.weapon.guns.GunD; +import com.hmdzl.spspd.items.weapon.guns.GunE; +import com.hmdzl.spspd.items.weapon.guns.GunWeapon; +import com.hmdzl.spspd.items.weapon.missiles.Boomerang; +import com.hmdzl.spspd.items.weapon.missiles.ManyKnive; +import com.hmdzl.spspd.sprites.ItemSprite.Glowing; +import com.hmdzl.spspd.items.weapon.guns.Sling; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.utils.Random; + +public class BlindAmmo extends SpAmmo { + +private static Glowing YELLOW = new ItemSprite.Glowing( 0xFFFF44 ); + + @Override + public Glowing glowing() { + return YELLOW; + } + + @Override + public void onHit(GunWeapon gunweapon, Char attacker, Char defender, int damage) { + + if (Random.Int(5) == 3) { + Buff.prolong(defender, Blindness.class,3f); + defender.sprite.emitter().burst(Speck.factory(Speck.LIGHT), 6); + } else if (Random.Int(5) == 3) { + Buff.prolong(defender, Vertigo.class, 3f); + } else defender.damage((int)(0.15*damage), attacker); + } + + @Override + public void onHit(Boomerang boomerang, Char attacker, Char defender, int damage) { + + if (Random.Int(5) == 3) { + Buff.prolong(defender, Blindness.class,3f); + defender.sprite.emitter().burst(Speck.factory(Speck.LIGHT), 6); + } else if (Random.Int(5) == 3) { + Buff.prolong(defender, Vertigo.class, 3f); + } else defender.damage((int)(0.15*damage), attacker); + } + @Override + public void onHit(ManyKnive manyknive, Char attacker, Char defender, int damage) { + + if (Random.Int(5) == 3) { + Buff.prolong(defender, Blindness.class,3f); + defender.sprite.emitter().burst(Speck.factory(Speck.LIGHT), 6); + } else if (Random.Int(5) == 3) { + Buff.prolong(defender, Vertigo.class, 3f); + } else defender.damage((int)(0.15*damage), attacker); + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/weapon/spammo/DewAmmo.java b/java/com/hmdzl/spspd/items/weapon/spammo/DewAmmo.java new file mode 100644 index 00000000..7b3dca24 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/spammo/DewAmmo.java @@ -0,0 +1,59 @@ +package com.hmdzl.spspd.items.weapon.spammo; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.weapon.guns.GunA; +import com.hmdzl.spspd.items.weapon.guns.GunB; +import com.hmdzl.spspd.items.weapon.guns.GunC; +import com.hmdzl.spspd.items.weapon.guns.GunD; +import com.hmdzl.spspd.items.weapon.guns.GunE; +import com.hmdzl.spspd.items.weapon.guns.GunWeapon; +import com.hmdzl.spspd.items.weapon.missiles.Boomerang; +import com.hmdzl.spspd.items.weapon.missiles.ManyKnive; +import com.hmdzl.spspd.sprites.ItemSprite.Glowing; +import com.hmdzl.spspd.items.weapon.guns.Sling; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.utils.Random; + +public class DewAmmo extends SpAmmo { + + //private static final Glowing BLACK = new Glowing(0x00000); + + //@Override + //public Glowing glowing() { + //return BLACK; + //} + + @Override + public void onHit(GunWeapon gunweapon, Char attacker, Char defender, int damage) { + defender.damage(Random.Int((int)(0.25*damage)), attacker); + defender.damage(Random.Int((int)(0.25*damage)), attacker); + defender.damage(Random.Int((int)(0.25*damage)), attacker); + defender.damage(Random.Int((int)(0.25*damage)), attacker); + defender.damage(Random.Int((int)(0.25*damage)), attacker); + defender.damage(Random.Int((int)(0.25*damage)), attacker); + + } + + @Override + public void onHit(Boomerang boomerang, Char attacker, Char defender, int damage) { + defender.damage(Random.Int((int)(0.25*damage)), attacker); + defender.damage(Random.Int((int)(0.25*damage)), attacker); + defender.damage(Random.Int((int)(0.25*damage)), attacker); + defender.damage(Random.Int((int)(0.25*damage)), attacker); + defender.damage(Random.Int((int)(0.25*damage)), attacker); + defender.damage(Random.Int((int)(0.25*damage)), attacker); + + } + @Override + public void onHit(ManyKnive manyknive, Char attacker, Char defender, int damage) { + defender.damage(Random.Int((int)(0.25*damage)), attacker); + defender.damage(Random.Int((int)(0.25*damage)), attacker); + defender.damage(Random.Int((int)(0.25*damage)), attacker); + defender.damage(Random.Int((int)(0.25*damage)), attacker); + defender.damage(Random.Int((int)(0.25*damage)), attacker); + defender.damage(Random.Int((int)(0.25*damage)), attacker); + + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/weapon/spammo/DreamAmmo.java b/java/com/hmdzl/spspd/items/weapon/spammo/DreamAmmo.java new file mode 100644 index 00000000..deb4c51e --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/spammo/DreamAmmo.java @@ -0,0 +1,49 @@ +package com.hmdzl.spspd.items.weapon.spammo; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.ArmorBreak; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Cripple; +import com.hmdzl.spspd.actors.buffs.Slow; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.weapon.guns.GunA; +import com.hmdzl.spspd.items.weapon.guns.GunB; +import com.hmdzl.spspd.items.weapon.guns.GunC; +import com.hmdzl.spspd.items.weapon.guns.GunD; +import com.hmdzl.spspd.items.weapon.guns.GunE; +import com.hmdzl.spspd.items.weapon.guns.GunWeapon; +import com.hmdzl.spspd.items.weapon.missiles.Boomerang; +import com.hmdzl.spspd.items.weapon.missiles.ManyKnive; +import com.hmdzl.spspd.sprites.ItemSprite.Glowing; +import com.hmdzl.spspd.items.weapon.guns.Sling; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class DreamAmmo extends SpAmmo { + + private static Glowing GREEN = new ItemSprite.Glowing(0x22CC44); + + @Override + public Glowing glowing() { + return GREEN; + } + + @Override + public void onHit(GunWeapon gunweapon, Char attacker, Char defender, int damage) { + defender.damage((int)(0.20*damage), attacker); + Buff.prolong(defender, ArmorBreak.class,6f).level(25); + Buff.prolong(defender, Slow.class,3f); + } + @Override + public void onHit(Boomerang boomerang, Char attacker, Char defender, int damage) { + defender.damage((int)(0.20*damage), attacker); + Buff.prolong(defender, ArmorBreak.class,6f).level(25); + Buff.prolong(defender, Slow.class,3f); + } + @Override + public void onHit(ManyKnive manyknive, Char attacker, Char defender, int damage) { + defender.damage((int)(0.20*damage), attacker); + Buff.prolong(defender, ArmorBreak.class,6f).level(25); + Buff.prolong(defender, Slow.class,3f); + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/weapon/spammo/EmptyAmmo.java b/java/com/hmdzl/spspd/items/weapon/spammo/EmptyAmmo.java new file mode 100644 index 00000000..a567f9a3 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/spammo/EmptyAmmo.java @@ -0,0 +1,53 @@ +package com.hmdzl.spspd.items.weapon.spammo; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Blindness; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Vertigo; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.weapon.guns.GunA; +import com.hmdzl.spspd.items.weapon.guns.GunB; +import com.hmdzl.spspd.items.weapon.guns.GunC; +import com.hmdzl.spspd.items.weapon.guns.GunD; +import com.hmdzl.spspd.items.weapon.guns.GunE; +import com.hmdzl.spspd.items.weapon.guns.GunWeapon; +import com.hmdzl.spspd.items.weapon.missiles.Boomerang; +import com.hmdzl.spspd.items.weapon.missiles.ManyKnive; +import com.hmdzl.spspd.sprites.ItemSprite.Glowing; +import com.hmdzl.spspd.items.weapon.guns.Sling; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.utils.Random; + +public class EmptyAmmo extends SpAmmo { + + //private static final Glowing BLACK = new Glowing(0x00000); + + //@Override + //public Glowing glowing() { + //return BLACK; + //} + + @Override + public void onHit(GunWeapon gunweapon, Char attacker, Char defender, int damage) { + + if(defender.properties().contains(Char.Property.BOSS)){ + defender.damage(Math.min(defender.HT/20,3000),this); + } + } + @Override + public void onHit(Boomerang boomerang, Char attacker, Char defender, int damage) { + + if(defender.properties().contains(Char.Property.BOSS)){ + defender.damage(Math.min(defender.HT/20,3000),this); + } + } + @Override + public void onHit(ManyKnive manyknive, Char attacker, Char defender, int damage) { + + if(defender.properties().contains(Char.Property.BOSS)){ + defender.damage(Math.min(defender.HT/20,3000),this); + } + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/weapon/spammo/EvolveAmmo.java b/java/com/hmdzl/spspd/items/weapon/spammo/EvolveAmmo.java new file mode 100644 index 00000000..d47bdf64 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/spammo/EvolveAmmo.java @@ -0,0 +1,83 @@ +package com.hmdzl.spspd.items.weapon.spammo; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.mobs.NormalCell; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.weapon.guns.GunWeapon; +import com.hmdzl.spspd.items.weapon.missiles.Boomerang; +import com.hmdzl.spspd.items.weapon.missiles.ManyKnive; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSprite.Glowing; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.watabou.utils.Random; + +public class EvolveAmmo extends SpAmmo { + + private static Glowing DEEPGREEN = new ItemSprite.Glowing(0x006633); + + @Override + public Glowing glowing() { + return DEEPGREEN; + } + + @Override + public void onHit(GunWeapon gunweapon, Char attacker, Char defender, int damage) { + + if (Random.Int(10) == 3) { + if (defender != null && defender != attacker + && !defender.properties().contains(Char.Property.BOSS) + && !defender.properties().contains(Char.Property.MINIBOSS)) { + NormalCell cell = new NormalCell(); + cell.HT = defender.HP; + cell.HP = cell.HT; + cell.pos = defender.pos; + defender.destroy(); + defender.sprite.killAndErase(); + Dungeon.level.mobs.remove(defender); + GameScene.add(cell); + CellEmitter.get(cell.pos).burst(Speck.factory(Speck.WOOL), 4); + } + } else defender.damage((int)(0.10*damage), attacker); + } + + @Override + public void onHit(Boomerang boomerang, Char attacker, Char defender, int damage) { + + if (Random.Int(10) == 3) { + if (defender != null && defender != attacker + && !defender.properties().contains(Char.Property.BOSS) + && !defender.properties().contains(Char.Property.MINIBOSS)) { + NormalCell cell = new NormalCell(); + cell.HT = defender.HP; + cell.HP = cell.HT; + cell.pos = defender.pos; + defender.destroy(); + defender.sprite.killAndErase(); + Dungeon.level.mobs.remove(defender); + GameScene.add(cell); + CellEmitter.get(cell.pos).burst(Speck.factory(Speck.WOOL), 4); + } + } else defender.damage((int)(0.10*damage), attacker); + } + @Override + public void onHit(ManyKnive manyknive, Char attacker, Char defender, int damage) { + + if (Random.Int(10) == 3) { + if (defender != null && defender != attacker + && !defender.properties().contains(Char.Property.BOSS) + && !defender.properties().contains(Char.Property.MINIBOSS)) { + NormalCell cell = new NormalCell(); + cell.HT = defender.HP; + cell.HP = cell.HT; + cell.pos = defender.pos; + defender.destroy(); + defender.sprite.killAndErase(); + Dungeon.level.mobs.remove(defender); + GameScene.add(cell); + CellEmitter.get(cell.pos).burst(Speck.factory(Speck.WOOL), 4); + } + } else defender.damage((int)(0.10*damage), attacker); + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/weapon/spammo/FireAmmo.java b/java/com/hmdzl/spspd/items/weapon/spammo/FireAmmo.java new file mode 100644 index 00000000..bd317335 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/spammo/FireAmmo.java @@ -0,0 +1,60 @@ +package com.hmdzl.spspd.items.weapon.spammo; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Burning; +import com.hmdzl.spspd.effects.particles.FlameParticle; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.weapon.guns.GunA; +import com.hmdzl.spspd.items.weapon.guns.GunB; +import com.hmdzl.spspd.items.weapon.guns.GunC; +import com.hmdzl.spspd.items.weapon.guns.GunD; +import com.hmdzl.spspd.items.weapon.guns.GunE; +import com.hmdzl.spspd.items.weapon.guns.GunWeapon; +import com.hmdzl.spspd.items.weapon.missiles.Boomerang; +import com.hmdzl.spspd.items.weapon.missiles.ManyKnive; +import com.hmdzl.spspd.sprites.ItemSprite.Glowing; +import com.hmdzl.spspd.items.weapon.guns.Sling; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.utils.Random; + +public class FireAmmo extends SpAmmo { + + private static Glowing ORANGE = new ItemSprite.Glowing( 0xFF4400 ); + + @Override + public Glowing glowing() { + return ORANGE; + } + + @Override + public void onHit(GunWeapon gunweapon, Char attacker, Char defender, int damage) { + + defender.sprite.emitter().burst(FlameParticle.FACTORY, 5); + if (Random.Int(5) == 4 ) { + Buff.affect(defender, Burning.class).reignite( defender ); + } else defender.damage((int)(0.25*damage), attacker); + + } + + @Override + public void onHit(Boomerang boomerang, Char attacker, Char defender, int damage) { + + defender.sprite.emitter().burst(FlameParticle.FACTORY, 5); + if (Random.Int(5) == 4 ) { + Buff.affect(defender, Burning.class).reignite( defender ); + } else defender.damage((int)(0.25*damage), attacker); + + } + @Override + public void onHit(ManyKnive manyknive, Char attacker, Char defender, int damage) { + + defender.sprite.emitter().burst(FlameParticle.FACTORY, 5); + if (Random.Int(5) == 4 ) { + Buff.affect(defender, Burning.class).reignite( defender ); + } else defender.damage((int)(0.25*damage), attacker); + + } + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/weapon/spammo/GoldAmmo.java b/java/com/hmdzl/spspd/items/weapon/spammo/GoldAmmo.java new file mode 100644 index 00000000..880abd5e --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/spammo/GoldAmmo.java @@ -0,0 +1,40 @@ +package com.hmdzl.spspd.items.weapon.spammo; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.items.weapon.guns.GunWeapon; +import com.hmdzl.spspd.items.weapon.missiles.Boomerang; +import com.hmdzl.spspd.items.weapon.missiles.ManyKnive; +import com.hmdzl.spspd.sprites.ItemSprite.Glowing; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.watabou.utils.Random; + +public class GoldAmmo extends SpAmmo { + +private static Glowing YELLOW = new ItemSprite.Glowing( 0xFFFF44 ); + + @Override + public Glowing glowing() { + return YELLOW; + } + + @Override + public void onHit(GunWeapon gunweapon, Char attacker, Char defender, int damage) { + defender.damage((int)(Dungeon.gold*0.01*Random.Float(0.25f,2.0f)), attacker); + + Dungeon.gold -= (int)(Dungeon.gold*0.01); + } + + @Override + public void onHit(Boomerang boomerang, Char attacker, Char defender, int damage) { + defender.damage((int)(Dungeon.gold*0.01*Random.Float(0.25f,2.0f)), attacker); + + Dungeon.gold -= (int)(Dungeon.gold*0.01); + } + @Override + public void onHit(ManyKnive manyknive, Char attacker, Char defender, int damage) { + defender.damage((int)(Dungeon.gold*0.01*Random.Float(0.25f,2.0f)), attacker); + + Dungeon.gold -= (int)(Dungeon.gold*0.01); + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/weapon/spammo/HeavyAmmo.java b/java/com/hmdzl/spspd/items/weapon/spammo/HeavyAmmo.java new file mode 100644 index 00000000..f85b69d0 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/spammo/HeavyAmmo.java @@ -0,0 +1,39 @@ +package com.hmdzl.spspd.items.weapon.spammo; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.weapon.guns.GunA; +import com.hmdzl.spspd.items.weapon.guns.GunB; +import com.hmdzl.spspd.items.weapon.guns.GunC; +import com.hmdzl.spspd.items.weapon.guns.GunD; +import com.hmdzl.spspd.items.weapon.guns.GunE; +import com.hmdzl.spspd.items.weapon.guns.GunWeapon; +import com.hmdzl.spspd.items.weapon.missiles.Boomerang; +import com.hmdzl.spspd.items.weapon.missiles.ManyKnive; +import com.hmdzl.spspd.sprites.ItemSprite.Glowing; +import com.hmdzl.spspd.items.weapon.guns.Sling; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class HeavyAmmo extends SpAmmo { + + private static final Glowing BLACK = new Glowing(0x00000); + + @Override + public Glowing glowing() { + return BLACK; + } + + @Override + public void onHit(GunWeapon gunweapon, Char attacker, Char defender, int damage) { + defender.damage((int)(0.75*damage), attacker); + } + @Override + public void onHit(Boomerang boomerang, Char attacker, Char defender, int damage) { + defender.damage((int)(0.75*damage), attacker); + } + @Override + public void onHit(ManyKnive manyknive, Char attacker, Char defender, int damage) { + defender.damage((int)(0.75*damage), attacker); + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/weapon/spammo/IceAmmo.java b/java/com/hmdzl/spspd/items/weapon/spammo/IceAmmo.java new file mode 100644 index 00000000..768665d8 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/spammo/IceAmmo.java @@ -0,0 +1,74 @@ +package com.hmdzl.spspd.items.weapon.spammo; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Chill; +import com.hmdzl.spspd.actors.buffs.Cold; +import com.hmdzl.spspd.actors.buffs.Frost; +import com.hmdzl.spspd.actors.buffs.Wet; +import com.hmdzl.spspd.effects.particles.SnowParticle; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.weapon.guns.GunA; +import com.hmdzl.spspd.items.weapon.guns.GunB; +import com.hmdzl.spspd.items.weapon.guns.GunC; +import com.hmdzl.spspd.items.weapon.guns.GunD; +import com.hmdzl.spspd.items.weapon.guns.GunE; +import com.hmdzl.spspd.items.weapon.guns.GunWeapon; +import com.hmdzl.spspd.items.weapon.missiles.Boomerang; +import com.hmdzl.spspd.items.weapon.missiles.ManyKnive; +import com.hmdzl.spspd.sprites.ItemSprite.Glowing; +import com.hmdzl.spspd.items.weapon.guns.Sling; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.utils.Random; + +public class IceAmmo extends SpAmmo { + + private static Glowing BLUE = new ItemSprite.Glowing(0x0000FF); + + @Override + public Glowing glowing() { + return BLUE; + } + + @Override + public void onHit(GunWeapon gunweapon, Char attacker, Char defender, int damage) { + + defender.damage((int)(0.25*damage), attacker); + + if (Random.Int(4) == 3) { + Buff.affect(defender, Frost.class, Frost.duration(defender)*Random.Float(2f, 4f)); + defender.sprite.emitter().burst(SnowParticle.FACTORY, 5); + } else { + Buff.prolong(defender, Wet.class, 2f); + Buff.prolong(defender, Cold.class,2f); + } + } + + @Override + public void onHit(Boomerang boomerang, Char attacker, Char defender, int damage) { + + defender.damage((int)(0.25*damage), attacker); + + if (Random.Int(4) == 3) { + Buff.affect(defender, Frost.class, Frost.duration(defender)*Random.Float(2f, 4f)); + defender.sprite.emitter().burst(SnowParticle.FACTORY, 5); + } else { + Buff.prolong(defender, Wet.class, 2f); + Buff.prolong(defender, Cold.class,2f); + } + } + @Override + public void onHit(ManyKnive manyknive, Char attacker, Char defender, int damage) { + + defender.damage((int)(0.25*damage), attacker); + + if (Random.Int(4) == 3) { + Buff.affect(defender, Frost.class, Frost.duration(defender)*Random.Float(2f, 4f)); + defender.sprite.emitter().burst(SnowParticle.FACTORY, 5); + } else { + Buff.prolong(defender, Wet.class, 2f); + Buff.prolong(defender, Cold.class,2f); + } + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/weapon/spammo/MossAmmo.java b/java/com/hmdzl/spspd/items/weapon/spammo/MossAmmo.java new file mode 100644 index 00000000..46d5a002 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/spammo/MossAmmo.java @@ -0,0 +1,63 @@ +package com.hmdzl.spspd.items.weapon.spammo; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Ooze; +import com.hmdzl.spspd.actors.buffs.Poison; +import com.hmdzl.spspd.effects.particles.EarthParticle; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.weapon.guns.GunA; +import com.hmdzl.spspd.items.weapon.guns.GunB; +import com.hmdzl.spspd.items.weapon.guns.GunC; +import com.hmdzl.spspd.items.weapon.guns.GunD; +import com.hmdzl.spspd.items.weapon.guns.GunE; +import com.hmdzl.spspd.items.weapon.guns.GunWeapon; +import com.hmdzl.spspd.items.weapon.missiles.Boomerang; +import com.hmdzl.spspd.items.weapon.missiles.ManyKnive; +import com.hmdzl.spspd.sprites.ItemSprite.Glowing; +import com.hmdzl.spspd.items.weapon.guns.Sling; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.utils.Random; + +public class MossAmmo extends SpAmmo { + + private static Glowing PURPLE = new ItemSprite.Glowing(0x8844CC); + + @Override + public Glowing glowing() { + return PURPLE; + } + + @Override + public void onHit(GunWeapon gunweapon, Char attacker, Char defender, int damage) { + defender.damage((int)(0.10*damage), attacker); + if (Random.Int(4) == 3) { + Buff.affect(defender, Ooze.class); + defender.sprite.emitter().burst(EarthParticle.FACTORY, 5); + } else { + Buff.affect(defender, Poison.class).set(Random.Int(4, 5)); + } + } + + @Override + public void onHit(Boomerang boomerang, Char attacker, Char defender, int damage) { + defender.damage((int)(0.10*damage), attacker); + if (Random.Int(4) == 3) { + Buff.affect(defender, Ooze.class); + defender.sprite.emitter().burst(EarthParticle.FACTORY, 5); + } else { + Buff.affect(defender, Poison.class).set(Random.Int(4, 5)); + } + } + @Override + public void onHit(ManyKnive manyknive, Char attacker, Char defender, int damage) { + defender.damage((int)(0.10*damage), attacker); + if (Random.Int(4) == 3) { + Buff.affect(defender, Ooze.class); + defender.sprite.emitter().burst(EarthParticle.FACTORY, 5); + } else { + Buff.affect(defender, Poison.class).set(Random.Int(4, 5)); + } + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/weapon/spammo/RotAmmo.java b/java/com/hmdzl/spspd/items/weapon/spammo/RotAmmo.java new file mode 100644 index 00000000..4e2e6b19 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/spammo/RotAmmo.java @@ -0,0 +1,63 @@ +package com.hmdzl.spspd.items.weapon.spammo; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Blindness; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Ooze; +import com.hmdzl.spspd.actors.buffs.Roots; +import com.hmdzl.spspd.actors.buffs.Vertigo; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.weapon.guns.GunA; +import com.hmdzl.spspd.items.weapon.guns.GunB; +import com.hmdzl.spspd.items.weapon.guns.GunC; +import com.hmdzl.spspd.items.weapon.guns.GunD; +import com.hmdzl.spspd.items.weapon.guns.GunE; +import com.hmdzl.spspd.items.weapon.guns.GunWeapon; +import com.hmdzl.spspd.items.weapon.missiles.Boomerang; +import com.hmdzl.spspd.items.weapon.missiles.ManyKnive; +import com.hmdzl.spspd.sprites.ItemSprite.Glowing; +import com.hmdzl.spspd.items.weapon.guns.Sling; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.utils.Random; + +public class RotAmmo extends SpAmmo { + + private static Glowing RED = new ItemSprite.Glowing(0xCC0000); + + @Override + public Glowing glowing() { + return RED; + } + + @Override + public void onHit(GunWeapon gunweapon, Char attacker, Char defender, int damage) { + + if (Random.Int(7) == 3) { + Buff.prolong(defender, Roots.class,3f); + } else + Buff.affect(defender, Ooze.class); + defender.damage((int)(0.5*damage), attacker); + } + + @Override + public void onHit(Boomerang boomerang, Char attacker, Char defender, int damage) { + + if (Random.Int(7) == 3) { + Buff.prolong(defender, Roots.class,3f); + } else + Buff.affect(defender, Ooze.class); + defender.damage((int)(0.5*damage), attacker); + } + @Override + public void onHit(ManyKnive manyknive, Char attacker, Char defender, int damage) { + + if (Random.Int(7) == 3) { + Buff.prolong(defender, Roots.class,3f); + } else + Buff.affect(defender, Ooze.class); + defender.damage((int)(0.5*damage), attacker); + } + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/weapon/spammo/SandAmmo.java b/java/com/hmdzl/spspd/items/weapon/spammo/SandAmmo.java new file mode 100644 index 00000000..d2779f56 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/spammo/SandAmmo.java @@ -0,0 +1,64 @@ +package com.hmdzl.spspd.items.weapon.spammo; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.ArmorBreak; +import com.hmdzl.spspd.actors.buffs.AttackDown; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Dry; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.weapon.guns.GunA; +import com.hmdzl.spspd.items.weapon.guns.GunB; +import com.hmdzl.spspd.items.weapon.guns.GunC; +import com.hmdzl.spspd.items.weapon.guns.GunD; +import com.hmdzl.spspd.items.weapon.guns.GunE; +import com.hmdzl.spspd.items.weapon.guns.GunWeapon; +import com.hmdzl.spspd.items.weapon.missiles.Boomerang; +import com.hmdzl.spspd.items.weapon.missiles.ManyKnive; +import com.hmdzl.spspd.sprites.ItemSprite.Glowing; +import com.hmdzl.spspd.items.weapon.guns.Sling; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.utils.Random; + +public class SandAmmo extends SpAmmo { + + private static Glowing GERY = new ItemSprite.Glowing(0xCCCCCC); + + @Override + public Glowing glowing() { + return GERY; + } + + + @Override + public void onHit(GunWeapon gunweapon, Char attacker, Char defender, int damage) { + if (Random.Int(5) == 3) { + Buff.affect(defender, AttackDown.class,3f).level(25); + Buff.affect(defender, ArmorBreak.class,3f).level(25); + defender.sprite.emitter().burst(Speck.factory(Speck.LIGHT), 6); + } else if (Random.Int(4) == 1) { + Buff.prolong(defender, Dry.class, 3f); + } else defender.damage((int)(0.15*damage), attacker); + } + @Override + public void onHit(Boomerang boomerang, Char attacker, Char defender, int damage) { + if (Random.Int(5) == 3) { + Buff.affect(defender, AttackDown.class,3f).level(25); + Buff.affect(defender, ArmorBreak.class,3f).level(25); + defender.sprite.emitter().burst(Speck.factory(Speck.LIGHT), 6); + } else if (Random.Int(4) == 1) { + Buff.prolong(defender, Dry.class, 3f); + } else defender.damage((int)(0.15*damage), attacker); + } + @Override + public void onHit(ManyKnive manyknive, Char attacker, Char defender, int damage) { + if (Random.Int(5) == 3) { + Buff.affect(defender, AttackDown.class,3f).level(25); + Buff.affect(defender, ArmorBreak.class,3f).level(25); + defender.sprite.emitter().burst(Speck.factory(Speck.LIGHT), 6); + } else if (Random.Int(4) == 1) { + Buff.prolong(defender, Dry.class, 3f); + } else defender.damage((int)(0.15*damage), attacker); + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/weapon/spammo/SpAmmo.java b/java/com/hmdzl/spspd/items/weapon/spammo/SpAmmo.java new file mode 100644 index 00000000..afb0a3ea --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/spammo/SpAmmo.java @@ -0,0 +1,46 @@ + +package com.hmdzl.spspd.items.weapon.spammo; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.weapon.guns.GunA; +import com.hmdzl.spspd.items.weapon.guns.GunB; +import com.hmdzl.spspd.items.weapon.guns.GunC; +import com.hmdzl.spspd.items.weapon.guns.GunD; +import com.hmdzl.spspd.items.weapon.guns.GunE; +import com.hmdzl.spspd.items.weapon.guns.GunWeapon; +import com.hmdzl.spspd.items.weapon.guns.Sling; +import com.hmdzl.spspd.items.weapon.missiles.Boomerang; +import com.hmdzl.spspd.items.weapon.missiles.ManyKnive; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public abstract class SpAmmo extends Item { + + { + image = ItemSpriteSheet.SPAMMO; + + stackable=false; + } + + public abstract void onHit(GunWeapon gunweapon, Char attacker, Char defender, int damage); + + public abstract void onHit(Boomerang boomerang, Char attacker, Char defender, int damage); + + public abstract void onHit(ManyKnive manyknive, Char attacker, Char defender, int damage); + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + @Override + public int price() { + return 100 * quantity; + } + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/weapon/spammo/StarAmmo.java b/java/com/hmdzl/spspd/items/weapon/spammo/StarAmmo.java new file mode 100644 index 00000000..64ce0f1f --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/spammo/StarAmmo.java @@ -0,0 +1,65 @@ +package com.hmdzl.spspd.items.weapon.spammo; + +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.particles.ShadowParticle; +import com.hmdzl.spspd.items.weapon.guns.GunWeapon; +import com.hmdzl.spspd.items.weapon.missiles.Boomerang; +import com.hmdzl.spspd.items.weapon.missiles.ManyKnive; +import com.hmdzl.spspd.sprites.ItemSprite.Glowing; +import com.watabou.utils.Random; + +public class StarAmmo extends SpAmmo { + + private static final Glowing BLACK = new Glowing(0x00000); + + @Override + public Glowing glowing() { + return BLACK; + } + + @Override + public void onHit(GunWeapon gunweapon, Char attacker, Char defender, int damage) { + + if (Random.Int(20) == 1) { + if (defender.properties().contains(Char.Property.BOSS) || defender.properties().contains(Char.Property.MINIBOSS)) { + defender.damage(Random.Int(defender.HT / 8, defender.HT / 4), this); + } else defender.damage(Random.Int(defender.HT, defender.HT * 2), this); + defender.sprite.emitter().burst(ShadowParticle.UP, 5); + if (!defender.isAlive() && attacker instanceof Hero) { + Badges.validateGrimWeapon(); + } + } else + defender.damage((int)(0.4*damage), attacker); + } + + @Override + public void onHit(Boomerang boomerang, Char attacker, Char defender, int damage) { + + if (Random.Int(20) == 1) { + if (defender.properties().contains(Char.Property.BOSS) || defender.properties().contains(Char.Property.MINIBOSS)) { + defender.damage(Random.Int(defender.HT / 8, defender.HT / 4), this); + } else defender.damage(Random.Int(defender.HT, defender.HT * 2), this); + defender.sprite.emitter().burst(ShadowParticle.UP, 5); + if (!defender.isAlive() && attacker instanceof Hero) { + Badges.validateGrimWeapon(); + } + } else + defender.damage((int)(0.4*damage), attacker); + } + @Override + public void onHit(ManyKnive manyknive, Char attacker, Char defender, int damage) { + + if (Random.Int(20) == 1) { + if (defender.properties().contains(Char.Property.BOSS) || defender.properties().contains(Char.Property.MINIBOSS)) { + defender.damage(Random.Int(defender.HT / 8, defender.HT / 4), this); + } else defender.damage(Random.Int(defender.HT, defender.HT * 2), this); + defender.sprite.emitter().burst(ShadowParticle.UP, 5); + if (!defender.isAlive() && attacker instanceof Hero) { + Badges.validateGrimWeapon(); + } + } else + defender.damage((int)(0.4*damage), attacker); + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/weapon/spammo/StormAmmo.java b/java/com/hmdzl/spspd/items/weapon/spammo/StormAmmo.java new file mode 100644 index 00000000..b2e794a6 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/spammo/StormAmmo.java @@ -0,0 +1,57 @@ +package com.hmdzl.spspd.items.weapon.spammo; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Shocked; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.weapon.guns.GunA; +import com.hmdzl.spspd.items.weapon.guns.GunB; +import com.hmdzl.spspd.items.weapon.guns.GunC; +import com.hmdzl.spspd.items.weapon.guns.GunD; +import com.hmdzl.spspd.items.weapon.guns.GunE; +import com.hmdzl.spspd.items.weapon.guns.GunWeapon; +import com.hmdzl.spspd.items.weapon.missiles.Boomerang; +import com.hmdzl.spspd.items.weapon.missiles.ManyKnive; +import com.hmdzl.spspd.sprites.ItemSprite.Glowing; +import com.hmdzl.spspd.items.weapon.guns.Sling; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.utils.Random; + +public class StormAmmo extends SpAmmo { + + private static Glowing WHITE = new ItemSprite.Glowing(0xFFFFFF); + + @Override + public Glowing glowing() { + return WHITE; + } + + @Override + public void onHit(GunWeapon gunweapon, Char attacker, Char defender, int damage) { + + if (Random.Int(6) == 3) { + Buff.prolong(defender, Shocked.class,2f); + + } else defender.damage((int)(0.40*damage), attacker); + + } + @Override + public void onHit(Boomerang boomerang, Char attacker, Char defender, int damage) { + + if (Random.Int(6) == 3) { + Buff.prolong(defender, Shocked.class,2f); + + } else defender.damage((int)(0.40*damage), attacker); + + } + @Override + public void onHit(ManyKnive manyknive, Char attacker, Char defender, int damage) { + + if (Random.Int(6) == 3) { + Buff.prolong(defender, Shocked.class,2f); + + } else defender.damage((int)(0.40*damage), attacker); + + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/weapon/spammo/SunAmmo.java b/java/com/hmdzl/spspd/items/weapon/spammo/SunAmmo.java new file mode 100644 index 00000000..b891d70b --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/spammo/SunAmmo.java @@ -0,0 +1,55 @@ +package com.hmdzl.spspd.items.weapon.spammo; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.GrowSeed; +import com.hmdzl.spspd.effects.particles.EarthParticle; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.weapon.guns.GunA; +import com.hmdzl.spspd.items.weapon.guns.GunB; +import com.hmdzl.spspd.items.weapon.guns.GunC; +import com.hmdzl.spspd.items.weapon.guns.GunD; +import com.hmdzl.spspd.items.weapon.guns.GunE; +import com.hmdzl.spspd.items.weapon.guns.GunWeapon; +import com.hmdzl.spspd.items.weapon.missiles.Boomerang; +import com.hmdzl.spspd.items.weapon.missiles.ManyKnive; +import com.hmdzl.spspd.sprites.ItemSprite.Glowing; +import com.hmdzl.spspd.items.weapon.guns.Sling; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.utils.Random; + +public class SunAmmo extends SpAmmo { + + private static Glowing PINK = new ItemSprite.Glowing(0xCCAA88); + + @Override + public Glowing glowing() { + return PINK; + } + + @Override + public void onHit(GunWeapon gunweapon, Char attacker, Char defender, int damage) { + if (Random.Int(7) == 3) { + Buff.affect(defender, GrowSeed.class).reignite(defender); + defender.sprite.emitter().burst(EarthParticle.FACTORY, 5); + } else defender.damage((int)(0.20*damage), attacker); + } + + @Override + public void onHit(Boomerang boomerang, Char attacker, Char defender, int damage) { + if (Random.Int(7) == 3) { + Buff.affect(defender, GrowSeed.class).reignite(defender); + defender.sprite.emitter().burst(EarthParticle.FACTORY, 5); + } else defender.damage((int)(0.20*damage), attacker); + } + + @Override + public void onHit(ManyKnive manyknive, Char attacker, Char defender, int damage) { + if (Random.Int(7) == 3) { + Buff.affect(defender, GrowSeed.class).reignite(defender); + defender.sprite.emitter().burst(EarthParticle.FACTORY, 5); + } else defender.damage((int)(0.20*damage), attacker); + } + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/weapon/spammo/ThornAmmo.java b/java/com/hmdzl/spspd/items/weapon/spammo/ThornAmmo.java new file mode 100644 index 00000000..18795d78 --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/spammo/ThornAmmo.java @@ -0,0 +1,62 @@ +package com.hmdzl.spspd.items.weapon.spammo; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Bleeding; +import com.hmdzl.spspd.actors.buffs.Blindness; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Cripple; +import com.hmdzl.spspd.actors.buffs.Vertigo; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.weapon.guns.GunA; +import com.hmdzl.spspd.items.weapon.guns.GunB; +import com.hmdzl.spspd.items.weapon.guns.GunC; +import com.hmdzl.spspd.items.weapon.guns.GunD; +import com.hmdzl.spspd.items.weapon.guns.GunE; +import com.hmdzl.spspd.items.weapon.guns.GunWeapon; +import com.hmdzl.spspd.items.weapon.missiles.Boomerang; +import com.hmdzl.spspd.items.weapon.missiles.ManyKnive; +import com.hmdzl.spspd.sprites.ItemSprite.Glowing; +import com.hmdzl.spspd.items.weapon.guns.Sling; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.utils.Random; + +public class ThornAmmo extends SpAmmo { + + private static Glowing BROWN = new ItemSprite.Glowing(0xCC6600); + + @Override + public Glowing glowing() { + return BROWN; + } + + @Override + public void onHit(GunWeapon gunweapon, Char attacker, Char defender, int damage) { + + if (Random.Int(5) == 3) { + Buff.affect(defender, Bleeding.class).set(Random.Int(5,damage)); + } else + Buff.prolong(defender, Cripple.class, 3f); + defender.damage((int)(0.20*damage), attacker); + } + + @Override + public void onHit(Boomerang boomerang, Char attacker, Char defender, int damage) { + + if (Random.Int(5) == 3) { + Buff.affect(defender, Bleeding.class).set(Random.Int(5,damage)); + } else + Buff.prolong(defender, Cripple.class, 3f); + defender.damage((int)(0.20*damage), attacker); + } + @Override + public void onHit(ManyKnive manyknive, Char attacker, Char defender, int damage) { + + if (Random.Int(5) == 3) { + Buff.affect(defender, Bleeding.class).set(Random.Int(5,damage)); + } else + Buff.prolong(defender, Cripple.class, 3f); + defender.damage((int)(0.20*damage), attacker); + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/items/weapon/spammo/WoodenAmmo.java b/java/com/hmdzl/spspd/items/weapon/spammo/WoodenAmmo.java new file mode 100644 index 00000000..acba2cba --- /dev/null +++ b/java/com/hmdzl/spspd/items/weapon/spammo/WoodenAmmo.java @@ -0,0 +1,53 @@ +package com.hmdzl.spspd.items.weapon.spammo; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Paralysis; +import com.hmdzl.spspd.actors.buffs.Vertigo; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.weapon.guns.GunA; +import com.hmdzl.spspd.items.weapon.guns.GunB; +import com.hmdzl.spspd.items.weapon.guns.GunC; +import com.hmdzl.spspd.items.weapon.guns.GunD; +import com.hmdzl.spspd.items.weapon.guns.GunE; +import com.hmdzl.spspd.items.weapon.guns.GunWeapon; +import com.hmdzl.spspd.items.weapon.missiles.Boomerang; +import com.hmdzl.spspd.items.weapon.missiles.ManyKnive; +import com.hmdzl.spspd.sprites.ItemSprite.Glowing; +import com.hmdzl.spspd.items.weapon.guns.Sling; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.utils.Random; + +public class WoodenAmmo extends SpAmmo { + + private static final Glowing BLACK = new Glowing(0x00000); + + @Override + public Glowing glowing() { + return BLACK; + } + + @Override + public void onHit(GunWeapon gunweapon, Char attacker, Char defender, int damage) { + Buff.prolong(defender,Vertigo.class,3f); + if (Random.Int(10) == 1){ + Buff.prolong(defender,Paralysis.class,3f); + } + } + @Override + public void onHit(Boomerang boomerang, Char attacker, Char defender, int damage) { + Buff.prolong(defender,Vertigo.class,3f); + if (Random.Int(8) == 1){ + Buff.prolong(defender,Paralysis.class,3f); + } + } + @Override + public void onHit(ManyKnive manyknive, Char attacker, Char defender, int damage) { + Buff.prolong(defender,Vertigo.class,3f); + if (Random.Int(8) == 1){ + Buff.prolong(defender,Paralysis.class,3f); + } + } + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/levels/BattleLevel.java b/java/com/hmdzl/spspd/levels/BattleLevel.java new file mode 100644 index 00000000..235370f7 --- /dev/null +++ b/java/com/hmdzl/spspd/levels/BattleLevel.java @@ -0,0 +1,236 @@ +/* + * 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 + */ +package com.hmdzl.spspd.levels; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.Statistics; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.mobs.Bestiary; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.items.Heap; +import com.hmdzl.spspd.items.bombs.LightBomb; +import com.hmdzl.spspd.levels.painters.Painter; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.GameScene; +import com.watabou.noosa.Scene; +import com.watabou.utils.Random; + +public class BattleLevel extends Level { + + { + color1 = 0x6a723d; + color2 = 0x88924c; + + viewDistance = 8; + } + + private static final int ROOM_LEFT = getWidth() / 2 - 2; + private static final int ROOM_RIGHT = getWidth() / 2 + 2; + private static final int ROOM_TOP = HEIGHT / 2 - 2; + private static final int ROOM_BOTTOM = HEIGHT / 2 + 2; + + @Override + public String tilesTex() { + return Assets.TILES_PRISON; + } + + @Override + public String waterTex() { + return Assets.WATER_PRISON; + } + + protected static final int REGROW_TIMER = 4; + protected static final int TIME_TO_RESPAWN = 30; + + @Override + protected boolean build() { + + int topMost = Integer.MAX_VALUE; + + for (int i = 0; i < 8; i++) { + int left, right, top, bottom; + if (Random.Int(2) == 0) { + left = Random.Int(1, ROOM_LEFT - 3); + right = ROOM_RIGHT + 3; + } else { + left = ROOM_LEFT - 3; + right = Random.Int(ROOM_RIGHT + 3, getWidth() - 1); + } + if (Random.Int(2) == 0) { + top = Random.Int(2, ROOM_TOP - 3); + bottom = ROOM_BOTTOM + 3; + } else { + top = ROOM_LEFT - 3; + bottom = Random.Int(ROOM_TOP + 3, HEIGHT - 1); + } + + Painter.fill(this, left, top, right - left + 1, bottom - top + 1, + Terrain.EMPTY); + + if (top < topMost) { + topMost = top; + exit = Random.Int(left, right) + (top - 1) * getWidth(); + } + } + + map[exit] = Terrain.WALL; + + + + Painter.fill(this, ROOM_LEFT, ROOM_TOP + 1, ROOM_RIGHT - ROOM_LEFT + 1, + ROOM_BOTTOM - ROOM_TOP, Terrain.EMPTY); + + + entrance = Random.Int(ROOM_LEFT + 1, ROOM_RIGHT - 1) + + Random.Int(ROOM_TOP + 1, ROOM_BOTTOM - 1) * getWidth(); + map[entrance] = Terrain.EMPTY; + + return true; + } + + @Override + protected void decorate() { + + for (int i = getWidth() + 1; i < getLength() - getWidth(); i++) { + if (map[i] == Terrain.EMPTY) { + int n = 0; + if (map[i + 1] == Terrain.WALL) { + n++; + } + if (map[i - 1] == Terrain.WALL) { + n++; + } + if (map[i + getWidth()] == Terrain.WALL) { + n++; + } + if (map[i - getWidth()] == Terrain.WALL) { + n++; + } + if (Random.Int(8) <= n) { + map[i] = Terrain.EMPTY_DECO; + } + } + } + + for (int i = 0; i < getLength(); i++) { + if (map[i] == Terrain.WALL && Random.Int(8) == 0) { + map[i] = Terrain.WALL_DECO; + } + if (map[i]==Terrain.ENTRANCE){map[i] = Terrain.EMPTY;} + if (map[i]==Terrain.EMPTY && heaps.get(i) == null && Random.Float()<.20){map[i] = Terrain.HIGH_GRASS;} + if (map[i]==Terrain.EMPTY && heaps.get(i) == null && Random.Float()<.25){map[i] = Terrain.GRASS;} + if (map[i]==Terrain.EMPTY && heaps.get(i) == null && Random.Float()<.30){map[i] = Terrain.SHRUB;} + } + + } + + //@Override + //protected void createMobs() { + //} + + //@Override + //public Actor respawner() { + // return null; + //} + + @Override + protected void createItems() { + + int pos = randomDestination(); + drop(new LightBomb(50), pos).type = Heap.Type.CHEST; + + } + + + + //@Override + //public int randomRespawnCell() { + // return -1; + //} + + + + + @Override + public String tileName(int tile) { + switch (tile) { + case Terrain.WATER: + return Messages.get(PrisonLevel.class, "water_name"); + default: + return super.tileName(tile); + } + } + + @Override + public String tileDesc(int tile) { + switch (tile) { + case Terrain.EMPTY_DECO: + return Messages.get(PrisonLevel.class, "empty_deco_desc"); + case Terrain.BOOKSHELF: + return Messages.get(PrisonLevel.class, "bookshelf_desc"); + default: + return super.tileDesc(tile); + } + } + + + @Override + public void addVisuals(Scene scene) { + CavesLevel.addVisuals(this, scene); + } + @Override + public int nMobs() { + return 16; + } + + @Override + protected void createMobs() { + int nMobs = nMobs(); + for (int i = 0; i < nMobs; i++) { + Mob mob = Bestiary.mob(Dungeon.depth); + do { + mob.pos = randomRespawnCellMob(); + } while (mob.pos == -1); + mobs.add(mob); + Actor.occupyCell(mob); + } + } + + @Override + public Actor respawner() { + return new Actor() { + @Override + protected boolean act() { + if (mobs.size() < nMobs()) { + + Mob mob = Bestiary.mutable(Dungeon.depth); + mob.state = mob.WANDERING; + mob.pos = randomRespawnCellMob(); + if (Dungeon.hero.isAlive() && mob.pos != -1) { + GameScene.add(mob); + } + } + spend(Dungeon.level.feeling == Feeling.DARK + || Statistics.amuletObtained ? TIME_TO_RESPAWN / 2 + : TIME_TO_RESPAWN); + return true; + } + }; + } +} diff --git a/java/com/hmdzl/spspd/levels/BossRushLevel.java b/java/com/hmdzl/spspd/levels/BossRushLevel.java new file mode 100644 index 00000000..ba80b1a5 --- /dev/null +++ b/java/com/hmdzl/spspd/levels/BossRushLevel.java @@ -0,0 +1,250 @@ +/* + * 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 + */ +package com.hmdzl.spspd.levels; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.mobs.Dragonking; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.particles.FlameParticle; +import com.hmdzl.spspd.items.Heap; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.keys.SkeletonKey; +import com.hmdzl.spspd.levels.painters.Painter; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.GameScene; +import com.watabou.noosa.Scene; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public class BossRushLevel extends Level { + + { + color1 = 0x801500; + color2 = 0xa68521; + + viewDistance = 8; + } + + private static final int ROOM_LEFT = getWidth() / 2 - 1; + private static final int ROOM_RIGHT = getWidth() / 2 + 1; + private static final int ROOM_TOP = HEIGHT / 2 - 1; + private static final int ROOM_BOTTOM = HEIGHT / 2 + 1; + + private int stairs = -1; + private boolean enteredArena = false; + private boolean keyDropped = false; + + @Override + public String tilesTex() { + return Assets.TILES_SEAL; + } + + @Override + public String waterTex() { + return Assets.WATER_CITY; + } + + private static final String STAIRS = "stairs"; + private static final String ENTERED = "entered"; + private static final String DROPPED = "droppped"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(STAIRS, stairs); + bundle.put(ENTERED, enteredArena); + bundle.put(DROPPED, keyDropped); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + stairs = bundle.getInt(STAIRS); + enteredArena = bundle.getBoolean(ENTERED); + keyDropped = bundle.getBoolean(DROPPED); + } + + @Override + protected boolean build() { + + for (int i = 0; i < 5; i++) { + + int top = Random.IntRange(2, ROOM_TOP - 1); + int bottom = Random.IntRange(ROOM_BOTTOM + 1, 22); + Painter.fill(this, 2 + i * 4, top, 4, bottom - top + 1, + Terrain.EMPTY); + + if (i == 2) { + exit = (i * 4 + 3) + (top - 1) * getWidth(); + } + + for (int j = 0; j < 4; j++) { + if (Random.Int(2) == 0) { + int y = Random.IntRange(top + 1, bottom - 1); + map[i * 4 + j + y * getWidth()] = Terrain.WALL_DECO; + } + } + } + + map[exit] = Terrain.LOCKED_EXIT; + + Painter.fill(this, ROOM_LEFT - 1, ROOM_TOP - 1, ROOM_RIGHT - ROOM_LEFT + + 3, ROOM_BOTTOM - ROOM_TOP + 3, Terrain.WALL); + + Painter.fill(this, ROOM_LEFT, ROOM_TOP, ROOM_RIGHT - ROOM_LEFT + 1, + ROOM_BOTTOM - ROOM_TOP + 1, Terrain.EMPTY); + + entrance = Random.Int(ROOM_LEFT + 1, ROOM_RIGHT - 1) + + Random.Int(ROOM_TOP + 1, ROOM_BOTTOM - 1) * getWidth(); + map[entrance] = Terrain.PEDESTAL; + + boolean[] patch = Patch.generate(0.45f, 6); + for (int i = 0; i < getLength(); i++) { + if (map[i] == Terrain.EMPTY && patch[i]) { + map[i] = Terrain.WATER; + } + } + + return true; + } + + @Override + protected void decorate() { + + for (int i = 0; i < getLength(); i++) { + if (map[i] == Terrain.EMPTY && Random.Int(10) == 0) { + map[i] = Terrain.EMPTY_DECO; + if (map[i]==Terrain.ENTRANCE){map[i] = Terrain.PEDESTAL;} + } + } + + } + + @Override + protected void createMobs() { + } + + @Override + public Actor respawner() { + return null; + } + + @Override + protected void createItems() { + + } + + @Override + public int randomRespawnCell() { + return -1; + } + + + @Override + public void press(int cell, Char hero) { + + super.press(cell, hero); + + if (!enteredArena && hero == Dungeon.hero && cell != entrance) { + + enteredArena = true; + locked = true; + + for (int i = ROOM_LEFT - 1; i <= ROOM_RIGHT + 1; i++) { + doMagic((ROOM_TOP - 1) * getWidth() + i); + doMagic((ROOM_BOTTOM + 1) * getWidth() + i); + } + for (int i = ROOM_TOP; i < ROOM_BOTTOM + 1; i++) { + doMagic(i * getWidth() + ROOM_LEFT - 1); + doMagic(i * getWidth() + ROOM_RIGHT + 1); + } + doMagic(entrance); + GameScene.updateMap(); + + Dungeon.observe(); + + Dragonking boss = new Dragonking(); + do { + boss.pos = Random.Int(getLength()); + } while (!passable[boss.pos] || Dungeon.visible[boss.pos]); + GameScene.add(boss); + + stairs = entrance; + entrance = -1; + + } + } + + private void doMagic(int cell) { + set(cell, Terrain.EMPTY_SP); + CellEmitter.get(cell).start(FlameParticle.FACTORY, 0.1f, 3); + } + + @Override + public Heap drop(Item item, int cell) { + + if (!keyDropped && item instanceof SkeletonKey) { + keyDropped = true; + locked = false; + + entrance = stairs; + set(entrance, Terrain.PEDESTAL); + GameScene.updateMap(entrance); + } + + return super.drop(item, cell); + } + + @Override + public String tileName(int tile) { + switch (tile) { + case Terrain.WATER: + return Messages.get(BossRushLevel.class, "water_name"); + case Terrain.GRASS: + return Messages.get(BossRushLevel.class, "grass_name"); + case Terrain.HIGH_GRASS: + return Messages.get(BossRushLevel.class, "high_grass_name"); + case Terrain.STATUE: + case Terrain.STATUE_SP: + return Messages.get(BossRushLevel.class, "statue_sp_name"); + default: + return super.tileName(tile); + } + } + + @Override + public String tileDesc(int tile) { + switch (tile) { + case Terrain.WATER: + return Messages.get(BossRushLevel.class, "water_desc"); + case Terrain.STATUE: + case Terrain.STATUE_SP: + return Messages.get(BossRushLevel.class, "statue_sp_desc"); + default: + return super.tileDesc(tile); + } + } + + @Override + public void addVisuals(Scene scene) { + HallsLevel.addVisuals(this, scene); + } +} diff --git a/java/com/hmdzl/spspd/levels/CatacombLevel.java b/java/com/hmdzl/spspd/levels/CatacombLevel.java new file mode 100644 index 00000000..1b71681d --- /dev/null +++ b/java/com/hmdzl/spspd/levels/CatacombLevel.java @@ -0,0 +1,247 @@ +/* + * 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 + */ +package com.hmdzl.spspd.levels; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.DungeonTilemap; +import com.hmdzl.spspd.items.TriforceOfCourage; +import com.hmdzl.spspd.levels.Room.Type; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.GameScene; +import com.watabou.noosa.Game; +import com.watabou.noosa.Scene; +import com.watabou.noosa.particles.Emitter; +import com.watabou.noosa.particles.PixelParticle; +import com.watabou.utils.ColorMath; +import com.watabou.utils.PointF; +import com.watabou.utils.Random; + +public class CatacombLevel extends RegularLevel { + + { + color1 = 0x48763c; + color2 = 0x59994a; + cleared=true; + + viewDistance = 3; + } + + + @Override + public String tilesTex() { + return Assets.TILES_SEWERS; + } + + @Override + public String waterTex() { + return Assets.WATER_SEWERS; + } + + @Override + protected boolean[] water() { + return Patch.generate(feeling == Feeling.WATER ? 0.60f : 0.45f, 5); + } + + @Override + protected boolean[] grass() { + return Patch.generate(feeling == Feeling.GRASS ? 0.60f : 0.40f, 4); + } + + @Override + protected boolean assignRoomType() { + + int count = 0; + for (Room r : rooms) { + if (r.type == Type.NULL) { + int connections = r.connected.size(); + if (connections == 0) { + + } else if (Random.Int(connections * connections) == 0) { + r.type = Type.STANDARD; + count++; + } else { + r.type = Type.TUNNEL; + } + } + } + + while (count < 4) { + Room r = randomRoom(Type.TUNNEL, 1); + if (r != null) { + r.type = Type.STANDARD; + count++; + } + } + + return true; + } + + + @Override + protected void decorate() { + + for (int i = 0; i < getWidth(); i++) { + if (map[i] == Terrain.WALL && map[i + getWidth()] == Terrain.WATER + && Random.Int(4) == 0) { + + map[i] = Terrain.WALL_DECO; + } + } + + for (int i = getWidth(); i < getLength() - getWidth(); i++) { + if (map[i] == Terrain.WALL && map[i - getWidth()] == Terrain.WALL + && map[i + getWidth()] == Terrain.WATER && Random.Int(2) == 0) { + + map[i] = Terrain.WALL_DECO; + } + } + + for (int i = getWidth() + 1; i < getLength() - getWidth() - 1; i++) { + if (map[i] == Terrain.EMPTY) { + + int count = (map[i + 1] == Terrain.WALL ? 1 : 0) + + (map[i - 1] == Terrain.WALL ? 1 : 0) + + (map[i + getWidth()] == Terrain.WALL ? 1 : 0) + + (map[i - getWidth()] == Terrain.WALL ? 1 : 0); + + if (Random.Int(16) < count * count) { + map[i] = Terrain.EMPTY_DECO; + } + } + } + + + int length = Level.getLength(); + + for (int i = 0; i < length; i++) { + + + if (map[i]==Terrain.ENTRANCE){map[i] = Terrain.PEDESTAL;} + if (map[i]==Terrain.EXIT){map[i] = Terrain.PEDESTAL; if (!Dungeon.triforceofcourage){drop(new TriforceOfCourage(), i);}} + if (map[i]==Terrain.CHASM){map[i] = Terrain.EMPTY;} + + } + } + + + @Override + public void addVisuals(Scene scene) { + super.addVisuals(scene); + addVisuals(this, scene); + } + + public static void addVisuals(Level level, Scene scene) { + for (int i = 0; i < getLength(); i++) { + if (level.map[i] == Terrain.WALL_DECO) { + scene.add(new Sink(i)); + } + } + } + + //@Override + //public int randomRespawnCell() { + // return -1; + //} + + @Override + public String tileName(int tile) { + switch (tile) { + case Terrain.WATER: + return Messages.get(SewerLevel.class, "water_name"); + default: + return super.tileName(tile); + } + } + + @Override + public String tileDesc(int tile) { + switch (tile) { + case Terrain.EMPTY_DECO: + return Messages.get(SewerLevel.class, "empty_deco_desc"); + case Terrain.BOOKSHELF: + return Messages.get(SewerLevel.class, "bookshelf_desc"); + default: + return super.tileDesc(tile); + } + } + + private static class Sink extends Emitter { + + private int pos; + private float rippleDelay = 0; + + private static final Emitter.Factory factory = new Factory() { + + @Override + public void emit(Emitter emitter, int index, float x, float y) { + WaterParticle p = (WaterParticle) emitter + .recycle(WaterParticle.class); + p.reset(x, y); + } + }; + + public Sink(int pos) { + super(); + + this.pos = pos; + + PointF p = DungeonTilemap.tileCenterToWorld(pos); + pos(p.x - 2, p.y + 1, 4, 0); + + pour(factory, 0.05f); + } + + @Override + public void update() { + if (visible = Dungeon.visible[pos]) { + + super.update(); + + if ((rippleDelay -= Game.elapsed) <= 0) { + GameScene.ripple(pos + getWidth()).y -= DungeonTilemap.SIZE / 2; + rippleDelay = Random.Float(0.2f, 0.3f); + } + } + } + } + + public static final class WaterParticle extends PixelParticle { + + public WaterParticle() { + super(); + + acc.y = 50; + am = 0.5f; + + color(ColorMath.random(0xb6ccc2, 0x3b6653)); + size(2); + } + + public void reset(float x, float y) { + revive(); + + this.x = x; + this.y = y; + + speed.set(Random.Float(-2, +2), 0); + + left = lifespan = 0.5f; + } + } +} diff --git a/java/com/hmdzl/spspd/levels/CavesBossLevel.java b/java/com/hmdzl/spspd/levels/CavesBossLevel.java new file mode 100644 index 00000000..07c44d37 --- /dev/null +++ b/java/com/hmdzl/spspd/levels/CavesBossLevel.java @@ -0,0 +1,318 @@ +/* + * 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 + */ +package com.hmdzl.spspd.levels; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.mobs.Bestiary; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.levels.painters.Painter; +import com.hmdzl.spspd.levels.traps.ToxicTrap; +import com.hmdzl.spspd.levels.traps.Trap; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.GameScene; +import com.watabou.noosa.Camera; +import com.watabou.noosa.Scene; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public class CavesBossLevel extends Level { + + { + color1 = 0x534f3e; + color2 = 0xb9d661; + + viewDistance = 6; + } + + private static final int ROOM_LEFT = getWidth() / 2 - 2; + private static final int ROOM_RIGHT = getWidth() / 2 + 2; + private static final int ROOM_TOP = HEIGHT / 2 - 2; + private static final int ROOM_BOTTOM = HEIGHT / 2 + 2; + + private int arenaDoor; + private int stairs = -1; + private boolean enteredArena = false; + + @Override + public String tilesTex() { + return Assets.TILES_CAVES; + } + + @Override + public String waterTex() { + return Assets.WATER_CAVES; + } + + private static final String DOOR = "door"; + private static final String ENTERED = "entered"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(DOOR, arenaDoor); + bundle.put(ENTERED, enteredArena); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + arenaDoor = bundle.getInt(DOOR); + enteredArena = bundle.getBoolean(ENTERED); + } + + @Override + protected boolean build() { + + int topMost = Integer.MAX_VALUE; + + for (int i = 0; i < 8; i++) { + int left, right, top, bottom; + if (Random.Int(2) == 0) { + left = Random.Int(1, ROOM_LEFT - 3); + right = ROOM_RIGHT + 3; + } else { + left = ROOM_LEFT - 3; + right = Random.Int(ROOM_RIGHT + 3, getWidth() - 1); + } + if (Random.Int(2) == 0) { + top = Random.Int(2, ROOM_TOP - 3); + bottom = ROOM_BOTTOM + 3; + } else { + top = ROOM_LEFT - 3; + bottom = Random.Int(ROOM_TOP + 3, HEIGHT - 1); + } + + Painter.fill(this, left, top, right - left + 1, bottom - top + 1, + Terrain.EMPTY); + + if (top < topMost) { + topMost = top; + exit = Random.Int(left, right) + (top - 1) * getWidth(); + } + } + + map[exit] = Terrain.LOCKED_EXIT; + + for (int i = 0; i < getLength(); i++) { + if (map[i] == Terrain.EMPTY && Random.Int(12) == 0) { + map[i] = Terrain.INACTIVE_TRAP; + Trap t = new ToxicTrap().reveal(); + t.active = false; + setTrap(t, i); + } + } + + Painter.fill(this, ROOM_LEFT - 1, ROOM_TOP - 1, ROOM_RIGHT - ROOM_LEFT + + 3, ROOM_BOTTOM - ROOM_TOP + 3, Terrain.WALL); + Painter.fill(this, ROOM_LEFT, ROOM_TOP + 1, ROOM_RIGHT - ROOM_LEFT + 1, + ROOM_BOTTOM - ROOM_TOP, Terrain.EMPTY); + + Painter.fill(this, ROOM_LEFT, ROOM_TOP, ROOM_RIGHT - ROOM_LEFT + 1, 1, + Terrain.INACTIVE_TRAP); + + arenaDoor = Random.Int(ROOM_LEFT, ROOM_RIGHT) + (ROOM_BOTTOM + 1) + * getWidth(); + map[arenaDoor] = Terrain.DOOR; + + entrance = Random.Int(ROOM_LEFT + 1, ROOM_RIGHT - 1) + + Random.Int(ROOM_TOP + 1, ROOM_BOTTOM - 1) * getWidth(); + map[entrance] = Terrain.ENTRANCE; + + boolean[] patch = Patch.generate(0.45f, 6); + for (int i = 0; i < getLength(); i++) { + if (map[i] == Terrain.EMPTY && patch[i]) { + map[i] = Terrain.WATER; + } + } + + return true; + } + + @Override + protected void decorate() { + + for (int i = getWidth() + 1; i < getLength() - getWidth(); i++) { + if (map[i] == Terrain.EMPTY) { + int n = 0; + if (map[i + 1] == Terrain.WALL) { + n++; + } + if (map[i - 1] == Terrain.WALL) { + n++; + } + if (map[i + getWidth()] == Terrain.WALL) { + n++; + } + if (map[i - getWidth()] == Terrain.WALL) { + n++; + } + if (Random.Int(8) <= n) { + map[i] = Terrain.EMPTY_DECO; + } + } + } + + for (int i = 0; i < getLength(); i++) { + if (map[i] == Terrain.WALL && Random.Int(8) == 0) { + map[i] = Terrain.WALL_DECO; + } + } + + int sign; + do { + sign = Random.Int(ROOM_LEFT, ROOM_RIGHT) + + Random.Int(ROOM_TOP, ROOM_BOTTOM) * getWidth(); + } while (sign == entrance); + map[sign] = Terrain.SIGN; + } + + @Override + protected void createMobs() { + } + + @Override + public Actor respawner() { + return null; + } + + @Override + protected void createItems() { + + } + + @Override + public int randomRespawnCell() { + return -1; + } + + @Override + public void press(int cell, Char hero) { + + super.press(cell, hero); + + if (!enteredArena && outsideEntraceRoom(cell) && hero == Dungeon.hero) { + + enteredArena = true; + seal(); + + Mob boss = Bestiary.mob(Dungeon.depth); + boss.state = boss.HUNTING; + do { + boss.pos = Random.Int(getLength()); + } while (!passable[boss.pos] || !outsideEntraceRoom(boss.pos) + || Dungeon.visible[boss.pos]); + GameScene.add(boss); + boss.notice(); + + + set(arenaDoor, Terrain.WALL); + GameScene.updateMap(arenaDoor); + Dungeon.observe(); + + CellEmitter.get(arenaDoor).start(Speck.factory(Speck.ROCK), 0.07f, + 10); + Camera.main.shake(3, 0.7f); + Sample.INSTANCE.play(Assets.SND_ROCKS); + } + } + + public void seal() { + if (entrance != 0) { + + locked = true; + + set(arenaDoor, Terrain.WALL); + GameScene.updateMap(arenaDoor); + Dungeon.observe(); + + CellEmitter.get(arenaDoor).start(Speck.factory(Speck.ROCK), 0.07f, + 10); + Camera.main.shake(3, 0.7f); + Sample.INSTANCE.play(Assets.SND_ROCKS); + + set(entrance, Terrain.WALL_DECO); + GameScene.updateMap(entrance); + GameScene.ripple(entrance); + + } + } + + public void unseal() { + if (stairs != 0) { + locked = false; + CellEmitter.get(arenaDoor).start(Speck.factory(Speck.ROCK), 0.07f, + 10); + set(arenaDoor, Terrain.EMPTY_DECO); + GameScene.updateMap(arenaDoor); + Dungeon.observe(); + set(entrance, Terrain.ENTRANCE); + GameScene.updateMap(entrance); + + } + } + + private boolean outsideEntraceRoom(int cell) { + int cx = cell % getWidth(); + int cy = cell / getWidth(); + return cx < ROOM_LEFT - 1 || cx > ROOM_RIGHT + 1 || cy < ROOM_TOP - 1 + || cy > ROOM_BOTTOM + 1; + } + + @Override + public String tileName(int tile) { + switch (tile) { + case Terrain.GRASS: + return Messages.get(CavesLevel.class, "grass_name"); + case Terrain.HIGH_GRASS: + return Messages.get(CavesLevel.class, "high_grass_name"); + case Terrain.WATER: + return Messages.get(CavesLevel.class, "water_name"); + default: + return super.tileName( tile ); + } + } + + @Override + public String tileDesc(int tile) { + switch (tile) { + case Terrain.ENTRANCE: + return Messages.get(CavesLevel.class, "entrance_desc"); + case Terrain.EXIT: + return Messages.get(CavesLevel.class, "exit_desc"); + case Terrain.HIGH_GRASS: + return Messages.get(CavesLevel.class, "high_grass_desc"); + case Terrain.WALL_DECO: + return Messages.get(CavesLevel.class, "wall_deco_desc"); + case Terrain.BOOKSHELF: + return Messages.get(CavesLevel.class, "bookshelf_desc"); + default: + return super.tileDesc( tile ); + } + } + + @Override + public void addVisuals(Scene scene) { + CavesLevel.addVisuals(this, scene); + } +} diff --git a/java/com/hmdzl/spspd/levels/CavesLevel.java b/java/com/hmdzl/spspd/levels/CavesLevel.java new file mode 100644 index 00000000..cef6711a --- /dev/null +++ b/java/com/hmdzl/spspd/levels/CavesLevel.java @@ -0,0 +1,359 @@ +/* + * 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 + */ +package com.hmdzl.spspd.levels; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.DungeonTilemap; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.hero.HeroClass; +import com.hmdzl.spspd.actors.mobs.npcs.Blacksmith; +import com.hmdzl.spspd.actors.mobs.npcs.Tinkerer2; +import com.hmdzl.spspd.items.bombs.DungeonBomb; +import com.hmdzl.spspd.items.quest.Mushroom; +import com.hmdzl.spspd.levels.Room.Type; +import com.hmdzl.spspd.levels.painters.Painter; +import com.hmdzl.spspd.levels.traps.*; +import com.hmdzl.spspd.messages.Messages; +import com.watabou.noosa.Game; +import com.watabou.noosa.Group; +import com.watabou.noosa.Scene; +import com.watabou.noosa.particles.PixelParticle; +import com.watabou.utils.PointF; +import com.watabou.utils.Random; +import com.watabou.utils.Rect; + +public class CavesLevel extends RegularLevel { + + { + color1 = 0x534f3e; + color2 = 0xb9d661; + + viewDistance = 6; + } + + @Override + public String tilesTex() { + return Assets.TILES_CAVES; + } + + @Override + public String waterTex() { + return Assets.WATER_CAVES; + } + + @Override + protected boolean[] water() { + return Patch.generate(feeling == Feeling.WATER ? 0.60f : 0.45f, 6); + } + + @Override + protected boolean[] grass() { + return Patch.generate(feeling == Feeling.GRASS ? 0.55f : 0.35f, 3); + } + + @Override + protected Class[] trapClasses() { + return Dungeon.depth == 14 ? + new Class[]{ FireTrap.class, FrostTrap.class, PoisonTrap.class, SpearTrap.class, VenomTrap.class, ShockTrap.class, + ExplosiveTrap.class, FlashingTrap.class, GrippingTrap.class, ParalyticTrap.class, LightningTrap.class, RockfallTrap.class, OozeTrap.class, + ConfusionTrap.class, FlockTrap.class, GuardianTrap.class, SummoningTrap.class, TeleportationTrap.class, + WarpingTrap.class, StormTrap.class}: + new Class[]{ FireTrap.class, FrostTrap.class, PoisonTrap.class, SpearTrap.class, VenomTrap.class, ShockTrap.class, + ExplosiveTrap.class, FlashingTrap.class, GrippingTrap.class, ParalyticTrap.class, LightningTrap.class, RockfallTrap.class, OozeTrap.class, + ConfusionTrap.class, FlockTrap.class, GuardianTrap.class, PitfallTrap.class, SummoningTrap.class, TeleportationTrap.class, + WarpingTrap.class, StormTrap.class}; + } + + @Override + protected float[] trapChances() { + return Dungeon.depth == 14 ? + new float[]{ 8, 8, 8, 8, 8, 8, + 4, 4, 4, 4, 4, 4, 4, + 2, 2, 2, 2, 2, + 1, 1 }: + new float[]{ 8, 8, 8, 8, 8, 8, + 4, 4, 4, 4, 4, 4, 4, + 2, 2, 2, 2, 2, 2, + 1, 1 }; + } + + @Override + protected void setPar(){ + Dungeon.pars[Dungeon.depth] = 400+(Dungeon.depth*50)+(secretDoors*20); + } + + @Override + protected void createItems() { + + if (Dungeon.depth == 12){ + Tinkerer2 npc = new Tinkerer2(); + do { + npc.pos = randomRespawnCell(); + } while (npc.pos == -1 || heaps.get(npc.pos) != null); + mobs.add(npc); + Actor.occupyCell(npc); + } + + if (Dungeon.depth == 11){ + addItemToSpawn(new Mushroom()); + } + + if (Dungeon.hero.heroClass==HeroClass.PERFORMER && Random.Int(3) == 0){addItemToSpawn(new DungeonBomb());} + super.createItems(); + } + + + @Override + protected boolean assignRoomType() { + super.assignRoomType(); + + if (!Blacksmith.Quest.spawn(rooms) && Dungeon.depth == 14) + return false; + + return true; + } + + @Override + protected void decorate() { + + for (Room room : rooms) { + if (room.type != Room.Type.STANDARD) { + continue; + } + + if (room.width() <= 3 || room.height() <= 3) { + continue; + } + + int s = room.square(); + + if (Random.Int(s) > 8) { + int corner = (room.left + 1) + (room.top + 1) * getWidth(); + if (map[corner - 1] == Terrain.WALL + && map[corner - getWidth()] == Terrain.WALL) { + map[corner] = Terrain.WALL; + } + } + + if (Random.Int(s) > 8) { + int corner = (room.right - 1) + (room.top + 1) * getWidth(); + if (map[corner + 1] == Terrain.WALL + && map[corner - getWidth()] == Terrain.WALL) { + map[corner] = Terrain.WALL; + } + } + + if (Random.Int(s) > 8) { + int corner = (room.left + 1) + (room.bottom - 1) * getWidth(); + if (map[corner - 1] == Terrain.WALL + && map[corner + getWidth()] == Terrain.WALL) { + map[corner] = Terrain.WALL; + } + } + + if (Random.Int(s) > 8) { + int corner = (room.right - 1) + (room.bottom - 1) * getWidth(); + if (map[corner + 1] == Terrain.WALL + && map[corner + getWidth()] == Terrain.WALL) { + map[corner] = Terrain.WALL; + } + } + + for (Room n : room.connected.keySet()) { + if ((n.type == Room.Type.STANDARD || n.type == Room.Type.TUNNEL) + && Random.Int(3) == 0) { + Painter.set(this, room.connected.get(n), Terrain.EMPTY_DECO); + } + } + } + + for (int i = getWidth() + 1; i < getLength() - getWidth(); i++) { + if (map[i] == Terrain.EMPTY) { + int n = 0; + if (map[i + 1] == Terrain.WALL) { + n++; + } + if (map[i - 1] == Terrain.WALL) { + n++; + } + if (map[i + getWidth()] == Terrain.WALL) { + n++; + } + if (map[i - getWidth()] == Terrain.WALL) { + n++; + } + if (Random.Int(6) <= n) { + map[i] = Terrain.EMPTY_DECO; + } + } + } + + for (int i = 0; i < getLength(); i++) { + if (map[i] == Terrain.WALL && Random.Int(8) == 0) { + map[i] = Terrain.WALL_DECO; + } + } + + while (true) { + int pos = roomEntrance.random(); + if (pos != entrance) { + map[pos] = Terrain.SIGN; + break; + } + } + + setPar(); + + if (Dungeon.bossLevel(Dungeon.depth + 1)) { + return; + } + + for (Room r : rooms) { + if (r.type == Type.STANDARD) { + for (Room n : r.neigbours) { + if (n.type == Type.STANDARD && !r.connected.containsKey(n)) { + Rect w = r.intersect(n); + if (w.left == w.right && w.bottom - w.top >= 5) { + + w.top += 2; + w.bottom -= 1; + + w.right++; + + Painter.fill(this, w.left, w.top, 1, w.height(), + Terrain.CHASM); + + } else if (w.top == w.bottom && w.right - w.left >= 5) { + + w.left += 2; + w.right -= 1; + + w.bottom++; + + Painter.fill(this, w.left, w.top, w.width(), 1, + Terrain.CHASM); + } + } + } + } + } + + + } + + @Override + public String tileName(int tile) { + switch (tile) { + case Terrain.GRASS: + return Messages.get(CavesLevel.class, "grass_name"); + case Terrain.HIGH_GRASS: + return Messages.get(CavesLevel.class, "high_grass_name"); + case Terrain.WATER: + return Messages.get(CavesLevel.class, "water_name"); + default: + return super.tileName(tile); + } + } + + @Override + public String tileDesc(int tile) { + switch (tile) { + case Terrain.ENTRANCE: + return Messages.get(CavesLevel.class, "entrance_desc"); + case Terrain.EXIT: + return Messages.get(CavesLevel.class, "exit_desc"); + case Terrain.HIGH_GRASS: + return Messages.get(CavesLevel.class, "high_grass_desc"); + case Terrain.WALL_DECO: + return Messages.get(CavesLevel.class, "wall_deco_desc"); + case Terrain.BOOKSHELF: + return Messages.get(CavesLevel.class, "bookshelf_desc"); + default: + return super.tileDesc(tile); + } + } + + @Override + public void addVisuals(Scene scene) { + super.addVisuals(scene); + addVisuals(this, scene); + } + + public static void addVisuals(Level level, Scene scene) { + for (int i = 0; i < getLength(); i++) { + if (level.map[i] == Terrain.WALL_DECO) { + scene.add(new Vein(i)); + } + } + } + + private static class Vein extends Group { + + private int pos; + + private float delay; + + public Vein(int pos) { + super(); + + this.pos = pos; + + delay = Random.Float(2); + } + + @Override + public void update() { + + if (visible = Dungeon.visible[pos]) { + + super.update(); + + if ((delay -= Game.elapsed) <= 0) { + + delay = Random.Float(); + + PointF p = DungeonTilemap.tileToWorld(pos); + ((Sparkle) recycle(Sparkle.class)).reset( + p.x + Random.Float(DungeonTilemap.SIZE), p.y + + Random.Float(DungeonTilemap.SIZE)); + } + } + } + } + + public static final class Sparkle extends PixelParticle { + + public void reset(float x, float y) { + revive(); + + this.x = x; + this.y = y; + + left = lifespan = 0.5f; + } + + @Override + public void update() { + super.update(); + + float p = left / lifespan; + size((am = p < 0.5f ? p * 2 : (1 - p) * 2) * 2); + } + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/levels/ChaosLevel.java b/java/com/hmdzl/spspd/levels/ChaosLevel.java new file mode 100644 index 00000000..c992503e --- /dev/null +++ b/java/com/hmdzl/spspd/levels/ChaosLevel.java @@ -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 + */ +package com.hmdzl.spspd.levels; + +import javax.microedition.khronos.opengles.GL10; + +import android.opengl.GLES20; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.DungeonTilemap; +import com.hmdzl.spspd.levels.traps.*; +import com.hmdzl.spspd.messages.Messages; +import com.watabou.noosa.Game; +import com.watabou.noosa.Group; +import com.watabou.noosa.Scene; +import com.watabou.noosa.particles.PixelParticle; +import com.watabou.utils.PointF; +import com.watabou.utils.Random; + +public class ChaosLevel extends RegularLevel { + + { + minRoomSize = 6; + + color1 = 0x801500; + color2 = 0xa68521; + cleared=true; + viewDistance = 6; + } + + @Override + public String tilesTex() { + return Assets.TILES_SEAL; + } + + @Override + public String waterTex() { + return Assets.WATER_CITY; + } + + @Override + protected boolean[] water() { + return Patch.generate(feeling == Feeling.WATER ? 0.55f : 0.40f, 6); + } + + @Override + protected boolean[] grass() { + return Patch.generate(feeling == Feeling.GRASS ? 0.55f : 0.30f, 3); + } + + @Override + protected Class[] trapClasses() { + return new Class[]{DistortionTrap.class}; + } + + @Override + protected float[] trapChances() { + return new float[]{10}; + } + + @Override + protected void decorate() { + + for (int i = getWidth() + 1; i < getLength() - getWidth() - 1; i++) { + if (map[i] == Terrain.EMPTY) { + + int count = 0; + for (int j = 0; j < NEIGHBOURS8.length; j++) { + if ((Terrain.flags[map[i + NEIGHBOURS8[j]]] & Terrain.PASSABLE) > 0) { + count++; + } + } + + if (Random.Int(80) < count) { + map[i] = Terrain.EMPTY_DECO; + } + + } else if (map[i] == Terrain.WALL + && map[i - 1] != Terrain.WALL_DECO + && map[i - getWidth()] != Terrain.WALL_DECO + && Random.Int(20) == 0) { + + map[i] = Terrain.WALL_DECO; + + } + } + + int length = Level.getLength(); + + for (int i = 0; i < length; i++) { + + + if (map[i]==Terrain.ENTRANCE){map[i] = Terrain.PEDESTAL;} + if (map[i]==Terrain.EXIT){map[i] = Terrain.PEDESTAL; } + if (map[i]==Terrain.CHASM){map[i] = Terrain.EMPTY;} + + } + + + } + + @Override + public void addVisuals(Scene scene) { + super.addVisuals(scene); + addVisuals(this, scene); + } + + public static void addVisuals(Level level, Scene scene) { + for (int i = 0; i < getLength(); i++) { + if (level.map[i] == 63) { + scene.add(new Stream(i)); + } + } + } + + private static class Stream extends Group { + + private int pos; + + private float delay; + + public Stream(int pos) { + super(); + + this.pos = pos; + + delay = Random.Float(2); + } + + @Override + public void update() { + + if (visible = Dungeon.visible[pos]) { + + super.update(); + + if ((delay -= Game.elapsed) <= 0) { + + delay = Random.Float(2); + + PointF p = DungeonTilemap.tileToWorld(pos); + ((FireParticle) recycle(FireParticle.class)).reset(p.x + + Random.Float(DungeonTilemap.SIZE), + p.y + Random.Float(DungeonTilemap.SIZE)); + } + } + } + + @Override + public void draw() { + GLES20.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE); + super.draw(); + GLES20.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA); + } + } + + public static class FireParticle extends PixelParticle.Shrinking { + + public FireParticle() { + super(); + + color(0xEE7722); + lifespan = 1f; + + acc.set(0, +80); + } + + public void reset(float x, float y) { + revive(); + + this.x = x; + this.y = y; + + left = lifespan; + + speed.set(0, -40); + size = 4; + } + + @Override + public void update() { + super.update(); + float p = left / lifespan; + am = p > 0.8f ? (1 - p) * 5 : 1; + } + } + @Override + public String tileName( int tile ) { + switch (tile) { + case Terrain.WATER: + return Messages.get(ChaosLevel.class, "water_name"); + default: + return super.tileName( tile ); + } + } +} diff --git a/java/com/hmdzl/spspd/levels/ChasmLevel.java b/java/com/hmdzl/spspd/levels/ChasmLevel.java new file mode 100644 index 00000000..970c11fb --- /dev/null +++ b/java/com/hmdzl/spspd/levels/ChasmLevel.java @@ -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 + */ +package com.hmdzl.spspd.levels; + +import java.util.ArrayList; +import java.util.HashSet; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.DungeonTilemap; +import com.hmdzl.spspd.actors.mobs.Sentinel; +import com.hmdzl.spspd.items.TriforceOfWisdom; +import com.hmdzl.spspd.items.potions.PotionOfLevitation; +import com.hmdzl.spspd.levels.Room.Type; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.plants.Phaseshift; +import com.hmdzl.spspd.scenes.GameScene; +import com.watabou.noosa.Game; +import com.watabou.noosa.Scene; +import com.watabou.noosa.particles.Emitter; +import com.watabou.noosa.particles.PixelParticle; +import com.watabou.utils.ColorMath; +import com.watabou.utils.PointF; +import com.watabou.utils.Random; + +public class ChasmLevel extends RegularLevel { + + { + color1 = 0x48763c; + color2 = 0x59994a; + cleared=true; + } + + + @Override + public String tilesTex() { + return Assets.TILES_PRISON; + } + + @Override + public String waterTex() { + return Assets.WATER_PRISON; + } + + @Override + protected boolean[] water() { + return Patch.generate(feeling == Feeling.WATER ? 0.60f : 0.45f, 5); + } + + @Override + protected boolean[] grass() { + return Patch.generate(feeling == Feeling.GRASS ? 0.60f : 0.40f, 4); + } + + @Override + protected void createItems() { + super.createItems(); + + spawn(this, roomEntrance); + + } + + public static void spawn(ChasmLevel level, Room room) { + int pos; + do {pos = room.random();} + while (level.heaps.get(pos) != null); + level.drop(new PotionOfLevitation(), pos); + } + + @Override + protected boolean assignRoomType() { + + specialsc = new ArrayList(Room.SPECIALSTRANSCEND); + + //if (Dungeon.isChallenged(Challenges.NO_HERBALISM)) { + // sorry warden, no lucky sungrass or blandfruit seeds for you! + //specialsc.remove(Room.Type.GARDEN); + // } + + int specialRooms = 0; + + for (Room r : rooms) { + if (r.type == Type.NULL && r.connected.size() == 1) { + + if (specialsc.size() > 0 && r.width() > 3 && r.height() > 3 + //&& Random.Int(specialRooms * specialRooms + 2) == 0 + ) { + + + int n = specialsc.size(); + r.type = specialsc.get(Math.min(Random.Int(n),Random.Int(n))); + + Room.useType(r.type); + //specialsc.remove(r.type); + specialRooms++; + + } else if (Random.Int(2) == 0) { + + HashSet neigbours = new HashSet(); + for (Room n : r.neigbours) { + if (!r.connected.containsKey(n) + && !Room.SPECIALSTRANSCEND.contains(n.type) + && n.type != Type.PIT) { + + neigbours.add(n); + } + } + if (neigbours.size() > 1) { + r.connect(Random.element(neigbours)); + } + } + } + } + + + int count = 0; + for (Room r : rooms) { + if (r.type == Type.NULL) { + int connections = r.connected.size(); + if (connections == 0) { + + } else if (Random.Int(connections * connections) == 0) { + r.type = Type.STANDARD; + count++; + } else { + r.type = Type.TUNNEL; + } + } + } + + while (count < 4) { + Room r = randomRoom(Type.TUNNEL, 1); + if (r != null) { + r.type = Type.STANDARD; + count++; + } + } + + for (Room r : rooms) { + if (r.type == Type.TUNNEL) { + r.type = Type.PASSAGE; + } + } + + return true; + } + + + + @Override + protected void decorate() { + + for (int i = 0; i < getWidth(); i++) { + if (map[i] == Terrain.WALL && map[i + getWidth()] == Terrain.WATER + && Random.Int(4) == 0) { + + map[i] = Terrain.WALL_DECO; + } + } + + for (int i = getWidth(); i < getLength() - getWidth(); i++) { + if (map[i] == Terrain.WALL && map[i - getWidth()] == Terrain.WALL + && map[i + getWidth()] == Terrain.WATER && Random.Int(2) == 0) { + + map[i] = Terrain.WALL_DECO; + } + } + + for (int i = getWidth() + 1; i < getLength() - getWidth() - 1; i++) { + if (map[i] == Terrain.EMPTY) { + + int count = (map[i + 1] == Terrain.WALL ? 1 : 0) + + (map[i - 1] == Terrain.WALL ? 1 : 0) + + (map[i + getWidth()] == Terrain.WALL ? 1 : 0) + + (map[i - getWidth()] == Terrain.WALL ? 1 : 0); + + if (Random.Int(16) < count * count) { + map[i] = Terrain.EMPTY_DECO; + } + } + } + + + int length = Level.getLength(); + + for (int i = 0; i < length; i++) { + + + if (map[i]==Terrain.ENTRANCE){map[i] = Terrain.EMPTY;} + if (map[i]==Terrain.EXIT){map[i] = Terrain.PEDESTAL; if (!Dungeon.triforceofwisdom){drop(new TriforceOfWisdom(), i);}} + if (map[i]==Terrain.EMPTY_SP && heaps.get(i) == null && Random.Float()<.25){map[i] = Terrain.TRAP_AIR;} + if (map[i]==Terrain.EMPTY_SP && heaps.get(i) == null && Random.Float()<.05){ + Sentinel sentinel = new Sentinel(); + sentinel.pos = i; + mobs.add(sentinel); + } + if (map[i]==Terrain.EMPTY && heaps.get(i) == null && Random.Float()<.02){ + drop(new Phaseshift.Seed(), i); + } + + + } + } + + + @Override + public void addVisuals(Scene scene) { + super.addVisuals(scene); + addVisuals(this, scene); + } + + public static void addVisuals(Level level, Scene scene) { + for (int i = 0; i < getLength(); i++) { + if (level.map[i] == Terrain.WALL_DECO) { + scene.add(new Sink(i)); + } + } + } + + //@Override + //public int randomRespawnCell() { + // return -1; + //} + + @Override + public String tileName(int tile) { + switch (tile) { + case Terrain.WATER: + return Messages.get(PrisonLevel.class, "water_name"); + default: + return super.tileName(tile); + } + } + + @Override + public String tileDesc(int tile) { + switch (tile) { + case Terrain.EMPTY_DECO: + return Messages.get(PrisonLevel.class, "empty_deco_desc"); + case Terrain.BOOKSHELF: + return Messages.get(PrisonLevel.class, "bookshelf_desc"); + default: + return super.tileDesc(tile); + } + } + + private static class Sink extends Emitter { + + private int pos; + private float rippleDelay = 0; + + private static final Emitter.Factory factory = new Factory() { + + @Override + public void emit(Emitter emitter, int index, float x, float y) { + WaterParticle p = (WaterParticle) emitter + .recycle(WaterParticle.class); + p.reset(x, y); + } + }; + + public Sink(int pos) { + super(); + + this.pos = pos; + + PointF p = DungeonTilemap.tileCenterToWorld(pos); + pos(p.x - 2, p.y + 1, 4, 0); + + pour(factory, 0.05f); + } + + @Override + public void update() { + if (visible = Dungeon.visible[pos]) { + + super.update(); + + if ((rippleDelay -= Game.elapsed) <= 0) { + GameScene.ripple(pos + getWidth()).y -= DungeonTilemap.SIZE / 2; + rippleDelay = Random.Float(0.2f, 0.3f); + } + } + } + } + + public static final class WaterParticle extends PixelParticle { + + public WaterParticle() { + super(); + + acc.y = 50; + am = 0.5f; + + color(ColorMath.random(0xb6ccc2, 0x3b6653)); + size(2); + } + + public void reset(float x, float y) { + revive(); + + this.x = x; + this.y = y; + + speed.set(Random.Float(-2, +2), 0); + + left = lifespan = 0.5f; + } + } + +} diff --git a/java/com/hmdzl/spspd/levels/CityBossLevel.java b/java/com/hmdzl/spspd/levels/CityBossLevel.java new file mode 100644 index 00000000..80e92579 --- /dev/null +++ b/java/com/hmdzl/spspd/levels/CityBossLevel.java @@ -0,0 +1,280 @@ +/* + * 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 + */ +package com.hmdzl.spspd.levels; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.mobs.Bestiary; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.levels.painters.Painter; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.GameScene; +import com.watabou.noosa.Camera; +import com.watabou.noosa.Scene; +import com.watabou.noosa.audio.Sample; +import com.watabou.noosa.tweeners.AlphaTweener; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public class CityBossLevel extends Level { + + { + color1 = 0x4b6636; + color2 = 0xf2f2f2; + } + + private static final int TOP = 2; + private static final int HALL_WIDTH = 7; + private static final int HALL_HEIGHT = 15; + private static final int CHAMBER_HEIGHT = 3; + + private static final int LEFT = (getWidth() - HALL_WIDTH) / 2; + private static final int CENTER = LEFT + HALL_WIDTH / 2; + + private int arenaDoor; + private int stairs = -1; + private boolean enteredArena = false; + + @Override + public String tilesTex() { + return Assets.TILES_CITY; + } + + @Override + public String waterTex() { + return Assets.WATER_CITY; + } + + private static final String DOOR = "door"; + private static final String ENTERED = "entered"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(DOOR, arenaDoor); + bundle.put(ENTERED, enteredArena); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + arenaDoor = bundle.getInt(DOOR); + enteredArena = bundle.getBoolean(ENTERED); + } + + @Override + protected boolean build() { + + Painter.fill(this, LEFT, TOP, HALL_WIDTH, HALL_HEIGHT, Terrain.EMPTY); + Painter.fill(this, CENTER, TOP, 1, HALL_HEIGHT, Terrain.EMPTY_SP); + + map[(TOP + 1) * getWidth() + CENTER] = Terrain.EMPTY_WELL; + + int y = TOP + 1; + while (y < TOP + HALL_HEIGHT) { + map[y * getWidth() + CENTER - 2] = Terrain.STATUE_SP; + map[y * getWidth() + CENTER + 2] = Terrain.STATUE_SP; + y += 2; + } + + int left = pedestal(true); + int right = pedestal(false); + map[left] = map[right] = Terrain.PEDESTAL; + for (int i = left + 1; i < right; i++) { + map[i] = Terrain.EMPTY_SP; + } + + exit = (TOP - 1) * getWidth() + CENTER; + map[exit] = Terrain.LOCKED_EXIT; + + arenaDoor = (TOP + HALL_HEIGHT) * getWidth() + CENTER; + map[arenaDoor] = Terrain.DOOR; + + Painter.fill(this, LEFT, TOP + HALL_HEIGHT + 1, HALL_WIDTH, + CHAMBER_HEIGHT, Terrain.EMPTY); + Painter.fill(this, LEFT, TOP + HALL_HEIGHT + 1, 1, CHAMBER_HEIGHT, + Terrain.BOOKSHELF); + Painter.fill(this, LEFT + HALL_WIDTH - 1, TOP + HALL_HEIGHT + 1, 1, + CHAMBER_HEIGHT, Terrain.BOOKSHELF); + + entrance = (TOP + HALL_HEIGHT + 2 + Random.Int(CHAMBER_HEIGHT - 1)) + * getWidth() + LEFT + (/* 1 + */Random.Int(HALL_WIDTH - 2)); + map[entrance] = Terrain.ENTRANCE; + + return true; + } + + @Override + protected void decorate() { + + for (int i = 0; i < getLength(); i++) { + if (map[i] == Terrain.EMPTY && Random.Int(10) == 0) { + map[i] = Terrain.EMPTY_DECO; + } else if (map[i] == Terrain.WALL && Random.Int(8) == 0) { + map[i] = Terrain.WALL_DECO; + } + } + + int sign = arenaDoor + getWidth() + 1; + map[sign] = Terrain.SIGN; + } + + public static int pedestal(boolean left) { + if (left) { + return (TOP + HALL_HEIGHT / 2) * getWidth() + CENTER - 2; + } else { + return (TOP + HALL_HEIGHT / 2) * getWidth() + CENTER + 2; + } + } + + @Override + protected void createMobs() { + } + + @Override + public Actor respawner() { + return null; + } + + @Override + protected void createItems() { + + } + + @Override + public int randomRespawnCell() { + return -1; + } + + @Override + public void press(int cell, Char hero) { + + super.press(cell, hero); + + if (!enteredArena && outsideEntraceRoom(cell) && hero == Dungeon.hero) { + + enteredArena = true; + seal(); + + Mob boss = Bestiary.mob(Dungeon.depth); + //Mob tomb = new DwarfKingTomb(); + boss.state = boss.HUNTING; + int count = 0; + do { + boss.pos = Random.Int(getLength()); + //tomb.pos = (TOP + 1) * getWidth() + CENTER; + } while (!passable[boss.pos] + || !outsideEntraceRoom(boss.pos) + || (Dungeon.visible[boss.pos] && count++ < 20)); + GameScene.add(boss); + //GameScene.add(tomb); + + if (Dungeon.visible[boss.pos]) { + boss.notice(); + boss.sprite.alpha(0); + boss.sprite.parent.add(new AlphaTweener(boss.sprite, 1, 0.1f)); + } + + set(arenaDoor, Terrain.WALL); + GameScene.updateMap(arenaDoor); + Dungeon.observe(); + } + } + + public void seal() { + if (entrance != 0) { + + locked = true; + + set(arenaDoor, Terrain.WALL); + GameScene.updateMap(arenaDoor); + Dungeon.observe(); + + CellEmitter.get(arenaDoor).start(Speck.factory(Speck.ROCK), 0.07f, + 10); + Camera.main.shake(3, 0.7f); + Sample.INSTANCE.play(Assets.SND_ROCKS); + + set(entrance, Terrain.WALL_DECO); + GameScene.updateMap(entrance); + GameScene.ripple(entrance); + + } + } + + public void unseal() { + if (stairs != 0) { + locked = false; + CellEmitter.get(arenaDoor).start(Speck.factory(Speck.ROCK), 0.07f, + 10); + set(arenaDoor, Terrain.EMPTY_DECO); + GameScene.updateMap(arenaDoor); + Dungeon.observe(); + set(entrance, Terrain.ENTRANCE); + GameScene.updateMap(entrance); + + } + } + + private boolean outsideEntraceRoom(int cell) { + return cell / getWidth() < arenaDoor / getWidth(); + } + + @Override + public String tileName(int tile) { + switch (tile) { + case Terrain.WATER: + return Messages.get(CityLevel.class, "water_name"); + case Terrain.HIGH_GRASS: + return Messages.get(CityLevel.class, "high_grass_name"); + default: + return super.tileName(tile); + } + } + + @Override + public String tileDesc(int tile) { + switch (tile) { + case Terrain.ENTRANCE: + return Messages.get(CityLevel.class, "entrance_desc"); + case Terrain.EXIT: + return Messages.get(CityLevel.class, "exit_desc"); + case Terrain.WALL_DECO: + case Terrain.EMPTY_DECO: + return Messages.get(CityLevel.class, "deco_desc"); + case Terrain.EMPTY_SP: + return Messages.get(CityLevel.class, "sp_desc"); + case Terrain.STATUE: + case Terrain.STATUE_SP: + return Messages.get(CityLevel.class, "statue_desc"); + case Terrain.BOOKSHELF: + return Messages.get(CityLevel.class, "bookshelf_desc"); + default: + return super.tileDesc(tile); + } + } + + @Override + public void addVisuals(Scene scene) { + CityLevel.addVisuals(this, scene); + } +} diff --git a/java/com/hmdzl/spspd/levels/CityLevel.java b/java/com/hmdzl/spspd/levels/CityLevel.java new file mode 100644 index 00000000..a2ace297 --- /dev/null +++ b/java/com/hmdzl/spspd/levels/CityLevel.java @@ -0,0 +1,250 @@ +/* + * 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 + */ +package com.hmdzl.spspd.levels; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.DungeonTilemap; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.hero.HeroClass; +import com.hmdzl.spspd.actors.mobs.GoldThief; +import com.hmdzl.spspd.actors.mobs.npcs.Imp; +import com.hmdzl.spspd.items.bombs.DungeonBomb; +import com.hmdzl.spspd.levels.Room.Type; +import com.hmdzl.spspd.levels.traps.*; +import com.hmdzl.spspd.messages.Messages; +import com.watabou.noosa.Scene; +import com.watabou.noosa.particles.Emitter; +import com.watabou.noosa.particles.PixelParticle; +import com.watabou.utils.PointF; +import com.watabou.utils.Random; + +public class CityLevel extends RegularLevel { + + { + color1 = 0x4b6636; + color2 = 0xf2f2f2; + } + + @Override + public String tilesTex() { + return Assets.TILES_CITY; + } + + @Override + public String waterTex() { + return Assets.WATER_CITY; + } + + @Override + protected boolean[] water() { + return Patch.generate(feeling == Feeling.WATER ? 0.65f : 0.45f, 4); + } + + @Override + protected boolean[] grass() { + return Patch.generate(feeling == Feeling.GRASS ? 0.60f : 0.40f, 3); + } + + @Override + protected void setPar(){ + Dungeon.pars[Dungeon.depth] = 300+(Dungeon.depth*50)+(secretDoors*20); + } + + @Override + protected Class[] trapClasses() { + return new Class[]{ BlazingTrap.class, FrostTrap.class, SpearTrap.class, VenomTrap.class, ShockTrap.class, + ExplosiveTrap.class, GrippingTrap.class, LightningTrap.class, RockfallTrap.class, OozeTrap.class, WeakeningTrap.class, + CursingTrap.class, FlockTrap.class, GuardianTrap.class, PitfallTrap.class, SummoningTrap.class, TeleportationTrap.class, StormTrap.class, + DisarmingTrap.class, WarpingTrap.class}; + } + + @Override + protected float[] trapChances() { + return new float[]{ 8, 8, 8, 8, 8, + 4, 4, 4, 4, 4, 4, + 2, 2, 2, 2, 2, 2, 2, + 1, 1 }; + } + + @Override + protected boolean assignRoomType() { + super.assignRoomType(); + + for (Room r : rooms) { + if (r.type == Type.TUNNEL) { + r.type = Type.PASSAGE; + } + } + + return true; + } + + @Override + protected void decorate() { + + for (int i = 0; i < getLength(); i++) { + if (map[i] == Terrain.EMPTY && Random.Int(10) == 0) { + map[i] = Terrain.EMPTY_DECO; + } else if (map[i] == Terrain.WALL && Random.Int(8) == 0) { + map[i] = Terrain.WALL_DECO; + } + } + + while (true) { + int pos = roomEntrance.random(); + if (pos != entrance) { + map[pos] = Terrain.SIGN; + break; + } + } + + setPar(); + } + + @Override + protected void createItems() { + if (Dungeon.hero.heroClass==HeroClass.PERFORMER && Random.Int(1) == 0){addItemToSpawn(new DungeonBomb());} + super.createItems(); + + Imp.Quest.spawn(this); + spawnGoldThief(this); + } + + public static void spawnGoldThief(CityLevel level) { + if (Dungeon.depth == 19 && !Dungeon.goldthiefspawned){ + + GoldThief thief = new GoldThief(); + do { + thief.pos = level.randomRespawnCell(); + } while (thief.pos == -1); + level.mobs.add(thief); + Actor.occupyCell(thief); + + Dungeon.goldthiefspawned = true; + } + } + + @Override + public String tileName(int tile) { + switch (tile) { + case Terrain.WATER: + return Messages.get(CityLevel.class, "water_name"); + case Terrain.HIGH_GRASS: + return Messages.get(CityLevel.class, "high_grass_name"); + default: + return super.tileName(tile); + } + } + + @Override + public String tileDesc(int tile) { + switch (tile) { + case Terrain.ENTRANCE: + return Messages.get(CityLevel.class, "entrance_desc"); + case Terrain.EXIT: + return Messages.get(CityLevel.class, "exit_desc"); + case Terrain.WALL_DECO: + case Terrain.EMPTY_DECO: + return Messages.get(CityLevel.class, "deco_desc"); + case Terrain.EMPTY_SP: + return Messages.get(CityLevel.class, "sp_desc"); + case Terrain.STATUE: + case Terrain.STATUE_SP: + return Messages.get(CityLevel.class, "statue_desc"); + case Terrain.BOOKSHELF: + return Messages.get(CityLevel.class, "bookshelf_desc"); + default: + return super.tileDesc(tile); + } + } + + @Override + public void addVisuals(Scene scene) { + super.addVisuals(scene); + addVisuals(this, scene); + } + + public static void addVisuals(Level level, Scene scene) { + for (int i = 0; i < getLength(); i++) { + if (level.map[i] == Terrain.WALL_DECO) { + scene.add(new Smoke(i)); + } + } + } + + private static class Smoke extends Emitter { + + private int pos; + + private static final Emitter.Factory factory = new Factory() { + + @Override + public void emit(Emitter emitter, int index, float x, float y) { + SmokeParticle p = (SmokeParticle) emitter + .recycle(SmokeParticle.class); + p.reset(x, y); + } + }; + + public Smoke(int pos) { + super(); + + this.pos = pos; + + PointF p = DungeonTilemap.tileCenterToWorld(pos); + pos(p.x - 4, p.y - 2, 4, 0); + + pour(factory, 0.2f); + } + + @Override + public void update() { + if (visible = Dungeon.visible[pos]) { + super.update(); + } + } + } + + public static final class SmokeParticle extends PixelParticle { + + public SmokeParticle() { + super(); + + color(0x000000); + speed.set(Random.Float(8), -Random.Float(8)); + } + + public void reset(float x, float y) { + revive(); + + this.x = x; + this.y = y; + + left = lifespan = 2f; + } + + @Override + public void update() { + super.update(); + float p = left / lifespan; + am = p > 0.8f ? 1 - p : p * 0.25f; + size(8 - p * 4); + } + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/levels/CrabBossLevel.java b/java/com/hmdzl/spspd/levels/CrabBossLevel.java new file mode 100644 index 00000000..318e9b93 --- /dev/null +++ b/java/com/hmdzl/spspd/levels/CrabBossLevel.java @@ -0,0 +1,271 @@ +/* + * 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 + */ +package com.hmdzl.spspd.levels; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.mobs.CrabKing; +import com.hmdzl.spspd.actors.mobs.HermitCrab; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.actors.mobs.Shell; +import com.hmdzl.spspd.items.Heap; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.keys.SkeletonKey; +import com.hmdzl.spspd.levels.painters.Painter; +import com.hmdzl.spspd.scenes.GameScene; +import com.watabou.noosa.Scene; +import com.watabou.noosa.tweeners.AlphaTweener; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public class CrabBossLevel extends Level { + + { + color1 = 0x4b6636; + color2 = 0xf2f2f2; + cleared=true; + } + + private static final int TOP = 2; + private static final int HALL_WIDTH = 13; + private static final int HALL_HEIGHT = 15; + private static final int CHAMBER_HEIGHT = 3; + + private static final int LEFT = (getWidth() - HALL_WIDTH) / 2; + private static final int CENTER = LEFT + HALL_WIDTH / 2; + + private int arenaDoor; + private boolean enteredArena = false; + private boolean keyDropped = false; + + @Override + public String tilesTex() { + return Assets.TILES_BEACH; + } + + @Override + public String waterTex() { + return Assets.WATER_PRISON; + } + + private static final String DOOR = "door"; + private static final String ENTERED = "entered"; + private static final String DROPPED = "droppped"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(DOOR, arenaDoor); + bundle.put(ENTERED, enteredArena); + bundle.put(DROPPED, keyDropped); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + arenaDoor = bundle.getInt(DOOR); + enteredArena = bundle.getBoolean(ENTERED); + keyDropped = bundle.getBoolean(DROPPED); + } + + @Override + protected boolean build() { + + Painter.fill(this, LEFT, TOP, HALL_WIDTH, HALL_HEIGHT, Terrain.WATER); + Painter.fill(this, CENTER, TOP, 1, HALL_HEIGHT, Terrain.WATER); + + int y = TOP + 1; + while (y < TOP + HALL_HEIGHT) { + map[y * getWidth() + CENTER - 2] = Terrain.STATUE; + map[y * getWidth() + CENTER + 2] = Terrain.STATUE; + y += 2; + } + + exit = (TOP - 1) * getWidth() + CENTER; + map[exit] = Terrain.LOCKED_EXIT; + + arenaDoor = (TOP + HALL_HEIGHT) * getWidth() + CENTER; + map[arenaDoor] = Terrain.DOOR; + + Painter.fill(this, LEFT, TOP + HALL_HEIGHT + 1, HALL_WIDTH, + CHAMBER_HEIGHT, Terrain.EMPTY); + Painter.fill(this, LEFT, TOP + HALL_HEIGHT + 1, 1, CHAMBER_HEIGHT, + Terrain.WATER); + Painter.fill(this, LEFT + HALL_WIDTH - 1, TOP + HALL_HEIGHT + 1, 1, + CHAMBER_HEIGHT, Terrain.WATER); + + entrance = (TOP + HALL_HEIGHT + 2 + Random.Int(CHAMBER_HEIGHT - 1)) + * getWidth() + LEFT + (/* 1 + */Random.Int(HALL_WIDTH - 2)); + map[entrance] = Terrain.PEDESTAL; + + map[exit] = Terrain.WALL; + + return true; + } + + @Override + protected void decorate() { + + for (int i = 0; i < getLength(); i++) { + if (map[i] == Terrain.EMPTY && Random.Int(10) == 0) { + map[i] = Terrain.EMPTY_DECO; + } else if (map[i] == Terrain.WALL && Random.Int(8) == 0) { + map[i] = Terrain.WALL_DECO; + } + } + + //int sign = arenaDoor + WIDTH + 1; + //map[sign] = Terrain.SIGN; + } + + public static int pedestal(boolean left) { + if (left) { + return (TOP + HALL_HEIGHT / 2) * getWidth() + CENTER - 2; + } else { + return (TOP + HALL_HEIGHT / 2) * getWidth() + CENTER + 2; + } + } + + @Override + protected void createMobs() { + } + + @Override + public Actor respawner() { + return null; + } + + @Override + protected void createItems() { + + } + + @Override + public int randomRespawnCell() { + return -1; + } + + @Override + public void press(int cell, Char hero) { + + super.press(cell, hero); + + if (!enteredArena && outsideEntraceRoom(cell) && hero == Dungeon.hero) { + + enteredArena = true; + //locked = true; + + Mob boss = new CrabKing(); + Mob shell = new Shell(); + Mob crab1 = new HermitCrab(); + Mob crab2 = new HermitCrab(); + Mob crab3 = new HermitCrab(); + Mob crab4 = new HermitCrab(); + boss.state = boss.HUNTING; + crab1.state = crab1.HUNTING; + crab2.state = crab2.HUNTING; + crab3.state = crab3.HUNTING; + crab4.state = crab4.HUNTING; + int count = 0; + do { + boss.pos = Random.Int(getLength()); + shell.pos = (TOP + 1) * getWidth() + CENTER; + crab1.pos = (TOP + 1) * getWidth() + CENTER+1; + crab2.pos = (TOP + 1) * getWidth() + CENTER-1; + crab3.pos = (TOP + 2) * getWidth() + CENTER; + crab4.pos = (TOP + 0) * getWidth() + CENTER; + } while (!passable[boss.pos] + || !outsideEntraceRoom(boss.pos) + || (Dungeon.visible[boss.pos] && count++ < 20)); + + GameScene.add(boss); + GameScene.add(shell); + + GameScene.add(crab1); + GameScene.add(crab2); + GameScene.add(crab3); + GameScene.add(crab4); + + if (Dungeon.visible[boss.pos]) { + boss.notice(); + boss.sprite.alpha(0); + boss.sprite.parent.add(new AlphaTweener(boss.sprite, 1, 0.1f)); + } + + //set(arenaDoor, Terrain.WALL); + //GameScene.updateMap(arenaDoor); + Dungeon.observe(); + } + } + + @Override + public Heap drop(Item item, int cell) { + + if (!keyDropped && item instanceof SkeletonKey) { + + keyDropped = true; + locked = false; + + set(arenaDoor, Terrain.DOOR); + GameScene.updateMap(arenaDoor); + Dungeon.observe(); + } + + return super.drop(item, cell); + } + + private boolean outsideEntraceRoom(int cell) { + return cell / getWidth() < arenaDoor / getWidth(); + } + + @Override + public String tileName(int tile) { + switch (tile) { + case Terrain.WATER: + return "Crystal clear pools."; + case Terrain.HIGH_GRASS: + return "Seaweed Tangles"; + default: + return super.tileName(tile); + } + } + + @Override + public String tileDesc(int tile) { + switch (tile) { + case Terrain.EMPTY_DECO: + return "Small crabs and shell fish litter the sandy floor."; + case Terrain.EMPTY_SP: + return "Thick carpet covers the floor."; + case Terrain.STATUE: + case Terrain.STATUE_SP: + return "A large sea shell is propped up in the sand."; + case Terrain.BOOKSHELF: + return "Mostly beach reads."; + default: + return super.tileDesc(tile); + } + } + + @Override + public void addVisuals(Scene scene) { + CityLevel.addVisuals(this, scene); + } +} diff --git a/java/com/hmdzl/spspd/levels/DeadEndLevel.java b/java/com/hmdzl/spspd/levels/DeadEndLevel.java new file mode 100644 index 00000000..e3ea02cf --- /dev/null +++ b/java/com/hmdzl/spspd/levels/DeadEndLevel.java @@ -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 + */ +package com.hmdzl.spspd.levels; + +import java.util.Arrays; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.messages.Messages; +import com.watabou.utils.Random; + +public class DeadEndLevel extends Level { + + private static final int SIZE = 5; + + { + color1 = 0x534f3e; + color2 = 0xb9d661; + } + + @Override + public String tilesTex() { + return Assets.TILES_CAVES; + } + + @Override + public String waterTex() { + return Assets.WATER_HALLS; + } + + @Override + protected boolean build() { + + Arrays.fill(map, Terrain.WALL); + + for (int i = 2; i < SIZE; i++) { + for (int j = 2; j < SIZE; j++) { + map[i * getWidth() + j] = Terrain.EMPTY; + } + } + + for (int i = 1; i <= SIZE; i++) { + map[getWidth() + i] = map[getWidth() * SIZE + i] = map[getWidth() * i + 1] = map[getWidth() + * i + SIZE] = Terrain.WATER; + } + + entrance = SIZE * getWidth() + SIZE / 2 + 1; + map[entrance] = Terrain.ENTRANCE; + + map[(SIZE / 2 + 1) * (getWidth() + 1)] = Terrain.SIGN; + + exit = 0; + + return true; + } + + @Override + protected void decorate() { + for (int i = 0; i < getLength(); i++) { + if (map[i] == Terrain.EMPTY && Random.Int(10) == 0) { + map[i] = Terrain.EMPTY_DECO; + } else if (map[i] == Terrain.WALL && Random.Int(8) == 0) { + map[i] = Terrain.WALL_DECO; + } + } + } + + /*@Override + public String tileName(int tile) { + switch (tile) { + case Terrain.WATER: + return "Suspiciously colored water"; + case Terrain.HIGH_GRASS: + return "High blooming flowers"; + default: + return super.tileName(tile); + } + }*/ + + @Override + protected void createMobs() { + } + + @Override + protected void createItems() { + } + + @Override + public String tileName(int tile) { + switch (tile) { + case Terrain.GRASS: + return Messages.get(CavesLevel.class, "grass_name"); + case Terrain.HIGH_GRASS: + return Messages.get(CavesLevel.class, "high_grass_name"); + case Terrain.WATER: + return Messages.get(CavesLevel.class, "water_name"); + default: + return super.tileName(tile); + } + } + + @Override + public String tileDesc(int tile) { + switch (tile) { + case Terrain.ENTRANCE: + return Messages.get(CavesLevel.class, "entrance_desc"); + case Terrain.EXIT: + return Messages.get(CavesLevel.class, "exit_desc"); + case Terrain.HIGH_GRASS: + return Messages.get(CavesLevel.class, "high_grass_desc"); + case Terrain.WALL_DECO: + return Messages.get(CavesLevel.class, "wall_deco_desc"); + case Terrain.BOOKSHELF: + return Messages.get(CavesLevel.class, "bookshelf_desc"); + default: + return super.tileDesc(tile); + } + } + + @Override + public int randomRespawnCell() { + return entrance - getWidth(); + } + +} diff --git a/java/com/hmdzl/spspd/levels/DragonCaveLevel.java b/java/com/hmdzl/spspd/levels/DragonCaveLevel.java new file mode 100644 index 00000000..55061b5a --- /dev/null +++ b/java/com/hmdzl/spspd/levels/DragonCaveLevel.java @@ -0,0 +1,517 @@ +/* + * 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 + */ +package com.hmdzl.spspd.levels; + +import java.util.Collection; +import java.util.HashSet; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.WellWater; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.actors.mobs.npcs.Sheep; +import com.hmdzl.spspd.actors.mobs.npcs.SheepSokoban; +import com.hmdzl.spspd.actors.mobs.npcs.SheepSokobanBlack; +import com.hmdzl.spspd.actors.mobs.npcs.SheepSokobanCorner; +import com.hmdzl.spspd.actors.mobs.npcs.SheepSokobanSwitch; +import com.hmdzl.spspd.items.Gold; +import com.hmdzl.spspd.items.Heap; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.eggs.ShadowDragonEgg; +import com.hmdzl.spspd.items.artifacts.TimekeepersHourglass; +import com.hmdzl.spspd.items.scrolls.ScrollOfUpgrade; +import com.hmdzl.spspd.items.wands.WandOfFlock; +import com.hmdzl.spspd.levels.features.Chasm; +import com.hmdzl.spspd.levels.features.Door; +import com.hmdzl.spspd.levels.features.HighGrass; +import com.hmdzl.spspd.levels.traps.ActivatePortalTrap; +import com.hmdzl.spspd.levels.traps.ChangeSheepTrap; +import com.hmdzl.spspd.levels.traps.FleecingTrap; +import com.hmdzl.spspd.levels.traps.SokobanPortalTrap; +import com.hmdzl.spspd.plants.Plant; +import com.hmdzl.spspd.scenes.GameScene; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Bundlable; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public class DragonCaveLevel extends Level { + + + { + color1 = 0x534f3e; + color2 = 0xb9d661; + WIDTH = 48; + HEIGHT = 48; + LENGTH = HEIGHT*WIDTH; + cleared=true; + } + + + public HashSet heapstogen; + public int[] heapgenspots; + public int[] teleportspots; + public int[] portswitchspots; + public int[] teleportassign; + public int[] destinationspots; + public int[] destinationassign; + public int prizeNo; + + private static final String HEAPSTOGEN = "heapstogen"; + private static final String HEAPGENSPOTS = "heapgenspots"; + private static final String TELEPORTSPOTS = "teleportspots"; + private static final String PORTSWITCHSPOTS = "portswitchspots"; + private static final String DESTINATIONSPOTS = "destinationspots"; + private static final String TELEPORTASSIGN = "teleportassign"; + private static final String DESTINATIONASSIGN= "destinationassign"; + private static final String PRIZENO = "prizeNo"; + + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(HEAPSTOGEN, heapstogen); + bundle.put(HEAPGENSPOTS, heapgenspots); + bundle.put(TELEPORTSPOTS, teleportspots); + bundle.put(PORTSWITCHSPOTS, portswitchspots); + bundle.put(DESTINATIONSPOTS, destinationspots); + bundle.put(DESTINATIONASSIGN, destinationassign); + bundle.put(TELEPORTASSIGN, teleportassign); + bundle.put(PRIZENO, prizeNo); + } + + + + @Override + public void restoreFromBundle(Bundle bundle) { + + super.restoreFromBundle(bundle); + + heapgenspots = bundle.getIntArray(HEAPGENSPOTS); + teleportspots = bundle.getIntArray(TELEPORTSPOTS); + portswitchspots = bundle.getIntArray(PORTSWITCHSPOTS); + destinationspots = bundle.getIntArray(DESTINATIONSPOTS); + destinationassign = bundle.getIntArray(DESTINATIONASSIGN); + teleportassign = bundle.getIntArray(TELEPORTASSIGN); + prizeNo = bundle.getInt(PRIZENO); + + heapstogen = new HashSet(); + + Collection collectionheap = bundle.getCollection(HEAPSTOGEN); + for (Bundlable i : collectionheap) { + Item item = (Item) i; + if (item != null) { + heapstogen.add(item); + } + } + } + + @Override + public void create() { + heapstogen = new HashSet(); + heapgenspots = new int[10]; + teleportspots = new int[10]; + portswitchspots = new int[10]; + destinationspots = new int[10]; + destinationassign = new int[10]; + teleportassign = new int[10]; + super.create(); + } + + public void addItemToGen(Item item, int arraypos, int pos) { + if (item != null) { + heapstogen.add(item); + heapgenspots[arraypos]=pos; + } + } + + + public Item genPrizeItem() { + return genPrizeItem(null); + } + + + public Item genPrizeItem(Class match) { + + boolean keysLeft = false; + + if (heapstogen.size() == 0) + return null; + + for (Item item : heapstogen) { + if (match.isInstance(item)) { + heapstogen.remove(item); + keysLeft=true; + return item; + } + } + + if (match == null || !keysLeft) { + Item item = Random.element(heapstogen); + heapstogen.remove(item); + return item; + } + + return null; + } + + @Override + public void press(int cell, Char ch) { + + if (pit[cell] && ch == Dungeon.hero) { + Chasm.heroFall(cell); + return; + } + + TimekeepersHourglass.timeFreeze timeFreeze = null; + + if (ch != null) + timeFreeze = ch.buff(TimekeepersHourglass.timeFreeze.class); + + boolean trap = false; + boolean interrupt = false; + + switch (map[cell]) { + + case Terrain.FLEECING_TRAP: + + if (ch==null){ + interrupt=true; + } + + if (ch != null && ch==Dungeon.hero){ + trap = true; + FleecingTrap.trigger(cell, ch); + } + break; + + case Terrain.CHANGE_SHEEP_TRAP: + + if (ch instanceof SheepSokoban || ch instanceof SheepSokobanSwitch || ch instanceof SheepSokobanCorner || ch instanceof Sheep || ch instanceof WandOfFlock.MagicSheep){ + trap = true; + ChangeSheepTrap.trigger(cell, ch); + } + break; + + case Terrain.WOOL_RUG: + + break; + + case Terrain.SOKOBAN_PORT_SWITCH: + trap=false; + if (ch!=null){ + ActivatePortalTrap.trigger(cell, ch); + + + int arraypos = -1; //position in array of teleport switch + int portpos = -1; //position on map of teleporter + int portarraypos = -1; //position in array of teleporter + int destpos = -1; //destination position assigned to switch + + for(int i = 0; i < portswitchspots.length; i++) { + if(portswitchspots[i] == cell) { + arraypos = i; + break; + } + } + + portpos = teleportassign[arraypos]; + destpos = destinationassign[arraypos]; + + /* Stepping on switch deactivates the portal */ + destpos = -1; + + for(int i = 0; i < teleportspots.length; i++) { + if(teleportspots[i] == portpos) { + portarraypos = i; + break; + } + } + + if (map[portpos] == Terrain.PORT_WELL){ + destinationspots[portarraypos]=destpos; + } + + + } + break; + + + case Terrain.PORT_WELL: + + if (ch != null && ch==Dungeon.hero){ + + int portarray=-1; + int destinationspot=cell; + + for(int i = 0; i < teleportspots.length; i++) { + if(teleportspots[i] == cell) { + portarray = i; + break; + } + } + + if(portarray != -1) { + destinationspot=destinationspots[portarray]; + if (destinationspot>0){ + SokobanPortalTrap.trigger(cell, ch, destinationspot); + } + } + } + break; + + case Terrain.HIGH_GRASS: + HighGrass.trample(this, cell, ch); + break; + + case Terrain.WELL: + WellWater.affectCell(cell); + break; + + /*case Terrain.ALCHEMY: + if (ch == null) { + Alchemy.transmute(cell); + } + break;*/ + + case Terrain.DOOR: + Door.enter(cell); + break; + } + + if (trap){ + + if (Dungeon.visible[cell]) + Sample.INSTANCE.play(Assets.SND_TRAP); + + if (ch == Dungeon.hero) + Dungeon.hero.interrupt(); + + set(cell, Terrain.INACTIVE_TRAP); + GameScene.updateMap(cell); + } + + if (interrupt){ + + Dungeon.hero.interrupt(); + GameScene.updateMap(cell); + } + + Plant plant = plants.get(cell); + if (plant != null) { + plant.activate(ch); + } + } + + + + @Override + public void mobPress(Mob mob) { + + int cell = mob.pos; + + if (pit[cell] && !mob.flying) { + Chasm.mobFall(mob); + return; + } + + + } + + @Override + public String tileName(int tile) { + switch (tile) { + case Terrain.WOOL_RUG: + return "Wool rug"; + case Terrain.FLEECING_TRAP: + return "Fleecing trap"; + case Terrain.CHANGE_SHEEP_TRAP: + return "Change sheep trap"; + case Terrain.SOKOBAN_ITEM_REVEAL: + return "Item creation switch"; + case Terrain.SOKOBAN_SHEEP: + return "Floor"; + case Terrain.SWITCH_SOKOBAN_SHEEP: + return "Floor"; + case Terrain.CORNER_SOKOBAN_SHEEP: + return "Floor"; + case Terrain.BLACK_SOKOBAN_SHEEP: + return "Floor"; + case Terrain.SOKOBAN_PORT_SWITCH: + return "Portal switch"; + case Terrain.PORT_WELL: + return "Portal"; + case Terrain.WATER: + return "Dark cold water."; + default: + return super.tileName(tile); + } + } + + + @Override + public String tileDesc(int tile) { + switch (tile) { + case Terrain.SOKOBAN_SHEEP: + return ""; + case Terrain.SWITCH_SOKOBAN_SHEEP: + return ""; + case Terrain.CORNER_SOKOBAN_SHEEP: + return ""; + case Terrain.BLACK_SOKOBAN_SHEEP: + return ""; + case Terrain.FLEECING_TRAP: + return "Stepping onto a fleecing trap will destroy your armor or eject you from the level."; + case Terrain.CHANGE_SHEEP_TRAP: + return "This trap will change the form of any sheep."; + case Terrain.SOKOBAN_ITEM_REVEAL: + return "This switch creates an item somewhere on the level."; + case Terrain.SOKOBAN_PORT_SWITCH: + return "This switch turns on and off a portal somewhere."; + case Terrain.PORT_WELL: + return "This is a portal to another location on this level."; + case Terrain.WOOL_RUG: + return "A plush wool rug. Very nice!"; + case Terrain.EMPTY_DECO: + return "There are old blood stains on the floor."; + case Terrain.BOOKSHELF: + return "This is probably a vestige of a prison library. Might it burn?"; + default: + return super.tileDesc(tile); + } + } + + + @Override + public String tilesTex() { + return Assets.TILES_PUZZLE; + } + + @Override + public String waterTex() { + return Assets.WATER_PRISON; + } + + @Override + protected boolean build() { + + map = SokobanLayouts2.DRAGON_CAVE.clone(); + decorate(); + + buildFlagMaps(); + cleanWalls(); + createSwitches(); + createSheep(); + + entrance = 5 + WIDTH * 37; + exit = 0; + + + return true; + } + @Override + protected void decorate() { + /* + for (int i = 0; i < getLength(); i++) { + + } + */ + } + + @Override + protected void createMobs() { + /* + SokobanSentinel mob = new SokobanSentinel(); + mob.pos = 38 + WIDTH * 21; + mobs.add(mob); + Actor.occupyCell(mob); + + SokobanSentinel mob2 = new SokobanSentinel(); + mob2.pos = 25 + WIDTH * 36; + mobs.add(mob2); + Actor.occupyCell(mob2); + */ + } + + + + protected void createSheep() { + for (int i = 0; i < LENGTH; i++) { + if (map[i]==Terrain.SOKOBAN_SHEEP){SheepSokoban npc = new SheepSokoban(); mobs.add(npc); npc.pos = i; Actor.occupyCell(npc);} + else if (map[i]==Terrain.CORNER_SOKOBAN_SHEEP){SheepSokobanCorner npc = new SheepSokobanCorner(); mobs.add(npc); npc.pos = i; Actor.occupyCell(npc);} + else if (map[i]==Terrain.SWITCH_SOKOBAN_SHEEP){SheepSokobanSwitch npc = new SheepSokobanSwitch(); mobs.add(npc); npc.pos = i; Actor.occupyCell(npc);} + else if (map[i]==Terrain.BLACK_SOKOBAN_SHEEP){SheepSokobanBlack npc = new SheepSokobanBlack(); mobs.add(npc); npc.pos = i; Actor.occupyCell(npc);} + else if (map[i]==Terrain.PORT_WELL){ + + /* + Portal portal = new Portal(); + portal.seed(i, 1); + blobs.put(Portal.class, portal); + */ + } + + } + } + + + protected void createSwitches(){ + + //spots where your portals are + + + //spots where your portal switches are + + + //assign each switch to a portal + + + //assign each switch to a destination spot + + + //set the original destination of portals + + } + + + @Override + protected void createItems() { + int goldmin=1; int goldmax=100; + if (first){ + goldmin=400; goldmax=800; + } + for (int i = 0; i < LENGTH; i++) { + if (map[i]==Terrain.SOKOBAN_HEAP){ + if (first && Random.Int(5)==0){drop(new ScrollOfUpgrade(), i).type = Heap.Type.SKELETON;} + else {drop(new Gold(Random.Int(goldmin, goldmax)), i).type = Heap.Type.SKELETON;} + } + } + if (first){ + drop(new ShadowDragonEgg(), 43 + WIDTH * 35); + } + } + + @Override + public int randomRespawnCell() { + return -1; + } + + + +} diff --git a/java/com/hmdzl/spspd/levels/FieldBossLevel.java b/java/com/hmdzl/spspd/levels/FieldBossLevel.java new file mode 100644 index 00000000..81dce9d6 --- /dev/null +++ b/java/com/hmdzl/spspd/levels/FieldBossLevel.java @@ -0,0 +1,262 @@ +/* + * 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 + */ +package com.hmdzl.spspd.levels; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.actors.mobs.GnollKing; +import com.hmdzl.spspd.items.Heap; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.keys.SkeletonKey; +import com.hmdzl.spspd.items.potions.PotionOfLiquidFlame; +import com.hmdzl.spspd.levels.painters.Painter; +import com.hmdzl.spspd.scenes.GameScene; +import com.watabou.noosa.Scene; +import com.watabou.noosa.tweeners.AlphaTweener; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public class FieldBossLevel extends Level { + + { + color1 = 0x48763c; + color2 = 0x59994a; + cleared=true; + viewDistance = 8; + } + + private static final int TOP = 2; + private static final int HALL_WIDTH = 13; + private static final int HALL_HEIGHT = 15; + private static final int CHAMBER_HEIGHT = 3; + + private static final int LEFT = (getWidth() - HALL_WIDTH) / 2; + private static final int CENTER = LEFT + HALL_WIDTH / 2; + + private int arenaDoor; + private boolean enteredArena = false; + private boolean keyDropped = false; + + @Override + public String tilesTex() { + return Assets.TILES_FOREST; + } + + @Override + public String waterTex() { + return Assets.WATER_SEWERS; + } + + private static final String DOOR = "door"; + private static final String ENTERED = "entered"; + private static final String DROPPED = "droppped"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(DOOR, arenaDoor); + bundle.put(ENTERED, enteredArena); + bundle.put(DROPPED, keyDropped); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + arenaDoor = bundle.getInt(DOOR); + enteredArena = bundle.getBoolean(ENTERED); + keyDropped = bundle.getBoolean(DROPPED); + } + + @Override + protected boolean build() { + + Painter.fill(this, LEFT, TOP, HALL_WIDTH, HALL_HEIGHT, Terrain.EMPTY); + Painter.fill(this, CENTER, TOP, 1, HALL_HEIGHT, Terrain.EMPTY); + + int y = TOP + 1; + while (y < TOP + HALL_HEIGHT) { + map[y * getWidth() + CENTER - 2] = Terrain.WALL; + map[y * getWidth() + CENTER + 2] = Terrain.WALL; + y += 2; + } + + exit = (TOP - 1) * getWidth() + CENTER; + map[exit] = Terrain.LOCKED_EXIT; + + arenaDoor = (TOP + HALL_HEIGHT) * getWidth() + CENTER; + map[arenaDoor] = Terrain.DOOR; + + Painter.fill(this, LEFT, TOP + HALL_HEIGHT + 1, HALL_WIDTH, + CHAMBER_HEIGHT, Terrain.EMPTY); + Painter.fill(this, LEFT, TOP + HALL_HEIGHT + 1, 1, CHAMBER_HEIGHT, + Terrain.WATER); + Painter.fill(this, LEFT + HALL_WIDTH - 1, TOP + HALL_HEIGHT + 1, 1, + CHAMBER_HEIGHT, Terrain.WATER); + + entrance = (TOP + HALL_HEIGHT + 2 + Random.Int(CHAMBER_HEIGHT - 1)) + * getWidth() + LEFT + (/* 1 + */Random.Int(HALL_WIDTH - 2)); + map[entrance] = Terrain.PEDESTAL; + + map[exit] = Terrain.WALL; + + return true; + } + + @Override + protected void decorate() { + + for (int i = 0; i < getLength(); i++) { + if (map[i] == Terrain.EMPTY && Random.Int(10) == 0) { + map[i] = Terrain.EMPTY_DECO; + } else if (map[i] == Terrain.WALL && Random.Int(8) == 0) { + map[i] = Terrain.WALL_DECO; + } + } + + int shrub1 = arenaDoor + getWidth(); + int shrub2 = arenaDoor + getWidth() + 1; + int shrub3 = arenaDoor + getWidth() - 1; + int potionpos = arenaDoor + 2*getWidth(); + map[shrub1] = Terrain.HIGH_GRASS; + map[shrub2] = Terrain.HIGH_GRASS; + map[shrub3] = Terrain.HIGH_GRASS; + drop(new PotionOfLiquidFlame(), potionpos); + + for (int i = 0; i < getLength(); i++) { + if (map[i] == Terrain.WALL && Random.Int(8) == 0) { + map[i] = Terrain.WALL_DECO; + } + if (map[i]==Terrain.ENTRANCE){map[i] = Terrain.EMPTY;} + if (map[i]==Terrain.EMPTY && heaps.get(i) == null && Random.Float()<.20){map[i] = Terrain.HIGH_GRASS;} + if (map[i]==Terrain.EMPTY && heaps.get(i) == null && Random.Float()<.25){map[i] = Terrain.GRASS;} + if (map[i]==Terrain.EMPTY && heaps.get(i) == null && Random.Float()<.30){map[i] = Terrain.SHRUB;} + } + + //int sign = arenaDoor + WIDTH + 1; + //map[sign] = Terrain.SIGN; + } + + public static int pedestal(boolean left) { + if (left) { + return (TOP + HALL_HEIGHT / 2) * getWidth() + CENTER - 2; + } else { + return (TOP + HALL_HEIGHT / 2) * getWidth() + CENTER + 2; + } + } + + @Override + protected void createMobs() { + } + + @Override + public Actor respawner() { + return null; + } + + @Override + protected void createItems() { + + } + + @Override + public int randomRespawnCell() { + return -1; + } + + @Override + public void press(int cell, Char hero) { + + super.press(cell, hero); + + if (!enteredArena && outsideEntraceRoom(cell) && hero == Dungeon.hero) { + + enteredArena = true; + //locked = true; + + Mob boss = new GnollKing(); + boss.state = boss.HUNTING; + int count = 0; + do { + boss.pos = Random.Int(getLength()); + } while (!passable[boss.pos] + || !outsideEntraceRoom(boss.pos) + || (Dungeon.visible[boss.pos] && count++ < 20)); + + GameScene.add(boss); + + if (Dungeon.visible[boss.pos]) { + boss.notice(); + boss.sprite.alpha(0); + boss.sprite.parent.add(new AlphaTweener(boss.sprite, 1, 0.1f)); + } + + //set(arenaDoor, Terrain.WALL); + //GameScene.updateMap(arenaDoor); + Dungeon.observe(); + } + } + + @Override + public Heap drop(Item item, int cell) { + + if (!keyDropped && item instanceof SkeletonKey) { + + keyDropped = true; + locked = false; + + set(arenaDoor, Terrain.DOOR); + GameScene.updateMap(arenaDoor); + Dungeon.observe(); + } + + return super.drop(item, cell); + } + + private boolean outsideEntraceRoom(int cell) { + return cell / getWidth() < arenaDoor / getWidth(); + } + + public String tileName(int tile) { + switch (tile) { + case Terrain.WATER: + return "Murky water"; + default: + return super.tileName(tile); + } + } + + @Override + public String tileDesc(int tile) { + switch (tile) { + case Terrain.EMPTY_DECO: + return "The grass is worn away to reveal bedrock. "; + case Terrain.BOOKSHELF: + return "The bookshelf is packed with cheap useless books. Might it burn?"; + default: + return super.tileDesc(tile); + } + } + + @Override + public void addVisuals(Scene scene) { + CavesLevel.addVisuals(this, scene); + } +} diff --git a/java/com/hmdzl/spspd/levels/FieldLevel.java b/java/com/hmdzl/spspd/levels/FieldLevel.java new file mode 100644 index 00000000..48b58f49 --- /dev/null +++ b/java/com/hmdzl/spspd/levels/FieldLevel.java @@ -0,0 +1,234 @@ +/* + * 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 + */ +package com.hmdzl.spspd.levels; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.Statistics; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.mobs.Bestiary; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.levels.painters.Painter; +import com.hmdzl.spspd.scenes.GameScene; +import com.watabou.noosa.Scene; +import com.watabou.utils.Random; + +public class FieldLevel extends Level { + + { + color1 = 0x48763c; + color2 = 0x59994a; + cleared=true; + + viewDistance = 6; + } + + + + private static final int ROOM_LEFT = getWidth() / 2 - 2; + private static final int ROOM_RIGHT = getWidth() / 2 + 2; + private static final int ROOM_TOP = HEIGHT / 2 - 2; + private static final int ROOM_BOTTOM = HEIGHT / 2 + 2; + + @Override + public String tilesTex() { + return Assets.TILES_FOREST; + } + + @Override + public String waterTex() { + return Assets.WATER_SEWERS; + } + + protected static final float TIME_TO_RESPAWN = 20; + protected static final int REGROW_TIMER = 4; + + @Override + protected boolean build() { + + int topMost = Integer.MAX_VALUE; + + for (int i = 0; i < 8; i++) { + int left, right, top, bottom; + if (Random.Int(2) == 0) { + left = Random.Int(1, ROOM_LEFT - 3); + right = ROOM_RIGHT + 3; + } else { + left = ROOM_LEFT - 3; + right = Random.Int(ROOM_RIGHT + 3, getWidth() - 1); + } + if (Random.Int(2) == 0) { + top = Random.Int(2, ROOM_TOP - 3); + bottom = ROOM_BOTTOM + 3; + } else { + top = ROOM_LEFT - 3; + bottom = Random.Int(ROOM_TOP + 3, HEIGHT - 1); + } + + Painter.fill(this, left, top, right - left + 1, bottom - top + 1, + Terrain.EMPTY); + + if (top < topMost) { + topMost = top; + exit = Random.Int(left, right) + (top - 1) * getWidth(); + } + } + + map[exit] = Terrain.WALL; + + + + Painter.fill(this, ROOM_LEFT, ROOM_TOP + 1, ROOM_RIGHT - ROOM_LEFT + 1, + ROOM_BOTTOM - ROOM_TOP, Terrain.EMPTY); + + + entrance = Random.Int(ROOM_LEFT + 1, ROOM_RIGHT - 1) + + Random.Int(ROOM_TOP + 1, ROOM_BOTTOM - 1) * getWidth(); + map[entrance] = Terrain.EMPTY; + + return true; + } + + @Override + protected void decorate() { + + for (int i = getWidth() + 1; i < getLength() - getWidth(); i++) { + if (map[i] == Terrain.EMPTY) { + int n = 0; + if (map[i + 1] == Terrain.WALL) { + n++; + } + if (map[i - 1] == Terrain.WALL) { + n++; + } + if (map[i + getWidth()] == Terrain.WALL) { + n++; + } + if (map[i - getWidth()] == Terrain.WALL) { + n++; + } + if (Random.Int(8) <= n) { + map[i] = Terrain.EMPTY_DECO; + } + } + } + + for (int i = 0; i < getLength(); i++) { + if (map[i] == Terrain.WALL && Random.Int(8) == 0) { + map[i] = Terrain.WALL_DECO; + } + if (map[i]==Terrain.ENTRANCE){map[i] = Terrain.EMPTY;} + if (map[i]==Terrain.EMPTY && heaps.get(i) == null && Random.Float()<.20){map[i] = Terrain.HIGH_GRASS;} + if (map[i]==Terrain.EMPTY && heaps.get(i) == null && Random.Float()<.25){map[i] = Terrain.GRASS;} + if (map[i]==Terrain.EMPTY && heaps.get(i) == null && Random.Float()<.30){map[i] = Terrain.SHRUB;} + } + + } + + //@Override + //protected void createMobs() { + //} + + //@Override + //public Actor respawner() { + // return null; + //} + + @Override + protected void createItems() {} + + + + + //@Override + //public int randomRespawnCell() { + // return -1; + //} + + + + + @Override + public String tileName(int tile) { + switch (tile) { + case Terrain.WATER: + return "Murky water"; + default: + return super.tileName(tile); + } + } + + @Override + public String tileDesc(int tile) { + switch (tile) { + case Terrain.EMPTY_DECO: + return "The grass is worn away to reveal bedrock."; + case Terrain.BOOKSHELF: + return "The bookshelf is packed with cheap useless books. Might it burn?"; + default: + return super.tileDesc(tile); + } + } + + + @Override + public void addVisuals(Scene scene) { + CavesLevel.addVisuals(this, scene); + } + @Override + public int nMobs() { + return 10; + } + + @Override + protected void createMobs() { + int nMobs = nMobs(); + for (int i = 0; i < nMobs; i++) { + Mob mob = Bestiary.mob(Dungeon.depth); + do { + mob.pos = randomRespawnCellMob(); + } while (mob.pos == -1); + mobs.add(mob); + Actor.occupyCell(mob); + } + } + + @Override + public Actor respawner() { + return new Actor() { + @Override + protected boolean act() { + if (mobs.size() < nMobs()) { + + Mob mob = Bestiary.mutable(Dungeon.depth); + mob.state = mob.WANDERING; + mob.pos = randomRespawnCellMob(); + if (Dungeon.hero.isAlive() && mob.pos != -1) { + GameScene.add(mob); + } + } + spend(Dungeon.level.feeling == Feeling.DARK + || Statistics.amuletObtained ? TIME_TO_RESPAWN / 2 + : TIME_TO_RESPAWN); + return true; + } + }; + } + + +} diff --git a/java/com/hmdzl/spspd/levels/FishingBossLevel.java b/java/com/hmdzl/spspd/levels/FishingBossLevel.java new file mode 100644 index 00000000..a5fdbc05 --- /dev/null +++ b/java/com/hmdzl/spspd/levels/FishingBossLevel.java @@ -0,0 +1,272 @@ +/* + * 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 + */ +package com.hmdzl.spspd.levels; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.mobs.CrabKing; +import com.hmdzl.spspd.actors.mobs.HermitCrab; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.actors.mobs.Shell; +import com.hmdzl.spspd.items.Heap; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.keys.SkeletonKey; +import com.hmdzl.spspd.levels.painters.Painter; +import com.hmdzl.spspd.scenes.GameScene; +import com.watabou.noosa.Scene; +import com.watabou.noosa.tweeners.AlphaTweener; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public class FishingBossLevel extends Level { + + { + color1 = 0x4b6636; + color2 = 0xf2f2f2; + cleared=true; + } + + private static final int TOP = 2; + private static final int HALL_WIDTH = 13; + private static final int HALL_HEIGHT = 15; + private static final int CHAMBER_HEIGHT = 3; + + private static final int LEFT = (getWidth() - HALL_WIDTH) / 2; + private static final int CENTER = LEFT + HALL_WIDTH / 2; + + private int arenaDoor; + private boolean enteredArena = false; + private boolean keyDropped = false; + + @Override + public String tilesTex() { + return Assets.TILES_PRISON; + } + + @Override + public String waterTex() { + return Assets.WATER_PRISON; + } + + private static final String DOOR = "door"; + private static final String ENTERED = "entered"; + private static final String DROPPED = "droppped"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(DOOR, arenaDoor); + bundle.put(ENTERED, enteredArena); + bundle.put(DROPPED, keyDropped); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + arenaDoor = bundle.getInt(DOOR); + enteredArena = bundle.getBoolean(ENTERED); + keyDropped = bundle.getBoolean(DROPPED); + } + + @Override + protected boolean build() { + + Painter.fill(this, LEFT, TOP, HALL_WIDTH, HALL_HEIGHT, Terrain.EMPTY); + Painter.fill(this, CENTER, TOP, 1, HALL_HEIGHT, Terrain.EMPTY); + + int y = TOP + 1; + while (y < TOP + HALL_HEIGHT) { + map[y * getWidth() + CENTER - 2] = Terrain.STATUE_SP; + map[y * getWidth() + CENTER + 2] = Terrain.STATUE_SP; + y += 2; + } + + exit = (TOP - 1) * getWidth() + CENTER; + map[exit] = Terrain.LOCKED_EXIT; + + arenaDoor = (TOP + HALL_HEIGHT) * getWidth() + CENTER; + map[arenaDoor] = Terrain.DOOR; + + Painter.fill(this, LEFT, TOP + HALL_HEIGHT + 1, HALL_WIDTH, + CHAMBER_HEIGHT, Terrain.EMPTY); + Painter.fill(this, LEFT, TOP + HALL_HEIGHT + 1, 1, CHAMBER_HEIGHT, + Terrain.WATER); + Painter.fill(this, LEFT + HALL_WIDTH - 1, TOP + HALL_HEIGHT + 1, 1, + CHAMBER_HEIGHT, Terrain.WATER); + + entrance = (TOP + HALL_HEIGHT + 2 + Random.Int(CHAMBER_HEIGHT - 1)) + * getWidth() + LEFT + (/* 1 + */Random.Int(HALL_WIDTH - 2)); + map[entrance] = Terrain.PEDESTAL; + + map[exit] = Terrain.WALL; + + return true; + } + + @Override + protected void decorate() { + + for (int i = 0; i < getLength(); i++) { + if (map[i] == Terrain.EMPTY && Random.Int(10) == 0) { + map[i] = Terrain.EMPTY_DECO; + } else if (map[i] == Terrain.WALL && Random.Int(8) == 0) { + map[i] = Terrain.WALL_DECO; + } + } + + //int sign = arenaDoor + WIDTH + 1; + //map[sign] = Terrain.SIGN; + } + + public static int pedestal(boolean left) { + if (left) { + return (TOP + HALL_HEIGHT / 2) * getWidth() + CENTER - 2; + } else { + return (TOP + HALL_HEIGHT / 2) * getWidth() + CENTER + 2; + } + } + + @Override + protected void createMobs() { + } + + @Override + public Actor respawner() { + return null; + } + + @Override + protected void createItems() { + + } + + @Override + public int randomRespawnCell() { + return -1; + } + + @Override + public void press(int cell, Char hero) { + + super.press(cell, hero); + + if (!enteredArena && outsideEntraceRoom(cell) && hero == Dungeon.hero) { + + enteredArena = true; + //locked = true; + + Mob boss = new CrabKing(); + Mob shell = new Shell(); + Mob crab1 = new HermitCrab(); + Mob crab2 = new HermitCrab(); + Mob crab3 = new HermitCrab(); + Mob crab4 = new HermitCrab(); + boss.state = boss.HUNTING; + int count = 0; + do { + boss.pos = Random.Int(getLength()); + shell.pos = (TOP + 1) * getWidth() + CENTER; + crab1.pos = (TOP + 1) * getWidth() + CENTER+1; + crab2.pos = (TOP + 1) * getWidth() + CENTER-1; + crab3.pos = (TOP + 2) * getWidth() + CENTER; + crab4.pos = (TOP + 0) * getWidth() + CENTER; + } while (!passable[boss.pos] + || !outsideEntraceRoom(boss.pos) + || (Dungeon.visible[boss.pos] && count++ < 20)); + + GameScene.add(boss); + GameScene.add(shell); + + GameScene.add(crab1); + GameScene.add(crab2); + GameScene.add(crab3); + GameScene.add(crab4); + + if (Dungeon.visible[boss.pos]) { + boss.notice(); + boss.sprite.alpha(0); + boss.sprite.parent.add(new AlphaTweener(boss.sprite, 1, 0.1f)); + } + + set(arenaDoor, Terrain.WALL); + GameScene.updateMap(arenaDoor); + Dungeon.observe(); + } + } + + @Override + public Heap drop(Item item, int cell) { + + if (!keyDropped && item instanceof SkeletonKey) { + + keyDropped = true; + locked = false; + + set(arenaDoor, Terrain.DOOR); + GameScene.updateMap(arenaDoor); + Dungeon.observe(); + } + + return super.drop(item, cell); + } + + private boolean outsideEntraceRoom(int cell) { + return cell / getWidth() < arenaDoor / getWidth(); + } + + @Override + public String tileName(int tile) { + switch (tile) { + case Terrain.WATER: + return "Suspiciously colored water"; + case Terrain.HIGH_GRASS: + return "High blooming flowers"; + default: + return super.tileName(tile); + } + } + + @Override + public String tileDesc(int tile) { + switch (tile) { + case Terrain.ENTRANCE: + return "A ramp leads up to the upper depth."; + case Terrain.EXIT: + return "A ramp leads down to the lower depth."; + case Terrain.WALL_DECO: + case Terrain.EMPTY_DECO: + return "Several tiles are missing here."; + case Terrain.EMPTY_SP: + return "Thick carpet covers the floor."; + case Terrain.STATUE: + case Terrain.STATUE_SP: + return "The statue depicts some dwarf standing in a heroic stance."; + case Terrain.BOOKSHELF: + return "The rows of books on different disciplines fill the bookshelf."; + default: + return super.tileDesc(tile); + } + } + + @Override + public void addVisuals(Scene scene) { + CityLevel.addVisuals(this, scene); + } +} diff --git a/java/com/hmdzl/spspd/levels/FishingLevel.java b/java/com/hmdzl/spspd/levels/FishingLevel.java new file mode 100644 index 00000000..70f7b0bd --- /dev/null +++ b/java/com/hmdzl/spspd/levels/FishingLevel.java @@ -0,0 +1,262 @@ +/* + * 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 + */ +package com.hmdzl.spspd.levels; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.Statistics; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.mobs.Bestiary; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.items.bombs.FishingBomb; +import com.hmdzl.spspd.items.Heap; +import com.hmdzl.spspd.items.potions.PotionOfLevitation; +import com.hmdzl.spspd.levels.painters.Painter; +import com.hmdzl.spspd.scenes.GameScene; +import com.watabou.noosa.Scene; +import com.watabou.utils.Random; + +public class FishingLevel extends Level { + + { + color1 = 0x534f3e; + color2 = 0xb9d661; + cleared=true; + + viewDistance = 8; + } + + private static final int ROOM_LEFT = getWidth() / 2 - 2; + private static final int ROOM_RIGHT = getWidth() / 2 + 2; + private static final int ROOM_TOP = HEIGHT / 2 - 2; + private static final int ROOM_BOTTOM = HEIGHT / 2 + 2; + + @Override + public String tilesTex() { + return Assets.TILES_BEACH; + } + + @Override + public String waterTex() { + return Assets.WATER_PRISON; + } + + + + @Override + protected boolean build() { + + int topMost = Integer.MAX_VALUE; + + for (int i = 0; i < 8; i++) { + int left, right, top, bottom; + if (Random.Int(2) == 0) { + left = Random.Int(1, ROOM_LEFT - 3); + right = ROOM_RIGHT + 3; + } else { + left = ROOM_LEFT - 3; + right = Random.Int(ROOM_RIGHT + 3, getWidth() - 1); + } + if (Random.Int(2) == 0) { + top = Random.Int(2, ROOM_TOP - 3); + bottom = ROOM_BOTTOM + 3; + } else { + top = ROOM_LEFT - 3; + bottom = Random.Int(ROOM_TOP + 3, HEIGHT - 1); + } + + Painter.fill(this, left, top, right - left + 1, bottom - top + 1, + Terrain.EMPTY); + + if (top < topMost) { + topMost = top; + exit = Random.Int(left, right) + (top - 1) * getWidth(); + } + } + + + map[exit] = Terrain.WALL; + + + Painter.fill(this, ROOM_LEFT, ROOM_TOP + 1, ROOM_RIGHT - ROOM_LEFT + 1, + ROOM_BOTTOM - ROOM_TOP, Terrain.EMPTY); + + + entrance = Random.Int(ROOM_LEFT + 1, ROOM_RIGHT - 1) + + Random.Int(ROOM_TOP + 1, ROOM_BOTTOM - 1) * getWidth(); + + for (int i = 0; i < getLength(); i++) { + + if (map[i]==Terrain.EMPTY && Random.Float()<.95){map[i] = Terrain.WATER;} + } + + boolean[] patch = Patch.generate(0.45f, 6); + for (int i = 0; i < getLength(); i++) { + if (map[i] == Terrain.WATER && patch[i]) { + map[i] = Terrain.EMPTY; + } + } + + return true; + } + + @Override + protected void decorate() { + + for (int i = getWidth() + 1; i < getLength() - getWidth(); i++) { + if (map[i] == Terrain.EMPTY) { + int n = 0; + if (map[i + 1] == Terrain.WALL) { + n++; + } + if (map[i - 1] == Terrain.WALL) { + n++; + } + if (map[i + getWidth()] == Terrain.WALL) { + n++; + } + if (map[i - getWidth()] == Terrain.WALL) { + n++; + } + if (Random.Int(8) <= n) { + map[i] = Terrain.EMPTY_DECO; + } + } + } + + for (int i = 0; i < getLength(); i++) { + if (map[i] == Terrain.WALL && Random.Int(8) == 0) { + map[i] = Terrain.WALL_DECO; + } + if (map[i]==Terrain.ENTRANCE){map[i] = Terrain.EMPTY;} + } + + } + + //@Override + //protected void createMobs() { + //} + + @Override + protected void createItems() { + + int pos = entrance + 1; + drop(new FishingBomb(50), pos).type = Heap.Type.CHEST; + drop(new PotionOfLevitation(), pos); + + } + + + + //@Override + //public int randomRespawnCell() { + // return -1; + //} + + + + + @Override + public String tileName(int tile) { + switch (tile) { + case Terrain.WATER: + return "Dark cold water."; + case Terrain.HIGH_GRASS: + return "Seaweed tangles. "; + default: + return super.tileName(tile); + } + } + + @Override + public String tileDesc(int tile) { + switch (tile) { + case Terrain.ENTRANCE: + return "A ramp leads up to the upper depth."; + case Terrain.EXIT: + return "A ramp leads down to the lower depth."; + case Terrain.WALL_DECO: + case Terrain.EMPTY_DECO: + return "Small crabs and shell fish litter the sandy floor."; + case Terrain.EMPTY_SP: + return "Thick carpet covers the floor."; + case Terrain.STATUE: + case Terrain.STATUE_SP: + return "A large sea shell is propped up in the sand."; + case Terrain.BOOKSHELF: + return "Mostly beach reads."; + default: + return super.tileDesc(tile); + } + } + + + @Override + public void addVisuals(Scene scene) { + CavesLevel.addVisuals(this, scene); + } + @Override + public int nMobs() { + return 30; + } + + @Override + protected void createMobs() { + int nMobs = nMobs(); + for (int i = 0; i < nMobs; i++) { + Mob mob = Bestiary.mob(Dungeon.depth); + do { + mob.pos = randomRespawnCellFishMob(); + } while (mob.pos == -1); + mobs.add(mob); + Actor.occupyCell(mob); + } + } + + + + public int randomRespawnCellFishMob() { + int cell; + do { + cell = Random.Int(getLength()); + } while (map[cell]!=Terrain.WATER); + return cell; + } + + @Override + public Actor respawner() { + return new Actor() { + @Override + protected boolean act() { + if (mobs.size() < nMobs()) { + + Mob mob = Bestiary.mutable(Dungeon.depth); + mob.state = mob.WANDERING; + mob.pos = randomRespawnCellFishMob(); + if (Dungeon.hero.isAlive() && mob.pos != -1) { + GameScene.add(mob); + } + } + spend(Dungeon.level.feeling == Feeling.DARK + || Statistics.amuletObtained ? TIME_TO_RESPAWN / 2 + : TIME_TO_RESPAWN); + return true; + } + }; + } +} diff --git a/java/com/hmdzl/spspd/levels/FortressLevel.java b/java/com/hmdzl/spspd/levels/FortressLevel.java new file mode 100644 index 00000000..3ddfe4b2 --- /dev/null +++ b/java/com/hmdzl/spspd/levels/FortressLevel.java @@ -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 + */ +package com.hmdzl.spspd.levels; + +import java.util.ArrayList; +import java.util.HashSet; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.mobs.npcs.Tinkerer3; +import com.hmdzl.spspd.items.quest.Mushroom; +import com.hmdzl.spspd.items.TriforceOfPower; +import com.hmdzl.spspd.levels.Room.Type; +import com.watabou.utils.Random; + +public class FortressLevel extends RegularLevel { + + { + color1 = 0x4b6636; + color2 = 0xf2f2f2; + cleared=true; + } + + protected static final int REGROW_TIMER = 4; + + @Override + public String tilesTex() { + return Assets.TILES_CITY; + } + + @Override + public String waterTex() { + return Assets.WATER_CITY; + } + + @Override + protected boolean[] water() { + return Patch.generate(feeling == Feeling.WATER ? 0.65f : 0.45f, 4); + } + + @Override + protected boolean[] grass() { + return Patch.generate(feeling == Feeling.GRASS ? 0.60f : 0.40f, 3); + } + + + @Override + protected boolean assignRoomType() { + + specialsf = new ArrayList(Room.SPECIALSFORT); + + //if (Dungeon.isChallenged(Challenges.NO_HERBALISM)) { + // sorry warden, no lucky sungrass or blandfruit seeds for you! + //specialsf.remove(Room.Type.GARDEN); + // } + + int specialRooms = 0; + + for (Room r : rooms) { + if (r.type == Type.NULL && r.connected.size() == 1) { + + if (specialsf.size() > 0 && r.width() > 3 && r.height() > 3 + //&& Random.Int(specialRooms * specialRooms + 2) == 0 + ) { + + + int n = specialsf.size(); + r.type = specialsf.get(Math.min(Random.Int(n),Random.Int(n))); + + Room.useType(r.type); + //specialsf.remove(r.type); + specialRooms++; + + } else if (Random.Int(2) == 0) { + + HashSet neigbours = new HashSet(); + for (Room n : r.neigbours) { + if (!r.connected.containsKey(n) + && !Room.SPECIALSFORT.contains(n.type) + && n.type != Type.PIT) { + + neigbours.add(n); + } + } + if (neigbours.size() > 1) { + r.connect(Random.element(neigbours)); + } + } + } + } + + + int count = 0; + for (Room r : rooms) { + if (r.type == Type.NULL) { + int connections = r.connected.size(); + if (connections == 0) { + + } else if (Random.Int(connections * connections) == 0) { + r.type = Type.STANDARD; + count++; + } else { + r.type = Type.STANDARD; + } + } + } + + while (count < 4) { + Room r = randomRoom(Type.TUNNEL, 1); + if (r != null) { + r.type = Type.STANDARD; + count++; + } + } + + for (Room r : rooms) { + if (r.type == Type.TUNNEL) { + r.type = Type.PASSAGE; + } + } + + return true; + } + + @Override + protected void decorate() { + + for (int i = 0; i < getLength(); i++) { + if (map[i] == Terrain.EMPTY && Random.Int(10) == 0) { + map[i] = Terrain.EMPTY_DECO; + } else if (map[i] == Terrain.WALL && Random.Int(8) == 0) { + map[i] = Terrain.WALL_DECO; + } + } + + while (true) { + int pos = roomEntrance.random(); + if (pos != entrance) { + break; + } + } + + + int length = Level.getLength(); + + for (int i = 0; i < length; i++) { + + + if (map[i]==Terrain.ENTRANCE){map[i] = Terrain.PEDESTAL;} + if (map[i]==Terrain.EXIT){map[i] = Terrain.PEDESTAL; if (!Dungeon.triforceofpower){drop(new TriforceOfPower(), i);}} + if (map[i]==Terrain.CHASM){map[i] = Terrain.EMPTY;} + + + } + } + + @Override + protected void createItems() { + + addItemToSpawn(new Mushroom()); + + Tinkerer3 npc = new Tinkerer3(); + do { + npc.pos = randomRespawnCell(); + } while (npc.pos == -1 || heaps.get(npc.pos) != null); + mobs.add(npc); + Actor.occupyCell(npc); + + + super.createItems(); + + spawn(this, roomEntrance); + + + + } + + public static void spawn(FortressLevel level, Room room) { + int pos; + do {pos = room.random();} + while (level.heaps.get(pos) != null); + //level.drop(new Rice(), pos); + } + + + @Override + public String tileName(int tile) { + switch (tile) { + case Terrain.WATER: + return "Suspiciously colored water"; + case Terrain.HIGH_GRASS: + return "High blooming flowers"; + default: + return super.tileName(tile); + } + } + + @Override + public String tileDesc(int tile) { + switch (tile) { + case Terrain.ENTRANCE: + return "A ramp leads up to the upper depth."; + case Terrain.EXIT: + return "A ramp leads down to the lower depth."; + case Terrain.WALL_DECO: + case Terrain.EMPTY_DECO: + return "Several tiles are missing here."; + case Terrain.EMPTY_SP: + return "Thick carpet covers the floor."; + case Terrain.STATUE: + case Terrain.STATUE_SP: + return "The statue depicts some dwarf standing in a heroic stance."; + case Terrain.BOOKSHELF: + return "The rows of books on different disciplines fill the bookshelf."; + default: + return super.tileDesc(tile); + } + } + + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/levels/HallsBossLevel.java b/java/com/hmdzl/spspd/levels/HallsBossLevel.java new file mode 100644 index 00000000..b68664ef --- /dev/null +++ b/java/com/hmdzl/spspd/levels/HallsBossLevel.java @@ -0,0 +1,486 @@ +/* + * 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 + */ +package com.hmdzl.spspd.levels; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.mobs.Yog; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.particles.FlameParticle; +import com.hmdzl.spspd.items.Heap; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.keys.SkeletonKey; +import com.hmdzl.spspd.levels.painters.Painter; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.GameScene; +import com.watabou.noosa.Scene; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +/*public class HallsBossLevel extends Level { + + { + color1 = 0x801500; + color2 = 0xa68521; + + viewDistance = 3; + + } + private static final int ROOM_LEFT = getWidth() / 2 - 1; + private static final int ROOM_RIGHT = getWidth() / 2 + 1; + private static final int ROOM_TOP = HEIGHT / 2 - 1; + private static final int ROOM_BOTTOM = HEIGHT / 2 + 1; + + private int stairs = -1; + private boolean enteredArena = true; + private boolean keyDropped = false; + + @Override + public String tilesTex() { + return Assets.TILES_HALLS; + } + + @Override + public String waterTex() { + return Assets.WATER_HALLS; + } + + private static final String STAIRS = "stairs"; + private static final String ENTERED = "entered"; + private static final String DROPPED = "droppped"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(STAIRS, stairs); + bundle.put(DROPPED, keyDropped); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + stairs = bundle.getInt(STAIRS); + enteredArena = bundle.getBoolean(ENTERED); + keyDropped = bundle.getBoolean(DROPPED); + } + + @Override + protected boolean build() { + + for (int i = 0; i < 5; i++) { + + int top = Random.IntRange(2, ROOM_TOP - 1); + int bottom = Random.IntRange(ROOM_BOTTOM + 1, 22); + Painter.fill(this, 2 + i * 4, top, 4, bottom - top + 1, + Terrain.EMPTY); + + if (i == 2) { + exit = (i * 4 + 3) + (top - 1) * getWidth(); + } + + for (int j = 0; j < 4; j++) { + if (Random.Int(2) == 0) { + int y = Random.IntRange(top + 1, bottom - 1); + map[i * 4 + j + y * getWidth()] = Terrain.WALL_DECO; + } + } + } + + map[exit] = Terrain.LOCKED_EXIT; + + Painter.fill(this, ROOM_LEFT - 1, ROOM_TOP - 1, ROOM_RIGHT - ROOM_LEFT + + 3, ROOM_BOTTOM - ROOM_TOP + 3, Terrain.WALL); + + Painter.fill(this, ROOM_LEFT, ROOM_TOP, ROOM_RIGHT - ROOM_LEFT + 1, + ROOM_BOTTOM - ROOM_TOP + 1, Terrain.EMPTY); + + entrance = Random.Int(ROOM_LEFT + 1, ROOM_RIGHT - 1) + + Random.Int(ROOM_TOP + 1, ROOM_BOTTOM - 1) * getWidth(); + + map[entrance] = Terrain.ENTRANCE; + + boolean[] patch = Patch.generate(0.45f, 6); + for (int i = 0; i < getLength(); i++) { + if (map[i] == Terrain.EMPTY && patch[i]) { + map[i] = Terrain.WATER; + } + } + + return true; + } + + @Override + protected void decorate() { + + for (int i = 0; i < getLength(); i++) { + if (map[i] == Terrain.EMPTY && Random.Int(10) == 0) { + map[i] = Terrain.EMPTY_DECO; + //if (map[i]==Terrain.ENTRANCE){map[i] = Terrain.PEDESTAL;} + } + } + + //sealedlevel=false; + + + } + + @Override + protected void createMobs() { + } + + @Override + public Actor respawner() { + return null; + } + + @Override + protected void createItems() { + Item item = Bones.get(); + if (item != null) { + int pos; + do { + pos = Random.IntRange(ROOM_LEFT, ROOM_RIGHT) + + Random.IntRange(ROOM_TOP + 1, ROOM_BOTTOM) * getWidth(); + } while (pos == entrance || map[pos] == Terrain.SIGN); + drop(item, pos).type = Heap.Type.REMAINS; + } + } + + @Override + public int randomRespawnCell() { + if (entrance == -1) return entrance; + int cell = entrance + NEIGHBOURS8[Random.Int(8)]; + while (!passable[cell]) { + cell = entrance + NEIGHBOURS8[Random.Int(8)]; + } + return cell; + } + + + @Override + public void press(int cell, Char hero) { + + super.press(cell, hero); + + if (!enteredArena && hero == Dungeon.hero && cell != entrance) { + + enteredArena = true; + //locked = true; + seal(); + + for (int i = ROOM_LEFT - 1; i <= ROOM_RIGHT + 1; i++) { + doMagic((ROOM_TOP - 1) * getWidth() + i); + doMagic((ROOM_BOTTOM + 1) * getWidth() + i); + } + for (int i = ROOM_TOP; i < ROOM_BOTTOM + 1; i++) { + doMagic(i * getWidth() + ROOM_LEFT - 1); + doMagic(i * getWidth() + ROOM_RIGHT + 1); + } + doMagic(entrance); + GameScene.updateMap(); + + Dungeon.observe(); + + Yog boss = new Yog(); + do { + boss.pos = Random.Int(getLength()); + } while (!passable[boss.pos] || Dungeon.visible[boss.pos]); + GameScene.add(boss); + boss.spawnFists(); + + stairs = entrance; + entrance = -1; + } + } + + private void doMagic(int cell) { + set(cell, Terrain.EMPTY_SP); + CellEmitter.get(cell).start(FlameParticle.FACTORY, 0.1f, 3); + } + + @Override + public Heap drop(Item item, int cell) { + + if (!keyDropped && item instanceof SkeletonKey) { + keyDropped = true; + unseal(); + + entrance = stairs; + set(entrance, Terrain.ENTRANCE); + GameScene.updateMap(entrance); + } + + return super.drop(item, cell); + } + + @Override + public String tileName(int tile) { + switch (tile) { + case Terrain.WATER: + return Messages.get(HallsLevel.class, "water_name"); + case Terrain.GRASS: + return Messages.get(HallsLevel.class, "grass_name"); + case Terrain.HIGH_GRASS: + return Messages.get(HallsLevel.class, "high_grass_name"); + case Terrain.STATUE: + case Terrain.STATUE_SP: + return Messages.get(HallsLevel.class, "statue_name"); + default: + return super.tileName(tile); + } + } + + @Override + public String tileDesc(int tile) { + switch (tile) { + case Terrain.WATER: + return Messages.get(HallsLevel.class, "water_desc"); + case Terrain.STATUE: + case Terrain.STATUE_SP: + return Messages.get(HallsLevel.class, "statue_desc"); + case Terrain.BOOKSHELF: + return Messages.get(HallsLevel.class, "bookshelf_desc"); + default: + return super.tileDesc(tile); + } + } + + @Override + public void addVisuals(Scene scene) { + HallsLevel.addVisuals(this, scene); + } +}*/ +public class HallsBossLevel extends Level { + + { + color1 = 0x801500; + color2 = 0xa68521; + + viewDistance = 5; + } + + private static final int ROOM_LEFT = WIDTH / 2 - 1; + private static final int ROOM_RIGHT = WIDTH / 2 + 1; + private static final int ROOM_TOP = HEIGHT / 2 - 1; + private static final int ROOM_BOTTOM = HEIGHT / 2 + 1; + + private int stairs = -1; + private boolean enteredArena = false; + private boolean keyDropped = false; + + @Override + public String tilesTex() { + return Assets.TILES_HALLS; + } + + @Override + public String waterTex() { + return Assets.WATER_HALLS; + } + + private static final String STAIRS = "stairs"; + private static final String ENTERED = "entered"; + private static final String DROPPED = "droppped"; + + @Override + public void storeInBundle( Bundle bundle ) { + super.storeInBundle( bundle ); + bundle.put( STAIRS, stairs ); + bundle.put( ENTERED, enteredArena ); + bundle.put( DROPPED, keyDropped ); + } + + @Override + public void restoreFromBundle( Bundle bundle ) { + super.restoreFromBundle( bundle ); + stairs = bundle.getInt( STAIRS ); + enteredArena = bundle.getBoolean( ENTERED ); + keyDropped = bundle.getBoolean( DROPPED ); + } + + @Override + protected boolean build() { + + for (int i=0; i < 5; i++) { + + int top = Random.IntRange( 2, ROOM_TOP - 1 ); + int bottom = Random.IntRange( ROOM_BOTTOM + 1, 22 ); + Painter.fill( this, 2 + i * 4, top, 4, bottom - top + 1, Terrain.EMPTY ); + + if (i == 2) { + exit = (i * 4 + 3) + (top - 1) * WIDTH ; + } + + for (int j=0; j < 4; j++) { + if (Random.Int( 2 ) == 0) { + int y = Random.IntRange( top + 1, bottom - 1 ); + map[i*4+j + y*WIDTH] = Terrain.WALL_DECO; + } + } + } + map[exit] = Terrain.LOCKED_EXIT; + + Painter.fill( this, ROOM_LEFT - 1, ROOM_TOP - 1, + ROOM_RIGHT - ROOM_LEFT + 3, ROOM_BOTTOM - ROOM_TOP + 3, Terrain.WALL ); + Painter.fill( this, ROOM_LEFT, ROOM_TOP, + ROOM_RIGHT - ROOM_LEFT + 1, ROOM_BOTTOM - ROOM_TOP + 1, Terrain.EMPTY ); + + entrance = Random.Int( ROOM_LEFT + 1, ROOM_RIGHT - 1 ) + Random.Int( ROOM_TOP + 1, ROOM_BOTTOM - 1 ) * WIDTH; + map[entrance] = Terrain.ENTRANCE; + + boolean[] patch = Patch.generate( 0.45f, 6 ); + for (int i=0; i < LENGTH; i++) { + if (map[i] == Terrain.EMPTY && patch[i]) { + map[i] = Terrain.WATER; + } + } + + return true; + } + + @Override + protected void decorate() { + + for (int i=0; i < LENGTH; i++) { + if (map[i] == Terrain.EMPTY && Random.Int( 10 ) == 0) { + map[i] = Terrain.EMPTY_DECO; + } + } + } + + @Override + protected void createMobs() { + } + + public Actor respawner() { + return null; + } + + @Override + protected void createItems() { + + } + + @Override + public int randomRespawnCell() { + if (entrance == -1) return entrance; + int cell = entrance + NEIGHBOURS8[Random.Int(8)]; + while (!passable[cell]){ + cell = entrance + NEIGHBOURS8[Random.Int(8)]; + } + return cell; + } + + @Override + public void press( int cell, Char hero ) { + + super.press( cell, hero ); + + if (!enteredArena && hero == Dungeon.hero && cell != entrance) { + + enteredArena = true; + seal(); + + for (int i=ROOM_LEFT-1; i <= ROOM_RIGHT + 1; i++) { + doMagic( (ROOM_TOP - 1) * WIDTH + i ); + doMagic( (ROOM_BOTTOM + 1) * WIDTH + i ); + } + for (int i=ROOM_TOP; i < ROOM_BOTTOM + 1; i++) { + doMagic( i * WIDTH + ROOM_LEFT - 1 ); + doMagic( i * WIDTH + ROOM_RIGHT + 1 ); + } + doMagic( entrance ); + GameScene.updateMap(); + + Dungeon.observe(); + + Yog boss = new Yog(); + do { + boss.pos = Random.Int( LENGTH ); + } while ( + !passable[boss.pos] || + Dungeon.visible[boss.pos]); + GameScene.add( boss ); + boss.spawnFists(); + + stairs = entrance; + entrance = -1; + } + } + + private void doMagic( int cell ) { + set( cell, Terrain.EMPTY_SP ); + CellEmitter.get( cell ).start( FlameParticle.FACTORY, 0.1f, 3 ); + } + + @Override + public Heap drop( Item item, int cell ) { + + if (!keyDropped && item instanceof SkeletonKey) { + keyDropped = true; + unseal(); + + entrance = stairs; + set( entrance, Terrain.ENTRANCE ); + GameScene.updateMap( entrance ); + } + + return super.drop( item, cell ); + } + + @Override + public String tileName( int tile ) { + switch (tile) { + case Terrain.WATER: + return Messages.get(HallsLevel.class, "water_name"); + case Terrain.GRASS: + return Messages.get(HallsLevel.class, "grass_name"); + case Terrain.HIGH_GRASS: + return Messages.get(HallsLevel.class, "high_grass_name"); + case Terrain.STATUE: + case Terrain.STATUE_SP: + return Messages.get(HallsLevel.class, "statue_name"); + default: + return super.tileName( tile ); + } + } + + @Override + public String tileDesc(int tile) { + switch (tile) { + case Terrain.WATER: + return Messages.get(HallsLevel.class, "water_desc"); + case Terrain.STATUE: + case Terrain.STATUE_SP: + return Messages.get(HallsLevel.class, "statue_desc"); + case Terrain.BOOKSHELF: + return Messages.get(HallsLevel.class, "bookshelf_desc"); + default: + return super.tileDesc( tile ); + } + } + + @Override + public void addVisuals(Scene scene) { + HallsLevel.addVisuals(this, scene); + } +} + + diff --git a/java/com/hmdzl/spspd/levels/HallsLevel.java b/java/com/hmdzl/spspd/levels/HallsLevel.java new file mode 100644 index 00000000..5d43e67f --- /dev/null +++ b/java/com/hmdzl/spspd/levels/HallsLevel.java @@ -0,0 +1,272 @@ +/* + * 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 + */ +package com.hmdzl.spspd.levels; + +import javax.microedition.khronos.opengles.GL10; + +import android.opengl.GLES20; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.DungeonTilemap; +import com.hmdzl.spspd.actors.mobs.Sentinel; +import com.hmdzl.spspd.items.DwarfHammer; +import com.hmdzl.spspd.items.Torch; +import com.hmdzl.spspd.levels.traps.*; +import com.hmdzl.spspd.messages.Messages; +import com.watabou.noosa.Game; +import com.watabou.noosa.Group; +import com.watabou.noosa.Scene; +import com.watabou.noosa.particles.PixelParticle; +import com.watabou.utils.PointF; +import com.watabou.utils.Random; + +public class HallsLevel extends RegularLevel { + + { + minRoomSize = 6; + + viewDistance = Math.max(25 - Dungeon.depth, 1); + + color1 = 0x801500; + color2 = 0xa68521; + } + + @Override + public void create() { + addItemToSpawn(new Torch()); + super.create(); + } + + @Override + public String tilesTex() { + return Assets.TILES_HALLS; + } + + @Override + public String waterTex() { + return Assets.WATER_HALLS; + } + + @Override + protected void setPar(){ + Dungeon.pars[Dungeon.depth] = 200+(Dungeon.depth*50)+(secretDoors*20); + } + + @Override + protected boolean[] water() { + return Patch.generate(feeling == Feeling.WATER ? 0.55f : 0.40f, 6); + } + + @Override + protected boolean[] grass() { + return Patch.generate(feeling == Feeling.GRASS ? 0.55f : 0.30f, 3); + } + + @Override + protected Class[] trapClasses() { + return new Class[]{ BlazingTrap.class, DisintegrationTrap.class, FrostTrap.class, SpearTrap.class, VenomTrap.class, StormTrap.class, + ExplosiveTrap.class, GrippingTrap.class, LightningTrap.class, OozeTrap.class, WeakeningTrap.class, + CursingTrap.class, FlockTrap.class, GrimTrap.class, GuardianTrap.class, SummoningTrap.class, TeleportationTrap.class, + DisarmingTrap.class}; + } + + @Override + protected float[] trapChances() { + return new float[]{ 8, 8, 8, 8, 8, 8, + 4, 4, 4, 4, 4, + 2, 2, 2, 2, 2, 2, + 1}; + } + + @Override + protected void decorate() { + + for (int i = getWidth() + 1; i < getLength() - getWidth() - 1; i++) { + if (map[i] == Terrain.EMPTY) { + + int count = 0; + for (int j = 0; j < NEIGHBOURS8.length; j++) { + if ((Terrain.flags[map[i + NEIGHBOURS8[j]]] & Terrain.PASSABLE) > 0) { + count++; + } + } + + if (Random.Int(80) < count) { + map[i] = Terrain.EMPTY_DECO; + } + + } else if (map[i] == Terrain.WALL + && map[i - 1] != Terrain.WALL_DECO + && map[i - getWidth()] != Terrain.WALL_DECO + && Random.Int(20) == 0) { + + map[i] = Terrain.WALL_DECO; + + } + } + + while (true) { + int pos = roomEntrance.random(); + if (pos != entrance) { + map[pos] = Terrain.SIGN; + break; + } + } + + for (int i = 0; i < getLength(); i++) { + + if (map[i]==Terrain.EXIT){map[i] = Terrain.PEDESTAL; + sealedlevel=true; + if(Dungeon.depth==24){ + Sentinel sentinel = new Sentinel(); + sentinel.pos = i; + mobs.add(sentinel);} + } + + } + + setPar(); + + + } + + @Override + protected void createItems() { + if (Dungeon.depth!=25){addItemToSpawn(new DwarfHammer());} + super.createItems(); + } + + @Override + public String tileName(int tile) { + switch (tile) { + case Terrain.WATER: + return Messages.get(HallsLevel.class, "water_name"); + case Terrain.GRASS: + return Messages.get(HallsLevel.class, "grass_name"); + case Terrain.HIGH_GRASS: + return Messages.get(HallsLevel.class, "high_grass_name"); + case Terrain.STATUE: + case Terrain.STATUE_SP: + return Messages.get(HallsLevel.class, "statue_name"); + default: + return super.tileName(tile); + } + } + + @Override + public String tileDesc(int tile) { + switch (tile) { + case Terrain.WATER: + return Messages.get(HallsLevel.class, "water_desc"); + case Terrain.STATUE: + case Terrain.STATUE_SP: + return Messages.get(HallsLevel.class, "statue_desc"); + case Terrain.BOOKSHELF: + return Messages.get(HallsLevel.class, "bookshelf_desc"); + default: + return super.tileDesc(tile); + } + } + + @Override + public void addVisuals(Scene scene) { + super.addVisuals(scene); + addVisuals(this, scene); + } + + public static void addVisuals(Level level, Scene scene) { + for (int i = 0; i < getLength(); i++) { + if (level.map[i] == 63) { + scene.add(new Stream(i)); + } + } + } + + private static class Stream extends Group { + + private int pos; + + private float delay; + + public Stream(int pos) { + super(); + + this.pos = pos; + + delay = Random.Float(2); + } + + @Override + public void update() { + + if (visible = Dungeon.visible[pos]) { + + super.update(); + + if ((delay -= Game.elapsed) <= 0) { + + delay = Random.Float(2); + + PointF p = DungeonTilemap.tileToWorld(pos); + ((FireParticle) recycle(FireParticle.class)).reset(p.x + + Random.Float(DungeonTilemap.SIZE), + p.y + Random.Float(DungeonTilemap.SIZE)); + } + } + } + + @Override + public void draw() { + GLES20.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE); + super.draw(); + GLES20.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA); + } + } + + public static class FireParticle extends PixelParticle.Shrinking { + + public FireParticle() { + super(); + + color(0xEE7722); + lifespan = 1f; + + acc.set(0, +80); + } + + public void reset(float x, float y) { + revive(); + + this.x = x; + this.y = y; + + left = lifespan; + + speed.set(0, -40); + size = 4; + } + + @Override + public void update() { + super.update(); + float p = left / lifespan; + am = p > 0.8f ? (1 - p) * 5 : 1; + } + } +} diff --git a/java/com/hmdzl/spspd/levels/InfestBossLevel.java b/java/com/hmdzl/spspd/levels/InfestBossLevel.java new file mode 100644 index 00000000..9c8108c3 --- /dev/null +++ b/java/com/hmdzl/spspd/levels/InfestBossLevel.java @@ -0,0 +1,393 @@ +/* + * 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 + */ +package com.hmdzl.spspd.levels; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.Statistics; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.mobs.Bestiary; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.actors.mobs.ShadowYog; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.levels.painters.Painter; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.noosa.Camera; +import com.watabou.noosa.Scene; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public class InfestBossLevel extends Level { + + { + color1 = 0x534f3e; + color2 = 0xb9d661; + cleared=true; + + viewDistance = 6; + } + + private static final int ROOM_LEFT = getWidth() / 2 - 2; + private static final int ROOM_RIGHT = getWidth() / 2 + 2; + private static final int ROOM_TOP = HEIGHT / 2 - 2; + private static final int ROOM_BOTTOM = HEIGHT / 2 + 2; + + private int arenaDoor; + private boolean enteredArena = false; + private boolean keyDropped = false; + + @Override + public String tilesTex() { + return Assets.TILES_CAVES; + } + + @Override + public String waterTex() { + return Assets.WATER_CAVES; + } + + private static final String DOOR = "door"; + private static final String ENTERED = "entered"; + private static final String DROPPED = "droppped"; + + protected static final float TIME_TO_RESPAWN = 20; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(DOOR, arenaDoor); + bundle.put(ENTERED, enteredArena); + bundle.put(DROPPED, keyDropped); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + arenaDoor = bundle.getInt(DOOR); + enteredArena = bundle.getBoolean(ENTERED); + keyDropped = bundle.getBoolean(DROPPED); + } + + @Override + protected boolean build() { + + int topMost = Integer.MAX_VALUE; + + for (int i = 0; i < 8; i++) { + int left, right, top, bottom; + if (Random.Int(2) == 0) { + left = Random.Int(1, ROOM_LEFT - 3); + right = ROOM_RIGHT + 3; + } else { + left = ROOM_LEFT - 3; + right = Random.Int(ROOM_RIGHT + 3, getWidth() - 1); + } + if (Random.Int(2) == 0) { + top = Random.Int(2, ROOM_TOP - 3); + bottom = ROOM_BOTTOM + 3; + } else { + top = ROOM_LEFT - 3; + bottom = Random.Int(ROOM_TOP + 3, HEIGHT - 1); + } + + Painter.fill(this, left, top, right - left + 1, bottom - top + 1, + Terrain.EMPTY); + + if (top < topMost) { + topMost = top; + exit = Random.Int(left, right) + (top - 1) * getWidth(); + } + } + + map[exit] = Terrain.WALL; + + for (int i = 0; i < getLength(); i++) { + if (map[i] == Terrain.EMPTY && Random.Int(20) == 0) { + map[i] = Terrain.TRAP; + } + } + + Painter.fill(this, ROOM_LEFT - 1, ROOM_TOP - 1, ROOM_RIGHT - ROOM_LEFT + + 3, ROOM_BOTTOM - ROOM_TOP + 3, Terrain.WALL); + Painter.fill(this, ROOM_LEFT, ROOM_TOP + 1, ROOM_RIGHT - ROOM_LEFT + 1, + ROOM_BOTTOM - ROOM_TOP, Terrain.EMPTY); + + Painter.fill(this, ROOM_LEFT, ROOM_TOP, ROOM_RIGHT - ROOM_LEFT + 1, 1, + Terrain.INACTIVE_TRAP); + + arenaDoor = Random.Int(ROOM_LEFT, ROOM_RIGHT) + (ROOM_BOTTOM + 1) + * getWidth(); + map[arenaDoor] = Terrain.DOOR; + + entrance = Random.Int(ROOM_LEFT + 1, ROOM_RIGHT - 1) + + Random.Int(ROOM_TOP + 1, ROOM_BOTTOM - 1) * getWidth(); + map[entrance] = Terrain.ENTRANCE; + + return true; + } + + @Override + protected void decorate() { + + for (int i = getWidth() + 1; i < getLength() - getWidth(); i++) { + if (map[i] == Terrain.EMPTY) { + int n = 0; + if (map[i + 1] == Terrain.WALL) { + n++; + } + if (map[i - 1] == Terrain.WALL) { + n++; + } + if (map[i + getWidth()] == Terrain.WALL) { + n++; + } + if (map[i - getWidth()] == Terrain.WALL) { + n++; + } + if (Random.Int(8) <= n) { + map[i] = Terrain.EMPTY_DECO; + } + } + } + + for (int i = 0; i < getLength(); i++) { + if (map[i] == Terrain.WALL && Random.Int(8) == 0) { + map[i] = Terrain.WALL_DECO; + } + if (map[i]==Terrain.ENTRANCE){map[i] = Terrain.PEDESTAL;} + } + + } + + //@Override + //protected void createMobs() { + //} + + //@Override + //public Actor respawner() { + // return null; + //} + + @Override + protected void createItems() { + } + + //@Override + //public int randomRespawnCell() { + // return -1; + //} + + @Override + public void press(int cell, Char hero) { + + super.press(cell, hero); + + if (!enteredArena && outsideEntraceRoom(cell) && hero == Dungeon.hero) { + + enteredArena = true; + //locked = true; + + ShadowYog boss = new ShadowYog(); + boss.state = boss.SLEEPING; + do { + boss.pos = Random.Int(getLength()); + } while (!passable[boss.pos] || !outsideEntraceRoom(boss.pos) + || Dungeon.visible[boss.pos]); + GameScene.add(boss); + GLog.n("we are legion"); + + ShadowYog boss2 = new ShadowYog(); + boss2.state = boss2.SLEEPING; + do { + boss2.pos = Random.Int(getLength()); + } while (!passable[boss2.pos] || !outsideEntraceRoom(boss2.pos) + || Dungeon.visible[boss2.pos]); + GameScene.add(boss2); + GLog.n("we are legion"); + + ShadowYog boss3 = new ShadowYog(); + boss3.state = boss3.SLEEPING; + do { + boss3.pos = Random.Int(getLength()); + } while (!passable[boss3.pos] || !outsideEntraceRoom(boss3.pos) + || Dungeon.visible[boss3.pos]); + GameScene.add(boss3); + GLog.n("we are legion"); + + ShadowYog boss4 = new ShadowYog(); + boss4.state = boss4.SLEEPING; + do { + boss4.pos = Random.Int(getLength()); + } while (!passable[boss4.pos] || !outsideEntraceRoom(boss4.pos) + || Dungeon.visible[boss4.pos]); + GameScene.add(boss4); + GLog.n("we are legion"); + + ShadowYog boss5 = new ShadowYog(); + boss5.state = boss5.SLEEPING; + do { + boss5.pos = Random.Int(getLength()); + } while (!passable[boss5.pos] || !outsideEntraceRoom(boss5.pos) + || Dungeon.visible[boss5.pos]); + GameScene.add(boss5); + GLog.n("we are legion"); + + ShadowYog boss6 = new ShadowYog(); + boss6.state = boss6.SLEEPING; + do { + boss6.pos = Random.Int(getLength()); + } while (!passable[boss6.pos] || !outsideEntraceRoom(boss6.pos) + || Dungeon.visible[boss6.pos]); + GameScene.add(boss6); + GLog.n("we are legion"); + + ShadowYog boss7 = new ShadowYog(); + boss7.state = boss7.SLEEPING; + do { + boss7.pos = Random.Int(getLength()); + } while (!passable[boss7.pos] || !outsideEntraceRoom(boss7.pos) + || Dungeon.visible[boss7.pos]); + GameScene.add(boss7); + GLog.n("we are legion"); + + ShadowYog boss8 = new ShadowYog(); + boss8.state = boss8.SLEEPING; + do { + boss8.pos = Random.Int(getLength()); + } while (!passable[boss8.pos] || !outsideEntraceRoom(boss8.pos) + || Dungeon.visible[boss8.pos]); + GameScene.add(boss8); + GLog.n("we are legion"); + + ShadowYog boss9 = new ShadowYog(); + boss9.state = boss9.SLEEPING; + do { + boss9.pos = Random.Int(getLength()); + } while (!passable[boss9.pos] || !outsideEntraceRoom(boss9.pos) + || Dungeon.visible[boss9.pos]); + GameScene.add(boss9); + GLog.n("we are legion"); + + ShadowYog boss10 = new ShadowYog(); + boss10.state = boss10.SLEEPING; + do { + boss10.pos = Random.Int(getLength()); + } while (!passable[boss10.pos] || !outsideEntraceRoom(boss10.pos) + || Dungeon.visible[boss10.pos]); + GameScene.add(boss10); + GLog.n("we are legion"); + + //set(arenaDoor, Terrain.WALL); + GameScene.updateMap(arenaDoor); + Dungeon.observe(); + + CellEmitter.get(arenaDoor).start(Speck.factory(Speck.ROCK), 0.07f, 10); + Camera.main.shake(3, 0.7f); + Sample.INSTANCE.play(Assets.SND_ROCKS); + } + } + + + private boolean outsideEntraceRoom(int cell) { + int cx = cell % getWidth(); + int cy = cell / getWidth(); + return cx < ROOM_LEFT - 1 || cx > ROOM_RIGHT + 1 || cy < ROOM_TOP - 1 + || cy > ROOM_BOTTOM + 1; + } + + @Override + public String tileName(int tile) { + switch (tile) { + case Terrain.GRASS: + return Messages.get(CavesLevel.class, "grass_name"); + case Terrain.HIGH_GRASS: + return Messages.get(CavesLevel.class, "high_grass_name"); + case Terrain.WATER: + return Messages.get(CavesLevel.class, "water_name"); + default: + return super.tileName( tile ); + } + } + + @Override + public String tileDesc(int tile) { + switch (tile) { + case Terrain.ENTRANCE: + return Messages.get(CavesLevel.class, "entrance_desc"); + case Terrain.EXIT: + return Messages.get(CavesLevel.class, "exit_desc"); + case Terrain.HIGH_GRASS: + return Messages.get(CavesLevel.class, "high_grass_desc"); + case Terrain.WALL_DECO: + return Messages.get(CavesLevel.class, "wall_deco_desc"); + case Terrain.BOOKSHELF: + return Messages.get(CavesLevel.class, "bookshelf_desc"); + default: + return super.tileDesc( tile ); + } + } + + @Override + public void addVisuals(Scene scene) { + CavesLevel.addVisuals(this, scene); + } + @Override + public int nMobs() { + return 20; + } + + @Override + protected void createMobs() { + int nMobs = nMobs(); + for (int i = 0; i < nMobs; i++) { + Mob mob = Bestiary.mob(Dungeon.depth); + do { + mob.pos = randomRespawnCellMob(); + } while (mob.pos == -1); + mobs.add(mob); + Actor.occupyCell(mob); + } + } + + @Override + public Actor respawner() { + return new Actor() { + @Override + protected boolean act() { + if (mobs.size() < nMobs()) { + + Mob mob = Bestiary.mutable(Dungeon.depth); + mob.state = mob.WANDERING; + mob.pos = randomRespawnCellMob(); + if (Dungeon.hero.isAlive() && mob.pos != -1) { + GameScene.add(mob); + } + } + spend(Dungeon.level.feeling == Feeling.DARK + || Statistics.amuletObtained ? TIME_TO_RESPAWN / 2 + : TIME_TO_RESPAWN); + return true; + } + }; + } +} diff --git a/java/com/hmdzl/spspd/levels/LastLevel.java b/java/com/hmdzl/spspd/levels/LastLevel.java new file mode 100644 index 00000000..a15011fe --- /dev/null +++ b/java/com/hmdzl/spspd/levels/LastLevel.java @@ -0,0 +1,179 @@ +/* + * 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 + */ +package com.hmdzl.spspd.levels; + +import java.util.Arrays; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.items.PuddingCup; +import com.hmdzl.spspd.levels.painters.Painter; +import com.hmdzl.spspd.messages.Messages; +import com.watabou.noosa.Scene; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public class LastLevel extends Level { + + private static final int SIZE = 30; + + { + color1 = 0x801500; + color2 = 0xa68521; + + viewDistance = 8; + } + + private int pedestal; + + @Override + public String tilesTex() { + return Assets.TILES_HALLS; + } + + @Override + public String waterTex() { + return Assets.WATER_HALLS; + } + + @Override + public void create() { + super.create(); + for (int i = 0; i < getLength(); i++) { + int flags = Terrain.flags[map[i]]; + if ((flags & Terrain.PIT) != 0) { + passable[i] = avoid[i] = false; + solid[i] = true; + } + } + } + + @Override + protected boolean build() { + + Arrays.fill(map, Terrain.CHASM); + + Painter.fill(this, 7, 31, 19, 1, Terrain.WALL); + Painter.fill(this, 15, 10, 3, 21, Terrain.EMPTY); + Painter.fill(this, 13, 30, 7, 1, Terrain.EMPTY); + Painter.fill(this, 14, 29, 5, 1, Terrain.EMPTY); + + Painter.fill(this, 14, 9, 5, 7, Terrain.EMPTY); + Painter.fill(this, 13, 10, 7, 5, Terrain.EMPTY); + + // Painter.fill( this, 2, 2, SIZE-2, SIZE-2, Terrain.EMPTY ); + // Painter.fill( this, SIZE/2, SIZE/2, 3, 3, Terrain.EMPTY_SP ); + + entrance = SIZE * getWidth() + SIZE / 2 + 1; + map[entrance] = Terrain.ENTRANCE; + + pedestal = (SIZE / 2 + 1) * (getWidth() + 1) - 4 * getWidth(); + map[pedestal] = Terrain.PEDESTAL; + map[pedestal - 1 - getWidth()] = map[pedestal + 1 - getWidth()] = map[pedestal + - 1 + getWidth()] = map[pedestal + 1 + getWidth()] = Terrain.STATUE_SP; + + exit = pedestal; + + int pos = pedestal; + + map[pos - getWidth()] = map[pos - 1] = map[pos + 1] = map[pos - 2] = map[pos + 2] = Terrain.WATER; + pos += getWidth(); + map[pos] = map[pos - 2] = map[pos + 2] = map[pos - 3] = map[pos + 3] = Terrain.WATER; + pos += getWidth(); + map[pos - 3] = map[pos - 2] = map[pos - 1] = map[pos] = map[pos + 1] = map[pos + 2] = map[pos + 3] = Terrain.WATER; + pos += getWidth(); + map[pos - 2] = map[pos + 2] = Terrain.WATER; + + feeling = Feeling.NONE; + viewDistance = 8; + + return true; + } + + @Override + protected void decorate() { + for (int i = 0; i < getLength(); i++) { + if (map[i] == Terrain.EMPTY && Random.Int(10) == 0) { + map[i] = Terrain.EMPTY_DECO; + } + } + } + + @Override + protected void createMobs() { + } + + @Override + protected void createItems() { + drop(new PuddingCup(), pedestal); + } + + @Override + public int randomRespawnCell() { + return -1; + } + + @Override + public String tileName(int tile) { + switch (tile) { + case Terrain.WATER: + return Messages.get(HallsLevel.class, "water_name"); + case Terrain.GRASS: + return Messages.get(HallsLevel.class, "grass_name"); + case Terrain.HIGH_GRASS: + return Messages.get(HallsLevel.class, "high_grass_name"); + case Terrain.STATUE: + case Terrain.STATUE_SP: + return Messages.get(HallsLevel.class, "statue_name"); + default: + return super.tileName(tile); + } + } + + @Override + public String tileDesc(int tile) { + switch (tile) { + case Terrain.WATER: + return Messages.get(HallsLevel.class, "water_desc"); + case Terrain.STATUE: + case Terrain.STATUE_SP: + return Messages.get(HallsLevel.class, "statue_desc"); + case Terrain.BOOKSHELF: + return Messages.get(HallsLevel.class, "bookshelf_desc"); + default: + return super.tileDesc(tile); + } + } + + @Override + public void addVisuals(Scene scene) { + super.addVisuals(scene); + HallsLevel.addVisuals(this, scene); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + for (int i = 0; i < getLength(); i++) { + int flags = Terrain.flags[map[i]]; + if ((flags & Terrain.PIT) != 0) { + passable[i] = avoid[i] = false; + solid[i] = true; + } + } + } +} diff --git a/java/com/hmdzl/spspd/levels/LastShopLevel.java b/java/com/hmdzl/spspd/levels/LastShopLevel.java new file mode 100644 index 00000000..3cb3d282 --- /dev/null +++ b/java/com/hmdzl/spspd/levels/LastShopLevel.java @@ -0,0 +1,225 @@ +/* + * 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 + */ +package com.hmdzl.spspd.levels; + +import java.util.List; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.levels.Room.Type; +import com.hmdzl.spspd.messages.Messages; +import com.watabou.noosa.Scene; +import com.watabou.utils.Graph; +import com.watabou.utils.Random; + +public class LastShopLevel extends RegularLevel { + + { + color1 = 0x4b6636; + color2 = 0xf2f2f2; + } + + @Override + public String tilesTex() { + return Assets.TILES_CITY; + } + + @Override + public String waterTex() { + return Assets.WATER_CITY; + } + + @Override + protected boolean build() { + + feeling = Feeling.CHASM; + viewDistance = 6; + + initRooms(); + + int distance; + int retry = 0; + int minDistance = (int) Math.sqrt(rooms.size()); + do { + int innerRetry = 0; + do { + if (innerRetry++ > 10) { + return false; + } + roomEntrance = Random.element(rooms); + } while (roomEntrance.width() < 4 || roomEntrance.height() < 4); + + innerRetry = 0; + do { + if (innerRetry++ > 10) { + return false; + } + roomExit = Random.element(rooms); + } while (roomExit == roomEntrance || roomExit.width() < 6 + || roomExit.height() < 6 || roomExit.top == 0); + + Graph.buildDistanceMap(rooms, roomExit); + distance = Graph.buildPath(rooms, roomEntrance, roomExit).size(); + + if (retry++ > 10) { + return false; + } + + } while (distance < minDistance); + + roomEntrance.type = Type.ENTRANCE; + roomExit.type = Type.EXIT; + + Graph.buildDistanceMap(rooms, roomExit); + List path = Graph.buildPath(rooms, roomEntrance, roomExit); + + Graph.setPrice(path, roomEntrance.distance); + + Graph.buildDistanceMap(rooms, roomExit); + path = Graph.buildPath(rooms, roomEntrance, roomExit); + + Room room = roomEntrance; + for (Room next : path) { + room.connect(next); + room = next; + } + + Room roomShop = null; + int shopSquare = 0; + for (Room r : rooms) { + if (r.type == Type.NULL && r.connected.size() > 0) { + r.type = Type.PASSAGE; + if (r.square() > shopSquare) { + roomShop = r; + shopSquare = r.square(); + } + } + } + + if (roomShop == null || shopSquare < 54) { + return false; + } else { + roomShop.type = Room.Type.SHOP; + } + + paint(); + + paintWater(); + paintGrass(); + + return true; + } + + @Override + protected void decorate() { + + for (int i = 0; i < getLength(); i++) { + if (map[i] == Terrain.EMPTY && Random.Int(10) == 0) { + + map[i] = Terrain.EMPTY_DECO; + + } else if (map[i] == Terrain.WALL && Random.Int(8) == 0) { + + map[i] = Terrain.WALL_DECO; + + } else if (map[i] == Terrain.SECRET_DOOR) { + + map[i] = Terrain.DOOR; + + } + } + + + while (true) { + int pos = roomEntrance.random(); + if (pos != entrance) { + map[pos] = Terrain.SIGN; + break; + } + } + + } + + @Override + protected void createMobs() { + } + + @Override + public Actor respawner() { + return null; + } + + @Override + protected void createItems() { + } + + @Override + public int randomRespawnCell() { + return -1; + } + + @Override + public String tileName(int tile) { + switch (tile) { + case Terrain.WATER: + return Messages.get(CityLevel.class, "water_name"); + case Terrain.HIGH_GRASS: + return Messages.get(CityLevel.class, "high_grass_name"); + default: + return super.tileName(tile); + } + } + + @Override + public String tileDesc(int tile) { + switch (tile) { + case Terrain.ENTRANCE: + return Messages.get(CityLevel.class, "entrance_desc"); + case Terrain.EXIT: + return Messages.get(CityLevel.class, "exit_desc"); + case Terrain.WALL_DECO: + case Terrain.EMPTY_DECO: + return Messages.get(CityLevel.class, "deco_desc"); + case Terrain.EMPTY_SP: + return Messages.get(CityLevel.class, "sp_desc"); + case Terrain.STATUE: + case Terrain.STATUE_SP: + return Messages.get(CityLevel.class, "statue_desc"); + case Terrain.BOOKSHELF: + return Messages.get(CityLevel.class, "bookshelf_desc"); + default: + return super.tileDesc(tile); + } + } + + @Override + protected boolean[] water() { + return Patch.generate(0.35f, 4); + } + + @Override + protected boolean[] grass() { + return Patch.generate(0.30f, 3); + } + + @Override + public void addVisuals(Scene scene) { + super.addVisuals(scene); + CityLevel.addVisuals(this, scene); + } +} diff --git a/java/com/hmdzl/spspd/levels/Level.java b/java/com/hmdzl/spspd/levels/Level.java new file mode 100644 index 00000000..8f11c488 --- /dev/null +++ b/java/com/hmdzl/spspd/levels/Level.java @@ -0,0 +1,2035 @@ +/* + * 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 + */ +package com.hmdzl.spspd.levels; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Challenges; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.Statistics; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.Alchemy; +import com.hmdzl.spspd.actors.blobs.Blob; +import com.hmdzl.spspd.actors.blobs.WellWater; +import com.hmdzl.spspd.actors.buffs.AflyBless; +import com.hmdzl.spspd.actors.buffs.Awareness; +import com.hmdzl.spspd.actors.buffs.Blindness; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.ExitFind; +import com.hmdzl.spspd.actors.buffs.MindVision; +import com.hmdzl.spspd.actors.buffs.Shadows; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.hero.HeroClass; +import com.hmdzl.spspd.actors.mobs.Bestiary; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.actors.mobs.npcs.SheepSokoban; +import com.hmdzl.spspd.actors.mobs.npcs.SheepSokobanCorner; +import com.hmdzl.spspd.actors.mobs.npcs.SheepSokobanSwitch; +import com.hmdzl.spspd.actors.mobs.pets.BlueDragon; +import com.hmdzl.spspd.actors.mobs.pets.BugDragon; +import com.hmdzl.spspd.actors.mobs.pets.Bunny; +import com.hmdzl.spspd.actors.mobs.pets.CocoCat; +import com.hmdzl.spspd.actors.mobs.pets.Fly; +import com.hmdzl.spspd.actors.mobs.pets.GentleCrab; +import com.hmdzl.spspd.actors.mobs.pets.GoldDragon; +import com.hmdzl.spspd.actors.mobs.pets.GreenDragon; +import com.hmdzl.spspd.actors.mobs.pets.LeryFire; +import com.hmdzl.spspd.actors.mobs.pets.LightDragon; +import com.hmdzl.spspd.actors.mobs.pets.Monkey; +import com.hmdzl.spspd.actors.mobs.pets.PET; +import com.hmdzl.spspd.actors.mobs.pets.RedDragon; +import com.hmdzl.spspd.actors.mobs.pets.RibbonRat; +import com.hmdzl.spspd.actors.mobs.pets.Scorpion; +import com.hmdzl.spspd.actors.mobs.pets.ShadowDragon; +import com.hmdzl.spspd.actors.mobs.pets.Snake; +import com.hmdzl.spspd.actors.mobs.pets.Spider; +import com.hmdzl.spspd.actors.mobs.pets.Stone; + +import com.hmdzl.spspd.actors.mobs.pets.Velocirooster; +import com.hmdzl.spspd.actors.mobs.pets.VioletDragon; + +import com.hmdzl.spspd.actors.mobs.pets.YearPet; +import com.hmdzl.spspd.effects.Pushing; +import com.hmdzl.spspd.effects.particles.FlowParticle; +import com.hmdzl.spspd.effects.particles.WindParticle; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.items.Heap; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.Stylus; +import com.hmdzl.spspd.items.Torch; +import com.hmdzl.spspd.items.StoneOre; +import com.hmdzl.spspd.items.Weightstone; +import com.hmdzl.spspd.items.artifacts.DriedRose; +import com.hmdzl.spspd.items.artifacts.TimekeepersHourglass; +import com.hmdzl.spspd.items.misc.LuckyBadge; +import com.hmdzl.spspd.items.potions.PotionOfMight; +import com.hmdzl.spspd.items.potions.PotionOfStrength; +import com.hmdzl.spspd.items.scrolls.ScrollOfMagicalInfusion; +import com.hmdzl.spspd.items.scrolls.ScrollOfUpgrade; +import com.hmdzl.spspd.levels.features.Chasm; +import com.hmdzl.spspd.levels.features.Door; +import com.hmdzl.spspd.levels.features.HighGrass; +import com.hmdzl.spspd.levels.painters.Painter; +import com.hmdzl.spspd.levels.traps.ChangeSheepTrap; +import com.hmdzl.spspd.levels.traps.FleecingTrap; +import com.hmdzl.spspd.levels.traps.HeapGenTrap; +import com.hmdzl.spspd.levels.traps.*; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.ui.CustomTileVisual; +import com.hmdzl.spspd.mechanics.ShadowCaster; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.plants.Plant; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.noosa.Scene; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Bundlable; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; +import com.watabou.utils.SparseArray; + +public abstract class Level implements Bundlable { + + public static enum Feeling { + NONE, CHASM, WATER, GRASS, DARK, TRAP + }; + + + + /* -W-1 -W -W+1 + * -1 P +1 + * W-1 W W+1 + * + */ + + public static int WIDTH = 48; + public static int HEIGHT = 48; + public static int LENGTH = WIDTH * HEIGHT; + + //public static int WIDTH = 50; + //public static int HEIGHT = 50; + //public static int LENGTH = (WIDTH-2) * (HEIGHT-2); + + public static final int[] NEIGHBOURS4 = { -getWidth(), +1, +getWidth(), -1 }; + public static final int[] NEIGHBOURS8 = { +1, -1, +getWidth(), -getWidth(), + +1 + getWidth(), +1 - getWidth(), -1 + getWidth(), -1 - getWidth() }; + public static final int[] NEIGHBOURS9 = { 0, +1, -1, +getWidth(), -getWidth(), + +1 + getWidth(), +1 - getWidth(), -1 + getWidth(), -1 - getWidth() }; + + // Note that use of these without checking values is unsafe, mobs can be + // within 2 tiles of the + // edge of the map, unsafe use in that case will cause an array out of + // bounds exception. + public static final int[] NEIGHBOURS8DIST2 = { +2 + 2 * getWidth(), + +1 + 2 * getWidth(), 2 * getWidth(), -1 + 2 * getWidth(), -2 + 2 * getWidth(), + +2 + getWidth(), +1 + getWidth(), +getWidth(), -1 + getWidth(), -2 + getWidth(), +2, +1, -1, + -2, +2 - getWidth(), +1 - getWidth(), -getWidth(), -1 - getWidth(), -2 - getWidth(), + +2 - 2 * getWidth(), +1 - 2 * getWidth(), -2 * getWidth(), -1 - 2 * getWidth(), + -2 - 2 * getWidth() }; + public static final int[] NEIGHBOURS9DIST2 = { +2 + 2 * getWidth(), + +1 + 2 * getWidth(), 2 * getWidth(), -1 + 2 * getWidth(), -2 + 2 * getWidth(), + +2 + getWidth(), +1 + getWidth(), +getWidth(), -1 + getWidth(), -2 + getWidth(), +2, +1, 0, + -1, -2, +2 - getWidth(), +1 - getWidth(), -getWidth(), -1 - getWidth(), -2 - getWidth(), + +2 - 2 * getWidth(), +1 - 2 * getWidth(), -2 * getWidth(), -1 - 2 * getWidth(), + -2 - 2 * getWidth() }; + + protected static final float TIME_TO_RESPAWN = 50; + protected static final int REGROW_TIMER = 10; + protected static final int DROP_TIMER = 10; + protected static final int PET_TICK = 1; + + private static final String TXT_HIDDEN_PLATE_CLICKS = "A hidden pressure plate clicks!"; + + public static boolean resizingNeeded; + public static boolean first; + public static int loadedMapSize; + + public int[] map; + public boolean[] visited; + public boolean[] mapped; + + public int movepar=0; + public int currentmoves=0; + public boolean genpetnext = false; + + //private int newvd; + public int viewDistance = /*Dungeon.isChallenged(Challenges.DARKNESS) ? 5 :*/ 8; + + public static boolean[] fieldOfView = new boolean[getLength()]; + + public static boolean[] passable = new boolean[getLength()]; + //public static boolean[] losBlocking = new boolean[getLength()]; + public static boolean[] losBlockHigh = new boolean[getLength()]; + public static boolean[] losBlockLow = new boolean[getLength()]; + public static boolean[] flamable = new boolean[getLength()]; + public static boolean[] shockable = new boolean[getLength()]; + public static boolean[] secret = new boolean[getLength()]; + public static boolean[] solid = new boolean[getLength()]; + public static boolean[] avoid = new boolean[getLength()]; + public static boolean[] water = new boolean[getLength()]; + public static boolean[] pit = new boolean[getLength()]; + + public static boolean[] discoverable = new boolean[getLength()]; + + public Feeling feeling = Feeling.NONE; + + + public int entrance; + public int exit; + public int pitSign; + + // when a boss level has become locked. + public boolean locked = false; + public boolean special = false; + public boolean cleared = false; + public boolean forcedone = false; + public boolean sealedlevel = false; + + public HashSet mobs; + public SparseArray heaps; + public HashMap, Blob> blobs; + public SparseArray plants; + public SparseArray traps; + public HashSet customTiles; + + protected ArrayList itemsToSpawn = new ArrayList(); + + public int color1 = 0x004400; + public int color2 = 0x88CC44; + + protected static boolean pitRoomNeeded = false; + protected static boolean weakFloorCreated = false; + public boolean reset = false; + + private static final String MAP = "map"; + private static final String VISITED = "visited"; + private static final String MAPPED = "mapped"; + private static final String ENTRANCE = "entrance"; + private static final String EXIT = "exit"; + private static final String LOCKED = "locked"; + private static final String HEAPS = "heaps"; + private static final String PLANTS = "plants"; + private static final String TRAPS = "traps"; + private static final String CUSTOM_TILES= "customTiles"; + private static final String MOBS = "mobs"; + private static final String BLOBS = "blobs"; + private static final String FEELING = "feeling"; + private static final String PITSIGN = "pitSign"; + private static final String MOVES = "currentmoves"; + private static final String CLEARED = "cleared"; + private static final String RESET = "reset"; + private static final String FORCEDONE = "forcedone"; + private static final String GENPETNEXT = "genpetnext"; + private static final String SEALEDLEVEL = "sealedlevel"; + + + public void create() { + + resizingNeeded = false; + + map = new int[getLength()]; + visited = new boolean[getLength()]; + Arrays.fill(visited, false); + mapped = new boolean[getLength()]; + Arrays.fill(mapped, false); + + mobs = new HashSet(); + heaps = new SparseArray(); + blobs = new HashMap, Blob>(); + plants = new SparseArray(); + traps = new SparseArray<>(); + customTiles = new HashSet<>(); + + if (!Dungeon.bossLevel()) { + addItemToSpawn(Generator.random(Generator.Category.FOOD)); + addItemToSpawn(Generator.random(Generator.Category.FOOD)); + if (Dungeon.posNeeded()) { + addItemToSpawn(new PotionOfStrength()); + Dungeon.limitedDrops.strengthPotions.count++; + } + if (Dungeon.souNeeded()) { + addItemToSpawn(new ScrollOfUpgrade()); + Dungeon.limitedDrops.upgradeScrolls.count++; + } + if (Random.Int(2) == 0) { + addItemToSpawn(new Stylus()); + addItemToSpawn(new Weightstone()); + } + + int bonus = 0; + for (Buff buff : Dungeon.hero.buffs(LuckyBadge.GreatLucky.class)) { + bonus += ((LuckyBadge.GreatLucky) buff).level; + } + if (Dungeon.hero.heroClass == HeroClass.SOLDIER) + bonus += 5; + + for (Buff buff : Dungeon.hero.buffs(AflyBless.class)) { + bonus += 5; + } + if (Random.Float() > Math.pow(0.95, bonus)) { + if (Random.Int(2) == 0) + addItemToSpawn(new ScrollOfMagicalInfusion()); + else + addItemToSpawn(new PotionOfMight()); + } + + DriedRose rose = Dungeon.hero.belongings.getItem(DriedRose.class); + if (rose != null && !rose.cursed) { + // this way if a rose is dropped later in the game, player still + // has a chance to max it out. + int petalsNeeded = (int) Math + .ceil((float) ((Dungeon.depth / 2) - rose.droppedPetals) / 3); + + for (int i = 1; i <= petalsNeeded; i++) { + // the player may miss a single petal and still max their + // rose. + if (rose.droppedPetals < 12) { + addItemToSpawn(new DriedRose.Petal()); + rose.droppedPetals++; + } + } + } + + if (Dungeon.depth > 1 && Dungeon.depth < 6) { + if (Dungeon.depth == 4 && !Dungeon.earlygrass) { + feeling = Feeling.GRASS; + } else { + switch (Random.Int(10)) { + case 0: + if (!Dungeon.bossLevel(Dungeon.depth + 1)) { + feeling = Feeling.CHASM; + } + break; + case 1: + feeling = Feeling.WATER; + break; + case 2: case 3: case 4: + feeling = Feeling.GRASS; + Dungeon.earlygrass = true; + break; + } + } + } else if (Dungeon.depth > 5 && Dungeon.depth < 22) { + switch (Random.Int(10)) { + case 0: + if (!Dungeon.bossLevel(Dungeon.depth + 1)) { + feeling = Feeling.CHASM; + } + break; + case 1: + feeling = Feeling.WATER; + break; + case 2: + feeling = Feeling.GRASS; + break; + case 3: + feeling = Feeling.DARK; + addItemToSpawn(new Torch()); + addItemToSpawn(new Torch()); + addItemToSpawn(new Torch()); + viewDistance = (int) Math.ceil(viewDistance / 3f); + break; + } + } else if (Dungeon.depth > 21 && Dungeon.depth < 27) { + switch (Random.Int(10)) { + case 1: + feeling = Feeling.WATER; + break; + case 2: + feeling = Feeling.GRASS; + break; + case 3: + case 0: + feeling = Feeling.DARK; + addItemToSpawn(new Torch()); + addItemToSpawn(new Torch()); + addItemToSpawn(new Torch()); + viewDistance = (int) Math.ceil(viewDistance / 3f); + break; + } + } else if (Dungeon.depth==29) { + feeling = Feeling.WATER; + } else if (Dungeon.depth==31) { + feeling = Feeling.DARK; + viewDistance = (int) Math.ceil(viewDistance / 3f); + } else if (Dungeon.depth>55) { + addItemToSpawn(new StoneOre()); + addItemToSpawn(new StoneOre()); + addItemToSpawn(new StoneOre()); + addItemToSpawn(new StoneOre()); + addItemToSpawn(new StoneOre()); + addItemToSpawn(new StoneOre()); + addItemToSpawn(new StoneOre()); + addItemToSpawn(new StoneOre()); + addItemToSpawn(new StoneOre()); + }else if (Dungeon.depth==32) { + feeling = Feeling.WATER; + } else if (Dungeon.depth==33) { + feeling = Feeling.TRAP; + } + + } + + boolean pitNeeded = Dungeon.depth > 1 && weakFloorCreated; + + do { + Arrays.fill(map, feeling == Feeling.CHASM ? Terrain.CHASM + : (feeling == Feeling.TRAP ? Terrain.TRAP_AIR : Terrain.WALL)); + + pitRoomNeeded = pitNeeded; + weakFloorCreated = false; + + } while (!build()); + decorate(); + + buildFlagMaps(); + cleanWalls(); + + createMobs(); + createItems(); + } + + public void reset() { + + for (Mob mob : mobs.toArray(new Mob[0])) { + if (!mob.reset()) { + mobs.remove(mob); + } + } + createMobs(); + reset=true; + } + + @Override + public void restoreFromBundle(Bundle bundle) { + + mobs = new HashSet(); + heaps = new SparseArray(); + blobs = new HashMap, Blob>(); + plants = new SparseArray(); + traps = new SparseArray<>(); + customTiles = new HashSet<>(); + + map = bundle.getIntArray(MAP); + visited = bundle.getBooleanArray(VISITED); + mapped = bundle.getBooleanArray(MAPPED); + + entrance = bundle.getInt(ENTRANCE); + exit = bundle.getInt(EXIT); + pitSign = bundle.getInt(PITSIGN); + currentmoves = bundle.getInt(MOVES); + + locked = bundle.getBoolean(LOCKED); + + cleared = bundle.getBoolean(CLEARED); + reset = bundle.getBoolean(RESET); + forcedone = bundle.getBoolean(FORCEDONE); + genpetnext = bundle.getBoolean(GENPETNEXT); + sealedlevel = bundle.getBoolean(SEALEDLEVEL); + + weakFloorCreated = false; + + adjustMapSize(); + + Collection collection = bundle.getCollection(HEAPS); + for (Bundlable h : collection) { + Heap heap = (Heap) h; + if (resizingNeeded) { + heap.pos = adjustPos(heap.pos); + } + if (!heap.isEmpty()) + heaps.put(heap.pos, heap); + } + + collection = bundle.getCollection(PLANTS); + for (Bundlable p : collection) { + Plant plant = (Plant) p; + if (resizingNeeded) { + plant.pos = adjustPos(plant.pos); + } + plants.put(plant.pos, plant); + } + + collection = bundle.getCollection( TRAPS ); + for (Bundlable p : collection) { + Trap trap = (Trap)p; + if (resizingNeeded) { + trap.pos = adjustPos( trap.pos ); + } + traps.put( trap.pos, trap ); + } + + collection = bundle.getCollection(MOBS); + for (Bundlable m : collection) { + Mob mob = (Mob) m; + if (mob != null) { + if (resizingNeeded) { + mob.pos = adjustPos(mob.pos); + } + mobs.add(mob); + } + } + + collection = bundle.getCollection(BLOBS); + for (Bundlable b : collection) { + Blob blob = (Blob) b; + blobs.put(blob.getClass(), blob); + } + + collection = bundle.getCollection( CUSTOM_TILES ); + for (Bundlable p : collection) { + CustomTileVisual vis = (CustomTileVisual)p; + if (resizingNeeded) { + //TODO: add proper resizing logic here + } + customTiles.add( vis ); + } + + feeling = bundle.getEnum(FEELING, Feeling.class); + if (feeling == Feeling.DARK) + viewDistance = (int) Math.ceil(viewDistance / 3f); + + buildFlagMaps(); + cleanWalls(); + } + + @Override + public void storeInBundle(Bundle bundle) { + bundle.put(MAP, map); + bundle.put(VISITED, visited); + bundle.put(MAPPED, mapped); + bundle.put(ENTRANCE, entrance); + bundle.put(EXIT, exit); + bundle.put(LOCKED, locked); + bundle.put(HEAPS, heaps.values()); + bundle.put(PLANTS, plants.values()); + bundle.put( TRAPS, traps.values() ); + bundle.put( CUSTOM_TILES, customTiles ); + bundle.put(MOBS, mobs); + bundle.put(BLOBS, blobs.values()); + bundle.put(FEELING, feeling); + bundle.put(PITSIGN, pitSign); + bundle.put(MOVES, currentmoves); + bundle.put(CLEARED, cleared); + bundle.put(RESET, reset); + bundle.put(FORCEDONE, forcedone); + bundle.put(GENPETNEXT, genpetnext); + bundle.put(SEALEDLEVEL, sealedlevel); + } + + public int tunnelTile() { + return feeling == Feeling.CHASM ? Terrain.EMPTY_SP : (feeling == Feeling.TRAP ? Terrain.EMPTY_SP : Terrain.EMPTY ); + } + + private void adjustMapSize() { + // For levels saved before 1.6.3 + // Seeing as shattered started on 1.7.1 this is never used, but the code + // may be resused in future. + if (map.length < getLength()) { + + resizingNeeded = true; + loadedMapSize = (int) Math.sqrt(map.length); + + int[] map = new int[getLength()]; + Arrays.fill(map, Terrain.WALL); + + boolean[] visited = new boolean[getLength()]; + Arrays.fill(visited, false); + + boolean[] mapped = new boolean[getLength()]; + Arrays.fill(mapped, false); + + for (int i = 0; i < loadedMapSize; i++) { + System.arraycopy(this.map, i * loadedMapSize, map, i * getWidth(), + loadedMapSize); + System.arraycopy(this.visited, i * loadedMapSize, visited, i + * getWidth(), loadedMapSize); + System.arraycopy(this.mapped, i * loadedMapSize, mapped, i + * getWidth(), loadedMapSize); + } + + this.map = map; + this.visited = visited; + this.mapped = mapped; + + entrance = adjustPos(entrance); + exit = adjustPos(exit); + } else { + resizingNeeded = false; + } + } + + public int adjustPos(int pos) { + return (pos / loadedMapSize) * getWidth() + (pos % loadedMapSize); + } + + public String tilesTex() { + return null; + } + + public String waterTex() { + return null; + } + + abstract protected boolean build(); + + abstract protected void decorate(); + + abstract protected void createMobs(); + + abstract protected void createItems(); + + + public void seal(){ + if (!locked) { + locked = true; + //Buff.affect(Dungeon.hero, LockedFloor.class); + } + } + + public void unseal(){ + if (locked) { + locked = false; + } + } + + public void addVisuals(Scene scene) { + for (int i = 0; i < getLength(); i++) { + if (pit[i]) { + scene.add(new WindParticle.Wind(i)); + if (i >= getWidth() && water[i - getWidth()]) { + scene.add(new FlowParticle.Flow(i - getWidth())); + } + } + } + } + + public int nMobs() { + return 0; + } + + public Mob findMob( int pos ){ + for (Mob mob : mobs){ + if (mob.pos == pos){ + return mob; + } + } + return null; + } + + public int movepar(){ + return movepar+Statistics.prevfloormoves; + } + + + public Actor respawner() { + return new Actor() { + @Override + protected boolean act() { + if (((Dungeon.dewDraw || Dungeon.dewWater)&& Dungeon.level.cleared && mobs.size() < nMobs()) + || (!(Dungeon.dewDraw || Dungeon.dewWater) && mobs.size() < nMobs())) + { + Mob mob = Bestiary.mutable(Dungeon.depth); + mob.state = mob.WANDERING; + mob.pos = randomRespawnCell(); + if (Dungeon.hero.isAlive() && mob.pos != -1) { + GameScene.add(mob); + } + } + spend(Dungeon.level.feeling == Feeling.DARK + || Statistics.amuletObtained ? TIME_TO_RESPAWN / 2 + : TIME_TO_RESPAWN); + return true; + } + }; + } + + public Actor respawnerPet() { + return new Actor() { + @Override + protected boolean act() { + //GLog.i("Check Pet"); + int petpos = -1; + int heropos = Dungeon.hero.pos; + if (Actor.findChar(heropos) != null && Dungeon.hero.petfollow) { + //GLog.i("Check Pet 2"); + ArrayList candidates = new ArrayList(); + boolean[] passable = Level.passable; + + for (int n : Level.NEIGHBOURS8) { + int c = heropos + n; + if (passable[c] && Actor.findChar(c) == null) { + candidates.add(c); + } + } + + petpos = candidates.size() > 0 ? Random.element(candidates) : -1; + } + + if (petpos != -1 && Dungeon.hero.haspet && Dungeon.hero.petfollow) { + + PET petCheck = checkpet(); + if(petCheck!=null){petCheck.destroy();petCheck.sprite.killAndErase();} + + if (Dungeon.hero.petType==1){ + Spider pet = new Spider(); + spawnPet(pet,petpos,heropos); + } + if (Dungeon.hero.petType==2){ + CocoCat pet = new CocoCat(); + spawnPet(pet,petpos,heropos); + } + if (Dungeon.hero.petType==3){ + Velocirooster pet = new Velocirooster(); + spawnPet(pet,petpos,heropos); + } + if (Dungeon.hero.petType==4){ + RedDragon pet = new RedDragon(); + spawnPet(pet,petpos,heropos); + } + if (Dungeon.hero.petType==5){ + GreenDragon pet = new GreenDragon(); + spawnPet(pet,petpos,heropos); + } + if (Dungeon.hero.petType==6){ + VioletDragon pet = new VioletDragon(); + spawnPet(pet,petpos,heropos); + } + if (Dungeon.hero.petType==7){ + BlueDragon pet = new BlueDragon(); + spawnPet(pet,petpos,heropos); + } + if (Dungeon.hero.petType==8){ + Scorpion pet = new Scorpion(); + spawnPet(pet,petpos,heropos); + } + if (Dungeon.hero.petType==9){ + Bunny pet = new Bunny(); + spawnPet(pet,petpos,heropos); + } + if (Dungeon.hero.petType==10){ + LightDragon pet = new LightDragon(); + spawnPet(pet,petpos,heropos); + } + if (Dungeon.hero.petType==11){ + BugDragon pet = new BugDragon(); + spawnPet(pet,petpos,heropos); + } + if (Dungeon.hero.petType==12){ + ShadowDragon pet = new ShadowDragon(); + spawnPet(pet,petpos,heropos); + } + if (Dungeon.hero.petType==13){ + CocoCat pet = new CocoCat(); + spawnPet(pet,petpos,heropos); + } + if (Dungeon.hero.petType==14){ + LeryFire pet = new LeryFire(); + spawnPet(pet,petpos,heropos); + } + if (Dungeon.hero.petType==15){ + GoldDragon pet = new GoldDragon(); + spawnPet(pet,petpos,heropos); + } + if (Dungeon.hero.petType==16){ + Snake pet = new Snake(); + spawnPet(pet,petpos,heropos); + } + if (Dungeon.hero.petType==17){ + Fly pet = new Fly(); + spawnPet(pet,petpos,heropos); + } + if (Dungeon.hero.petType==18){ + Stone pet = new Stone(); + spawnPet(pet,petpos,heropos); + } + if (Dungeon.hero.petType==19){ + Monkey pet = new Monkey(); + spawnPet(pet,petpos,heropos); + } + if (Dungeon.hero.petType==20){ + GentleCrab pet = new GentleCrab(); + spawnPet(pet,petpos,heropos); + } + if (Dungeon.hero.petType==21){ + RibbonRat pet = new RibbonRat(); + spawnPet(pet,petpos,heropos); + } + if (Dungeon.hero.petType==22){ + YearPet pet = new YearPet(); + spawnPet(pet,petpos,heropos); + } + } + + spend(PET_TICK); + return true; + } + }; + } + + private PET checkpet(){ + for (Mob mob : Dungeon.level.mobs) { + if(mob instanceof PET) { + return (PET) mob; + } + } + return null; + } + + public void spawnPet(PET pet, Integer petpos, Integer heropos){ + pet.spawn(Dungeon.hero.petLevel); + pet.HP = Dungeon.hero.petHP; + pet.pos = petpos; + pet.state = pet.HUNTING; + pet.experience = Dungeon.hero.petExperience; + pet.cooldown = Dungeon.hero.petCooldown; + + GameScene.add(pet); + Actor.addDelayed(new Pushing(pet, heropos, petpos), -1f); + Dungeon.hero.petfollow = false; + } + + public boolean checkOriginalGenMobs (){ + for (Mob mob : Dungeon.level.mobs.toArray(new Mob[0])) { + if (mob.originalgen){return true;} + } + return false; + } + + public Actor regrower() { + return new Actor() { + @Override + protected boolean act() { + + int growPos = -1; + for (int i = 0; i < 20; i++) { + growPos = randomRegrowthCell(); + + if (growPos != -1) { + break; + } + } + if (growPos != -1) { + if (map[growPos] == Terrain.GRASS){ + Level.set(growPos, Terrain.HIGH_GRASS); + } + GameScene.updateMap(); + Dungeon.observe(); + } + + + spend(REGROW_TIMER); + return true; + } + }; + } + + public Actor waterer() { + return new Actor() { + @Override + protected boolean act() { + + int growPos = -1; + for (int i = 0; i < 20; i++) { + growPos = randomRegrowthCell(); + + if (growPos != -1) { + break; + } + } + if (growPos != -1) { + if (map[growPos] == Terrain.GRASS || map[growPos] == Terrain.EMBERS){ + Level.set(growPos, Terrain.WATER); + } + GameScene.updateMap(); + Dungeon.observe(); + } + + + spend(REGROW_TIMER); + return true; + } + }; + } + + public int randomRegrowthCell() { + int cell; + int count = 1; + do { + cell = Random.Int(getLength()); + count++; + } while (map[cell] != Terrain.GRASS && count < 100); + return cell; + } + + public Actor floordropper() { + return new Actor() { + @Override + protected boolean act() { + + int dropPos = -1; + for (int i = 0; i < 20; i++) { + dropPos = randomChasmCell(); + + if (dropPos != -1) { + //GLog.i("one "); + break; + } + } + + if (dropPos != -1) { + + //GLog.i("two %s",dropPos); + if (map[dropPos] == Terrain.EMPTY && Actor.findChar(dropPos) == null){ + + //GLog.i("three "); + //if the tile above is not chasm then set to chasm floor. If is chasm then set to chasm + + if (map[dropPos-getWidth()]==Terrain.WALL || + map[dropPos-getWidth()]==Terrain.WALL_DECO){ + + set(dropPos, Terrain.CHASM_WALL); + //GLog.i("four "); + } + else if (map[dropPos-getWidth()]!=Terrain.CHASM && + map[dropPos-getWidth()]!=Terrain.CHASM_FLOOR && + map[dropPos-getWidth()]!=Terrain.CHASM_WALL) + { + set(dropPos, Terrain.CHASM_FLOOR); + } + else { + set(dropPos, Terrain.CHASM); + // GLog.i("five "); + } + + if (map[dropPos+getWidth()]==Terrain.CHASM_FLOOR){ + set(dropPos+getWidth(), Terrain.CHASM); + // GLog.i("six "); + } + + + } + GameScene.updateMap(dropPos); + GameScene.updateMap(dropPos-getWidth()); + GameScene.updateMap(dropPos+getWidth()); + Dungeon.observe(); + } + + spend(DROP_TIMER); + return true; + } + }; + } + + public int randomChasmCell() { + int cell; + int count = 1; + do { + cell = Random.Int(getWidth()+1, getLength()-(getWidth()+1)); + count++; + } while (map[cell] != Terrain.EMPTY && count < 100); + return cell; + } + + public int randomRespawnCell() { + int cell; + do { + cell = Random.Int(getLength()); + } while (!passable[cell] || Dungeon.visible[cell] + || Actor.findChar(cell) != null); + return cell; + } + + public int randomRespawnCellMob() { + int cell; + do { + cell = Random.Int(getLength()); + } while (!passable[cell] || Dungeon.visible[cell] + || Actor.findChar(cell) != null); + return cell; + } + + public int dropRespawnCell() { + int cell; + do { + cell = Random.Int(getLength()); + } while ((map[cell]!=Terrain.EMPTY && + map[cell]!=Terrain.EMPTY_DECO && + map[cell]!=Terrain.EMPTY_SP && + map[cell]!=Terrain.GRASS && + map[cell]!=Terrain.WATER) + || !passable[cell]); + return cell; + } + + public int wellRespawnCellMob() { + int cell; + do { + cell = Random.Int(getLength()); + } while (!passable[cell] || map[cell]!=Terrain.EMPTY_WELL || Dungeon.visible[cell] + || Actor.findChar(cell) != null); + return cell; + } + + public int randomRespawnCellSheep(int start, int dist) { + int cell; + do { + cell = Random.Int(getLength()); + } while (!avoid[cell] || Actor.findChar(cell) != null || map[cell]!=Terrain.FLEECING_TRAP + || distance(start, cell) > dist); + return cell; + } + + public int countFleeceTraps(int start, int dist) { + int count=0; + for (int cell = 0; cell < getLength(); cell++) { + if(avoid[cell] && Actor.findChar(cell) == null && map[cell]==Terrain.FLEECING_TRAP && distance(start, cell) < dist){ + count++; + } + } + return count; + } + + + public int randomRespawnCellFish() { + int cell; + do { + cell = Random.Int(getLength()); + } while (!passable[cell] || Actor.findChar(cell) != null || (map[cell]!=Terrain.EMPTY && map[cell]!=Terrain.EMPTY_SP && map[cell]!=Terrain.GRASS && map[cell]!=Terrain.HIGH_GRASS) ); + return cell; + } + + public int randomDestination() { + int cell; + do { + cell = Random.Int(getLength()); + } while (!passable[cell]); + return cell; + } + + public void addItemToSpawn(Item item) { + if (item != null) { + itemsToSpawn.add(item); + } + } + + public Item findPrizeItem() { + return findPrizeItem(null); + } + + public Item findPrizeItem(Class match) { + if (itemsToSpawn.size() == 0) + return null; + + if (match == null) { + Item item = Random.element(itemsToSpawn); + itemsToSpawn.remove(item); + return item; + } + + for (Item item : itemsToSpawn) { + if (match.isInstance(item)) { + itemsToSpawn.remove(item); + return item; + } + } + + return null; + } + + protected void buildFlagMaps() { + + for (int i = 0; i < getLength(); i++) { + int flags = Terrain.flags[map[i]]; + passable[i] = (flags & Terrain.PASSABLE) != 0; + //losBlocking[i] = (flags & Terrain.LOS_BLOCKING) != 0; + losBlockLow[i] = (flags & Terrain.LOS_BLOCKING) != 0; + losBlockHigh[i] = losBlockLow[i] && (flags & Terrain.SOLID) != 0 ; + flamable[i] = (flags & Terrain.FLAMABLE) != 0; + //shockable[i] = (flags & Terrain.SHOCKABLE) != 0; + secret[i] = (flags & Terrain.SECRET) != 0; + solid[i] = (flags & Terrain.SOLID) != 0; + avoid[i] = (flags & Terrain.AVOID) != 0; + water[i] = (flags & Terrain.LIQUID) != 0; + pit[i] = (flags & Terrain.PIT) != 0; + } + + int lastRow = getLength() - getWidth(); + for (int i = 0; i < getWidth(); i++) { + passable[i] = avoid[i] = false; + passable[lastRow + i] = avoid[lastRow + i] = false; + } + for (int i = getWidth(); i < lastRow; i += getWidth()) { + passable[i] = avoid[i] = false; + passable[i + getWidth() - 1] = avoid[i + getWidth() - 1] = false; + } + + for (int i = getWidth(); i < getLength() - getWidth(); i++) { + + if (water[i]) { + int t = Terrain.WATER_TILES; + for (int j = 0; j < NEIGHBOURS4.length; j++) { + if ((Terrain.flags[map[i + NEIGHBOURS4[j]]] & Terrain.UNSTITCHABLE) != 0) { + t += 1 << j; + } + } + map[i] = t; + } + + if (pit[i]) { + if (!pit[i - getWidth()]) { + int c = map[i - getWidth()]; + if (c == Terrain.EMPTY_SP || c == Terrain.STATUE_SP) { + map[i] = Terrain.CHASM_FLOOR_SP; + } else if (water[i - getWidth()]) { + map[i] = Terrain.CHASM_WATER; + } else if ((Terrain.flags[c] & Terrain.UNSTITCHABLE) != 0) { + map[i] = Terrain.CHASM_WALL; + } else { + map[i] = Terrain.CHASM_FLOOR; + } + } + } + } + } + + private int getWaterTile( int pos ) { + int t = Terrain.WATER_TILES; + for (int j=0; j < NEIGHBOURS4.length; j++) { + if ((Terrain.flags[map[pos + NEIGHBOURS4[j]]] & Terrain.UNSTITCHABLE) != 0) { + t += 1 << j; + } + } + return t; + } + + public void destroy( int pos ) { + if ((Terrain.flags[map[pos]] & Terrain.UNSTITCHABLE) == 0) { + + set( pos, Terrain.EMBERS ); + + } else { + boolean flood = false; + for (int j=0; j < NEIGHBOURS4.length; j++) { + if (water[pos + NEIGHBOURS4[j]]) { + flood = true; + break; + } + } + if (flood) { + set( pos, getWaterTile( pos ) ); + } else { + set( pos, Terrain.EMBERS ); + } + } + } + + protected void cleanWalls() { + for (int i = 0; i < getLength(); i++) { + + boolean d = false; + + for (int j = 0; j < NEIGHBOURS9.length; j++) { + int n = i + NEIGHBOURS9[j]; + if (n >= 0 && n < getLength() && map[n] != Terrain.WALL + && map[n] != Terrain.WALL_DECO) { + d = true; + break; + } + } + + if (d) { + d = false; + + for (int j = 0; j < NEIGHBOURS9.length; j++) { + int n = i + NEIGHBOURS9[j]; + if (n >= 0 && n < getLength() && !pit[n]) { + d = true; + break; + } + } + } + + discoverable[i] = d; + } + } + + public static void set(int cell, int terrain) { + Painter.set(Dungeon.level, cell, terrain); + + int flags = Terrain.flags[terrain]; + passable[cell] = (flags & Terrain.PASSABLE) != 0; + //losBlocking[cell] = (flags & Terrain.LOS_BLOCKING) != 0; + losBlockLow[cell] = (flags & Terrain.LOS_BLOCKING) != 0; + losBlockHigh[cell] = losBlockLow[cell] && (flags & Terrain.SOLID) != 0; + flamable[cell] = (flags & Terrain.FLAMABLE) != 0; + //shockable[cell] = (flags & Terrain.SHOCKABLE) != 0; + secret[cell] = (flags & Terrain.SECRET) != 0; + solid[cell] = (flags & Terrain.SOLID) != 0; + avoid[cell] = (flags & Terrain.AVOID) != 0; + pit[cell] = (flags & Terrain.PIT) != 0; + water[cell] = terrain == Terrain.WATER || (terrain >= Terrain.WATER_TILES && terrain 1) || !sighted) { + + int ax = Math.max(0, cx - sense); + int bx = Math.min(cx + sense, getWidth() - 1); + int ay = Math.max(0, cy - sense); + int by = Math.min(cy + sense, HEIGHT - 1); + + int len = bx - ax + 1; + int pos = ax + ay * getWidth(); + for (int y = ay; y <= by; y++, pos += getWidth()) { + Arrays.fill(fieldOfView, pos, pos + len, true); + } + + for (int i = 0; i < getLength(); i++) { + fieldOfView[i] &= discoverable[i]; + } + } + + if (c.isAlive() && c == Dungeon.hero) { + if (c.buff(MindVision.class) != null) { + for (Mob mob : mobs) { + int p = mob.pos; + fieldOfView[p] = true; + fieldOfView[p + 1] = true; + fieldOfView[p - 1] = true; + fieldOfView[p + getWidth() + 1] = true; + fieldOfView[p + getWidth() - 1] = true; + fieldOfView[p - getWidth() + 1] = true; + fieldOfView[p - getWidth() - 1] = true; + fieldOfView[p + getWidth()] = true; + fieldOfView[p - getWidth()] = true; + } + } else if (((Hero) c).heroClass == HeroClass.HUNTRESS) { + for (Mob mob : mobs) { + int p = mob.pos; + if (distance(c.pos, p) == 2) { + fieldOfView[p] = true; + fieldOfView[p + 1] = true; + fieldOfView[p - 1] = true; + fieldOfView[p + getWidth() + 1] = true; + fieldOfView[p + getWidth() - 1] = true; + fieldOfView[p - getWidth() + 1] = true; + fieldOfView[p - getWidth() - 1] = true; + fieldOfView[p + getWidth()] = true; + fieldOfView[p - getWidth()] = true; + } + } + } + if (c.buff(Awareness.class) != null) { + for (Heap heap : heaps.values()) { + int p = heap.pos; + fieldOfView[p] = true; + fieldOfView[p + 1] = true; + fieldOfView[p - 1] = true; + fieldOfView[p + getWidth() + 1] = true; + fieldOfView[p + getWidth() - 1] = true; + fieldOfView[p - getWidth() + 1] = true; + fieldOfView[p - getWidth() - 1] = true; + fieldOfView[p + getWidth()] = true; + fieldOfView[p - getWidth()] = true; + } + } + + if (c.buff(ExitFind.class) != null && Dungeon.depth < 26) { + int p = Dungeon.level.exit; + fieldOfView[p] = true; + fieldOfView[p + 1] = true; + fieldOfView[p - 1] = true; + fieldOfView[p + getWidth() + 1] = true; + fieldOfView[p + getWidth() - 1] = true; + fieldOfView[p - getWidth() + 1] = true; + fieldOfView[p - getWidth() - 1] = true; + fieldOfView[p + getWidth()] = true; + fieldOfView[p - getWidth()] = true; + + } + } + + for (Heap heap : heaps.values()) + if (!heap.seen && fieldOfView[heap.pos]) + heap.seen = true; + + return fieldOfView; + } + + public static int distance(int a, int b) { + int ax = a % getWidth(); + int ay = a / getWidth(); + int bx = b % getWidth(); + int by = b / getWidth(); + return Math.max(Math.abs(ax - bx), Math.abs(ay - by)); + } + + public static boolean adjacent(int a, int b) { + int diff = Math.abs(a - b); + return diff == 1 || diff == getWidth() || diff == getWidth() + 1 + || diff == getWidth() - 1; + } + + public static boolean insideMap( int tile ){ + //outside map array + return !((tile <= -1 || tile >= LENGTH) || + //top and bottom row + (tile <= 47 || tile >= LENGTH - WIDTH) || + //left and right column + (tile % WIDTH == 0 || tile % WIDTH == 47)); + + } + + public String tileName(int tile) { + + if (tile >= Terrain.WATER_TILES) { + return tileName(Terrain.WATER); + } + // && tile= Terrain.WATER_TILES) { + return tileDesc(Terrain.WATER); + } + if ((Terrain.flags[tile] & Terrain.PIT) != 0) { + return tileDesc(Terrain.CHASM); + } + return Messages.get(Level.class, "default_desc"); + } + } + + /* + +public static final int FLEECING_TRAP = 65; + public static final int WOOL_RUG = 66; + public static final int SOKOBAN_SHEEP = 67; + public static final int CORNER_SOKOBAN_SHEEP = 68; + public static final int SWITCH_SOKOBAN_SHEEP = 69; + public static final int CHANGE_SHEEP_TRAP = 70; + public static final int SOKOBAN_ITEM_REVEAL = 71; + public static final int SOKOBAN_HEAP = 72; + public static final int BLACK_SOKOBAN_SHEEP = 73; + public static final int SOKOBAN_PORT_SWITCH = 75; + public static final int PORT_WELL = 74; +*/ + public boolean darkness(){ + return (Dungeon.isChallenged(Challenges.DARKNESS) || Dungeon.level.feeling == Feeling.DARK); + } + public static int getWidth() { + return WIDTH; + } + + public static int getLength() { + return LENGTH; + } +} diff --git a/java/com/hmdzl/spspd/levels/MazeLayout.java b/java/com/hmdzl/spspd/levels/MazeLayout.java new file mode 100644 index 00000000..4230f81c --- /dev/null +++ b/java/com/hmdzl/spspd/levels/MazeLayout.java @@ -0,0 +1,216 @@ +/* + * 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 + */ +package com.hmdzl.spspd.levels; + +public class MazeLayout { + + //32X32 + private static final int W = Terrain.WALL; + private static final int T = Terrain.SHRUB; + private static final int Z = Terrain.HIGH_GRASS; + private static final int D = Terrain.DOOR; + private static final int L = Terrain.LOCKED_DOOR; + + //private static final int T = Terrain.INACTIVE_TRAP; + + private static final int E = Terrain.EMPTY; + //private static final int X = Terrain.EXIT; + + private static final int M = Terrain.WALL_DECO; + //private static final int P = Terrain.PEDESTAL; + + private static final int A = Terrain.SOKOBAN_SHEEP; + private static final int X = Terrain.CORNER_SOKOBAN_SHEEP; + private static final int C = Terrain.SWITCH_SOKOBAN_SHEEP; + private static final int B = Terrain.BLACK_SOKOBAN_SHEEP; + private static final int H = Terrain.SOKOBAN_HEAP; + private static final int I = Terrain.SOKOBAN_ITEM_REVEAL; + private static final int F = Terrain.FLEECING_TRAP; + private static final int U = Terrain.STATUE; + private static final int G = Terrain.CHANGE_SHEEP_TRAP; + private static final int S = Terrain.SECRET_DOOR; + private static final int R = Terrain.PORT_WELL; + private static final int V = Terrain.SOKOBAN_PORT_SWITCH; + /* + public boolean[][] maze; + */ + /* + public static final int[] MAZE1 = { + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, _, _, _, _, _, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, H, _, W, _, Z, Z, Z, _, W, Z, Z, Z, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, H, _, L, _, Z, E, Z, _, L, Z, Z, Z, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, H, _, W, _, Z, Z, Z, _, W, Z, Z, Z, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, I, X, _, _, _, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W + + }; + + */ + + /* + protected void buildMazeMask() { + + maze = new boolean[Level.WIDTH][Level.HEIGHT]; + + for (int x = 0; x < maze.length; x++) { + for (int y = 0; y < maze[0].length; y++) { + if (x == 0 || x == maze.length|| + y == 0 || y == maze[0].length) { + + + if (d.x == x + room.left && d.y == y + room.top) { + maze[x][y] = true; + } + } + + } else { + maze[x][y] = true; + } + } + } + + int fails = 0; + while (fails < 10000) { + + //find a random wall point + int x, y; + do { + x = Random.Int(maze.length); + y = Random.Int(maze[0].length); + } while (maze[x][y]); + + //decide on how we're going to move + int[] mov = decideDirection(maze, x, y); + if (mov == null) { + fails++; + } else { + + fails = 0; + int moves = 0; + do { + x += mov[0]; + y += mov[1]; + maze[x][y] = false; + moves++; + } while (Random.Int(moves+1) == 0 && checkValidMove(maze, x, y, mov)); + + } + + } + + fill(level, room, 1, Terrain.EMPTY); + for (int x = 0; x < maze.length; x++) + for (int y = 0; y < maze[0].length; y++) { + if (!maze[x][y]) { + fill(level, x + room.left, y + room.top, 1, 1, Terrain.WALL); + } + } + } + + + private static int[] decideDirection(boolean[][] maze, int x, int y){ + + //attempts to move up + if (Random.Int(4) == 0 && //1 in 4 chance + checkValidMove(maze, x, y, new int[]{0, -1})){ + return new int[]{0, -1}; + } + + //attempts to move right + if (Random.Int(3) == 0 && //1 in 3 chance + checkValidMove(maze, x, y, new int[]{1, 0})){ + return new int[]{1, 0}; + } + + //attempts to move down + if (Random.Int(2) == 0 && //1 in 2 chance + checkValidMove(maze, x, y, new int[]{0, 1})){ + return new int[]{0, 1}; + } + + //attempts to move left + if ( + checkValidMove(maze, x, y, new int[]{-1, 0})){ + return new int[]{-1, 0}; + } + + return null; + } + + private static boolean checkValidMove( boolean[][] maze, int x, int y, int[] mov){ + int sideX = 1 - Math.abs(mov[0]); + int sideY = 1 - Math.abs(mov[1]); + + //checking two tiles forward in the movement, and the tiles to their left/right + for (int i = 0; i < 2; i ++) { + x += mov[0]; + y += mov[1]; + //checks if tiles we're examining are valid and open + if ( x > 0 && x < maze.length-1 && y > 0 && y < maze[0].length-1 && + maze[x][y] && maze[x + sideX][y+ sideY] && maze[x - sideX][y - sideY]){ + continue; + } else { + return false; + } + } + return true; + } + */ +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/levels/MineBossLayouts.java b/java/com/hmdzl/spspd/levels/MineBossLayouts.java new file mode 100644 index 00000000..1602eab9 --- /dev/null +++ b/java/com/hmdzl/spspd/levels/MineBossLayouts.java @@ -0,0 +1,107 @@ +/* + * 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 + */ +package com.hmdzl.spspd.levels; + +import com.watabou.utils.Random; + +public class MineBossLayouts { + + //32X32 + private static final int W = Terrain.WALL; + private static final int T = Terrain.SHRUB; + private static final int Z = Terrain.HIGH_GRASS; + private static final int D = Terrain.DOOR; + private static final int L = Terrain.LOCKED_DOOR; + + //private static final int T = Terrain.INACTIVE_TRAP; + + private static final int E = Terrain.EMPTY; + //private static final int I = Terrain.EXIT; + + private static final int M = Terrain.WALL_DECO; + //private static final int P = Terrain.PEDESTAL; + + private static final int A = Terrain.SOKOBAN_SHEEP; + private static final int X = Terrain.CORNER_SOKOBAN_SHEEP; + private static final int C = Terrain.SWITCH_SOKOBAN_SHEEP; + private static final int B = Terrain.BLACK_SOKOBAN_SHEEP; + private static final int H = Terrain.SOKOBAN_HEAP; + //private static final int I = Terrain.SOKOBAN_ITEM_REVEAL; + private static final int F = Terrain.FLEECING_TRAP; + private static final int U = Terrain.STATUE; + private static final int G = Terrain.CHANGE_SHEEP_TRAP; + private static final int S = Terrain.SECRET_DOOR; + private static final int R = Terrain.PORT_WELL; + private static final int V = Terrain.SOKOBAN_PORT_SWITCH; + + private static final int J = Terrain.WATER; + private static final int Y = Terrain.ALCHEMY; + private static final int K = Terrain.EMPTY_SP; + + public static final int[] MINE_BOSS = { + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, E, E, E, E, E, E, E, E, X, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, W, W, W, W, W, W, + W, W, W, W, E, E, E, E, E, E, X, E, E, E, E, E, E, E, X, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, W, W, W, W, + W, W, W, W, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, W, W, W, W, + W, W, W, W, E, E, E, E, E, E, E, A, A, A, A, A, A, A, E, E, E, E, E, E, E, E, E, E, E, E, A, A, A, A, A, A, A, E, E, E, E, E, E, E, W, W, W, W, + W, W, W, W, E, E, E, E, E, E, E, A, A, A, A, A, A, A, E, E, E, E, E, E, E, E, E, E, E, E, A, A, A, A, A, A, A, E, E, E, E, E, E, E, W, W, W, W, + W, W, W, W, E, E, E, E, E, E, E, A, A, A, A, A, A, A, E, E, E, E, E, E, E, E, E, E, E, E, A, A, E, E, E, A, A, E, E, E, E, E, E, E, W, W, W, W, + W, W, W, W, E, E, E, E, E, X, E, A, A, A, E, A, A, A, E, X, E, E, E, E, E, E, E, E, E, E, A, A, E, E, E, A, A, E, E, E, E, E, E, E, W, W, W, W, + W, W, W, W, E, E, E, E, E, E, E, A, A, A, A, A, A, A, E, E, E, E, E, E, E, E, E, E, E, E, A, A, E, E, E, A, A, E, E, E, E, E, E, E, W, W, W, W, + W, W, W, W, E, E, E, E, E, E, E, A, A, A, A, A, A, A, E, E, E, E, E, E, E, E, E, E, E, E, A, A, A, A, A, A, A, E, E, E, E, E, E, E, W, W, W, W, + W, W, W, W, E, E, E, E, E, E, E, A, A, A, A, A, A, A, E, E, E, E, E, E, E, E, E, E, E, E, A, A, A, A, A, A, A, E, E, E, E, E, E, E, W, W, W, W, + W, W, W, W, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, W, W, W, W, + W, W, W, W, E, E, E, E, E, E, X, E, E, E, E, E, E, E, X, E, E, E, E, U, U, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, W, W, W, W, + W, W, W, W, E, E, E, E, E, E, E, E, E, E, X, E, E, E, E, E, E, E, E, U, U, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, W, W, W, W, + W, W, W, W, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, U, U, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, W, W, W, W, + W, W, W, W, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, U, U, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, W, W, W, W, + W, W, W, W, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, U, E, E, U, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, W, W, W, W, + W, W, W, W, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, W, W, W, W, + W, W, W, W, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, W, W, W, W, + W, W, W, W, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, W, W, W, W, + W, W, W, W, W, W, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, W, W, W, W, W, W, + W, W, W, W, W, W, W, E, E, E, E, E, W, W, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, W, W, E, E, E, E, E, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, E, E, E, W, W, W, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, W, W, W, E, E, E, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, L, W, W, W, W, W, W, L, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, E, E, E, E, E, E, E, E, E, E, E, E, E, E, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, E, W, E, W, E, W, E, E, W, E, W, E, W, E, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, E, W, E, W, E, W, E, E, W, E, W, E, W, E, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, E, W, E, W, E, E, E, E, E, E, W, E, W, E, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, E, W, E, E, E, E, E, E, E, E, E, E, W, E, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, E, W, E, W, E, W, E, E, W, E, W, E, W, E, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, E, W, E, W, E, W, E, E, W, E, W, E, W, E, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, E, E, E, W, E, W, E, E, W, E, W, E, E, E, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W + }; + +} diff --git a/java/com/hmdzl/spspd/levels/MinesBossLevel.java b/java/com/hmdzl/spspd/levels/MinesBossLevel.java new file mode 100644 index 00000000..e021c640 --- /dev/null +++ b/java/com/hmdzl/spspd/levels/MinesBossLevel.java @@ -0,0 +1,317 @@ +/* + * 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 + */ +package com.hmdzl.spspd.levels; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.WellWater; +import com.hmdzl.spspd.actors.mobs.LitTower; +import com.hmdzl.spspd.actors.mobs.MineSentinel; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.actors.mobs.Otiluke; +import com.hmdzl.spspd.actors.mobs.npcs.SheepSokoban; +import com.hmdzl.spspd.actors.mobs.npcs.SheepSokobanBlack; +import com.hmdzl.spspd.actors.mobs.npcs.SheepSokobanCorner; +import com.hmdzl.spspd.actors.mobs.npcs.SheepSokobanSwitch; +import com.hmdzl.spspd.items.Heap; +import com.hmdzl.spspd.items.Palantir; +import com.hmdzl.spspd.items.artifacts.TimekeepersHourglass; +import com.hmdzl.spspd.items.keys.IronKey; +import com.hmdzl.spspd.levels.features.Chasm; +import com.hmdzl.spspd.levels.features.Door; +import com.hmdzl.spspd.levels.features.HighGrass; +import com.hmdzl.spspd.levels.traps.ChangeSheepTrap; +import com.hmdzl.spspd.levels.traps.FleecingTrap; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.plants.Plant; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.windows.WndOtilukeMessage; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Bundle; + +public class MinesBossLevel extends Level { + + + { + color1 = 0x534f3e; + color2 = 0xb9d661; + WIDTH = 48; + HEIGHT = 48; + LENGTH = HEIGHT*WIDTH; + + } + + + private boolean entered = false; + private static final String ENTERED = "entered"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(ENTERED, entered); + + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + entered = bundle.getBoolean(ENTERED); + + } + + + + @Override + public void press(int cell, Char ch) { + + + if (ch == Dungeon.hero && !entered) { + + entered = true; + locked = true; + GameScene.show(new WndOtilukeMessage()); + + } + + if (pit[cell] && ch == Dungeon.hero) { + Chasm.heroFall(cell); + return; + } + + TimekeepersHourglass.timeFreeze timeFreeze = null; + + if (ch != null) + timeFreeze = ch.buff(TimekeepersHourglass.timeFreeze.class); + + boolean trap = false; + + switch (map[cell]) { + + case Terrain.FLEECING_TRAP: + + if (ch != null && ch==Dungeon.hero){ + trap = true; + FleecingTrap.trigger(cell, ch); + } + break; + + case Terrain.CHANGE_SHEEP_TRAP: + + if (ch instanceof SheepSokoban || ch instanceof SheepSokobanSwitch || ch instanceof SheepSokobanCorner ){ + trap = true; + ChangeSheepTrap.trigger(cell, ch); + } + break; + + + case Terrain.HIGH_GRASS: + HighGrass.trample(this, cell, ch); + break; + + case Terrain.WELL: + WellWater.affectCell(cell); + break; + + /*case Terrain.ALCHEMY: + if (ch == null) { + Alchemy.transmute(cell); + } + break;*/ + + case Terrain.DOOR: + Door.enter(cell); + break; + } + + if (trap){ + + if (Dungeon.visible[cell]) + Sample.INSTANCE.play(Assets.SND_TRAP); + + if (ch == Dungeon.hero) + Dungeon.hero.interrupt(); + + set(cell, Terrain.INACTIVE_TRAP); + GameScene.updateMap(cell); + } + + Plant plant = plants.get(cell); + if (plant != null) { + plant.activate(ch); + } + } + + + + @Override + public void mobPress(Mob mob) { + + int cell = mob.pos; + + if (pit[cell] && !mob.flying) { + Chasm.mobFall(mob); + return; + } + + boolean trap = true; + boolean fleece = false; + boolean sheep = false; + switch (map[cell]) { + + case Terrain.FLEECING_TRAP: + if (mob instanceof SheepSokoban || mob instanceof SheepSokobanSwitch || mob instanceof SheepSokobanCorner || mob instanceof SheepSokobanBlack ){ + fleece=true; + } + FleecingTrap.trigger(cell, mob); + break; + + case Terrain.DOOR: + Door.enter(cell); + + default: + trap = false; + } + + if (trap && !fleece && !sheep) { + if (Dungeon.visible[cell]) { + Sample.INSTANCE.play(Assets.SND_TRAP); + } + set(cell, Terrain.INACTIVE_TRAP); + GameScene.updateMap(cell); + } + + if (trap && fleece) { + if (Dungeon.visible[cell]) { + Sample.INSTANCE.play(Assets.SND_TRAP); + } + set(cell, Terrain.WOOL_RUG); + GameScene.updateMap(cell); + } + + if (trap && sheep) { + if (Dungeon.visible[cell]) { + Sample.INSTANCE.play(Assets.SND_TRAP); + } + set(cell, Terrain.EMPTY); + GameScene.updateMap(cell); + } + + + Plant plant = plants.get(cell); + if (plant != null) { + plant.activate(mob); + } + + Dungeon.observe(); + } + + @Override + public String tilesTex() { + return Assets.TILES_PUZZLE; + } + + @Override + public String waterTex() { + return Assets.WATER_PRISON; + } + + @Override + protected boolean build() { + + + map = MineBossLayouts.MINE_BOSS.clone(); + + decorate(); + + buildFlagMaps(); + cleanWalls(); + + entrance = 17 + WIDTH * 44; + exit = 0 ; + + + return true; + } + @Override + protected void decorate() { + //do nothing, all decorations are hard-coded. + } + + @Override + protected void createMobs() { + for (int i = 0; i < LENGTH; i++) { + if (map[i]==Terrain.SOKOBAN_SHEEP){ + MineSentinel npc = new MineSentinel(); + mobs.add(npc); npc.pos = i; + Actor.occupyCell(npc); + } else if (map[i]==Terrain.CORNER_SOKOBAN_SHEEP){ + LitTower npc = new LitTower(); + mobs.add(npc); npc.pos = i; + Actor.occupyCell(npc); + } + } + + Otiluke mob = new Otiluke(); + mobs.add(mob); mob.pos = 33 + WIDTH * 10; + Actor.occupyCell(mob); + } + + + + + @Override + public String tileName( int tile ) { + switch (tile) { + case Terrain.WATER: + return Messages.get(PrisonLevel.class, "water_name"); + default: + return super.tileName( tile ); + } + } + + @Override + public String tileDesc(int tile) { + switch (tile) { + case Terrain.EMPTY_DECO: + return Messages.get(PrisonLevel.class, "empty_deco_desc"); + case Terrain.BOOKSHELF: + return Messages.get(PrisonLevel.class, "bookshelf_desc"); + default: + return super.tileDesc( tile ); + } + } + + + + @Override + protected void createItems() { + + drop(new IronKey(Dungeon.depth), 30 + WIDTH * 44).type = Heap.Type.CHEST; + drop(new Palantir(), 14 + WIDTH * 10); + + } + + @Override + public int randomRespawnCell() { + return -1; + } + + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/levels/Patch.java b/java/com/hmdzl/spspd/levels/Patch.java new file mode 100644 index 00000000..f2b702dc --- /dev/null +++ b/java/com/hmdzl/spspd/levels/Patch.java @@ -0,0 +1,85 @@ +/* + * 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 + */ +package com.hmdzl.spspd.levels; + +import com.watabou.utils.Random; + +public class Patch { + + private static boolean[] cur = new boolean[Level.getLength()]; + private static boolean[] off = new boolean[Level.getLength()]; + + public static boolean[] generate(float seed, int nGen) { + + int w = Level.getWidth(); + int h = Level.HEIGHT; + + for (int i = 0; i < Level.getLength(); i++) { + off[i] = Random.Float() < seed; + } + + for (int i = 0; i < nGen; i++) { + + for (int y = 1; y < h - 1; y++) { + for (int x = 1; x < w - 1; x++) { + + int pos = x + y * w; + int count = 0; + if (off[pos - w - 1]) { + count++; + } + if (off[pos - w]) { + count++; + } + if (off[pos - w + 1]) { + count++; + } + if (off[pos - 1]) { + count++; + } + if (off[pos + 1]) { + count++; + } + if (off[pos + w - 1]) { + count++; + } + if (off[pos + w]) { + count++; + } + if (off[pos + w + 1]) { + count++; + } + + if (!off[pos] && count >= 5) { + cur[pos] = true; + } else if (off[pos] && count >= 4) { + cur[pos] = true; + } else { + cur[pos] = false; + } + } + } + + boolean[] tmp = cur; + cur = off; + off = tmp; + } + + return off; + } +} diff --git a/java/com/hmdzl/spspd/levels/PotLevel.java b/java/com/hmdzl/spspd/levels/PotLevel.java new file mode 100644 index 00000000..61ad44f9 --- /dev/null +++ b/java/com/hmdzl/spspd/levels/PotLevel.java @@ -0,0 +1,453 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2017 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ + +package com.hmdzl.spspd.levels; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.Challenges; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.Statistics; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.Alchemy; +import com.hmdzl.spspd.actors.blobs.Alter; +import com.hmdzl.spspd.actors.blobs.WellWater; +import com.hmdzl.spspd.actors.mobs.AdultDragonViolet; +import com.hmdzl.spspd.actors.mobs.Bestiary; +import com.hmdzl.spspd.actors.mobs.BombBug; +import com.hmdzl.spspd.actors.mobs.Piranha; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.actors.mobs.TestMob; +import com.hmdzl.spspd.actors.mobs.TestMob2; +import com.hmdzl.spspd.actors.mobs.npcs.AFly; +import com.hmdzl.spspd.actors.mobs.npcs.ARealMan; +import com.hmdzl.spspd.actors.mobs.npcs.Apostle; +import com.hmdzl.spspd.actors.mobs.npcs.DreamPlayer; +import com.hmdzl.spspd.actors.mobs.npcs.GoblinPlayer; +import com.hmdzl.spspd.actors.mobs.npcs.HoneyPoooot; +import com.hmdzl.spspd.actors.mobs.npcs.Ice13; +import com.hmdzl.spspd.actors.mobs.npcs.Juh9870; +import com.hmdzl.spspd.actors.mobs.npcs.Kostis12345; +import com.hmdzl.spspd.actors.mobs.npcs.Lynn; +import com.hmdzl.spspd.actors.mobs.npcs.Millilitre; +import com.hmdzl.spspd.actors.mobs.npcs.NutPainter; +import com.hmdzl.spspd.actors.mobs.npcs.OldNewStwist; +import com.hmdzl.spspd.actors.mobs.npcs.Omicronrg9; +import com.hmdzl.spspd.actors.mobs.npcs.OtilukeNPC; +import com.hmdzl.spspd.actors.mobs.npcs.RENnpc; +import com.hmdzl.spspd.actors.mobs.npcs.RainTrainer; +import com.hmdzl.spspd.actors.mobs.npcs.SadSaltan; +import com.hmdzl.spspd.actors.mobs.npcs.SaidbySun; +import com.hmdzl.spspd.actors.mobs.npcs.Sheep; +import com.hmdzl.spspd.actors.mobs.npcs.SheepSokoban; +import com.hmdzl.spspd.actors.mobs.npcs.SheepSokobanBlack; +import com.hmdzl.spspd.actors.mobs.npcs.SheepSokobanCorner; +import com.hmdzl.spspd.actors.mobs.npcs.SheepSokobanSwitch; +import com.hmdzl.spspd.actors.mobs.npcs.Shopkeeper; +import com.hmdzl.spspd.actors.mobs.npcs.Shower; +import com.hmdzl.spspd.actors.mobs.npcs.Tinkerer4; +import com.hmdzl.spspd.actors.mobs.npcs.Tinkerer5; +import com.hmdzl.spspd.actors.mobs.npcs.Udawos; +import com.hmdzl.spspd.actors.mobs.npcs.TypedScroll; +import com.hmdzl.spspd.actors.mobs.npcs.G2159687; +import com.hmdzl.spspd.actors.mobs.npcs.ConsideredHamster; +import com.hmdzl.spspd.actors.mobs.npcs.NYRDS; +import com.hmdzl.spspd.actors.mobs.npcs.Evan; +import com.hmdzl.spspd.actors.mobs.npcs.UncleS; +import com.hmdzl.spspd.actors.mobs.npcs.Watabou; +import com.hmdzl.spspd.actors.mobs.npcs.Bilboldev; +import com.hmdzl.spspd.actors.mobs.npcs.HBB; +import com.hmdzl.spspd.actors.mobs.npcs.SFB; +import com.hmdzl.spspd.actors.mobs.npcs.Jinkeloid; +import com.hmdzl.spspd.actors.mobs.npcs.Rustyblade; +import com.hmdzl.spspd.actors.mobs.npcs.HeXA; +import com.hmdzl.spspd.actors.mobs.npcs.SP931; +import com.hmdzl.spspd.actors.mobs.npcs.Lery; +import com.hmdzl.spspd.actors.mobs.npcs.Lyn; +import com.hmdzl.spspd.actors.mobs.npcs.Coconut; +import com.hmdzl.spspd.actors.mobs.npcs.FruitCat; +import com.hmdzl.spspd.actors.mobs.npcs.Locastan; +import com.hmdzl.spspd.actors.mobs.npcs.Tempest102; +import com.hmdzl.spspd.actors.mobs.npcs.Dachhack; +import com.hmdzl.spspd.actors.mobs.npcs.MemoryOfSand; +import com.hmdzl.spspd.actors.mobs.npcs.StormAndRain; +import com.hmdzl.spspd.actors.mobs.npcs.HateSokoban; +import com.hmdzl.spspd.actors.mobs.npcs.AliveFish; +import com.hmdzl.spspd.actors.mobs.npcs.LaJi; +import com.hmdzl.spspd.actors.mobs.npcs.WhiteGhost; +import com.hmdzl.spspd.actors.mobs.npcs.XixiZero; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.food.Nut; +import com.hmdzl.spspd.items.food.vegetable.NutVegetable; +import com.hmdzl.spspd.items.eggs.Egg; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.items.Heap; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.Ankh; +import com.hmdzl.spspd.items.AdamantArmor; +import com.hmdzl.spspd.items.AdamantRing; +import com.hmdzl.spspd.items.AdamantWand; +import com.hmdzl.spspd.items.AdamantWeapon; +import com.hmdzl.spspd.items.food.completefood.PetFood; +import com.hmdzl.spspd.items.misc.SkillOfAtk; +import com.hmdzl.spspd.items.misc.SkillOfDef; +import com.hmdzl.spspd.items.misc.SkillOfMig; +import com.hmdzl.spspd.items.quest.DarkGold; + + +import com.hmdzl.spspd.items.artifacts.TimekeepersHourglass; +import com.hmdzl.spspd.items.scrolls.ScrollOfUpgrade; +import com.hmdzl.spspd.items.scrolls.ScrollOfMagicalInfusion; +import com.hmdzl.spspd.items.scrolls.ScrollOfRegrowth; +import com.hmdzl.spspd.items.wands.WandOfFlock; +import com.hmdzl.spspd.items.weapon.guns.ToyGun; +import com.hmdzl.spspd.items.weapon.melee.special.Brick; +import com.hmdzl.spspd.items.weapon.melee.special.FireCracker; +import com.hmdzl.spspd.items.weapon.melee.special.HookHam; +import com.hmdzl.spspd.items.weapon.melee.special.KeyWeapon; +import com.hmdzl.spspd.items.weapon.melee.special.Lollipop; +import com.hmdzl.spspd.items.weapon.melee.special.Pumpkin; +import com.hmdzl.spspd.items.weapon.melee.special.RunicBlade; +import com.hmdzl.spspd.items.weapon.melee.special.SJRBMusic; +import com.hmdzl.spspd.items.weapon.melee.special.TestWeapon; +import com.hmdzl.spspd.items.weapon.melee.special.Tree; +import com.hmdzl.spspd.items.weapon.missiles.MiniMoai; +import com.hmdzl.spspd.items.weapon.missiles.MoneyPack; +import com.hmdzl.spspd.items.weapon.missiles.PocketBall; +import com.hmdzl.spspd.levels.features.Chasm; +import com.hmdzl.spspd.levels.features.Door; +import com.hmdzl.spspd.levels.features.HighGrass; +import com.hmdzl.spspd.levels.painters.Painter; +import com.hmdzl.spspd.levels.traps.ChangeSheepTrap; +import com.hmdzl.spspd.levels.traps.FleecingTrap; +import com.hmdzl.spspd.levels.traps.SokobanPortalTrap; +import com.hmdzl.spspd.levels.traps.ToxicTrap; +import com.hmdzl.spspd.levels.traps.Trap; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.plants.Phaseshift; +import com.hmdzl.spspd.plants.Plant; +import com.hmdzl.spspd.plants.Starflower; +import com.hmdzl.spspd.scenes.GameScene; +import com.watabou.noosa.Camera; +import com.watabou.noosa.Group; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Bundlable; +import com.watabou.utils.Bundle; +import com.watabou.utils.PathFinder; +import com.watabou.utils.Random; +import com.watabou.utils.Rect; + +import java.util.Collection; +import java.util.HashSet; + +public class PotLevel extends Level { + + + { + color1 = 0x534f3e; + color2 = 0xb9d661; + WIDTH = 48; + HEIGHT = 48; + LENGTH = HEIGHT*WIDTH; + } + + + public HashSet heapstogen; + public int[] heapgenspots; + public int[] teleportspots; + public int[] portswitchspots; + public int[] teleportassign; + public int[] destinationspots; + public int[] destinationassign; + public int prizeNo; + + private static final String HEAPSTOGEN = "heapstogen"; + private static final String HEAPGENSPOTS = "heapgenspots"; + private static final String TELEPORTSPOTS = "teleportspots"; + private static final String PORTSWITCHSPOTS = "portswitchspots"; + private static final String DESTINATIONSPOTS = "destinationspots"; + private static final String TELEPORTASSIGN = "teleportassign"; + private static final String DESTINATIONASSIGN= "destinationassign"; + private static final String PRIZENO = "prizeNo"; + + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(HEAPSTOGEN, heapstogen); + bundle.put(HEAPGENSPOTS, heapgenspots); + bundle.put(TELEPORTSPOTS, teleportspots); + bundle.put(PORTSWITCHSPOTS, portswitchspots); + bundle.put(DESTINATIONSPOTS, destinationspots); + bundle.put(DESTINATIONASSIGN, destinationassign); + bundle.put(TELEPORTASSIGN, teleportassign); + bundle.put(PRIZENO, prizeNo); + } + + + + @Override + public void restoreFromBundle(Bundle bundle) { + + super.restoreFromBundle(bundle); + + heapgenspots = bundle.getIntArray(HEAPGENSPOTS); + teleportspots = bundle.getIntArray(TELEPORTSPOTS); + portswitchspots = bundle.getIntArray(PORTSWITCHSPOTS); + destinationspots = bundle.getIntArray(DESTINATIONSPOTS); + destinationassign = bundle.getIntArray(DESTINATIONASSIGN); + teleportassign = bundle.getIntArray(TELEPORTASSIGN); + prizeNo = bundle.getInt(PRIZENO); + + heapstogen = new HashSet(); + + Collection collectionheap = bundle.getCollection(HEAPSTOGEN); + for (Bundlable i : collectionheap) { + Item item = (Item) i; + if (item != null) { + heapstogen.add(item); + } + } + } + + @Override + public void create() { + heapstogen = new HashSet(); + heapgenspots = new int[10]; + teleportspots = new int[10]; + portswitchspots = new int[10]; + destinationspots = new int[10]; + destinationassign = new int[10]; + teleportassign = new int[10]; + super.create(); + } + + public void addItemToGen(Item item, int arraypos, int pos) { + if (item != null) { + heapstogen.add(item); + heapgenspots[arraypos]=pos; + } + } + + + public Item genPrizeItem() { + return genPrizeItem(null); + } + + + public Item genPrizeItem(Class match) { + + boolean keysLeft = false; + + if (heapstogen.size() == 0) + return null; + + for (Item item : heapstogen) { + if (match.isInstance(item)) { + heapstogen.remove(item); + keysLeft=true; + return item; + } + } + + if (match == null || !keysLeft) { + Item item = Random.element(heapstogen); + heapstogen.remove(item); + return item; + } + + return null; + } + + @Override + public void press(int cell, Char ch) { + + if (pit[cell] && ch == Dungeon.hero) { + Chasm.heroFall(cell); + return; + } + + TimekeepersHourglass.timeFreeze timeFreeze = null; + + if (ch != null) + timeFreeze = ch.buff(TimekeepersHourglass.timeFreeze.class); + + boolean trap = false; + + switch (map[cell]) { + + case Terrain.FLEECING_TRAP: + + if (ch != null && ch==Dungeon.hero){ + trap = true; + FleecingTrap.trigger(cell, ch); + } + break; + + case Terrain.CHANGE_SHEEP_TRAP: + + if (ch instanceof SheepSokoban || ch instanceof SheepSokobanSwitch || ch instanceof SheepSokobanCorner || ch instanceof Sheep || ch instanceof WandOfFlock.MagicSheep){ + trap = true; + ChangeSheepTrap.trigger(cell, ch); + } + break; + + case Terrain.PORT_WELL: + + if (ch != null && ch==Dungeon.hero){ + + int portarray=-1; + int destinationspot=cell; + + for(int i = 0; i < teleportspots.length; i++) { + if(teleportspots[i] == cell) { + portarray = i; + break; + } + } + + if(portarray != -1) { + destinationspot=destinationspots[portarray]; + if (destinationspot>0){ + SokobanPortalTrap.trigger(cell, ch, destinationspot); + } + } + } + break; + + case Terrain.HIGH_GRASS: + HighGrass.trample(this, cell, ch); + break; + + case Terrain.WELL: + WellWater.affectCell(cell); + break; + + /*case Terrain.ALCHEMY: + if (ch == null) { + Alchemy.transmute(cell); + } + break;*/ + + case Terrain.DOOR: + Door.enter(cell); + break; + } + + if (trap){ + + if (Dungeon.visible[cell]) + Sample.INSTANCE.play(Assets.SND_TRAP); + + if (ch == Dungeon.hero) + Dungeon.hero.interrupt(); + + set(cell, Terrain.INACTIVE_TRAP); + GameScene.updateMap(cell); + } + + Plant plant = plants.get(cell); + if (plant != null) { + plant.activate(ch); + } + } + + @Override + public String tilesTex() { + return Assets.TILES_PUZZLE; + } + + @Override + public String waterTex() { + return Assets.WATER_PRISON; + } + + @Override + protected boolean build() { + + map = SaveRoomLayouts.SAFE_ROOM_DEFAULT.clone(); + + decorate(); + + buildFlagMaps(); + cleanWalls(); + + entrance = 23 + WIDTH * 15; + exit = 0 + WIDTH * 47; + + + return true; + } + @Override + protected void decorate() { + //do nothing, all decorations are hard-coded. + } + + @Override + protected void createMobs() { + int nMobs = nMobs(); + for (int i = 0; i < nMobs; i++) { + Mob mob = Bestiary.mob(Dungeon.depth); + do { + mob.pos = randomRespawnCellMob(); + } while (mob.pos == -1); + mobs.add(mob); + Actor.occupyCell(mob); + } + } + + @Override + public String tileName( int tile ) { + switch (tile) { + case Terrain.WATER: + return Messages.get(PrisonLevel.class, "water_name"); + default: + return super.tileName( tile ); + } + } + + @Override + public String tileDesc(int tile) { + switch (tile) { + case Terrain.EMPTY_DECO: + return Messages.get(PrisonLevel.class, "empty_deco_desc"); + case Terrain.BOOKSHELF: + return Messages.get(PrisonLevel.class, "bookshelf_desc"); + default: + return super.tileDesc( tile ); + } + } + + + + @Override + protected void createItems() { + + } + + @Override + public int randomRespawnCell() { + return -1; + } + +} diff --git a/java/com/hmdzl/spspd/levels/PrisonBossLevel.java b/java/com/hmdzl/spspd/levels/PrisonBossLevel.java new file mode 100644 index 00000000..ac5c28b3 --- /dev/null +++ b/java/com/hmdzl/spspd/levels/PrisonBossLevel.java @@ -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 + */ +package com.hmdzl.spspd.levels; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.mobs.Bestiary; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.GameScene; +import com.watabou.noosa.Scene; +import com.watabou.utils.Bundle; + +import static com.hmdzl.spspd.Dungeon.hero; + +public class PrisonBossLevel extends Level { + + { + color1 = 0x6a723d; + color2 = 0x88924c; + } + + //private Room anteroom; + //private int arenaDoor; + + private int stairs = -1; + private boolean enteredArena = false; + + + @Override + public String tilesTex() { + return Assets.TILES_PRISON; + } + + @Override + public String waterTex() { + return Assets.WATER_PRISON; + } + + //private static final String ARENA = "arena"; + //private static final String STAIRS = "stairs"; + //private static final String DOOR = "door"; + private static final String ENTERED = "entered"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + //bundle.put(DOOR, arenaDoor); + //bundle.put( STAIRS, stairs ); + bundle.put(ENTERED, enteredArena); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + //arenaDoor = bundle.getInt(DOOR); + //stairs = bundle.getInt( STAIRS ); + enteredArena = bundle.getBoolean(ENTERED); + } + + @Override + protected boolean build() { + map = MAP_START.clone(); + decorate(); + + buildFlagMaps(); + cleanWalls(); + + entrance = 23 + WIDTH * 15; + exit = 23 + WIDTH * 37; + + + return true; + + } + + @Override + protected void decorate() { + //do nothing, all decorations are hard-coded. + } + + @Override + protected void createMobs() { + } + + @Override + public Actor respawner() { + return null; + } + + @Override + protected void createItems() { + } + + @Override + public void press(int cell, Char ch) { + + super.press(cell, ch); + + if (!enteredArena && hero == Dungeon.hero && cell != entrance) { + + enteredArena = true; + seal(); + + Mob boss = Bestiary.mob(Dungeon.depth); + boss.state = boss.HUNTING; + boss.pos = 23 + WIDTH * 21; + GameScene.add(boss); + boss.notice(); + + GameScene.updateMap(); + Dungeon.observe(); + + + } + } + + @Override + public int randomRespawnCell() { + return -1; + } + + public void seal() { + if (entrance != 0) { + + locked = true; + + set(entrance, Terrain.WALL_DECO); + GameScene.updateMap(entrance); + GameScene.ripple(entrance); + + } + } + + public void unseal() { + if (stairs != 0) { + + locked = false; + + set(entrance, Terrain.ENTRANCE); + GameScene.updateMap(entrance); + + } + } + + @Override + public String tileName(int tile) { + switch (tile) { + case Terrain.WATER: + return Messages.get(PrisonLevel.class, "water_name"); + default: + return super.tileName(tile); + } + } + + @Override + public String tileDesc(int tile) { + switch (tile) { + case Terrain.EMPTY_DECO: + return Messages.get(PrisonLevel.class, "empty_deco_desc"); + case Terrain.BOOKSHELF: + return Messages.get(PrisonLevel.class, "bookshelf_desc"); + default: + return super.tileDesc(tile); + } + } + + @Override + public void addVisuals(Scene scene) { + PrisonLevel.addVisuals(this, scene); + } + + private static final int W = Terrain.WALL; + private static final int D = Terrain.DOOR; + private static final int I = Terrain.HIGH_GRASS; + private static final int O = Terrain.EMPTY; //for readability + private static final int S = Terrain.SIGN; + private static final int A = Terrain.WATER; + + private static final int T = Terrain.INACTIVE_TRAP; + + private static final int E = Terrain.ENTRANCE; + private static final int X = Terrain.LOCKED_EXIT; + + private static final int M = Terrain.WALL_DECO; + private static final int P = Terrain.PEDESTAL; + + private static final int[] MAP_START = + { + M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, + M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, + M, M, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, M, M, + M, M, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, M, M, + M, M, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, M, M, + M, M, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, M, M, + M, M, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, M, M, + M, M, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, M, M, + M, M, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, M, M, + M, M, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, M, M, + M, M, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, M, M, + M, M, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, M, M, + M, M, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, M, M, + M, M, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, O, O, O, O, O, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, M, M, + M, M, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, O, I, O, W, O, S, O, T, O, W, O, O, I, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, M, M, + M, M, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, O, W, T, D, O, O, E, O, O, D, O, W, O, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, M, M, + M, M, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, O, I, O, W, O, I, O, A, O, W, T, O, O, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, M, M, + M, M, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, D, W, W, W, O, O, O, O, O, W, W, W, D, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, M, M, + M, M, W, W, W, W, W, W, W, W, W, W, W, W, W, O, O, A, O, W, W, W, W, D, W, W, W, W, O, O, A, A, W, W, W, W, W, W, W, W, W, W, W, W, W, W, M, M, + M, M, W, W, W, W, W, W, W, W, W, W, W, W, W, O, W, W, O, W, O, I, O, O, O, I, O, W, W, O, A, A, W, W, W, W, W, W, W, W, W, W, W, W, W, W, M, M, + M, M, W, W, W, W, W, W, W, W, W, W, W, W, W, O, I, A, O, W, O, W, W, T, W, W, O, W, O, O, O, O, W, W, W, W, W, W, W, W, W, W, W, W, W, W, M, M, + M, M, W, W, W, W, W, W, W, W, W, W, W, W, W, T, O, A, O, D, O, O, T, P, T, O, O, D, T, O, W, O, W, W, W, W, W, W, W, W, W, W, W, W, W, W, M, M, + M, M, W, W, W, W, W, W, W, W, W, W, W, W, W, O, W, W, O, W, O, O, T, O, T, O, O, W, T, O, O, O, W, W, W, W, W, W, W, W, W, W, W, W, W, W, M, M, + M, M, W, W, W, W, W, W, W, W, W, W, W, W, W, O, O, A, O, W, O, W, W, T, W, W, O, W, O, W, O, O, W, W, W, W, W, W, W, W, W, W, W, W, W, W, M, M, + M, M, W, W, W, W, W, W, W, W, W, W, W, W, W, O, O, A, O, W, O, I, O, O, O, I, O, W, O, O, O, O, W, W, W, W, W, W, W, W, W, W, W, W, W, W, M, M, + M, M, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, D, W, W, D, W, W, D, W, W, D, W, W, D, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, M, M, + M, M, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, O, O, W, O, W, O, A, O, W, O, O, O, O, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, M, M, + M, M, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, O, A, W, O, W, A, W, A, W, W, W, O, O, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, M, M, + M, M, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, T, O, O, T, D, O, A, O, D, O, O, O, O, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, M, M, + M, M, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, O, W, O, O, W, O, W, O, W, O, O, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, M, M, + M, M, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, O, W, O, O, W, O, O, O, W, O, A, O, O, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, M, M, + M, M, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, D, W, W, W, W, W, D, W, W, W, W, W, D, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, M, M, + M, M, W, W, W, W, W, W, W, W, W, W, W, W, W, O, W, O, O, W, O, W, W, O, W, W, O, W, T, W, T, O, W, W, W, W, W, W, W, W, W, W, W, W, W, W, M, M, + M, M, W, W, W, W, W, W, W, W, W, W, W, W, W, O, T, O, O, O, T, W, W, O, W, W, O, W, T, W, T, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, M, M, + M, M, W, W, W, W, W, W, W, W, W, W, W, W, W, O, W, W, W, W, O, D, O, O, O, D, O, W, O, W, O, O, W, W, W, W, W, W, W, W, W, W, W, W, W, W, M, M, + M, M, W, W, W, W, W, W, W, W, W, W, W, W, W, O, W, O, O, W, O, W, W, O, W, W, O, W, O, W, A, O, W, W, W, W, W, W, W, W, W, W, W, W, W, W, M, M, + M, M, W, W, W, W, W, W, W, W, W, W, W, W, W, O, W, A, W, W, O, W, T, T, T, W, T, O, A, W, W, O, W, W, W, W, W, W, W, W, W, W, W, W, W, W, M, M, + M, M, W, W, W, W, W, W, W, W, W, W, W, W, W, O, I, I, I, O, O, W, T, X, T, W, O, O, W, O, O, O, W, W, W, W, W, W, W, W, W, W, W, W, W, W, M, M, + M, M, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, T, T, T, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, M, M, + M, M, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, M, M, + M, M, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, M, M, + M, M, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, M, M, + M, M, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, M, M, + M, M, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, M, M, + M, M, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, M, M, + M, M, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, M, M, + M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, + M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M + }; +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/levels/PrisonBossLevel2.java b/java/com/hmdzl/spspd/levels/PrisonBossLevel2.java new file mode 100644 index 00000000..705303cc --- /dev/null +++ b/java/com/hmdzl/spspd/levels/PrisonBossLevel2.java @@ -0,0 +1,380 @@ +/* + * 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 + */ +package com.hmdzl.spspd.levels; + +import java.util.List; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.mobs.Bestiary; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.items.Heap; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.keys.IronKey; +import com.hmdzl.spspd.items.keys.SkeletonKey; +import com.hmdzl.spspd.levels.Room.Type; +import com.hmdzl.spspd.levels.painters.Painter; +import com.hmdzl.spspd.levels.traps.SpearTrap; +import com.hmdzl.spspd.levels.traps.Trap; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.GameScene; +import com.watabou.noosa.Scene; +import com.watabou.utils.Bundle; +import com.watabou.utils.Graph; +import com.watabou.utils.Point; +import com.watabou.utils.Random; + +public class PrisonBossLevel2 extends RegularLevel { + + { + color1 = 0x6a723d; + color2 = 0x88924c; + } + + private Room anteroom; + private int arenaDoor; + + private boolean enteredArena = false; + private boolean keyDropped = false; + + @Override + public String tilesTex() { + return Assets.TILES_PRISON; + } + + @Override + public String waterTex() { + return Assets.WATER_PRISON; + } + + private static final String ARENA = "arena"; + private static final String DOOR = "door"; + private static final String ENTERED = "entered"; + private static final String DROPPED = "droppped"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(ARENA, roomExit); + bundle.put(DOOR, arenaDoor); + bundle.put(ENTERED, enteredArena); + bundle.put(DROPPED, keyDropped); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + roomExit = (Room) bundle.get(ARENA); + arenaDoor = bundle.getInt(DOOR); + enteredArena = bundle.getBoolean(ENTERED); + keyDropped = bundle.getBoolean(DROPPED); + } + + @Override + protected boolean build() { + + initRooms(); + + int distance; + int retry = 0; + + do { + + if (retry++ > 10) { + return false; + } + + int innerRetry = 0; + do { + if (innerRetry++ > 10) { + return false; + } + roomEntrance = Random.element(rooms); + } while (roomEntrance.width() < 4 || roomEntrance.height() < 4); + + innerRetry = 0; + do { + if (innerRetry++ > 10) { + return false; + } + roomExit = Random.element(rooms); + } while (roomExit == roomEntrance || roomExit.width() < 7 + || roomExit.height() < 7 || roomExit.top == 0); + + Graph.buildDistanceMap(rooms, roomExit); + distance = Graph.buildPath(rooms, roomEntrance, roomExit).size(); + + } while (distance < 3); + + roomEntrance.type = Type.ENTRANCE; + roomExit.type = Type.BOSS_EXIT; + + List path = Graph.buildPath(rooms, roomEntrance, roomExit); + Graph.setPrice(path, roomEntrance.distance); + + Graph.buildDistanceMap(rooms, roomExit); + path = Graph.buildPath(rooms, roomEntrance, roomExit); + + anteroom = path.get(path.size() - 2); + anteroom.type = Type.STANDARD; + + Room room = roomEntrance; + for (Room next : path) { + room.connect(next); + room = next; + } + + for (Room r : rooms) { + if (r.type == Type.NULL && r.connected.size() > 0) { + r.type = Type.PASSAGE; + } + } + + paint(); + + Room r = (Room) roomExit.connected.keySet().toArray()[0]; + if (roomExit.connected.get(r).y == roomExit.top) { + return false; + } + + paintWater(); + paintGrass(); + + placeTraps(); + + return true; + } + + @Override + protected boolean[] water() { + return Patch.generate(0.45f, 5); + } + + @Override + protected boolean[] grass() { + return Patch.generate(0.30f, 4); + } + + @Override + protected void paintDoors(Room r) { + + for (Room n : r.connected.keySet()) { + + if (r.type == Type.NULL) { + continue; + } + + Point door = r.connected.get(n); + + if (r.type == Room.Type.PASSAGE && n.type == Room.Type.PASSAGE) { + + Painter.set(this, door, Terrain.EMPTY); + + } else { + + Painter.set(this, door, Terrain.DOOR); + + } + + } + } + + @Override + protected void placeTraps() { + + int nTraps = nTraps(); + + for (int i = 0; i < nTraps; i++) { + + int trapPos = Random.Int(getLength()); + + if (map[trapPos] == Terrain.EMPTY) { + map[trapPos] = Terrain.INACTIVE_TRAP; + Trap t = new SpearTrap().reveal(); + t.active = false; + setTrap(t, trapPos); + } + } + } + + @Override + protected void decorate() { + + for (int i = getWidth() + 1; i < getLength() - getWidth() - 1; i++) { + if (map[i] == Terrain.EMPTY) { + + float c = 0.15f; + if (map[i + 1] == Terrain.WALL + && map[i + getWidth()] == Terrain.WALL) { + c += 0.2f; + } + if (map[i - 1] == Terrain.WALL + && map[i + getWidth()] == Terrain.WALL) { + c += 0.2f; + } + if (map[i + 1] == Terrain.WALL + && map[i - getWidth()] == Terrain.WALL) { + c += 0.2f; + } + if (map[i - 1] == Terrain.WALL + && map[i - getWidth()] == Terrain.WALL) { + c += 0.2f; + } + + if (Random.Float() < c) { + map[i] = Terrain.EMPTY_DECO; + } + } + } + + for (int i = 0; i < getWidth(); i++) { + if (map[i] == Terrain.WALL + && (map[i + getWidth()] == Terrain.EMPTY || map[i + getWidth()] == Terrain.EMPTY_SP) + && Random.Int(4) == 0) { + + map[i] = Terrain.WALL_DECO; + } + } + + for (int i = getWidth(); i < getLength() - getWidth(); i++) { + if (map[i] == Terrain.WALL + && map[i - getWidth()] == Terrain.WALL + && (map[i + getWidth()] == Terrain.EMPTY || map[i + getWidth()] == Terrain.EMPTY_SP) + && Random.Int(2) == 0) { + + map[i] = Terrain.WALL_DECO; + } + } + + while (true) { + int pos = roomEntrance.random(); + if (pos != entrance) { + map[pos] = Terrain.SIGN; + break; + } + } + + Point door = roomExit.entrance(); + arenaDoor = door.x + door.y * getWidth(); + Painter.set(this, arenaDoor, Terrain.LOCKED_DOOR); + + Painter.fill(this, roomExit.left + 2, roomExit.top + 2, + roomExit.width() - 3, roomExit.height() - 3, + Terrain.INACTIVE_TRAP); + } + + @Override + protected void createMobs() { + } + + @Override + public Actor respawner() { + return null; + } + + @Override + protected void createItems() { + + int keyPos = anteroom.random(); + while (!passable[keyPos]) { + keyPos = anteroom.random(); + } + drop(new IronKey(Dungeon.depth), keyPos).type = Heap.Type.CHEST; + + } + + @Override + public void press(int cell, Char ch) { + + super.press(cell, ch); + + if (ch == Dungeon.hero && !enteredArena && roomExit.inside(cell)) { + + enteredArena = true; + locked = true; + + int pos; + do { + pos = roomExit.random(); + } while (pos == cell || Actor.findChar(pos) != null); + + Mob boss = Bestiary.mob(Dungeon.depth); + boss.state = boss.HUNTING; + boss.pos = pos; + GameScene.add(boss); + boss.notice(); + + mobPress(boss); + + set(arenaDoor, Terrain.LOCKED_DOOR); + GameScene.updateMap(arenaDoor); + Dungeon.observe(); + + } + } + + @Override + public Heap drop(Item item, int cell) { + + if (!keyDropped && item instanceof SkeletonKey) { + + keyDropped = true; + locked = false; + + set(arenaDoor, Terrain.DOOR); + GameScene.updateMap(arenaDoor); + Dungeon.observe(); + } + + return super.drop(item, cell); + } + + @Override + public int randomRespawnCell() { + return -1; + } + + @Override + public String tileName( int tile ) { + switch (tile) { + case Terrain.WATER: + return Messages.get(PrisonLevel.class, "water_name"); + default: + return super.tileName( tile ); + } + } + + @Override + public String tileDesc(int tile) { + switch (tile) { + case Terrain.EMPTY_DECO: + return Messages.get(PrisonLevel.class, "empty_deco_desc"); + case Terrain.BOOKSHELF: + return Messages.get(PrisonLevel.class, "bookshelf_desc"); + default: + return super.tileDesc( tile ); + } + } + + @Override + public void addVisuals(Scene scene) { + PrisonLevel.addVisuals(this, scene); + } +} diff --git a/java/com/hmdzl/spspd/levels/PrisonLevel.java b/java/com/hmdzl/spspd/levels/PrisonLevel.java new file mode 100644 index 00000000..740a5c7f --- /dev/null +++ b/java/com/hmdzl/spspd/levels/PrisonLevel.java @@ -0,0 +1,242 @@ +/* + * 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 + */ +package com.hmdzl.spspd.levels; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.DungeonTilemap; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.hero.HeroClass; +import com.hmdzl.spspd.actors.mobs.MossySkeleton; +import com.hmdzl.spspd.actors.mobs.npcs.Wandmaker; +import com.hmdzl.spspd.effects.Halo; +import com.hmdzl.spspd.effects.particles.FlameParticle; +import com.hmdzl.spspd.items.bombs.DungeonBomb; +import com.hmdzl.spspd.levels.Room.Type; +import com.hmdzl.spspd.levels.traps.*; +import com.hmdzl.spspd.messages.Messages; +import com.watabou.noosa.Scene; +import com.watabou.noosa.particles.Emitter; +import com.watabou.utils.PointF; +import com.watabou.utils.Random; + +public class PrisonLevel extends RegularLevel { + + { + color1 = 0x6a723d; + color2 = 0x88924c; + } + + @Override + public String tilesTex() { + return Assets.TILES_PRISON; + } + + @Override + public String waterTex() { + return Assets.WATER_PRISON; + } + + @Override + protected boolean[] water() { + return Patch.generate(feeling == Feeling.WATER ? 0.65f : 0.45f, 4); + } + + @Override + protected boolean[] grass() { + return Patch.generate(feeling == Feeling.GRASS ? 0.60f : 0.40f, 3); + } + + @Override + protected Class[] trapClasses() { + return new Class[]{ ChillingTrap.class, FireTrap.class, PoisonTrap.class, SpearTrap.class, ToxicTrap.class, ShockTrap.class, + AlarmTrap.class, FlashingTrap.class, GrippingTrap.class, ParalyticTrap.class, LightningTrap.class, OozeTrap.class, + ConfusionTrap.class, FlockTrap.class, SummoningTrap.class, TeleportationTrap.class, }; + } + + @Override + protected float[] trapChances() { + return new float[]{ 4, 4, 4, 4, 4, + 2, 2, 2, 2, 2, 2, + 1, 1, 1, 1 }; + } + + @Override + protected boolean assignRoomType() { + super.assignRoomType(); + + for (Room r : rooms) { + if (r.type == Type.TUNNEL) { + r.type = Type.PASSAGE; + } + } + + return true; + } + + @Override + protected void setPar(){ + Dungeon.pars[Dungeon.depth] = 500+(Dungeon.depth*50)+(secretDoors*20); + } + + @Override + protected void createItems() { + if (Dungeon.hero.heroClass==HeroClass.PERFORMER && Random.Int(1) == 0){addItemToSpawn(new DungeonBomb());} + + super.createItems(); + + Wandmaker.Quest.spawn(this, roomEntrance); + spawnSkeleton(this); + } + + public static void spawnSkeleton(PrisonLevel level) { + if (Dungeon.depth == 9 && !Dungeon.skeletonspawned){ + + MossySkeleton skeleton = new MossySkeleton(); + do { + skeleton.pos = level.randomRespawnCell(); + } while (skeleton.pos == -1); + level.mobs.add(skeleton); + Actor.occupyCell(skeleton); + + Dungeon.skeletonspawned = true; + } + } + + + @Override + protected void decorate() { + + for (int i = getWidth() + 1; i < getLength() - getWidth() - 1; i++) { + if (map[i] == Terrain.EMPTY) { + + float c = 0.05f; + if (map[i + 1] == Terrain.WALL + && map[i + getWidth()] == Terrain.WALL) { + c += 0.2f; + } + if (map[i - 1] == Terrain.WALL + && map[i + getWidth()] == Terrain.WALL) { + c += 0.2f; + } + if (map[i + 1] == Terrain.WALL + && map[i - getWidth()] == Terrain.WALL) { + c += 0.2f; + } + if (map[i - 1] == Terrain.WALL + && map[i - getWidth()] == Terrain.WALL) { + c += 0.2f; + } + + if (Random.Float() < c) { + map[i] = Terrain.EMPTY_DECO; + } + } + } + + for (int i = 0; i < getWidth(); i++) { + if (map[i] == Terrain.WALL + && (map[i + getWidth()] == Terrain.EMPTY || map[i + getWidth()] == Terrain.EMPTY_SP) + && Random.Int(6) == 0) { + + map[i] = Terrain.WALL_DECO; + } + } + + for (int i = getWidth(); i < getLength() - getWidth(); i++) { + if (map[i] == Terrain.WALL + && map[i - getWidth()] == Terrain.WALL + && (map[i + getWidth()] == Terrain.EMPTY || map[i + getWidth()] == Terrain.EMPTY_SP) + && Random.Int(3) == 0) { + + map[i] = Terrain.WALL_DECO; + } + } + + while (true) { + int pos = roomEntrance.random(); + if (pos != entrance) { + map[pos] = Terrain.SIGN; + break; + } + } + + setPar(); + } + + @Override + public String tileName( int tile ) { + switch (tile) { + case Terrain.WATER: + return Messages.get(PrisonLevel.class, "water_name"); + default: + return super.tileName( tile ); + } + } + + @Override + public String tileDesc(int tile) { + switch (tile) { + case Terrain.EMPTY_DECO: + return Messages.get(PrisonLevel.class, "empty_deco_desc"); + case Terrain.BOOKSHELF: + return Messages.get(PrisonLevel.class, "bookshelf_desc"); + default: + return super.tileDesc( tile ); + } + } + + @Override + public void addVisuals(Scene scene) { + super.addVisuals(scene); + addVisuals(this, scene); + } + + public static void addVisuals(Level level, Scene scene) { + for (int i = 0; i < getLength(); i++) { + if (level.map[i] == Terrain.WALL_DECO) { + scene.add(new Torch(i)); + } + } + } + + private static class Torch extends Emitter { + + private int pos; + + public Torch(int pos) { + super(); + + this.pos = pos; + + PointF p = DungeonTilemap.tileCenterToWorld(pos); + pos(p.x - 1, p.y + 3, 2, 0); + + pour(FlameParticle.FACTORY, 0.15f); + + add(new Halo(16, 0xFFFFCC, 0.2f).point(p.x, p.y)); + } + + @Override + public void update() { + if (visible = Dungeon.visible[pos]) { + super.update(); + } + } + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/levels/RegularLevel.java b/java/com/hmdzl/spspd/levels/RegularLevel.java new file mode 100644 index 00000000..117c0ba6 --- /dev/null +++ b/java/com/hmdzl/spspd/levels/RegularLevel.java @@ -0,0 +1,779 @@ +/* + * 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 + */ +package com.hmdzl.spspd.levels; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.Statistics; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.buffs.AflyBless; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.hero.HeroClass; +import com.hmdzl.spspd.actors.mobs.Bestiary; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.items.Heap; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.misc.LuckyBadge; +import com.hmdzl.spspd.items.scrolls.Scroll; +import com.hmdzl.spspd.levels.Room.Type; +import com.hmdzl.spspd.levels.painters.Painter; +import com.hmdzl.spspd.levels.painters.ShopPainter; +import com.hmdzl.spspd.levels.traps.*; +import com.watabou.utils.Bundle; +import com.watabou.utils.Graph; +import com.watabou.utils.Random; +import com.watabou.utils.Rect; + +public abstract class RegularLevel extends Level { + + protected HashSet rooms; + + protected Room roomEntrance; + protected Room roomExit; + + protected ArrayList specials; + protected ArrayList secrets; + protected ArrayList specialsf; + protected ArrayList specialsc; + + public int secretDoors; + + @Override + protected boolean build() { + + if (!initRooms()) { + return false; + } + + int distance; + int retry = 0; + int minDistance = (int) Math.sqrt(rooms.size()); + do { + do { + roomEntrance = Random.element(rooms); + } while (roomEntrance.width() < 4 || roomEntrance.height() < 4); + + do { + roomExit = Random.element(rooms); + } while (roomExit == roomEntrance || roomExit.width() < 4 + || roomExit.height() < 4); + + Graph.buildDistanceMap(rooms, roomExit); + distance = roomEntrance.distance(); + + if (retry++ > 10) { + return false; + } + + } while (distance < minDistance); + + roomEntrance.type = Type.ENTRANCE; + roomExit.type = Type.EXIT; + + HashSet connected = new HashSet(); + connected.add(roomEntrance); + + Graph.buildDistanceMap(rooms, roomExit); + List path = Graph.buildPath(rooms, roomEntrance, roomExit); + + Room room = roomEntrance; + for (Room next : path) { + room.connect(next); + room = next; + connected.add(room); + } + + Graph.setPrice(path, roomEntrance.distance); + + Graph.buildDistanceMap(rooms, roomExit); + path = Graph.buildPath(rooms, roomEntrance, roomExit); + + room = roomEntrance; + for (Room next : path) { + room.connect(next); + room = next; + connected.add(room); + } + + int nConnected = (int) (rooms.size() * Random.Float(0.5f, 0.7f)); + while (connected.size() < nConnected) { + + Room cr = Random.element(connected); + Room or = Random.element(cr.neigbours); + if (!connected.contains(or)) { + + cr.connect(or); + connected.add(or); + } + } + + if (Dungeon.shopOnLevel()) { + Room shop = null; + for (Room r : roomEntrance.connected.keySet()) { + if (r.connected.size() == 1 + && ((r.width() - 1) * (r.height() - 1) >= ShopPainter + .spaceNeeded())) { + shop = r; + break; + } + } + + if (shop == null) { + return false; + } else { + shop.type = Room.Type.SHOP; + } + } + + specials = new ArrayList(Room.SPECIALS); + if (Dungeon.bossLevel(Dungeon.depth + 1) || Dungeon.townCheck(Dungeon.depth)) { + specials.remove(Room.Type.WEAK_FLOOR); + } + //if (Dungeon.isChallenged(Challenges.NO_ARMOR)) { + // no sense in giving an armor reward room on a run with no armor. + //specials.remove(Room.Type.CRYPT); + //} + //if (Dungeon.isChallenged(Challenges.NO_HERBALISM)) { + // sorry warden, no lucky sungrass or blandfruit seeds for you! + //specials.remove(Room.Type.GARDEN); + //} + + if (Dungeon.depth > 21 && Dungeon.depth < 25) { + specials.remove(Room.Type.WEAK_FLOOR); + } + + if (Dungeon.depth > 50 && Dungeon.depth < 100) { + specials.remove(Room.Type.WEAK_FLOOR); + specials.remove(Room.Type.ARMORY); + specials.remove(Room.Type.CRYPT); + specials.remove(Room.Type.GARDEN); + specials.remove(Room.Type.LABORATORY); + specials.remove(Room.Type.LIBRARY); + specials.remove(Room.Type.MAGIC_WELL); + specials.remove(Room.Type.POOL); + specials.remove(Room.Type.STATUE); + specials.remove(Room.Type.STORAGE); + specials.remove(Room.Type.TRAPS); + specials.remove(Room.Type.TREASURY); + specials.remove(Room.Type.VAULT); + } + + + if (!assignRoomType()) + return false; + + paint(); + paintWater(); + paintGrass(); + + placeTraps(); + + return true; + } + + protected void placeSign(){ + while (true) { + int pos = roomEntrance.random(); + if (pos != entrance && traps.get(pos) == null && findMob(pos) == null) { + map[pos] = Terrain.SIGN; + break; + } + } + } + + protected boolean initRooms() { + + rooms = new HashSet(); + split(new Rect(0, 0, getWidth() - 1, HEIGHT - 1)); + + if (rooms.size() < 8) { + return false; + } + + Room[] ra = rooms.toArray(new Room[0]); + for (int i = 0; i < ra.length - 1; i++) { + for (int j = i + 1; j < ra.length; j++) { + ra[i].addNeigbour(ra[j]); + } + } + + return true; + } + + protected boolean assignRoomType() { + + int specialRooms = 0; + + for (Room r : rooms) { + if (r.type == Type.NULL && r.connected.size() == 1) { + + if (specials.size() > 0 && r.width() > 3 && r.height() > 3 + && Random.Int(specialRooms * specialRooms + 2) == 0) { + + if (pitRoomNeeded) { + + r.type = Type.PIT; + pitRoomNeeded = false; + + } else if (Dungeon.depth % 5 == 2 + && specials.contains(Type.LABORATORY)) { + + r.type = Type.LABORATORY; + + } else if (specials.contains(Type.MAGIC_WELL)) { + + r.type = Type.MAGIC_WELL; + + } else { + + int n = specials.size(); + r.type = specials.get(Math.min(Random.Int(n), + Random.Int(n))); + if (r.type == Type.WEAK_FLOOR) { + weakFloorCreated = true; + } + + } + + Room.useType(r.type); + specials.remove(r.type); + specialRooms++; + + } else if (Random.Int(2) == 0) { + + HashSet neigbours = new HashSet(); + for (Room n : r.neigbours) { + if (!r.connected.containsKey(n) + && !Room.SPECIALS.contains(n.type) + && n.type != Type.PIT) { + + neigbours.add(n); + } + } + if (neigbours.size() > 1) { + r.connect(Random.element(neigbours)); + } + } + } + } + + int count = 0; + for (Room r : rooms) { + if (r.type == Type.NULL) { + int connections = r.connected.size(); + if (connections == 0) { + + } else if (Random.Int(connections * connections) == 0) { + r.type = Type.STANDARD; + count++; + } else { + r.type = Type.TUNNEL; + } + } + } + + while (count < 4) { + Room r = randomRoom(Type.TUNNEL, 1); + if (r != null) { + r.type = Type.STANDARD; + count++; + } + } + + return true; + } + + protected void paintWater() { + boolean[] lake = water(); + for (int i = 0; i < getLength(); i++) { + if (map[i] == Terrain.EMPTY && lake[i]) { + map[i] = Terrain.WATER; + } + } + } + + protected void paintGrass() { + boolean[] grass = grass(); + + if (feeling == Feeling.GRASS) { + + for (Room room : rooms) { + if (room.type != Type.NULL && room.type != Type.PASSAGE + && room.type != Type.TUNNEL) { + grass[(room.left + 1) + (room.top + 1) * getWidth()] = true; + grass[(room.right - 1) + (room.top + 1) * getWidth()] = true; + grass[(room.left + 1) + (room.bottom - 1) * getWidth()] = true; + grass[(room.right - 1) + (room.bottom - 1) * getWidth()] = true; + } + } + } + + for (int i = getWidth() + 1; i < getLength() - getWidth() - 1; i++) { + if (map[i] == Terrain.EMPTY && grass[i]) { + int count = 1; + for (int n : NEIGHBOURS8) { + if (grass[i + n]) { + count++; + } + } + map[i] = (Random.Float() < count / 12f) ? Terrain.HIGH_GRASS + : Terrain.GRASS; + } + } + } + + protected abstract boolean[] water(); + + protected abstract boolean[] grass(); + + protected void placeTraps() { + + int nTraps = nTraps(); + float[] trapChances = trapChances(); + Class[] trapClasses = trapClasses(); + + LinkedList validCells = new LinkedList(); + + for (int i = 0; i < LENGTH; i ++) { + if (map[i] == Terrain.EMPTY){ + + if(Dungeon.depth == 1){ + //extra check to prevent annoying inactive traps in hallways on floor 1 + Room r = room(i); + if (r != null && r.type != Type.TUNNEL){ + validCells.add(i); + } + } else + validCells.add(i); + } + } + + //no more than one trap every 5 valid tiles. + nTraps = Math.min(nTraps, validCells.size()/5); + + Collections.shuffle(validCells); + + for (int i = 0; i < nTraps; i++) { + + int trapPos = validCells.removeFirst(); + + try { + Trap trap = ((Trap)trapClasses[Random.chances( trapChances )].newInstance()).hide(); + setTrap( trap, trapPos ); + //some traps will not be hidden + map[trapPos] = trap.visible ? Terrain.TRAP : Terrain.SECRET_TRAP; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + } + + protected int nTraps() { + return Random.NormalIntRange( 1, 4+(Dungeon.depth/2) ); + } + + protected Class[] trapClasses(){ + return new Class[]{WornTrap.class}; + } + + protected float[] trapChances() { + return new float[]{1}; + } + + protected int minRoomSize = 7; + protected int maxRoomSize = 9; + + protected void split(Rect rect) { + + int w = rect.width(); + int h = rect.height(); + + if (w > maxRoomSize && h < minRoomSize) { + + int vw = Random.Int(rect.left + 3, rect.right - 3); + split(new Rect(rect.left, rect.top, vw, rect.bottom)); + split(new Rect(vw, rect.top, rect.right, rect.bottom)); + + } else if (h > maxRoomSize && w < minRoomSize) { + + int vh = Random.Int(rect.top + 3, rect.bottom - 3); + split(new Rect(rect.left, rect.top, rect.right, vh)); + split(new Rect(rect.left, vh, rect.right, rect.bottom)); + + } else if ((Math.random() <= (minRoomSize * minRoomSize / rect.square()) + && w <= maxRoomSize && h <= maxRoomSize) + || w < minRoomSize || h < minRoomSize) { + + rooms.add((Room) new Room().set(rect)); + + } else { + + if (Random.Float() < (float) (w - 2) / (w + h - 4)) { + int vw = Random.Int(rect.left + 3, rect.right - 3); + split(new Rect(rect.left, rect.top, vw, rect.bottom)); + split(new Rect(vw, rect.top, rect.right, rect.bottom)); + } else { + int vh = Random.Int(rect.top + 3, rect.bottom - 3); + split(new Rect(rect.left, rect.top, rect.right, vh)); + split(new Rect(rect.left, vh, rect.right, rect.bottom)); + } + + } + } + + protected void paint() { + + for (Room r : rooms) { + if (r.type != Type.NULL) { + placeDoors(r); + r.type.paint(this, r); + } else { + if (feeling == Feeling.CHASM && Random.Int(2) == 0) { + Painter.fill(this, r, Terrain.WALL); + } + } + } + + for (Room r : rooms) { + paintDoors(r); + } + } + + private void placeDoors(Room r) { + for (Room n : r.connected.keySet()) { + Room.Door door = r.connected.get(n); + if (door == null) { + + Rect i = r.intersect(n); + if (i.width() == 0) { + door = new Room.Door(i.left, + Random.Int(i.top + 1, i.bottom)); + } else { + door = new Room.Door(Random.Int(i.left + 1, i.right), i.top); + } + + r.connected.put(n, door); + n.connected.put(r, door); + } + } + } + + protected void paintDoors(Room r) { + for (Room n : r.connected.keySet()) { + + if (joinRooms(r, n)) { + continue; + } + + Room.Door d = r.connected.get(n); + int door = d.x + d.y * getWidth(); + + switch (d.type) { + case EMPTY: + map[door] = Terrain.EMPTY; + break; + case TUNNEL: + map[door] = tunnelTile(); + break; + case REGULAR: + if (Dungeon.depth <= 1) { + map[door] = Terrain.DOOR; + } else { + boolean secret = (Dungeon.depth < 6 ? Random + .Int(12 - Dungeon.depth) : Random.Int(6)) == 0; + map[door] = secret ? Terrain.SECRET_DOOR : Terrain.DOOR; + if (secret) { + secretDoors++; + } + } + break; + case UNLOCKED: + map[door] = Terrain.DOOR; + break; + case HIDDEN: + map[door] = Terrain.SECRET_DOOR; + break; + case BARRICADE: + map[door] = Random.Int(3) == 0 ? Terrain.BOOKSHELF + : Terrain.BARRICADE; + break; + case LOCKED: + map[door] = Terrain.LOCKED_DOOR; + break; + case ONEWAY: + map[door] = Terrain.STATUE_SSP; + break; + } + } + } + + protected boolean joinRooms(Room r, Room n) { + + if (r.type != Room.Type.STANDARD || n.type != Room.Type.STANDARD) { + return false; + } + + Rect w = r.intersect(n); + if (w.left == w.right) { + + if (w.bottom - w.top < 3) { + return false; + } + + if (w.height() == Math.max(r.height(), n.height())) { + return false; + } + + if (r.width() + n.width() > maxRoomSize) { + return false; + } + + w.top += 1; + w.bottom -= 0; + + w.right++; + + Painter.fill(this, w.left, w.top, 1, w.height(), Terrain.EMPTY); + + } else { + + if (w.right - w.left < 3) { + return false; + } + + if (w.width() == Math.max(r.width(), n.width())) { + return false; + } + + if (r.height() + n.height() > maxRoomSize) { + return false; + } + + w.left += 1; + w.right -= 0; + + w.bottom++; + + Painter.fill(this, w.left, w.top, w.width(), 1, Terrain.EMPTY); + } + + return true; + } + + protected void setPar(){ + Dungeon.pars[Dungeon.depth] = 600; + } + + @Override + public int nMobs() { + if (Dungeon.depth < 5 && !Statistics.amuletObtained){ + return 10 + Dungeon.depth + Random.Int(3); + } else if(!Statistics.amuletObtained) { + return 10 + Dungeon.depth % 3 + Random.Int(3); + } else { + return 10 + (5 - Dungeon.depth % 5) + Random.Int(3); + } + } + + @Override + protected void createMobs() { + int nMobs = nMobs(); + for (int i = 0; i < nMobs; i++) { + Mob mob = Bestiary.mob(Dungeon.depth); + do { + mob.pos = randomRespawnCell(); + mob.originalgen=true; + } while (mob.pos == -1); + mobs.add(mob); + Actor.occupyCell(mob); + } + } + + @Override + public int randomRespawnCell() { + + int count = 0; + int cell = -1; + + while (true) { + + if (++count > 30) { + return -1; + } + + Room room = randomRoom(Room.Type.STANDARD, 10); + if (room == null) { + continue; + } + + cell = room.random(); + if (!Dungeon.visible[cell] && Actor.findChar(cell) == null + && Level.passable[cell]) { + return cell; + } + + } + + } + + @Override + public int randomDestination() { + + int cell = -1; + + while (true) { + + Room room = Random.element(rooms); + if (room == null) { + continue; + } + + cell = room.random(); + if (Level.passable[cell]) { + return cell; + } + + } + } + + @Override + protected void createItems() { + + int nItems = 3; + int bonus = 0; + for (Buff buff : Dungeon.hero.buffs(LuckyBadge.GreatLucky.class)) { + bonus += ((LuckyBadge.GreatLucky) buff).level; + } + if (Dungeon.hero.heroClass == HeroClass.SOLDIER) + bonus += 5; + for (Buff buff : Dungeon.hero.buffs(AflyBless.class)) { + bonus += 5; + } + // just incase someone gets a ridiculous ring, cap this at 80% + bonus = Math.min(bonus, 10); + while (Random.Float() < (0.3f + bonus * 0.05f)) { + nItems++; + } + + for (int i = 0; i < nItems; i++) { + Heap.Type type = null; + switch (Random.Int(20)) { + case 0: + type = Heap.Type.SKELETON; + break; + case 1: + case 2: + case 3: + case 4: + type = Heap.Type.CHEST; + break; + case 5: + type = Dungeon.depth > 1 ? Heap.Type.MIMIC : Heap.Type.CHEST; + break; + default: + type = Heap.Type.HEAP; + } + drop(Generator.random(), randomDropCell()).type = type; + } + + for (Item item : itemsToSpawn) { + int cell = randomDropCell(); + if (item instanceof Scroll) { + while (map[cell] == Terrain.TRAP + || map[cell] == Terrain.SECRET_TRAP + && traps.get( cell ) instanceof FireTrap) { + cell = randomDropCell(); + } + } + drop(item, cell).type = Heap.Type.HEAP; + } + } + + protected Room randomRoom(Room.Type type, int tries) { + for (int i = 0; i < tries; i++) { + Room room = Random.element(rooms); + if (room.type == type) { + return room; + } + } + return null; + } + + public Room room(int pos) { + for (Room room : rooms) { + if (room.type != Type.NULL && room.inside(pos)) { + return room; + } + } + + return null; + } + + protected int randomDropCell() { + while (true) { + Room room = randomRoom(Room.Type.STANDARD, 1); + if (room != null) { + int pos = room.random(); + if (passable[pos]) { + return pos; + } + } + } + } + + @Override + public int pitCell() { + for (Room room : rooms) { + if (room.type == Type.PIT) { + return room.random(); + } + } + + return super.pitCell(); + } + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put("rooms", rooms); + } + + @SuppressWarnings("unchecked") + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + + rooms = new HashSet( + (Collection) ((Collection) bundle + .getCollection("rooms"))); + for (Room r : rooms) { + if (r.type == Type.WEAK_FLOOR) { + weakFloorCreated = true; + break; + } + } + } + +} diff --git a/java/com/hmdzl/spspd/levels/Room.java b/java/com/hmdzl/spspd/levels/Room.java new file mode 100644 index 00000000..9506b32e --- /dev/null +++ b/java/com/hmdzl/spspd/levels/Room.java @@ -0,0 +1,291 @@ +/* + * 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 + */ +package com.hmdzl.spspd.levels; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; + +import com.hmdzl.spspd.ShatteredPixelDungeon; +import com.hmdzl.spspd.levels.painters.ArmoryPainter; +import com.hmdzl.spspd.levels.painters.BarricadedPainter; +import com.hmdzl.spspd.levels.painters.BlacksmithPainter; +import com.hmdzl.spspd.levels.painters.BossExitPainter; +import com.hmdzl.spspd.levels.painters.CryptPainter; +import com.hmdzl.spspd.levels.painters.EntrancePainter; +import com.hmdzl.spspd.levels.painters.ExitPainter; +import com.hmdzl.spspd.levels.painters.GardenPainter; +import com.hmdzl.spspd.levels.painters.LaboratoryPainter; +import com.hmdzl.spspd.levels.painters.LibraryPainter; +import com.hmdzl.spspd.levels.painters.MagicWellPainter; +import com.hmdzl.spspd.levels.painters.Painter; +import com.hmdzl.spspd.levels.painters.PassagePainter; +import com.hmdzl.spspd.levels.painters.PitPainter; +import com.hmdzl.spspd.levels.painters.PoolPainter; +import com.hmdzl.spspd.levels.painters.RatKingPainter; +import com.hmdzl.spspd.levels.painters.RatKingPainter2; +import com.hmdzl.spspd.levels.painters.ShopPainter; +import com.hmdzl.spspd.levels.painters.StandardPainter; +import com.hmdzl.spspd.levels.painters.StatuePainter; +import com.hmdzl.spspd.levels.painters.StoragePainter; +import com.hmdzl.spspd.levels.painters.TrapsPainter; +import com.hmdzl.spspd.levels.painters.TreasuryPainter; +import com.hmdzl.spspd.levels.painters.TunnelPainter; +import com.hmdzl.spspd.levels.painters.VaultPainter; +import com.hmdzl.spspd.levels.painters.WeakFloorPainter; +import com.hmdzl.spspd.levels.painters.MemoryPainter; +import com.watabou.utils.Bundlable; +import com.watabou.utils.Bundle; +import com.watabou.utils.Graph; +import com.watabou.utils.Point; +import com.watabou.utils.Random; +import com.watabou.utils.Rect; + +public class Room extends Rect implements Graph.Node, Bundlable { + + public HashSet neigbours = new HashSet(); + public HashMap connected = new HashMap(); + + public int distance; + public int price = 1; + + public static enum Type { + NULL(null), + STANDARD(StandardPainter.class), + ENTRANCE(EntrancePainter.class), + EXIT(ExitPainter.class), + BOSS_EXIT(BossExitPainter.class), + TUNNEL(TunnelPainter.class), + PASSAGE(PassagePainter.class), + SHOP(ShopPainter.class), + BLACKSMITH(BlacksmithPainter.class), + TREASURY(TreasuryPainter.class), + ARMORY(ArmoryPainter.class), + LIBRARY(LibraryPainter.class), + LABORATORY(LaboratoryPainter.class), + VAULT(VaultPainter.class), + TRAPS(TrapsPainter.class), + STORAGE(StoragePainter.class), + BARRICADED ( BarricadedPainter.class ), + MAGIC_WELL(MagicWellPainter.class), + GARDEN(GardenPainter.class), + CRYPT(CryptPainter.class), + STATUE(StatuePainter.class), + POOL(PoolPainter.class), + RAT_KING(RatKingPainter.class), + WEAK_FLOOR(WeakFloorPainter.class), + PIT(PitPainter.class), + RAT_KING2(RatKingPainter2.class), + MEMORY(MemoryPainter.class); + + private Method paint; + + private Type(Class painter) { + try { + paint = painter.getMethod("paint", Level.class, Room.class); + } catch (Exception e) { + paint = null; + } + } + + public void paint(Level level, Room room) { + try { + paint.invoke(null, level, room); + } catch (Exception e) { + ShatteredPixelDungeon.reportException(e); + } + } + }; + + public static final ArrayList SPECIALS = new ArrayList( + Arrays.asList(Type.WEAK_FLOOR, Type.MAGIC_WELL, Type.CRYPT, + Type.POOL, Type.GARDEN, Type.LIBRARY, Type.ARMORY, + Type.TREASURY, Type.TRAPS, Type.STORAGE, Type.STATUE, + Type.LABORATORY, Type.VAULT, Type.MEMORY, Type.BARRICADED)); + + public static final ArrayList SPECIALSFORT = new ArrayList( + Arrays.asList(Type.GARDEN, Type.GARDEN, Type.GARDEN, Type.GARDEN, + Type.GARDEN, Type.GARDEN, Type.GARDEN, Type.GARDEN, + Type.GARDEN, Type.GARDEN)); + + public static final ArrayList SPECIALSTRANSCEND = new ArrayList( + Arrays.asList(Type.MAGIC_WELL, Type.MAGIC_WELL, Type.MAGIC_WELL, Type.MAGIC_WELL, + Type.MAGIC_WELL, Type.MAGIC_WELL, Type.MAGIC_WELL, Type.MAGIC_WELL, + Type.MAGIC_WELL, Type.MAGIC_WELL)); + + public Type type = Type.NULL; + + public int random() { + return random(0); + } + + public int random(int m) { + int x = Random.Int(left + 1 + m, right - m); + int y = Random.Int(top + 1 + m, bottom - m); + return x + y * Level.getWidth(); + } + + public void addNeigbour(Room other) { + + Rect i = intersect(other); + if ((i.width() == 0 && i.height() >= 3) + || (i.height() == 0 && i.width() >= 3)) { + neigbours.add(other); + other.neigbours.add(this); + } + + } + + public void connect(Room room) { + if (!connected.containsKey(room)) { + connected.put(room, null); + room.connected.put(this, null); + } + } + + public Door entrance() { + return connected.values().iterator().next(); + } + + public boolean inside(int p) { + int x = p % Level.getWidth(); + int y = p / Level.getWidth(); + return x > left && y > top && x < right && y < bottom; + } + + public Point center() { + return new Point((left + right) / 2 + + (((right - left) & 1) == 1 ? Random.Int(2) : 0), + (top + bottom) / 2 + + (((bottom - top) & 1) == 1 ? Random.Int(2) : 0)); + } + + public HashSet getCells(){ + HashSet points = getPoints(); + HashSet cells = new HashSet<>(); + for( Point point : points) + cells.add(point.x + point.y*Level.WIDTH); + return cells; + } + + // **** Graph.Node interface **** + + @Override + public int distance() { + return distance; + } + + @Override + public void distance(int value) { + distance = value; + } + + @Override + public int price() { + return price; + } + + @Override + public void price(int value) { + price = value; + } + + @Override + public Collection edges() { + return neigbours; + } + + @Override + public void storeInBundle(Bundle bundle) { + bundle.put("left", left); + bundle.put("top", top); + bundle.put("right", right); + bundle.put("bottom", bottom); + bundle.put("type", type.toString()); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + left = bundle.getInt("left"); + top = bundle.getInt("top"); + right = bundle.getInt("right"); + bottom = bundle.getInt("bottom"); + type = Type.valueOf(bundle.getString("type")); + } + + public static void shuffleTypes() { + int size = SPECIALS.size(); + for (int i = 0; i < size - 1; i++) { + int j = Random.Int(i, size); + if (j != i) { + Type t = SPECIALS.get(i); + SPECIALS.set(i, SPECIALS.get(j)); + SPECIALS.set(j, t); + } + } + } + + public static void useType(Type type) { + if (SPECIALS.remove(type)) { + SPECIALS.add(type); + } + } + + private static final String ROOMS = "rooms"; + + public static void restoreRoomsFromBundle(Bundle bundle) { + if (bundle.contains(ROOMS)) { + SPECIALS.clear(); + for (String type : bundle.getStringArray(ROOMS)) { + SPECIALS.add(Type.valueOf(type)); + } + } else { + shuffleTypes(); + } + } + + public static void storeRoomsInBundle(Bundle bundle) { + String[] array = new String[SPECIALS.size()]; + for (int i = 0; i < array.length; i++) { + array[i] = SPECIALS.get(i).toString(); + } + bundle.put(ROOMS, array); + } + + public static class Door extends Point { + + public static enum Type { + EMPTY, TUNNEL, REGULAR, UNLOCKED, HIDDEN, BARRICADE, LOCKED, ONEWAY + } + + public Type type = Type.EMPTY; + + public Door(int x, int y) { + super(x, y); + } + + public void set(Type type) { + if (type.compareTo(this.type) > 0) { + this.type = type; + } + } + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/levels/RoomOfZotLevel.java b/java/com/hmdzl/spspd/levels/RoomOfZotLevel.java new file mode 100644 index 00000000..d4b31024 --- /dev/null +++ b/java/com/hmdzl/spspd/levels/RoomOfZotLevel.java @@ -0,0 +1,405 @@ +/* + * 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 + */ +package com.hmdzl.spspd.levels; + +import java.util.Collection; +import java.util.HashSet; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.WellWater; +import com.hmdzl.spspd.actors.mobs.npcs.Sheep; +import com.hmdzl.spspd.actors.mobs.npcs.SheepSokoban; +import com.hmdzl.spspd.actors.mobs.npcs.SheepSokobanBlack; +import com.hmdzl.spspd.actors.mobs.npcs.SheepSokobanCorner; +import com.hmdzl.spspd.actors.mobs.npcs.SheepSokobanSwitch; +import com.hmdzl.spspd.items.Gold; +import com.hmdzl.spspd.items.Heap; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.artifacts.TimekeepersHourglass; +import com.hmdzl.spspd.items.misc.LuckyBadge; +import com.hmdzl.spspd.items.scrolls.ScrollOfUpgrade; +import com.hmdzl.spspd.items.wands.WandOfFlock; +import com.hmdzl.spspd.levels.features.Chasm; +import com.hmdzl.spspd.levels.features.Door; +import com.hmdzl.spspd.levels.features.HighGrass; +import com.hmdzl.spspd.levels.traps.ChangeSheepTrap; +import com.hmdzl.spspd.levels.traps.FleecingTrap; +import com.hmdzl.spspd.levels.traps.SokobanPortalTrap; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.plants.Plant; +import com.hmdzl.spspd.scenes.GameScene; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Bundlable; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public class RoomOfZotLevel extends Level { + + + { + color1 = 0x534f3e; + color2 = 0xb9d661; + WIDTH = 48; + HEIGHT = 48; + LENGTH = HEIGHT*WIDTH; + } + + + public HashSet heapstogen; + public int[] heapgenspots; + public int[] teleportspots; + public int[] portswitchspots; + public int[] teleportassign; + public int[] destinationspots; + public int[] destinationassign; + public int prizeNo; + + private static final String HEAPSTOGEN = "heapstogen"; + private static final String HEAPGENSPOTS = "heapgenspots"; + private static final String TELEPORTSPOTS = "teleportspots"; + private static final String PORTSWITCHSPOTS = "portswitchspots"; + private static final String DESTINATIONSPOTS = "destinationspots"; + private static final String TELEPORTASSIGN = "teleportassign"; + private static final String DESTINATIONASSIGN= "destinationassign"; + private static final String PRIZENO = "prizeNo"; + + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(HEAPSTOGEN, heapstogen); + bundle.put(HEAPGENSPOTS, heapgenspots); + bundle.put(TELEPORTSPOTS, teleportspots); + bundle.put(PORTSWITCHSPOTS, portswitchspots); + bundle.put(DESTINATIONSPOTS, destinationspots); + bundle.put(DESTINATIONASSIGN, destinationassign); + bundle.put(TELEPORTASSIGN, teleportassign); + bundle.put(PRIZENO, prizeNo); + } + + + + @Override + public void restoreFromBundle(Bundle bundle) { + + super.restoreFromBundle(bundle); + + heapgenspots = bundle.getIntArray(HEAPGENSPOTS); + teleportspots = bundle.getIntArray(TELEPORTSPOTS); + portswitchspots = bundle.getIntArray(PORTSWITCHSPOTS); + destinationspots = bundle.getIntArray(DESTINATIONSPOTS); + destinationassign = bundle.getIntArray(DESTINATIONASSIGN); + teleportassign = bundle.getIntArray(TELEPORTASSIGN); + prizeNo = bundle.getInt(PRIZENO); + + heapstogen = new HashSet(); + + Collection collectionheap = bundle.getCollection(HEAPSTOGEN); + for (Bundlable i : collectionheap) { + Item item = (Item) i; + if (item != null) { + heapstogen.add(item); + } + } + } + + @Override + public void create() { + heapstogen = new HashSet(); + heapgenspots = new int[10]; + teleportspots = new int[10]; + portswitchspots = new int[10]; + destinationspots = new int[10]; + destinationassign = new int[10]; + teleportassign = new int[10]; + super.create(); + } + + public void addItemToGen(Item item, int arraypos, int pos) { + if (item != null) { + heapstogen.add(item); + heapgenspots[arraypos]=pos; + } + } + + + public Item genPrizeItem() { + return genPrizeItem(null); + } + + + public Item genPrizeItem(Class match) { + + boolean keysLeft = false; + + if (heapstogen.size() == 0) + return null; + + for (Item item : heapstogen) { + if (match.isInstance(item)) { + heapstogen.remove(item); + keysLeft=true; + return item; + } + } + + if (match == null || !keysLeft) { + Item item = Random.element(heapstogen); + heapstogen.remove(item); + return item; + } + + return null; + } + + @Override + public void press(int cell, Char ch) { + + if (pit[cell] && ch == Dungeon.hero) { + Chasm.heroFall(cell); + return; + } + + TimekeepersHourglass.timeFreeze timeFreeze = null; + + if (ch != null) + timeFreeze = ch.buff(TimekeepersHourglass.timeFreeze.class); + + boolean trap = false; + + switch (map[cell]) { + + case Terrain.FLEECING_TRAP: + + if (ch != null && ch==Dungeon.hero){ + trap = true; + FleecingTrap.trigger(cell, ch); + } + break; + + case Terrain.CHANGE_SHEEP_TRAP: + + if (ch instanceof SheepSokoban || ch instanceof SheepSokobanSwitch || ch instanceof SheepSokobanCorner || ch instanceof Sheep || ch instanceof WandOfFlock.MagicSheep){ + trap = true; + ChangeSheepTrap.trigger(cell, ch); + } + break; + + case Terrain.PORT_WELL: + + if (ch != null && ch==Dungeon.hero){ + + int portarray=-1; + int destinationspot=cell; + + for(int i = 0; i < teleportspots.length; i++) { + if(teleportspots[i] == cell) { + portarray = i; + break; + } + } + + if(portarray != -1) { + destinationspot=destinationspots[portarray]; + if (destinationspot>0){ + SokobanPortalTrap.trigger(cell, ch, destinationspot); + } + } + } + break; + + case Terrain.HIGH_GRASS: + HighGrass.trample(this, cell, ch); + break; + + case Terrain.WELL: + WellWater.affectCell(cell); + break; + + /*case Terrain.ALCHEMY: + if (ch == null) { + Alchemy.transmute(cell); + } + break;*/ + + case Terrain.DOOR: + Door.enter(cell); + break; + } + + if (trap){ + + if (Dungeon.visible[cell]) + Sample.INSTANCE.play(Assets.SND_TRAP); + + if (ch == Dungeon.hero) + Dungeon.hero.interrupt(); + + set(cell, Terrain.INACTIVE_TRAP); + GameScene.updateMap(cell); + } + + Plant plant = plants.get(cell); + if (plant != null) { + plant.activate(ch); + } + } + + @Override + public String tilesTex() { + return Assets.TILES_PUZZLE; + } + + @Override + public String waterTex() { + return Assets.WATER_PRISON; + } + + @Override + protected boolean build() { + + map = SaveRoomLayouts.ROOM_OF_ZOT.clone(); + + decorate(); + + buildFlagMaps(); + cleanWalls(); + createSwitches(); + createSheep(); + + entrance = 23 + WIDTH * 15; + + + return true; + } + @Override + protected void decorate() { + //do nothing, all decorations are hard-coded. + } + + @Override + protected void createMobs() { + /* + SokobanSentinel mob = new SokobanSentinel(); + mob.pos = 38 + WIDTH * 21; + mobs.add(mob); + Actor.occupyCell(mob); + + SokobanSentinel mob2 = new SokobanSentinel(); + mob2.pos = 25 + WIDTH * 36; + mobs.add(mob2); + Actor.occupyCell(mob2); + */ + } + + + + + @Override + public String tileName( int tile ) { + switch (tile) { + case Terrain.WATER: + return Messages.get(PrisonLevel.class, "water_name"); + default: + return super.tileName( tile ); + } + } + + @Override + public String tileDesc(int tile) { + switch (tile) { + case Terrain.EMPTY_DECO: + return Messages.get(PrisonLevel.class, "empty_deco_desc"); + case Terrain.BOOKSHELF: + return Messages.get(PrisonLevel.class, "bookshelf_desc"); + default: + return super.tileDesc( tile ); + } + } + + + protected void createSheep() { + for (int i = 0; i < LENGTH; i++) { + if (map[i]==Terrain.SOKOBAN_SHEEP){SheepSokoban npc = new SheepSokoban(); mobs.add(npc); npc.pos = i; Actor.occupyCell(npc);} + else if (map[i]==Terrain.CORNER_SOKOBAN_SHEEP){SheepSokobanCorner npc = new SheepSokobanCorner(); mobs.add(npc); npc.pos = i; Actor.occupyCell(npc);} + else if (map[i]==Terrain.SWITCH_SOKOBAN_SHEEP){SheepSokobanSwitch npc = new SheepSokobanSwitch(); mobs.add(npc); npc.pos = i; Actor.occupyCell(npc);} + else if (map[i]==Terrain.BLACK_SOKOBAN_SHEEP){SheepSokobanBlack npc = new SheepSokobanBlack(); mobs.add(npc); npc.pos = i; Actor.occupyCell(npc);} + else if (map[i]==Terrain.PORT_WELL){ + + /* + Portal portal = new Portal(); + portal.seed(i, 1); + blobs.put(Portal.class, portal); + */ + } + + } + } + + + protected void createSwitches(){ + + //spots where your portal switches are + + + //spots where your portals are + + + + //assign each switch to a portal + + + //assign each switch to a destination spot + + + + //set the original destination of portals + + + } + + + @Override + protected void createItems() { + int goldmin=1; int goldmax=10; + boolean ringDrop = false; + if (first){ + goldmin=50; goldmax=100; + } + for (int i = 0; i < LENGTH; i++) { + if (map[i]==Terrain.EMPTY && heaps.get(i) == null && Random.Int(100)>70){ + if (first && !ringDrop){drop(new LuckyBadge(), i).type = Heap.Type.CHEST; ringDrop=true;} + else if (first && Random.Int(50)==0){drop(new ScrollOfUpgrade(), i).type = Heap.Type.CHEST;} + else {drop(new Gold(Random.Int(goldmin, goldmax)), i).type = Heap.Type.CHEST;} + } + } + + + } + + @Override + public int randomRespawnCell() { + return -1; + } + + + +} diff --git a/java/com/hmdzl/spspd/levels/SafeLevel.java b/java/com/hmdzl/spspd/levels/SafeLevel.java new file mode 100644 index 00000000..29993e00 --- /dev/null +++ b/java/com/hmdzl/spspd/levels/SafeLevel.java @@ -0,0 +1,406 @@ +/* + * 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 + */ +package com.hmdzl.spspd.levels; + +import java.util.Collection; +import java.util.HashSet; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.WellWater; +import com.hmdzl.spspd.actors.mobs.npcs.Sheep; +import com.hmdzl.spspd.actors.mobs.npcs.SheepSokoban; +import com.hmdzl.spspd.actors.mobs.npcs.SheepSokobanBlack; +import com.hmdzl.spspd.actors.mobs.npcs.SheepSokobanCorner; +import com.hmdzl.spspd.actors.mobs.npcs.SheepSokobanSwitch; +import com.hmdzl.spspd.items.Gold; +import com.hmdzl.spspd.items.Heap; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.artifacts.TimekeepersHourglass; +import com.hmdzl.spspd.items.misc.LuckyBadge; +import com.hmdzl.spspd.items.scrolls.ScrollOfUpgrade; +import com.hmdzl.spspd.items.wands.WandOfFlock; +import com.hmdzl.spspd.levels.features.Chasm; +import com.hmdzl.spspd.levels.features.Door; +import com.hmdzl.spspd.levels.features.HighGrass; +import com.hmdzl.spspd.levels.traps.ChangeSheepTrap; +import com.hmdzl.spspd.levels.traps.FleecingTrap; +import com.hmdzl.spspd.levels.traps.SokobanPortalTrap; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.plants.Plant; +import com.hmdzl.spspd.scenes.GameScene; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Bundlable; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public class SafeLevel extends Level { + + + { + color1 = 0x534f3e; + color2 = 0xb9d661; + WIDTH = 48; + HEIGHT = 48; + LENGTH = HEIGHT*WIDTH; + } + + + public HashSet heapstogen; + public int[] heapgenspots; + public int[] teleportspots; + public int[] portswitchspots; + public int[] teleportassign; + public int[] destinationspots; + public int[] destinationassign; + public int prizeNo; + + private static final String HEAPSTOGEN = "heapstogen"; + private static final String HEAPGENSPOTS = "heapgenspots"; + private static final String TELEPORTSPOTS = "teleportspots"; + private static final String PORTSWITCHSPOTS = "portswitchspots"; + private static final String DESTINATIONSPOTS = "destinationspots"; + private static final String TELEPORTASSIGN = "teleportassign"; + private static final String DESTINATIONASSIGN= "destinationassign"; + private static final String PRIZENO = "prizeNo"; + + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(HEAPSTOGEN, heapstogen); + bundle.put(HEAPGENSPOTS, heapgenspots); + bundle.put(TELEPORTSPOTS, teleportspots); + bundle.put(PORTSWITCHSPOTS, portswitchspots); + bundle.put(DESTINATIONSPOTS, destinationspots); + bundle.put(DESTINATIONASSIGN, destinationassign); + bundle.put(TELEPORTASSIGN, teleportassign); + bundle.put(PRIZENO, prizeNo); + } + + + + @Override + public void restoreFromBundle(Bundle bundle) { + + super.restoreFromBundle(bundle); + + heapgenspots = bundle.getIntArray(HEAPGENSPOTS); + teleportspots = bundle.getIntArray(TELEPORTSPOTS); + portswitchspots = bundle.getIntArray(PORTSWITCHSPOTS); + destinationspots = bundle.getIntArray(DESTINATIONSPOTS); + destinationassign = bundle.getIntArray(DESTINATIONASSIGN); + teleportassign = bundle.getIntArray(TELEPORTASSIGN); + prizeNo = bundle.getInt(PRIZENO); + + heapstogen = new HashSet(); + + Collection collectionheap = bundle.getCollection(HEAPSTOGEN); + for (Bundlable i : collectionheap) { + Item item = (Item) i; + if (item != null) { + heapstogen.add(item); + } + } + } + + @Override + public void create() { + heapstogen = new HashSet(); + heapgenspots = new int[10]; + teleportspots = new int[10]; + portswitchspots = new int[10]; + destinationspots = new int[10]; + destinationassign = new int[10]; + teleportassign = new int[10]; + super.create(); + } + + public void addItemToGen(Item item, int arraypos, int pos) { + if (item != null) { + heapstogen.add(item); + heapgenspots[arraypos]=pos; + } + } + + + public Item genPrizeItem() { + return genPrizeItem(null); + } + + + public Item genPrizeItem(Class match) { + + boolean keysLeft = false; + + if (heapstogen.size() == 0) + return null; + + for (Item item : heapstogen) { + if (match.isInstance(item)) { + heapstogen.remove(item); + keysLeft=true; + return item; + } + } + + if (match == null || !keysLeft) { + Item item = Random.element(heapstogen); + heapstogen.remove(item); + return item; + } + + return null; + } + + @Override + public void press(int cell, Char ch) { + + if (pit[cell] && ch == Dungeon.hero) { + Chasm.heroFall(cell); + return; + } + + TimekeepersHourglass.timeFreeze timeFreeze = null; + + if (ch != null) + timeFreeze = ch.buff(TimekeepersHourglass.timeFreeze.class); + + boolean trap = false; + + switch (map[cell]) { + + case Terrain.FLEECING_TRAP: + + if (ch != null && ch==Dungeon.hero){ + trap = true; + FleecingTrap.trigger(cell, ch); + } + break; + + case Terrain.CHANGE_SHEEP_TRAP: + + if (ch instanceof SheepSokoban || ch instanceof SheepSokobanSwitch || ch instanceof SheepSokobanCorner || ch instanceof Sheep || ch instanceof WandOfFlock.MagicSheep){ + trap = true; + ChangeSheepTrap.trigger(cell, ch); + } + break; + + case Terrain.PORT_WELL: + + if (ch != null && ch==Dungeon.hero){ + + int portarray=-1; + int destinationspot=cell; + + for(int i = 0; i < teleportspots.length; i++) { + if(teleportspots[i] == cell) { + portarray = i; + break; + } + } + + if(portarray != -1) { + destinationspot=destinationspots[portarray]; + if (destinationspot>0){ + SokobanPortalTrap.trigger(cell, ch, destinationspot); + } + } + } + break; + + case Terrain.HIGH_GRASS: + HighGrass.trample(this, cell, ch); + break; + + case Terrain.WELL: + WellWater.affectCell(cell); + break; + + /*case Terrain.ALCHEMY: + if (ch == null) { + Alchemy.transmute(cell); + } + break;*/ + + case Terrain.DOOR: + Door.enter(cell); + break; + } + + if (trap){ + + if (Dungeon.visible[cell]) + Sample.INSTANCE.play(Assets.SND_TRAP); + + if (ch == Dungeon.hero) + Dungeon.hero.interrupt(); + + set(cell, Terrain.INACTIVE_TRAP); + GameScene.updateMap(cell); + } + + Plant plant = plants.get(cell); + if (plant != null) { + plant.activate(ch); + } + } + + @Override + public String tilesTex() { + return Assets.TILES_PUZZLE; + } + + @Override + public String waterTex() { + return Assets.WATER_PRISON; + } + + @Override + protected boolean build() { + + map = SaveRoomLayouts.SAFE_ROOM_DEFAULT.clone(); + + decorate(); + + buildFlagMaps(); + cleanWalls(); + createSwitches(); + createSheep(); + + entrance = 23 + WIDTH * 15; + exit = 0 + WIDTH * 47; + + + return true; + } + @Override + protected void decorate() { + //do nothing, all decorations are hard-coded. + } + + @Override + protected void createMobs() { + /* + SokobanSentinel mob = new SokobanSentinel(); + mob.pos = 38 + WIDTH * 21; + mobs.add(mob); + Actor.occupyCell(mob); + + SokobanSentinel mob2 = new SokobanSentinel(); + mob2.pos = 25 + WIDTH * 36; + mobs.add(mob2); + Actor.occupyCell(mob2); + */ + } + + + + + @Override + public String tileName( int tile ) { + switch (tile) { + case Terrain.WATER: + return Messages.get(PrisonLevel.class, "water_name"); + default: + return super.tileName( tile ); + } + } + + @Override + public String tileDesc(int tile) { + switch (tile) { + case Terrain.EMPTY_DECO: + return Messages.get(PrisonLevel.class, "empty_deco_desc"); + case Terrain.BOOKSHELF: + return Messages.get(PrisonLevel.class, "bookshelf_desc"); + default: + return super.tileDesc( tile ); + } + } + + + protected void createSheep() { + for (int i = 0; i < LENGTH; i++) { + if (map[i]==Terrain.SOKOBAN_SHEEP){SheepSokoban npc = new SheepSokoban(); mobs.add(npc); npc.pos = i; Actor.occupyCell(npc);} + else if (map[i]==Terrain.CORNER_SOKOBAN_SHEEP){SheepSokobanCorner npc = new SheepSokobanCorner(); mobs.add(npc); npc.pos = i; Actor.occupyCell(npc);} + else if (map[i]==Terrain.SWITCH_SOKOBAN_SHEEP){SheepSokobanSwitch npc = new SheepSokobanSwitch(); mobs.add(npc); npc.pos = i; Actor.occupyCell(npc);} + else if (map[i]==Terrain.BLACK_SOKOBAN_SHEEP){SheepSokobanBlack npc = new SheepSokobanBlack(); mobs.add(npc); npc.pos = i; Actor.occupyCell(npc);} + else if (map[i]==Terrain.PORT_WELL){ + + /* + Portal portal = new Portal(); + portal.seed(i, 1); + blobs.put(Portal.class, portal); + */ + } + + } + } + + + protected void createSwitches(){ + + //spots where your portal switches are + + + //spots where your portals are + + + + //assign each switch to a portal + + + //assign each switch to a destination spot + + + + //set the original destination of portals + + + } + + + @Override + protected void createItems() { + int goldmin=1; int goldmax=10; + boolean ringDrop = false; + if (first){ + goldmin=25; goldmax=50; + } + for (int i = 0; i < LENGTH; i++) { + if (map[i]==Terrain.EMPTY && heaps.get(i) == null && Random.Int(100)>70){ + if (first && !ringDrop){drop(new LuckyBadge().identify(), i).type = Heap.Type.CHEST; ringDrop=true;} + else if (first && Random.Int(50)==0){drop(new ScrollOfUpgrade(), i).type = Heap.Type.CHEST;} + else {drop(new Gold(Random.Int(goldmin, goldmax)), i).type = Heap.Type.CHEST;} + } + } + + + } + + @Override + public int randomRespawnCell() { + return -1; + } + + + +} diff --git a/java/com/hmdzl/spspd/levels/SaveRoomLayouts.java b/java/com/hmdzl/spspd/levels/SaveRoomLayouts.java new file mode 100644 index 00000000..e0b91dfd --- /dev/null +++ b/java/com/hmdzl/spspd/levels/SaveRoomLayouts.java @@ -0,0 +1,149 @@ +/* + * 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 + */ +package com.hmdzl.spspd.levels; + +import com.watabou.utils.Random; + +public class SaveRoomLayouts { + + //32X32 + private static final int W = Terrain.WALL; + private static final int B = Terrain.BED; + private static final int Z = Terrain.HIGH_GRASS; + private static final int D = Terrain.DOOR; + private static final int L = Terrain.LOCKED_DOOR; + + private static final int T = Terrain.TENT; + + private static final int E = Terrain.EMPTY; + //private static final int I = Terrain.EXIT; + + private static final int M = Terrain.WALL_DECO; + private static final int P = Terrain.PEDESTAL; + + private static final int J = Terrain.WATER; + private static final int Y = Terrain.ALCHEMY; + private static final int K = Terrain.EMPTY_SP; + + + public static final int[] SAFE_ROOM_DEFAULT = { + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, E, E, E, E, E, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, K, K, K, W, E, K, K, K, E, W, E, E, E, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, B, K, K, D, E, K, T, K, E, D, E, Z, E, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, K, K, K, W, E, K, K, K, E, W, E, E, E, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, E, E, E, E, E, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, E, E, E, E, W, W, W, W, D, W, W, W, W, E, E, E, E, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, E, E, E, E, W, E, E, E, E, E, E, E, W, E, E, E, E, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, E, E, E, E, W, E, E, E, E, E, E, E, W, E, E, E, E, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, E, E, E, E, D, E, E, E, E, E, E, E, D, E, E, E, E, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, E, E, E, E, W, E, E, E, E, E, E, E, W, E, E, E, E, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, E, E, E, E, W, E, E, E, E, E, E, E, W, E, E, E, E, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, E, E, E, E, W, E, E, E, E, E, E, E, W, E, E, E, E, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, D, W, W, D, W, W, D, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, Y, K, K, W, Z, Z, Z, W, J, J, J, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, K, K, K, W, Z, Z, Z, W, J, J, J, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, K, K, K, W, Z, Z, Z, W, J, J, J, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, Z, Z, Z, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W + + }; + + public static final int[] ROOM_OF_ZOT = { + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, E, E, E, E, E, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, K, K, K, W, E, K, K, K, E, W, E, E, E, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, B, K, K, D, E, K, T, K, E, D, E, Z, E, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, K, K, K, W, E, K, K, K, E, W, E, E, E, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, E, E, E, E, E, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, E, E, E, E, W, W, W, W, D, W, W, W, W, E, E, E, E, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, E, E, E, E, W, E, E, E, E, E, E, E, W, E, E, E, E, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, E, E, E, E, W, E, E, E, E, E, E, E, W, E, E, E, E, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, E, E, E, E, D, E, E, E, E, E, E, E, D, E, E, E, E, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, E, E, E, E, W, E, E, E, E, E, E, E, W, E, E, E, E, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, E, E, E, E, W, E, E, E, E, E, E, E, W, E, E, E, E, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, E, E, E, E, W, E, E, E, E, E, E, E, W, E, E, E, E, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, D, W, W, D, W, W, D, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, Y, K, K, W, Z, Z, Z, W, J, J, J, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, K, K, K, W, Z, Z, Z, W, J, J, J, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, K, K, K, W, Z, Z, Z, W, J, J, J, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, Z, Z, Z, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W + + }; + + +} diff --git a/java/com/hmdzl/spspd/levels/SewerBossLevel.java b/java/com/hmdzl/spspd/levels/SewerBossLevel.java new file mode 100644 index 00000000..c057d914 --- /dev/null +++ b/java/com/hmdzl/spspd/levels/SewerBossLevel.java @@ -0,0 +1,308 @@ +/* + * 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 + */ +package com.hmdzl.spspd.levels; + +import java.util.ArrayList; +import java.util.List; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.mobs.Bestiary; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.levels.Room.Type; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.GameScene; +import com.watabou.noosa.Scene; +import com.watabou.utils.Bundle; +import com.watabou.utils.Graph; +import com.watabou.utils.Random; + +public class SewerBossLevel extends RegularLevel { + + { + color1 = 0x48763c; + color2 = 0x59994a; + } + + private int stairs = 0; + + @Override + public String tilesTex() { + return Assets.TILES_SEWERS; + } + + @Override + public String waterTex() { + return Assets.WATER_SEWERS; + } + + @Override + protected boolean build() { + + initRooms(); + + int distance; + // if we ever need to try 20 or more times to find a room, better to + // give up and try again. + int retry = 0; + + // start with finding an entrance room (will also contain exit) + // the room must be at least 4x4 and be nearer the top of the map(so + // that it is less likely something connects to the top) + do { + if (retry++ > 20) { + return false; + } + roomEntrance = Random.element(rooms); + } while (roomEntrance.width() < 4 || roomEntrance.height() < 4 + || roomEntrance.top == 0 || roomEntrance.top >= 12); + + roomEntrance.type = Type.ENTRANCE; + roomExit = roomEntrance; + + // now find the rest of the rooms for this boss mini-maze + Room curRoom = null; + Room lastRoom = roomEntrance; + // we make 4 rooms, last iteration is tieing the final room to the start + for (int i = 0; i <= 4; i++) { + retry = 0; + // find a suitable room the first four times + // suitable room should be empty, have a distance of 2 from the + // current room, and not touch the entrance. + if (i < 4) { + do { + if (retry++ > 20) { + return false; + } + curRoom = Random.element(rooms); + Graph.buildDistanceMap(rooms, curRoom); + distance = lastRoom.distance(); + } while (curRoom.type != Type.NULL || distance != 2 + || !curRoom.intersect(roomEntrance).isEmpty()); + + curRoom.type = Type.STANDARD; + + // otherwise, we're on the last iteration. + } else { + // set the current room to the entrance, so we can build a + // connection to it. + curRoom = roomEntrance; + } + + // now build a connection between the current room and the last one. + Graph.buildDistanceMap(rooms, curRoom); + List path = Graph.buildPath(rooms, lastRoom, curRoom); + + Graph.setPrice(path, lastRoom.distance); + + path = Graph.buildPath(rooms, lastRoom, curRoom); + + Room room = lastRoom; + for (Room next : path) { + room.connect(next); + room = next; + } + + if (i == 4) { + + // we must find a room for his royal highness! + // look at rooms adjacent to the final found room (likely to be + // furthest from start) + ArrayList candidates = new ArrayList(); + for (Room r : lastRoom.neigbours) { + if (r.type == Type.NULL && r.connected.size() == 0 + && !r.neigbours.contains(roomEntrance)) { + candidates.add(r); + } + } + + // if we have candidates, pick a room and put the king there + if (candidates.size() > 0) { + Room kingsRoom = Random.element(candidates); + kingsRoom.connect(lastRoom); + kingsRoom.type = Room.Type.RAT_KING; + + // unacceptable! make a new level... + } else { + return false; + } + } + lastRoom = curRoom; + } + + // the connection structure ensures that (most of the time) there is a + // nice loop for the player to kite the + // boss around. What's nice is that there is enough chaos such that the + // loop is rarely straightforward + // and boring. + + // fills our connection rooms in with tunnel + for (Room r : rooms) { + if (r.type == Type.NULL && r.connected.size() > 0) { + r.type = Type.TUNNEL; + } + } + + // make sure nothing is connecting at the top of the entrance, this + // would be bad. + for (Room r : roomEntrance.neigbours) { + if (r.bottom == roomEntrance.top && r.type != Type.NULL) + return false; + } + + paint(); + + // TODO: not handling this through a painter is kinda iffy, separate + // into a painter if you use it again. + // sticks the exit in the room entrance. + exit = roomEntrance.top * Level.getWidth() + + (roomEntrance.left + roomEntrance.right) / 2; + map[exit] = Terrain.LOCKED_EXIT; + + paintWater(); + paintGrass(); + + return true; + } + + @Override + protected boolean[] water() { + return Patch.generate(0.5f, 5); + } + + @Override + protected boolean[] grass() { + return Patch.generate(0.40f, 4); + } + + @Override + protected void decorate() { + int start = roomExit.top * getWidth() + roomExit.left + 1; + int end = start + roomExit.width() - 1; + for (int i = start; i < end; i++) { + if (i != exit) { + map[i] = Terrain.WALL_DECO; + map[i + getWidth()] = Terrain.WATER; + } else { + map[i + getWidth()] = Terrain.EMPTY; + } + } + + while (true) { + int pos = roomEntrance.random(); + if (pos != entrance) { + map[pos] = Terrain.SIGN; + break; + } + } + } + + @Override + public void addVisuals(Scene scene) { + SewerLevel.addVisuals(this, scene); + } + + @Override + protected void createMobs() { + Mob mob = Bestiary.mob(Dungeon.depth); + Room room; + do { + room = Random.element(rooms); + } while (room.type != Type.STANDARD); + mob.pos = room.random(); + mobs.add(mob); + } + + @Override + public Actor respawner() { + return null; + } + + @Override + protected void createItems() { + } + + @Override + public int randomRespawnCell() { + return -1; + } + public void seal() { + if (entrance != 0) { + + locked = true; + + set(entrance, Terrain.WATER_TILES); + GameScene.updateMap(entrance); + GameScene.ripple(entrance); + + stairs = entrance; + entrance = 0; + } + } + + public void unseal() { + if (stairs != 0) { + + locked = false; + + entrance = stairs; + stairs = 0; + + set(entrance, Terrain.ENTRANCE); + GameScene.updateMap(entrance); + + } + } + + private static final String STAIRS = "stairs"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(STAIRS, stairs); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + stairs = bundle.getInt(STAIRS); + } + + @Override + public String tileName( int tile ) { + switch (tile) { + case Terrain.WATER: + return Messages.get(SewerLevel.class, "water_name"); + default: + return super.tileName( tile ); + } + } + + @Override + public String tileDesc(int tile) { + switch (tile) { + case Terrain.EMPTY_DECO: + return Messages.get(SewerLevel.class, "empty_deco_desc"); + case Terrain.BOOKSHELF: + return Messages.get(SewerLevel.class, "bookshelf_desc"); + default: + return super.tileDesc( tile ); + } + } +} diff --git a/java/com/hmdzl/spspd/levels/SewerLevel.java b/java/com/hmdzl/spspd/levels/SewerLevel.java new file mode 100644 index 00000000..069d46cc --- /dev/null +++ b/java/com/hmdzl/spspd/levels/SewerLevel.java @@ -0,0 +1,302 @@ +/* + * 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 + */ +package com.hmdzl.spspd.levels; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Challenges; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.DungeonTilemap; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.hero.HeroClass; +import com.hmdzl.spspd.actors.mobs.npcs.Ghost; +import com.hmdzl.spspd.actors.mobs.GnollArcher; +import com.hmdzl.spspd.actors.mobs.npcs.Tinkerer1; +import com.hmdzl.spspd.items.DewVial; +import com.hmdzl.spspd.items.bombs.DungeonBomb; +import com.hmdzl.spspd.items.quest.Mushroom; +import com.hmdzl.spspd.items.food.fruit.Blackberry; +import com.hmdzl.spspd.items.food.fruit.Blueberry; +import com.hmdzl.spspd.items.food.fruit.Cloudberry; +import com.hmdzl.spspd.items.food.fruit.Moonberry; +import com.hmdzl.spspd.levels.traps.AlarmTrap; +import com.hmdzl.spspd.levels.traps.ChillingTrap; +import com.hmdzl.spspd.levels.traps.FlockTrap; +import com.hmdzl.spspd.levels.traps.OozeTrap; +import com.hmdzl.spspd.levels.traps.ShockTrap; +import com.hmdzl.spspd.levels.traps.SummoningTrap; +import com.hmdzl.spspd.levels.traps.TeleportationTrap; +import com.hmdzl.spspd.levels.traps.ToxicTrap; +import com.hmdzl.spspd.levels.traps.WornTrap; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.GameScene; +import com.watabou.noosa.Game; +import com.watabou.noosa.Scene; +import com.watabou.noosa.particles.Emitter; +import com.watabou.noosa.particles.PixelParticle; +import com.watabou.utils.ColorMath; +import com.watabou.utils.PointF; +import com.watabou.utils.Random; + +public class SewerLevel extends RegularLevel { + + { + color1 = 0x48763c; + color2 = 0x59994a; + } + + @Override + public String tilesTex() { + return Assets.TILES_SEWERS; + } + + + @Override + public String waterTex() { + return Assets.WATER_SEWERS; + } + + @Override + protected boolean[] water() { + return Patch.generate(feeling == Feeling.WATER ? 0.60f : 0.45f, 5); + } + + @Override + protected boolean[] grass() { + return Patch.generate(feeling == Feeling.GRASS ? 0.60f : 0.40f, 4); + } + + @Override + protected Class[] trapClasses() { + return Dungeon.depth == 1 ? + new Class[]{WornTrap.class} : + new Class[]{ChillingTrap.class, ToxicTrap.class, WornTrap.class, + AlarmTrap.class, OozeTrap.class, ShockTrap.class, + FlockTrap.class, SummoningTrap.class, TeleportationTrap.class, }; +} + + @Override + protected float[] trapChances() { + return Dungeon.depth == 1 ? + new float[]{1} : + new float[]{4, 4, 4, + 2, 2, 2, + 1, 1, 1}; + } + + @Override + protected void setPar(){ + Dungeon.pars[Dungeon.depth] = 500+(Dungeon.depth*50)+(secretDoors*50); + } + + @Override + protected void decorate() { + + for (int i = 0; i < getWidth(); i++) { + if (map[i] == Terrain.WALL && map[i + getWidth()] == Terrain.WATER + && Random.Int(4) == 0) { + + map[i] = Terrain.WALL_DECO; + } + } + + for (int i = getWidth(); i < getLength() - getWidth(); i++) { + if (map[i] == Terrain.WALL && map[i - getWidth()] == Terrain.WALL + && map[i + getWidth()] == Terrain.WATER && Random.Int(2) == 0) { + + map[i] = Terrain.WALL_DECO; + } + } + + for (int i = getWidth() + 1; i < getLength() - getWidth() - 1; i++) { + if (map[i] == Terrain.EMPTY) { + + int count = (map[i + 1] == Terrain.WALL ? 1 : 0) + + (map[i - 1] == Terrain.WALL ? 1 : 0) + + (map[i + getWidth()] == Terrain.WALL ? 1 : 0) + + (map[i - getWidth()] == Terrain.WALL ? 1 : 0); + + if (Random.Int(16) < count * count) { + map[i] = Terrain.EMPTY_DECO; + } + } + } + + while (true) { + int pos = roomEntrance.random(); + if (pos != entrance) { + map[pos] = Terrain.SIGN; + break; + } + } + + setPar(); + + + } + + @Override + protected void createItems() { + if (!Dungeon.limitedDrops.dewVial.dropped() && Dungeon.depth == 1) { + addItemToSpawn(new DewVial()); + Dungeon.limitedDrops.dewVial.drop(); + addItemToSpawn(new Moonberry()); + addItemToSpawn(new Blueberry()); + addItemToSpawn(new Cloudberry()); + addItemToSpawn(new Blackberry()); + + //addItemToSpawn(new Spectacles()); + //addItemToSpawn(new Towel()); + + //addItemToSpawn(new Egg()); + } + + if (Dungeon.depth == 1){ + Tinkerer1 npc = new Tinkerer1(); + do { + npc.pos = randomRespawnCell(); + } while (npc.pos == -1 || heaps.get(npc.pos) != null); + mobs.add(npc); + Actor.occupyCell(npc); + } + + if (Dungeon.depth == 2){ + addItemToSpawn(new Mushroom()); + } + + Ghost.Quest.spawn(this); + spawnGnoll(this); + + if (Dungeon.hero.heroClass==HeroClass.PERFORMER && Random.Int(3) == 0){addItemToSpawn(new DungeonBomb());} + super.createItems(); + } + + public static void spawnGnoll(SewerLevel level) { + if (Dungeon.depth == 4 && !Dungeon.gnollspawned){ + + GnollArcher gnoll = new GnollArcher(); + do { + gnoll.pos = level.randomRespawnCell(); + } while (gnoll.pos == -1); + level.mobs.add(gnoll); + Actor.occupyCell(gnoll); + + Dungeon.gnollspawned = true; + } + } + + + @Override + public void addVisuals(Scene scene) { + super.addVisuals(scene); + addVisuals(this, scene); + } + + public static void addVisuals(Level level, Scene scene) { + for (int i = 0; i < getLength(); i++) { + if (level.map[i] == Terrain.WALL_DECO) { + scene.add(new Sink(i)); + } + } + } + + @Override + public String tileName( int tile ) { + switch (tile) { + case Terrain.WATER: + return Messages.get(SewerLevel.class, "water_name"); + default: + return super.tileName( tile ); + } + } + + @Override + public String tileDesc(int tile) { + switch (tile) { + case Terrain.EMPTY_DECO: + return Messages.get(SewerLevel.class, "empty_deco_desc"); + case Terrain.BOOKSHELF: + return Messages.get(SewerLevel.class, "bookshelf_desc"); + default: + return super.tileDesc( tile ); + } + } + + private static class Sink extends Emitter { + + private int pos; + private float rippleDelay = 0; + + private static final Emitter.Factory factory = new Factory() { + + @Override + public void emit(Emitter emitter, int index, float x, float y) { + WaterParticle p = (WaterParticle) emitter + .recycle(WaterParticle.class); + p.reset(x, y); + } + }; + + public Sink(int pos) { + super(); + + this.pos = pos; + + PointF p = DungeonTilemap.tileCenterToWorld(pos); + pos(p.x - 2, p.y + 1, 4, 0); + + pour(factory, 0.05f); + } + + @Override + public void update() { + if (visible = Dungeon.visible[pos]) { + + super.update(); + + if ((rippleDelay -= Game.elapsed) <= 0) { + GameScene.ripple(pos + getWidth()).y -= DungeonTilemap.SIZE / 2; + rippleDelay = Random.Float(0.2f, 0.3f); + } + } + } + } + + public static final class WaterParticle extends PixelParticle { + + public WaterParticle() { + super(); + + acc.y = 50; + am = 0.5f; + + color(ColorMath.random(0xb6ccc2, 0x3b6653)); + size(2); + } + + public void reset(float x, float y) { + revive(); + + this.x = x; + this.y = y; + + speed.set(Random.Float(-2, +2), 0); + + left = lifespan = 0.5f; + } + } +} diff --git a/java/com/hmdzl/spspd/levels/ShadowEaterLevel.java b/java/com/hmdzl/spspd/levels/ShadowEaterLevel.java new file mode 100644 index 00000000..89a09d42 --- /dev/null +++ b/java/com/hmdzl/spspd/levels/ShadowEaterLevel.java @@ -0,0 +1,290 @@ +/* + * 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 + */ +package com.hmdzl.spspd.levels; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.Challenges; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.Statistics; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.Alchemy; +import com.hmdzl.spspd.actors.blobs.Alter; +import com.hmdzl.spspd.actors.blobs.WellWater; +import com.hmdzl.spspd.actors.mobs.AdultDragonViolet; +import com.hmdzl.spspd.actors.mobs.BombBug; +import com.hmdzl.spspd.actors.mobs.Piranha; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.actors.mobs.TestMob; +import com.hmdzl.spspd.actors.mobs.TestMob2; +import com.hmdzl.spspd.actors.mobs.npcs.AFly; +import com.hmdzl.spspd.actors.mobs.npcs.ARealMan; +import com.hmdzl.spspd.actors.mobs.npcs.Apostle; +import com.hmdzl.spspd.actors.mobs.npcs.DreamPlayer; +import com.hmdzl.spspd.actors.mobs.npcs.GoblinPlayer; +import com.hmdzl.spspd.actors.mobs.npcs.HoneyPoooot; +import com.hmdzl.spspd.actors.mobs.npcs.Ice13; +import com.hmdzl.spspd.actors.mobs.npcs.Juh9870; +import com.hmdzl.spspd.actors.mobs.npcs.Kostis12345; +import com.hmdzl.spspd.actors.mobs.npcs.Lynn; +import com.hmdzl.spspd.actors.mobs.npcs.Millilitre; +import com.hmdzl.spspd.actors.mobs.npcs.NutPainter; +import com.hmdzl.spspd.actors.mobs.npcs.OldNewStwist; +import com.hmdzl.spspd.actors.mobs.npcs.Omicronrg9; +import com.hmdzl.spspd.actors.mobs.npcs.OtilukeNPC; +import com.hmdzl.spspd.actors.mobs.npcs.RENnpc; +import com.hmdzl.spspd.actors.mobs.npcs.RainTrainer; +import com.hmdzl.spspd.actors.mobs.npcs.SadSaltan; +import com.hmdzl.spspd.actors.mobs.npcs.SaidbySun; +import com.hmdzl.spspd.actors.mobs.npcs.Shopkeeper; +import com.hmdzl.spspd.actors.mobs.npcs.Shower; +import com.hmdzl.spspd.actors.mobs.npcs.Tinkerer4; +import com.hmdzl.spspd.actors.mobs.npcs.Tinkerer5; +import com.hmdzl.spspd.actors.mobs.npcs.Udawos; +import com.hmdzl.spspd.actors.mobs.npcs.TypedScroll; +import com.hmdzl.spspd.actors.mobs.npcs.G2159687; +import com.hmdzl.spspd.actors.mobs.npcs.ConsideredHamster; +import com.hmdzl.spspd.actors.mobs.npcs.NYRDS; +import com.hmdzl.spspd.actors.mobs.npcs.Evan; +import com.hmdzl.spspd.actors.mobs.npcs.UncleS; +import com.hmdzl.spspd.actors.mobs.npcs.Watabou; +import com.hmdzl.spspd.actors.mobs.npcs.Bilboldev; +import com.hmdzl.spspd.actors.mobs.npcs.HBB; +import com.hmdzl.spspd.actors.mobs.npcs.SFB; +import com.hmdzl.spspd.actors.mobs.npcs.Jinkeloid; +import com.hmdzl.spspd.actors.mobs.npcs.Rustyblade; +import com.hmdzl.spspd.actors.mobs.npcs.HeXA; +import com.hmdzl.spspd.actors.mobs.npcs.SP931; +import com.hmdzl.spspd.actors.mobs.npcs.Lery; +import com.hmdzl.spspd.actors.mobs.npcs.Lyn; +import com.hmdzl.spspd.actors.mobs.npcs.Coconut; +import com.hmdzl.spspd.actors.mobs.npcs.FruitCat; +import com.hmdzl.spspd.actors.mobs.npcs.Locastan; +import com.hmdzl.spspd.actors.mobs.npcs.Tempest102; +import com.hmdzl.spspd.actors.mobs.npcs.Dachhack; +import com.hmdzl.spspd.actors.mobs.npcs.MemoryOfSand; +import com.hmdzl.spspd.actors.mobs.npcs.StormAndRain; +import com.hmdzl.spspd.actors.mobs.npcs.HateSokoban; +import com.hmdzl.spspd.actors.mobs.npcs.AliveFish; +import com.hmdzl.spspd.actors.mobs.npcs.LaJi; +import com.hmdzl.spspd.actors.mobs.npcs.WhiteGhost; +import com.hmdzl.spspd.actors.mobs.npcs.XixiZero; +import com.hmdzl.spspd.items.food.Nut; +import com.hmdzl.spspd.items.food.vegetable.NutVegetable; +import com.hmdzl.spspd.items.eggs.Egg; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.items.Heap; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.Ankh; +import com.hmdzl.spspd.items.AdamantArmor; +import com.hmdzl.spspd.items.AdamantRing; +import com.hmdzl.spspd.items.AdamantWand; +import com.hmdzl.spspd.items.AdamantWeapon; +import com.hmdzl.spspd.items.food.completefood.PetFood; +import com.hmdzl.spspd.items.misc.SkillOfAtk; +import com.hmdzl.spspd.items.misc.SkillOfDef; +import com.hmdzl.spspd.items.misc.SkillOfMig; +import com.hmdzl.spspd.items.quest.DarkGold; + + +import com.hmdzl.spspd.items.artifacts.TimekeepersHourglass; +import com.hmdzl.spspd.items.scrolls.ScrollOfUpgrade; +import com.hmdzl.spspd.items.scrolls.ScrollOfMagicalInfusion; +import com.hmdzl.spspd.items.scrolls.ScrollOfRegrowth; +import com.hmdzl.spspd.items.weapon.guns.ToyGun; +import com.hmdzl.spspd.items.weapon.melee.special.Brick; +import com.hmdzl.spspd.items.weapon.melee.special.FireCracker; +import com.hmdzl.spspd.items.weapon.melee.special.HookHam; +import com.hmdzl.spspd.items.weapon.melee.special.KeyWeapon; +import com.hmdzl.spspd.items.weapon.melee.special.Lollipop; +import com.hmdzl.spspd.items.weapon.melee.special.Pumpkin; +import com.hmdzl.spspd.items.weapon.melee.special.RunicBlade; +import com.hmdzl.spspd.items.weapon.melee.special.SJRBMusic; +import com.hmdzl.spspd.items.weapon.melee.special.TestWeapon; +import com.hmdzl.spspd.items.weapon.melee.special.Tree; +import com.hmdzl.spspd.items.weapon.missiles.MiniMoai; +import com.hmdzl.spspd.items.weapon.missiles.MoneyPack; +import com.hmdzl.spspd.items.weapon.missiles.PocketBall; +import com.hmdzl.spspd.levels.features.Chasm; +import com.hmdzl.spspd.levels.features.Door; +import com.hmdzl.spspd.levels.features.HighGrass; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.plants.Phaseshift; +import com.hmdzl.spspd.plants.Plant; +import com.hmdzl.spspd.plants.Starflower; +import com.hmdzl.spspd.scenes.GameScene; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +import static com.hmdzl.spspd.Dungeon.level; + +public class ShadowEaterLevel extends Level { + + + { + color1 = 0x534f3e; + color2 = 0xb9d661; + WIDTH = 48; + HEIGHT = 48; + LENGTH = HEIGHT*WIDTH; + special=false; + } + + @Override + public void create() { + + super.create(); + } + + + @Override + protected void createItems() { + + Mob painter = new NutPainter(); + painter.pos = 16 + WIDTH * 21; + mobs.add(painter); + + } + @Override + public void press(int cell, Char ch) { + + TimekeepersHourglass.timeFreeze timeFreeze = null; + + if (ch != null) + timeFreeze = ch.buff(TimekeepersHourglass.timeFreeze.class); + + boolean trap = false; + boolean interrupt = false; + + + + switch (map[cell]) { + + + case Terrain.HIGH_GRASS: + HighGrass.trample(this, cell, ch); + break; + + case Terrain.WELL: + WellWater.affectCell(cell); + break; + + case Terrain.ALCHEMY: + Alchemy alchemy = new Alchemy(); + level.blobs.put( Alchemy.class, alchemy ); + break; + + case Terrain.PEDESTAL: + if (ch == null ) { + Alter.transmute(cell); + } + break; + + case Terrain.DOOR: + Door.enter(cell); + break; + } + + if (trap){ + + if (Dungeon.visible[cell]) + Sample.INSTANCE.play(Assets.SND_TRAP); + + if (ch == Dungeon.hero) + Dungeon.hero.interrupt(); + + set(cell, Terrain.INACTIVE_TRAP); + GameScene.updateMap(cell); + } + + if (interrupt){ + + Dungeon.hero.interrupt(); + GameScene.updateMap(cell); + } + + Plant plant = plants.get(cell); + if (plant != null) { + plant.activate(ch); + } + } + + @Override + public String tilesTex() { + return Assets.TILES_TOWN; + } + + @Override + public String waterTex() { + return Assets.WATER_PRISON; + } + + @Override + protected boolean build() { + + map = TownLayouts.TOWN_LAYOUT.clone(); + decorate(); + + buildFlagMaps(); + cleanWalls(); + + entrance = 25 + WIDTH * 21; + exit = 5 + WIDTH * 40; + + + return true; + } + @Override + protected void decorate() { + + } + + @Override + protected void createMobs() { + + } + @Override + public String tileName( int tile ) { + switch (tile) { + case Terrain.WATER: + return Messages.get(PrisonLevel.class, "water_name"); + default: + return super.tileName( tile ); + } + } + + @Override + public String tileDesc(int tile) { + switch (tile) { + case Terrain.EMPTY_DECO: + return Messages.get(PrisonLevel.class, "empty_deco_desc"); + case Terrain.BOOKSHELF: + return Messages.get(PrisonLevel.class, "bookshelf_desc"); + default: + return super.tileDesc( tile ); + } + } + + @Override + public int randomRespawnCell() { + return -1; + } + +} diff --git a/java/com/hmdzl/spspd/levels/SkeletonBossLevel.java b/java/com/hmdzl/spspd/levels/SkeletonBossLevel.java new file mode 100644 index 00000000..27e1fb40 --- /dev/null +++ b/java/com/hmdzl/spspd/levels/SkeletonBossLevel.java @@ -0,0 +1,279 @@ +/* + * 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 + */ +package com.hmdzl.spspd.levels; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.actors.mobs.SkeletonHand1; +import com.hmdzl.spspd.actors.mobs.SkeletonHand2; +import com.hmdzl.spspd.actors.mobs.SkeletonKing; +import com.hmdzl.spspd.items.Heap; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.keys.SkeletonKey; +import com.hmdzl.spspd.items.potions.PotionOfLiquidFlame; +import com.hmdzl.spspd.levels.painters.Painter; +import com.hmdzl.spspd.scenes.GameScene; +import com.watabou.noosa.Scene; +import com.watabou.noosa.tweeners.AlphaTweener; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public class SkeletonBossLevel extends Level { + + { + color1 = 0x6a723d; + color2 = 0x88924c; + cleared=true; + viewDistance = 8; + } + + private static final int TOP = 2; + private static final int HALL_WIDTH = 13; + private static final int HALL_HEIGHT = 15; + private static final int CHAMBER_HEIGHT = 3; + + private static final int LEFT = (getWidth() - HALL_WIDTH) / 2; + private static final int CENTER = LEFT + HALL_WIDTH / 2; + + private int arenaDoor; + private boolean enteredArena = false; + private boolean keyDropped = false; + + @Override + public String tilesTex() { + return Assets.TILES_SKELETON; + } + + @Override + public String waterTex() { + return Assets.WATER_PRISON; + } + + private static final String DOOR = "door"; + private static final String ENTERED = "entered"; + private static final String DROPPED = "droppped"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(DOOR, arenaDoor); + bundle.put(ENTERED, enteredArena); + bundle.put(DROPPED, keyDropped); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + arenaDoor = bundle.getInt(DOOR); + enteredArena = bundle.getBoolean(ENTERED); + keyDropped = bundle.getBoolean(DROPPED); + } + + @Override + protected boolean build() { + + Painter.fill(this, LEFT, TOP, HALL_WIDTH, HALL_HEIGHT, Terrain.EMPTY); + Painter.fill(this, CENTER, TOP, 1, HALL_HEIGHT, Terrain.EMPTY); + + int y = TOP + 1; + while (y < TOP + HALL_HEIGHT) { + map[y * getWidth() + CENTER - 2] = Terrain.STATUE; + map[y * getWidth() + CENTER + 2] = Terrain.STATUE; + y += 2; + } + + exit = (TOP - 1) * getWidth() + CENTER; + map[exit] = Terrain.LOCKED_EXIT; + + arenaDoor = (TOP + HALL_HEIGHT) * getWidth() + CENTER; + map[arenaDoor] = Terrain.DOOR; + + Painter.fill(this, LEFT, TOP + HALL_HEIGHT + 1, HALL_WIDTH, + CHAMBER_HEIGHT, Terrain.EMPTY); + Painter.fill(this, LEFT, TOP + HALL_HEIGHT + 1, 1, CHAMBER_HEIGHT, + Terrain.WATER); + Painter.fill(this, LEFT + HALL_WIDTH - 1, TOP + HALL_HEIGHT + 1, 1, + CHAMBER_HEIGHT, Terrain.WATER); + + entrance = (TOP + HALL_HEIGHT + 2 + Random.Int(CHAMBER_HEIGHT - 1)) + * getWidth() + LEFT + (/* 1 + */Random.Int(HALL_WIDTH - 2)); + map[entrance] = Terrain.PEDESTAL; + + map[exit] = Terrain.WALL; + + return true; + } + + @Override + protected void decorate() { + + for (int i = 0; i < getLength(); i++) { + if (map[i] == Terrain.EMPTY && Random.Int(10) == 0) { + map[i] = Terrain.EMPTY_DECO; + } else if (map[i] == Terrain.WALL && Random.Int(8) == 0) { + map[i] = Terrain.WALL_DECO; + } + } + + int shrub1 = arenaDoor + getWidth(); + int shrub2 = arenaDoor + getWidth() + 1; + int shrub3 = arenaDoor + getWidth() - 1; + int potionpos = arenaDoor + 2*getWidth(); + map[shrub1] = Terrain.SHRUB; + map[shrub2] = Terrain.SHRUB; + map[shrub3] = Terrain.SHRUB; + drop(new PotionOfLiquidFlame(), potionpos); + + for (int i = 0; i < getLength(); i++) { + if (map[i] == Terrain.WALL && Random.Int(8) == 0) { + map[i] = Terrain.WALL_DECO; + } + if (map[i]==Terrain.ENTRANCE){map[i] = Terrain.EMPTY;} + if (map[i]==Terrain.EMPTY && heaps.get(i) == null && Random.Float()<.20){map[i] = Terrain.HIGH_GRASS;} + if (map[i]==Terrain.EMPTY && heaps.get(i) == null && Random.Float()<.25){map[i] = Terrain.GRASS;} + if (map[i]==Terrain.EMPTY && heaps.get(i) == null && Random.Float()<.30){map[i] = Terrain.SHRUB;} + } + + //int sign = arenaDoor + WIDTH + 1; + //map[sign] = Terrain.SIGN; + } + + public static int pedestal(boolean left) { + if (left) { + return (TOP + HALL_HEIGHT / 2) * getWidth() + CENTER - 2; + } else { + return (TOP + HALL_HEIGHT / 2) * getWidth() + CENTER + 2; + } + } + + @Override + protected void createMobs() { + } + + @Override + public Actor respawner() { + return null; + } + + @Override + protected void createItems() { + + } + + @Override + public int randomRespawnCell() { + return -1; + } + + @Override + public void press(int cell, Char hero) { + + super.press(cell, hero); + + if (!enteredArena && outsideEntraceRoom(cell) && hero == Dungeon.hero) { + + enteredArena = true; + //locked = true; + + Mob boss = new SkeletonKing(); + Mob hand1 = new SkeletonHand1(); + Mob hand2 = new SkeletonHand2(); + boss.state = boss.HUNTING; + hand1.state = hand1.HUNTING; + hand2.state = hand2.HUNTING; + int count = 0; + do { + boss.pos = Random.Int(getLength()); + hand1.pos = (TOP + 1) * getWidth() + CENTER; + hand2.pos = (TOP + 1) * getWidth() + CENTER+1; + + } while (!passable[boss.pos] + || !outsideEntraceRoom(boss.pos) + || (Dungeon.visible[boss.pos] && count++ < 20)); + + GameScene.add(boss); + + GameScene.add(hand1); + GameScene.add(hand2); + + + if (Dungeon.visible[boss.pos]) { + boss.notice(); + boss.sprite.alpha(0); + boss.sprite.parent.add(new AlphaTweener(boss.sprite, 1, 0.1f)); + } + + //set(arenaDoor, Terrain.WALL); + //GameScene.updateMap(arenaDoor); + Dungeon.observe(); + } + } + + @Override + public Heap drop(Item item, int cell) { + + if (!keyDropped && item instanceof SkeletonKey) { + + keyDropped = true; + locked = false; + + set(arenaDoor, Terrain.DOOR); + GameScene.updateMap(arenaDoor); + Dungeon.observe(); + } + + return super.drop(item, cell); + } + + private boolean outsideEntraceRoom(int cell) { + return cell / getWidth() < arenaDoor / getWidth(); + } + + public String tileName(int tile) { + switch (tile) { + case Terrain.WATER: + return "Dark cold water."; + case Terrain.HIGH_GRASS: + return "Ancient pottery."; + default: + return super.tileName(tile); + } + } + + @Override + public String tileDesc(int tile) { + switch (tile) { + case Terrain.EMPTY_DECO: + return "Oddly shaped bones are piled up here. Good thing they are not animated. "; + case Terrain.HIGH_GRASS: + return "Ancient pottery litters the floor."; + case Terrain.BOOKSHELF: + return "The bookshelf is packed with cheap useless books. Might it burn?"; + default: + return super.tileDesc(tile); + } + } + + @Override + public void addVisuals(Scene scene) { + CityLevel.addVisuals(this, scene); + } +} diff --git a/java/com/hmdzl/spspd/levels/SokobanCastle.java b/java/com/hmdzl/spspd/levels/SokobanCastle.java new file mode 100644 index 00000000..90a2319f --- /dev/null +++ b/java/com/hmdzl/spspd/levels/SokobanCastle.java @@ -0,0 +1,661 @@ +/* + * 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 + */ +package com.hmdzl.spspd.levels; + +import java.util.Collection; +import java.util.HashSet; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.WellWater; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.actors.mobs.SokobanSentinel; +import com.hmdzl.spspd.actors.mobs.npcs.Sheep; +import com.hmdzl.spspd.actors.mobs.npcs.SheepSokoban; +import com.hmdzl.spspd.actors.mobs.npcs.SheepSokobanBlack; +import com.hmdzl.spspd.actors.mobs.npcs.SheepSokobanCorner; +import com.hmdzl.spspd.actors.mobs.npcs.SheepSokobanSwitch; +import com.hmdzl.spspd.items.Gold; +import com.hmdzl.spspd.items.Heap; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.artifacts.TimekeepersHourglass; +import com.hmdzl.spspd.items.keys.IronKey; +import com.hmdzl.spspd.items.misc.Spectacles; +import com.hmdzl.spspd.items.potions.PotionOfLiquidFlame; +import com.hmdzl.spspd.items.scrolls.ScrollOfMagicalInfusion; +import com.hmdzl.spspd.items.scrolls.ScrollOfRegrowth; +import com.hmdzl.spspd.items.scrolls.ScrollOfUpgrade; + +import com.hmdzl.spspd.items.wands.WandOfFlock; +import com.hmdzl.spspd.levels.features.Chasm; +import com.hmdzl.spspd.levels.features.Door; +import com.hmdzl.spspd.levels.features.HighGrass; +import com.hmdzl.spspd.levels.traps.ActivatePortalTrap; +import com.hmdzl.spspd.levels.traps.ChangeSheepTrap; +import com.hmdzl.spspd.levels.traps.FleecingTrap; +import com.hmdzl.spspd.levels.traps.HeapGenTrap; +import com.hmdzl.spspd.levels.traps.SokobanPortalTrap; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.plants.Phaseshift; +import com.hmdzl.spspd.plants.Plant; +import com.hmdzl.spspd.plants.Starflower; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Bundlable; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public class SokobanCastle extends Level { + + + { + color1 = 0x534f3e; + color2 = 0xb9d661; + WIDTH = 48; + HEIGHT = 48; + LENGTH = HEIGHT*WIDTH; + } + + + public HashSet heapstogen; + public int[] heapgenspots; + public int[] teleportspots; + public int[] portswitchspots; + public int[] teleportassign; + public int[] destinationspots; + public int[] destinationassign; + public int prizeNo; + + private static final String HEAPSTOGEN = "heapstogen"; + private static final String HEAPGENSPOTS = "heapgenspots"; + private static final String TELEPORTSPOTS = "teleportspots"; + private static final String PORTSWITCHSPOTS = "portswitchspots"; + private static final String DESTINATIONSPOTS = "destinationspots"; + private static final String TELEPORTASSIGN = "teleportassign"; + private static final String DESTINATIONASSIGN= "destinationassign"; + private static final String PRIZENO = "prizeNo"; + + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(HEAPSTOGEN, heapstogen); + bundle.put(HEAPGENSPOTS, heapgenspots); + bundle.put(TELEPORTSPOTS, teleportspots); + bundle.put(PORTSWITCHSPOTS, portswitchspots); + bundle.put(DESTINATIONSPOTS, destinationspots); + bundle.put(DESTINATIONASSIGN, destinationassign); + bundle.put(TELEPORTASSIGN, teleportassign); + bundle.put(PRIZENO, prizeNo); + } + + + @Override + public String tileName(int tile) { + switch (tile) { + case Terrain.SOKOBAN_SHEEP: + case Terrain.SWITCH_SOKOBAN_SHEEP: + case Terrain.CORNER_SOKOBAN_SHEEP: + case Terrain.BLACK_SOKOBAN_SHEEP: + return Messages.get(Level.class, "floor_name"); + case Terrain.WATER: + return Messages.get(Level.class, "water_name"); + case Terrain.WOOL_RUG: + return Messages.get(Level.class, "wool_rug_name"); + case Terrain.FLEECING_TRAP: + return Messages.get(Level.class, "fleecing_trap_name"); + case Terrain.CHANGE_SHEEP_TRAP: + return Messages.get(Level.class, "change_sheep_trap_name"); + case Terrain.SOKOBAN_ITEM_REVEAL: + return Messages.get(Level.class, "sokoban_item_reveal_name"); + case Terrain.SOKOBAN_PORT_SWITCH: + return Messages.get(Level.class, "sokoban_port_switch_name"); + case Terrain.PORT_WELL: + return Messages.get(Level.class, "port_well_name"); + default: + return super.tileName(tile); + } + } + + + @Override + public String tileDesc(int tile) { + switch (tile) { + case Terrain.SOKOBAN_SHEEP: + case Terrain.SWITCH_SOKOBAN_SHEEP: + case Terrain.CORNER_SOKOBAN_SHEEP: + case Terrain.BLACK_SOKOBAN_SHEEP: + return Messages.get(Level.class, "default_desc"); + case Terrain.EMPTY_DECO: + return Messages.get(PrisonLevel.class, "empty_deco_desc"); + case Terrain.BOOKSHELF: + return Messages.get(PrisonLevel.class, "bookshelf_desc"); + case Terrain.WOOL_RUG: + return Messages.get(Level.class, "wool_rug_desc"); + case Terrain.FLEECING_TRAP: + return Messages.get(Level.class, "fleecing_trap_desc"); + case Terrain.CHANGE_SHEEP_TRAP: + return Messages.get(Level.class, "change_sheep_trap_desc"); + case Terrain.SOKOBAN_ITEM_REVEAL: + return Messages.get(Level.class, "sokoban_item_reveal_desc"); + case Terrain.SOKOBAN_PORT_SWITCH: + return Messages.get(Level.class, "sokoban_port_switch_desc"); + case Terrain.PORT_WELL: + return Messages.get(Level.class, "port_well_desc"); + default: + return super.tileDesc(tile); + } + } + + + @Override + public void restoreFromBundle(Bundle bundle) { + + super.restoreFromBundle(bundle); + + heapgenspots = bundle.getIntArray(HEAPGENSPOTS); + teleportspots = bundle.getIntArray(TELEPORTSPOTS); + portswitchspots = bundle.getIntArray(PORTSWITCHSPOTS); + destinationspots = bundle.getIntArray(DESTINATIONSPOTS); + destinationassign = bundle.getIntArray(DESTINATIONASSIGN); + teleportassign = bundle.getIntArray(TELEPORTASSIGN); + prizeNo = bundle.getInt(PRIZENO); + + heapstogen = new HashSet(); + + Collection collectionheap = bundle.getCollection(HEAPSTOGEN); + for (Bundlable i : collectionheap) { + Item item = (Item) i; + if (item != null) { + heapstogen.add(item); + } + } + } + + @Override + public void create() { + heapstogen = new HashSet(); + heapgenspots = new int[20]; + teleportspots = new int[10]; + portswitchspots = new int[10]; + destinationspots = new int[10]; + destinationassign = new int[10]; + teleportassign = new int[10]; + super.create(); + } + + public void addItemToGen(Item item, int arraypos, int pos) { + if (item != null) { + heapstogen.add(item); + heapgenspots[arraypos]=pos; + } + } + + + public Item genPrizeItem() { + return genPrizeItem(null); + } + + + public Item genPrizeItem(Class match) { + + boolean keysLeft = false; + + if (heapstogen.size() == 0) + return null; + + for (Item item : heapstogen) { + if (match.isInstance(item)) { + heapstogen.remove(item); + keysLeft=true; + return item; + } + } + + if (match == null || !keysLeft) { + Item item = Random.element(heapstogen); + heapstogen.remove(item); + return item; + } + + return null; + } + + @Override + public void press(int cell, Char ch) { + + if (pit[cell] && ch == Dungeon.hero) { + Chasm.heroFall(cell); + return; + } + + TimekeepersHourglass.timeFreeze timeFreeze = null; + + if (ch != null) + timeFreeze = ch.buff(TimekeepersHourglass.timeFreeze.class); + + boolean trap = false; + + switch (map[cell]) { + + case Terrain.FLEECING_TRAP: + + if (ch != null && ch==Dungeon.hero){ + trap = true; + FleecingTrap.trigger(cell, ch); + } + break; + + case Terrain.CHANGE_SHEEP_TRAP: + + if (ch instanceof SheepSokoban || ch instanceof SheepSokobanSwitch || ch instanceof SheepSokobanCorner || ch instanceof Sheep || ch instanceof WandOfFlock.MagicSheep){ + trap = true; + ChangeSheepTrap.trigger(cell, ch); + } + break; + + case Terrain.PORT_WELL: + + if (ch != null && ch==Dungeon.hero){ + + int portarray=-1; + int destinationspot=cell; + + for(int i = 0; i < teleportspots.length; i++) { + if(teleportspots[i] == cell) { + portarray = i; + break; + } + } + + if(portarray != -1) { + destinationspot=destinationspots[portarray]; + if (destinationspot>0){ + SokobanPortalTrap.trigger(cell, ch, destinationspot); + } + } + } + break; + + case Terrain.SOKOBAN_PORT_SWITCH: + trap=false; + ActivatePortalTrap.trigger(cell, ch); + + /* + int arraypos = -1; //position in array of teleport switch + int portpos = -1; //position on map of teleporter + int portarraypos = -1; //position in array of teleporter + int destpos = -1; //destination position assigned to switch + + for(int i = 0; i < portswitchspots.length; i++) { + if(portswitchspots[i] == cell) { + arraypos = i; + // GLog.i("Pos1 %s", arraypos); + break; + } + } + + portpos = teleportassign[arraypos]; + destpos = destinationassign[arraypos]; + + // Stepping on switch deactivates the portal + destpos = -1; + + //GLog.i("ass2 %s", portpos); + // GLog.i("dest3 %s", destpos); + + for(int i = 0; i < teleportspots.length; i++) { + if(teleportspots[i] == portpos) { + portarraypos = i; + // GLog.i("Pos4 %s", portarraypos); + break; + } + } + + if (map[portpos] == Terrain.PORT_WELL){ + destinationspots[portarraypos]=destpos; + //GLog.i("Pos5 %s", destpos); + GLog.i("Portal Deactivated!"); + } + + */ + + break; + + + case Terrain.HIGH_GRASS: + HighGrass.trample(this, cell, ch); + break; + + case Terrain.WELL: + WellWater.affectCell(cell); + break; + + /*case Terrain.ALCHEMY: + if (ch == null) { + Alchemy.transmute(cell); + } + break;*/ + + case Terrain.DOOR: + Door.enter(cell); + break; + } + + if (trap){ + + if (Dungeon.visible[cell]) + Sample.INSTANCE.play(Assets.SND_TRAP); + + if (ch == Dungeon.hero) + Dungeon.hero.interrupt(); + + set(cell, Terrain.INACTIVE_TRAP); + GameScene.updateMap(cell); + } + + Plant plant = plants.get(cell); + if (plant != null) { + plant.activate(ch); + } + } + + + + @Override + public void mobPress(Mob mob) { + + int cell = mob.pos; + + if (pit[cell] && !mob.flying) { + Chasm.mobFall(mob); + return; + } + + boolean trap = true; + boolean fleece = false; + boolean sheep = false; + switch (map[cell]) { + + case Terrain.FLEECING_TRAP: + if (mob instanceof SheepSokoban || mob instanceof SheepSokobanSwitch || mob instanceof SheepSokobanCorner || mob instanceof SheepSokobanBlack || mob instanceof Sheep || mob instanceof WandOfFlock.MagicSheep){ + fleece=true; + } + FleecingTrap.trigger(cell, mob); + break; + + case Terrain.CHANGE_SHEEP_TRAP: + trap=false; + if (mob instanceof SheepSokoban || mob instanceof SheepSokobanSwitch || mob instanceof SheepSokobanCorner || mob instanceof Sheep || mob instanceof WandOfFlock.MagicSheep){ + trap=true; + ChangeSheepTrap.trigger(cell, mob); + } + break; + + case Terrain.SOKOBAN_ITEM_REVEAL: + trap=false; + if (mob instanceof SheepSokoban || mob instanceof SheepSokobanSwitch || mob instanceof SheepSokobanCorner || mob instanceof SheepSokobanBlack || mob instanceof Sheep || mob instanceof WandOfFlock.MagicSheep){ + HeapGenTrap.trigger(cell, mob); + drop(genPrizeItem(IronKey.class),heapgenspots[prizeNo]); + prizeNo++; + sheep=true; + trap=true; + } + break; + + case Terrain.SOKOBAN_PORT_SWITCH: + trap=false; + if (mob instanceof SheepSokoban || mob instanceof SheepSokobanSwitch || mob instanceof SheepSokobanCorner || mob instanceof SheepSokobanBlack || mob instanceof Sheep || mob instanceof WandOfFlock.MagicSheep){ + ActivatePortalTrap.trigger(cell, mob); + + /* + public int[] teleportspots; location of teleports + public int[] portswitchspots; location of switches + public int[] teleportassign; assignment of teleports to switches + public int[] destinationspots; current assignment of destination spots to teleports + public int[] destinationassign; assignemnt of destination spots to switches + */ + + int arraypos = -1; //position in array of teleport switch + int portpos = -1; //position on map of teleporter + int portarray = -1; //position in array of teleporter + int destpos = -1; //destination position assigned to switch + + for(int i = 0; i < portswitchspots.length; i++) { + if(portswitchspots[i] == cell) { + arraypos = i; + //GLog.i("Pos1 %s", arraypos); + break; + } + } + + portpos = teleportassign[arraypos]; + destpos = destinationassign[arraypos]; + + //GLog.i("ass2 %s", portpos); + //GLog.i("dest3 %s", destpos); + + for(int i = 0; i < teleportspots.length; i++) { + if(teleportspots[i] == portpos) { + portarray = i; + //GLog.i("Pos4 %s", portarray); + break; + } + } + + if (map[portpos] == Terrain.PORT_WELL){ + destinationspots[portarray]=destpos; + //GLog.i("Pos5 %s", destpos); + GLog.i("Click!"); + } + + sheep=true; + } + break; + + case Terrain.DOOR: + Door.enter(cell); + + default: + trap = false; + } + + if (trap && !fleece && !sheep) { + if (Dungeon.visible[cell]) { + Sample.INSTANCE.play(Assets.SND_TRAP); + } + set(cell, Terrain.INACTIVE_TRAP); + GameScene.updateMap(cell); + } + + if (trap && fleece) { + if (Dungeon.visible[cell]) { + Sample.INSTANCE.play(Assets.SND_TRAP); + } + set(cell, Terrain.WOOL_RUG); + GameScene.updateMap(cell); + } + + if (trap && sheep) { + if (Dungeon.visible[cell]) { + Sample.INSTANCE.play(Assets.SND_TRAP); + } + set(cell, Terrain.EMPTY); + GameScene.updateMap(cell); + } + + + Plant plant = plants.get(cell); + if (plant != null) { + plant.activate(mob); + } + + Dungeon.observe(); + } + + @Override + public String tilesTex() { + return Assets.TILES_PUZZLE; + } + + @Override + public String waterTex() { + return Assets.WATER_PRISON; + } + + @Override + protected boolean build() { + + map = SokobanLayouts.SOKOBAN_CASTLE.clone(); + decorate(); + + buildFlagMaps(); + cleanWalls(); + createSwitches(); + createSheep(); + + entrance = 24 + WIDTH * 22; + exit = 0; + + + return true; + } + @Override + protected void decorate() { + //do nothing, all decorations are hard-coded. + } + + @Override + protected void createMobs() { + + /* + SokobanSentinel mob = new SokobanSentinel(); + mob.pos = 38 + WIDTH * 21; + mobs.add(mob); + Actor.occupyCell(mob); + */ + SokobanSentinel mob2 = new SokobanSentinel(); + mob2.pos = 38 + WIDTH * 20; + mobs.add(mob2); + Actor.occupyCell(mob2); + /* + SokobanSentinel mob3 = new SokobanSentinel(); + mob3.pos = 2 + WIDTH * 43; + mobs.add(mob3); + Actor.occupyCell(mob3); + */ + /* + AdultDragonViolet mob3 = new AdultDragonViolet(); + mob3.pos = 18 + WIDTH * 23; + mobs.add(mob3); + Actor.occupyCell(mob3); + */ + } + + + + protected void createSheep() { + for (int i = 0; i < LENGTH; i++) { + if (map[i]==Terrain.SOKOBAN_SHEEP){SheepSokoban npc = new SheepSokoban(); mobs.add(npc); npc.pos = i; Actor.occupyCell(npc);} + else if (map[i]==Terrain.CORNER_SOKOBAN_SHEEP){SheepSokobanCorner npc = new SheepSokobanCorner(); mobs.add(npc); npc.pos = i; Actor.occupyCell(npc);} + else if (map[i]==Terrain.SWITCH_SOKOBAN_SHEEP){SheepSokobanSwitch npc = new SheepSokobanSwitch(); mobs.add(npc); npc.pos = i; Actor.occupyCell(npc);} + else if (map[i]==Terrain.BLACK_SOKOBAN_SHEEP){SheepSokobanBlack npc = new SheepSokobanBlack(); mobs.add(npc); npc.pos = i; Actor.occupyCell(npc);} + else if (map[i]==Terrain.PORT_WELL){ + /* + Portal portal = new Portal(); + portal.seed(i, 1); + blobs.put(Portal.class, portal); + */ + } + + } + } + + + protected void createSwitches(){ + + //spots where your portals are + teleportspots[0] = 4 + WIDTH * 3; + teleportspots[1] = 7 + WIDTH * 27; + teleportspots[2] = 37 + WIDTH * 35; + + + //spots where your portal switches are + portswitchspots[0] = 32 + WIDTH * 40; + + + //assign each switch to a portal + teleportassign[0] = 37 + WIDTH * 35; + + + //assign each switch to a destination spot + destinationassign[0] = 9 + WIDTH * 37; + + + //set the original destination of portals + destinationspots[0] = 24 + WIDTH * 22; //6 + WIDTH * 5; + destinationspots[1] = 1 + WIDTH * 27; + destinationspots[2] = 0; + + + } + + + @Override + protected void createItems() { + int goldmin=300; int goldmax=500; + if (first){ + goldmin=400; goldmax=800; + } + for (int i = 0; i < LENGTH; i++) { + if (map[i]==Terrain.SOKOBAN_HEAP){ + if (first && Random.Int(5)==0){drop(new ScrollOfUpgrade(), i).type = Heap.Type.CHEST;} + else {drop(new Gold(Random.Int(goldmin, goldmax)), i).type = Heap.Type.CHEST;} + } + } + + addItemToGen(new IronKey(Dungeon.depth) , 0, 24 + WIDTH * 22); + addItemToGen(new IronKey(Dungeon.depth) , 1, 24 + WIDTH * 22); + addItemToGen(new IronKey(Dungeon.depth) , 2, 24 + WIDTH * 22); + addItemToGen(new IronKey(Dungeon.depth) , 3, 24 + WIDTH * 22); + addItemToGen(new IronKey(Dungeon.depth) , 4, 24 + WIDTH * 22); + addItemToGen(new IronKey(Dungeon.depth) , 5, 24 + WIDTH * 22); + + + if (first){ + addItemToGen(new Phaseshift.Seed() , 6, 30 + WIDTH * 23); + addItemToGen(new Starflower.Seed() , 7, 18 + WIDTH * 23); + addItemToGen(new Spectacles() , 8, 25 + WIDTH * 2); + addItemToGen(new ScrollOfMagicalInfusion() , 9, 26 + WIDTH * 2); + addItemToGen(new ScrollOfMagicalInfusion() , 10, 8 + WIDTH * 37); + addItemToGen(new ScrollOfRegrowth() , 11, 10 + WIDTH * 37); + } + + drop(new PotionOfLiquidFlame(), 9 + WIDTH * 24).type = Heap.Type.CHEST; + } + + @Override + public int randomRespawnCell() { + return -1; + } + + +} diff --git a/java/com/hmdzl/spspd/levels/SokobanIntroLevel.java b/java/com/hmdzl/spspd/levels/SokobanIntroLevel.java new file mode 100644 index 00000000..2d48d95c --- /dev/null +++ b/java/com/hmdzl/spspd/levels/SokobanIntroLevel.java @@ -0,0 +1,646 @@ +/* + * 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 + */ +package com.hmdzl.spspd.levels; + +import java.util.Collection; +import java.util.HashSet; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.WellWater; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.actors.mobs.npcs.Sheep; +import com.hmdzl.spspd.actors.mobs.npcs.SheepSokoban; +import com.hmdzl.spspd.actors.mobs.npcs.SheepSokobanBlack; +import com.hmdzl.spspd.actors.mobs.npcs.SheepSokobanCorner; +import com.hmdzl.spspd.actors.mobs.npcs.SheepSokobanSwitch; +import com.hmdzl.spspd.items.Gold; +import com.hmdzl.spspd.items.Heap; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.Towel; +import com.hmdzl.spspd.items.artifacts.TimekeepersHourglass; +import com.hmdzl.spspd.items.keys.IronKey; +import com.hmdzl.spspd.items.scrolls.ScrollOfUpgrade; + +import com.hmdzl.spspd.items.wands.WandOfFlock; +import com.hmdzl.spspd.levels.features.Chasm; +import com.hmdzl.spspd.levels.features.Door; +import com.hmdzl.spspd.levels.features.HighGrass; +import com.hmdzl.spspd.levels.traps.ActivatePortalTrap; +import com.hmdzl.spspd.levels.traps.ChangeSheepTrap; +import com.hmdzl.spspd.levels.traps.FleecingTrap; +import com.hmdzl.spspd.levels.traps.HeapGenTrap; +import com.hmdzl.spspd.levels.traps.SokobanPortalTrap; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.plants.Plant; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Bundlable; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public class SokobanIntroLevel extends Level { + + + { + color1 = 0x534f3e; + color2 = 0xb9d661; + WIDTH = 48; + HEIGHT = 48; + LENGTH = HEIGHT*WIDTH; + } + + + public HashSet heapstogen; + public int[] heapgenspots; + public int[] teleportspots; + public int[] portswitchspots; + public int[] teleportassign; + public int[] destinationspots; + public int[] destinationassign; + public int prizeNo; + + private static final String HEAPSTOGEN = "heapstogen"; + private static final String HEAPGENSPOTS = "heapgenspots"; + private static final String TELEPORTSPOTS = "teleportspots"; + private static final String PORTSWITCHSPOTS = "portswitchspots"; + private static final String DESTINATIONSPOTS = "destinationspots"; + private static final String TELEPORTASSIGN = "teleportassign"; + private static final String DESTINATIONASSIGN= "destinationassign"; + private static final String PRIZENO = "prizeNo"; + + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(HEAPSTOGEN, heapstogen); + bundle.put(HEAPGENSPOTS, heapgenspots); + bundle.put(TELEPORTSPOTS, teleportspots); + bundle.put(PORTSWITCHSPOTS, portswitchspots); + bundle.put(DESTINATIONSPOTS, destinationspots); + bundle.put(DESTINATIONASSIGN, destinationassign); + bundle.put(TELEPORTASSIGN, teleportassign); + bundle.put(PRIZENO, prizeNo); + } + + + + @Override + public void restoreFromBundle(Bundle bundle) { + + super.restoreFromBundle(bundle); + + heapgenspots = bundle.getIntArray(HEAPGENSPOTS); + teleportspots = bundle.getIntArray(TELEPORTSPOTS); + portswitchspots = bundle.getIntArray(PORTSWITCHSPOTS); + destinationspots = bundle.getIntArray(DESTINATIONSPOTS); + destinationassign = bundle.getIntArray(DESTINATIONASSIGN); + teleportassign = bundle.getIntArray(TELEPORTASSIGN); + prizeNo = bundle.getInt(PRIZENO); + + heapstogen = new HashSet(); + + Collection collectionheap = bundle.getCollection(HEAPSTOGEN); + for (Bundlable i : collectionheap) { + Item item = (Item) i; + if (item != null) { + heapstogen.add(item); + } + } + } + + @Override + public void create() { + heapstogen = new HashSet(); + heapgenspots = new int[10]; + teleportspots = new int[10]; + portswitchspots = new int[10]; + destinationspots = new int[10]; + destinationassign = new int[10]; + teleportassign = new int[10]; + super.create(); + } + + public void addItemToGen(Item item, int arraypos, int pos) { + if (item != null) { + heapstogen.add(item); + heapgenspots[arraypos]=pos; + } + } + + + public Item genPrizeItem() { + return genPrizeItem(null); + } + + + public Item genPrizeItem(Class match) { + + boolean keysLeft = false; + + if (heapstogen.size() == 0) + return null; + + for (Item item : heapstogen) { + if (match.isInstance(item)) { + heapstogen.remove(item); + keysLeft=true; + return item; + } + } + + if (match == null || !keysLeft) { + Item item = Random.element(heapstogen); + heapstogen.remove(item); + return item; + } + + return null; + } + + @Override + public void press(int cell, Char ch) { + + if (pit[cell] && ch == Dungeon.hero) { + Chasm.heroFall(cell); + return; + } + + TimekeepersHourglass.timeFreeze timeFreeze = null; + + if (ch != null) + timeFreeze = ch.buff(TimekeepersHourglass.timeFreeze.class); + + boolean trap = false; + boolean interrupt = false; + + switch (map[cell]) { + + case Terrain.FLEECING_TRAP: + + if (ch==null){ + interrupt=true; + } + + if (ch != null && ch==Dungeon.hero){ + trap = true; + FleecingTrap.trigger(cell, ch); + } + break; + + case Terrain.CHANGE_SHEEP_TRAP: + + if (ch instanceof SheepSokoban || ch instanceof SheepSokobanSwitch || ch instanceof SheepSokobanCorner || ch instanceof Sheep || ch instanceof WandOfFlock.MagicSheep){ + trap = true; + ChangeSheepTrap.trigger(cell, ch); + } + break; + + case Terrain.WOOL_RUG: + + break; + + case Terrain.SOKOBAN_PORT_SWITCH: + trap=false; + if (ch!=null){ + ActivatePortalTrap.trigger(cell, ch); + + /* + int arraypos = -1; //position in array of teleport switch + int portpos = -1; //position on map of teleporter + int portarraypos = -1; //position in array of teleporter + int destpos = -1; //destination position assigned to switch + + for(int i = 0; i < portswitchspots.length; i++) { + if(portswitchspots[i] == cell) { + arraypos = i; + break; + } + } + + portpos = teleportassign[arraypos]; + destpos = destinationassign[arraypos]; + + // Stepping on switch deactivates the portal + destpos = -1; + + for(int i = 0; i < teleportspots.length; i++) { + if(teleportspots[i] == portpos) { + portarraypos = i; + break; + } + } + + if (map[portpos] == Terrain.PORT_WELL){ + destinationspots[portarraypos]=destpos; + GLog.i("Portal Deactivated!"); + } + + */ + } + break; + + + case Terrain.PORT_WELL: + + if (ch != null && ch==Dungeon.hero){ + + int portarray=-1; + int destinationspot=cell; + + for(int i = 0; i < teleportspots.length; i++) { + if(teleportspots[i] == cell) { + portarray = i; + break; + } + } + + if(portarray != -1) { + destinationspot=destinationspots[portarray]; + if (destinationspot>0){ + SokobanPortalTrap.trigger(cell, ch, destinationspot); + } + } + } + break; + + case Terrain.HIGH_GRASS: + HighGrass.trample(this, cell, ch); + break; + + case Terrain.WELL: + WellWater.affectCell(cell); + break; + + /*case Terrain.ALCHEMY: + if (ch == null) { + Alchemy.transmute(cell); + } + break;*/ + + case Terrain.DOOR: + Door.enter(cell); + break; + } + + if (trap){ + + if (Dungeon.visible[cell]) + Sample.INSTANCE.play(Assets.SND_TRAP); + + if (ch == Dungeon.hero) + Dungeon.hero.interrupt(); + + set(cell, Terrain.INACTIVE_TRAP); + GameScene.updateMap(cell); + } + + if (interrupt){ + + Dungeon.hero.interrupt(); + GameScene.updateMap(cell); + } + + Plant plant = plants.get(cell); + if (plant != null) { + plant.activate(ch); + } + } + + + + @Override + public void mobPress(Mob mob) { + + int cell = mob.pos; + + if (pit[cell] && !mob.flying) { + Chasm.mobFall(mob); + return; + } + + boolean trap = true; + boolean fleece = false; + boolean sheep = false; + switch (map[cell]) { + + case Terrain.FLEECING_TRAP: + if (mob instanceof SheepSokoban || mob instanceof SheepSokobanSwitch || mob instanceof SheepSokobanCorner || mob instanceof SheepSokobanBlack || mob instanceof Sheep || mob instanceof WandOfFlock.MagicSheep){ + fleece=true; + } + FleecingTrap.trigger(cell, mob); + break; + + case Terrain.CHANGE_SHEEP_TRAP: + trap=false; + if (mob instanceof SheepSokoban || mob instanceof SheepSokobanSwitch || mob instanceof SheepSokobanCorner || mob instanceof Sheep || mob instanceof WandOfFlock.MagicSheep){ + trap=true; + ChangeSheepTrap.trigger(cell, mob); + } + break; + + case Terrain.SOKOBAN_ITEM_REVEAL: + trap=false; + if (mob instanceof SheepSokoban || mob instanceof SheepSokobanSwitch || mob instanceof SheepSokobanCorner || mob instanceof SheepSokobanBlack || mob instanceof Sheep || mob instanceof WandOfFlock.MagicSheep){ + HeapGenTrap.trigger(cell, mob); + drop(genPrizeItem(IronKey.class),heapgenspots[prizeNo]); + prizeNo++; + sheep=true; + trap=true; + } + break; + + case Terrain.SOKOBAN_PORT_SWITCH: + trap=false; + if (mob instanceof SheepSokoban || mob instanceof SheepSokobanSwitch || mob instanceof SheepSokobanCorner || mob instanceof SheepSokobanBlack || mob instanceof Sheep || mob instanceof WandOfFlock.MagicSheep){ + ActivatePortalTrap.trigger(cell, mob); + + /* + public int[] teleportspots; location of teleports + public int[] portswitchspots; location of switches + public int[] teleportassign; assignment of teleports to switches + public int[] destinationspots; current assignment of destination spots to teleports + public int[] destinationassign; assignemnt of destination spots to switches + */ + + int arraypos = -1; //position in array of teleport switch + int portpos = -1; //position on map of teleporter + int portarray = -1; //position in array of teleporter + int destpos = -1; //destination position assigned to switch + + for(int i = 0; i < portswitchspots.length; i++) { + if(portswitchspots[i] == cell) { + arraypos = i; + break; + } + } + + portpos = teleportassign[arraypos]; + destpos = destinationassign[arraypos]; + + for(int i = 0; i < teleportspots.length; i++) { + if(teleportspots[i] == portpos) { + portarray = i; + break; + } + } + + if (map[portpos] == Terrain.PORT_WELL){ + destinationspots[portarray]=destpos; + GLog.i("Click!"); + } + + sheep=true; + } + break; + + case Terrain.DOOR: + Door.enter(cell); + + default: + trap = false; + } + + if (trap && !fleece && !sheep) { + if (Dungeon.visible[cell]) { + Sample.INSTANCE.play(Assets.SND_TRAP); + } + set(cell, Terrain.INACTIVE_TRAP); + GameScene.updateMap(cell); + } + + if (trap && fleece) { + if (Dungeon.visible[cell]) { + Sample.INSTANCE.play(Assets.SND_TRAP); + } + set(cell, Terrain.WOOL_RUG); + GameScene.updateMap(cell); + } + + if (trap && sheep) { + if (Dungeon.visible[cell]) { + Sample.INSTANCE.play(Assets.SND_TRAP); + } + set(cell, Terrain.EMPTY); + GameScene.updateMap(cell); + } + + + Plant plant = plants.get(cell); + if (plant != null) { + plant.activate(mob); + } + + Dungeon.observe(); + } + + @Override + public String tilesTex() { + return Assets.TILES_PUZZLE; + } + + @Override + public String waterTex() { + return Assets.WATER_PRISON; + } + + @Override + protected boolean build() { + + map = SokobanLayouts.SOKOBAN_INTRO_LEVEL.clone(); + decorate(); + + buildFlagMaps(); + cleanWalls(); + createSwitches(); + createSheep(); + + entrance = 7 + WIDTH * 3; + exit = 0 ; + + + return true; + } + + + @Override + protected void decorate() { + //do nothing, all decorations are hard-coded. + } + + @Override + protected void createMobs() { + /* + SokobanSentinel mob = new SokobanSentinel(); + mob.pos = 38 + WIDTH * 21; + mobs.add(mob); + Actor.occupyCell(mob); + + SokobanSentinel mob2 = new SokobanSentinel(); + mob2.pos = 25 + WIDTH * 36; + mobs.add(mob2); + Actor.occupyCell(mob2); + */ + } + + +/* + public static final int FLEECING_TRAP = 65; + public static final int WOOL_RUG = 66; + public static final int SOKOBAN_SHEEP = 67; + public static final int CORNER_SOKOBAN_SHEEP = 68; + public static final int SWITCH_SOKOBAN_SHEEP = 69; + public static final int CHANGE_SHEEP_TRAP = 70; + public static final int SOKOBAN_ITEM_REVEAL = 71; + public static final int SOKOBAN_HEAP = 72; + public static final int BLACK_SOKOBAN_SHEEP = 73; + public static final int SOKOBAN_PORT_SWITCH = 75; + public static final int PORT_WELL = 74; + +*/ + + protected void createSheep() { + for (int i = 0; i < LENGTH; i++) { + if (map[i]==Terrain.SOKOBAN_SHEEP){SheepSokoban npc = new SheepSokoban(); mobs.add(npc); npc.pos = i; Actor.occupyCell(npc);} + else if (map[i]==Terrain.CORNER_SOKOBAN_SHEEP){SheepSokobanCorner npc = new SheepSokobanCorner(); mobs.add(npc); npc.pos = i; Actor.occupyCell(npc);} + else if (map[i]==Terrain.SWITCH_SOKOBAN_SHEEP){SheepSokobanSwitch npc = new SheepSokobanSwitch(); mobs.add(npc); npc.pos = i; Actor.occupyCell(npc);} + else if (map[i]==Terrain.BLACK_SOKOBAN_SHEEP){SheepSokobanBlack npc = new SheepSokobanBlack(); mobs.add(npc); npc.pos = i; Actor.occupyCell(npc);} + else if (map[i]==Terrain.PORT_WELL){ + + /* + Portal portal = new Portal(); + portal.seed(i, 1); + blobs.put(Portal.class, portal); + */ + } + + } + } + + + protected void createSwitches(){ + + //spots where your portals are + teleportspots[0] = 7 + WIDTH * 21; + + //spots where your portal switches are + portswitchspots[0] = 8 + WIDTH * 27; + + //assign each switch to a portal + teleportassign[0] = 7 + WIDTH * 21; + + //assign each switch to a destination spot + destinationassign[0] = 34 + WIDTH * 8; + + //set the original destination of portals + destinationspots[0] = 0; + } + + + @Override + public String tileName(int tile) { + switch (tile) { + case Terrain.SOKOBAN_SHEEP: + case Terrain.SWITCH_SOKOBAN_SHEEP: + case Terrain.CORNER_SOKOBAN_SHEEP: + case Terrain.BLACK_SOKOBAN_SHEEP: + return Messages.get(Level.class, "floor_name"); + case Terrain.WATER: + return Messages.get(Level.class, "water_name"); + case Terrain.WOOL_RUG: + return Messages.get(Level.class, "wool_rug_name"); + case Terrain.FLEECING_TRAP: + return Messages.get(Level.class, "fleecing_trap_name"); + case Terrain.CHANGE_SHEEP_TRAP: + return Messages.get(Level.class, "change_sheep_trap_name"); + case Terrain.SOKOBAN_ITEM_REVEAL: + return Messages.get(Level.class, "sokoban_item_reveal_name"); + case Terrain.SOKOBAN_PORT_SWITCH: + return Messages.get(Level.class, "sokoban_port_switch_name"); + case Terrain.PORT_WELL: + return Messages.get(Level.class, "port_well_name"); + default: + return super.tileName(tile); + } + } + + + @Override + public String tileDesc(int tile) { + switch (tile) { + case Terrain.SOKOBAN_SHEEP: + case Terrain.SWITCH_SOKOBAN_SHEEP: + case Terrain.CORNER_SOKOBAN_SHEEP: + case Terrain.BLACK_SOKOBAN_SHEEP: + return Messages.get(Level.class, "default_desc"); + case Terrain.EMPTY_DECO: + return Messages.get(PrisonLevel.class, "empty_deco_desc"); + case Terrain.BOOKSHELF: + return Messages.get(PrisonLevel.class, "bookshelf_desc"); + case Terrain.WOOL_RUG: + return Messages.get(Level.class, "wool_rug_desc"); + case Terrain.FLEECING_TRAP: + return Messages.get(Level.class, "fleecing_trap_desc"); + case Terrain.CHANGE_SHEEP_TRAP: + return Messages.get(Level.class, "change_sheep_trap_desc"); + case Terrain.SOKOBAN_ITEM_REVEAL: + return Messages.get(Level.class, "sokoban_item_reveal_desc"); + case Terrain.SOKOBAN_PORT_SWITCH: + return Messages.get(Level.class, "sokoban_port_switch_desc"); + case Terrain.PORT_WELL: + return Messages.get(Level.class, "port_well_desc"); + default: + return super.tileDesc(tile); + } + } + + @Override + protected void createItems() { + int goldmin=300; int goldmax=500; + if (first){ + goldmin=300; goldmax=500; + } + for (int i = 0; i < LENGTH; i++) { + if (map[i]==Terrain.SOKOBAN_HEAP){ + if (first && Random.Int(5)==0){drop(new ScrollOfUpgrade(), i).type = Heap.Type.CHEST;} + else {drop(new Gold(Random.Int(goldmin, goldmax)), i).type = Heap.Type.CHEST;} + } + } + + addItemToGen(new IronKey(Dungeon.depth) , 0, 24 + WIDTH * 21); + + + if (first){ + addItemToGen(new Towel() , 1, 37 + WIDTH * 21); + } else { + addItemToGen(new Gold(1) , 1, 37 + WIDTH * 21); + } + + } + + @Override + public int randomRespawnCell() { + return -1; + } + + + +} diff --git a/java/com/hmdzl/spspd/levels/SokobanLayouts.java b/java/com/hmdzl/spspd/levels/SokobanLayouts.java new file mode 100644 index 00000000..357e6057 --- /dev/null +++ b/java/com/hmdzl/spspd/levels/SokobanLayouts.java @@ -0,0 +1,261 @@ +/* + * 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 + */ +package com.hmdzl.spspd.levels; + +import com.watabou.utils.Random; + +public class SokobanLayouts { + + //32X32 + private static final int W = Terrain.WALL; + private static final int T = Terrain.SHRUB; + //private static final int Z = Terrain.HIGH_GRASS; + private static final int D = Terrain.DOOR; + private static final int L = Terrain.LOCKED_DOOR; + + //private static final int T = Terrain.INACTIVE_TRAP; + + private static final int E = Terrain.EMPTY; + private static final int Z = Terrain.EXIT; + + //private static final int M = Terrain.WALL_DECO; + //private static final int P = Terrain.PEDESTAL; + + private static final int A = Terrain.SOKOBAN_SHEEP; + private static final int X = Terrain.CORNER_SOKOBAN_SHEEP; + private static final int C = Terrain.SWITCH_SOKOBAN_SHEEP; + private static final int B = Terrain.BLACK_SOKOBAN_SHEEP; + private static final int H = Terrain.SOKOBAN_HEAP; + private static final int I = Terrain.SOKOBAN_ITEM_REVEAL; + private static final int F = Terrain.FLEECING_TRAP; + private static final int U = Terrain.STATUE; + private static final int G = Terrain.CHANGE_SHEEP_TRAP; + private static final int S = Terrain.SECRET_DOOR; + private static final int R = Terrain.PORT_WELL; + private static final int V = Terrain.SOKOBAN_PORT_SWITCH; + + public static final int[] SOKOBAN_INTRO_LEVEL = { + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, E, E, E, E, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, E, E, E, E, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, E, E, E, E, E, E, E, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, E, U, A, U, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, S, W, W, W, W, W, E, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, E, U, F, U, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, C, E, W, E, C, W, W, W, E, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, E, U, U, E, D, E, E, E, E, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, E, G, E, E, E, G, E, W, W, E, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, E, E, E, E, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, E, E, E, E, E, W, W, W, E, W, W, W, W, W, W, W, + W, W, W, W, E, E, W, W, W, W, W, W, U, U, A, U, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, E, E, E, E, E, W, W, W, E, W, W, W, W, W, W, W, + W, W, W, W, E, E, S, E, E, E, E, D, F, E, E, E, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, E, E, E, E, E, W, W, W, E, W, W, W, W, W, W, W, + W, W, W, W, H, W, W, U, U, E, E, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, E, U, F, U, E, W, W, W, E, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, U, F, A, E, W, E, E, E, E, W, E, E, E, E, E, W, W, W, W, W, W, W, W, W, W, E, U, F, U, E, W, W, W, E, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, U, U, X, U, W, E, E, E, E, W, E, C, E, E, U, W, W, W, W, W, W, W, W, W, W, E, U, F, U, E, W, W, W, E, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, H, U, U, F, D, E, E, C, E, W, E, G, E, E, F, D, E, E, E, E, W, W, W, W, W, G, U, F, U, G, W, W, W, E, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, S, W, W, W, W, E, E, E, E, W, E, E, E, E, U, W, C, G, G, E, W, W, W, W, W, C, U, H, U, C, W, W, W, E, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, F, W, W, W, W, E, E, E, E, D, E, E, E, E, E, W, E, E, E, E, W, W, W, W, W, W, W, S, W, W, W, W, W, E, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, E, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, E, E, E, U, W, W, W, W, W, W, W, E, W, W, W, W, W, E, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, S, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, E, E, U, F, W, W, W, W, W, W, W, E, W, W, W, W, W, E, W, W, W, W, W, W, W, + W, W, W, W, W, E, B, E, E, E, D, F, E, E, E, D, E, E, E, E, W, W, W, W, W, W, D, W, W, W, W, W, W, W, E, W, W, W, W, W, E, W, W, W, W, W, W, W, + W, W, W, W, W, E, E, E, E, E, W, U, U, U, E, W, E, E, E, E, W, W, W, W, W, W, E, W, W, W, W, W, W, E, E, E, W, W, W, W, E, W, W, W, W, W, W, W, + W, W, W, W, W, E, E, R, E, E, W, B, B, E, E, W, E, G, E, E, W, E, E, E, E, W, E, H, W, W, W, W, W, E, E, B, W, E, F, F, A, E, W, W, W, W, W, W, + W, W, W, W, W, E, E, E, E, E, W, U, U, U, E, W, E, G, E, E, W, E, E, E, E, D, E, W, W, W, W, W, W, E, E, E, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, E, E, E, E, E, W, H, F, E, E, W, E, G, E, E, W, E, I, A, E, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, D, W, W, W, W, W, W, W, W, W, W, E, C, E, E, W, E, E, E, E, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, E, E, E, E, E, W, W, W, W, W, W, E, E, E, E, L, E, E, E, E, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, E, E, X, E, E, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, E, E, I, V, E, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, E, E, E, E, E, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W + + }; + + public static final int[] SOKOBAN_CASTLE = { + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, I, T, I, T, I, T, I, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, W, + W, T, T, W, S, W, W, W, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, W, W, W, W, W, T, T, W, + W, T, T, W, R, U, E, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, E, F, H, W, T, T, W, + W, T, T, W, U, U, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, F, F, W, T, T, W, + W, T, T, W, E, E, E, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, E, E, E, W, T, T, W, + W, T, T, W, W, E, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, H, W, H, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, E, W, W, T, T, W, + W, T, T, W, W, E, W, W, W, W, G, E, W, F, G, C, F, E, E, F, E, B, W, F, W, F, W, F, F, H, F, H, F, F, F, F, W, E, E, W, W, W, E, W, T, T, W, W, + W, T, T, W, W, E, W, W, W, W, H, E, S, F, F, X, F, E, C, U, E, E, W, E, W, E, W, F, F, F, F, F, F, F, F, F, S, E, X, W, W, W, E, W, T, T, W, W, + W, T, T, W, W, E, W, W, W, W, E, E, W, F, F, X, F, G, C, U, E, E, W, E, W, E, W, F, F, F, F, F, F, F, F, F, W, E, E, W, W, W, E, W, T, T, W, W, + W, T, T, W, W, E, W, W, W, W, F, F, W, H, F, E, F, G, H, U, E, E, W, E, W, E, W, E, X, X, X, X, X, E, E, E, W, F, F, W, W, W, E, W, T, T, W, W, + W, T, T, W, W, E, W, W, W, W, W, W, W, W, W, W, W, W, L, W, W, W, W, E, B, E, W, W, W, W, D, W, W, W, W, S, W, W, S, W, W, W, E, W, T, T, W, W, + W, T, T, W, W, E, W, W, W, W, W, W, W, W, W, W, E, F, F, F, E, W, W, E, W, E, W, W, H, F, U, F, H, W, W, W, W, W, E, E, E, W, E, W, T, T, W, W, + W, T, T, W, W, E, W, W, W, W, W, W, W, W, W, W, U, F, U, F, U, W, W, E, W, E, W, W, U, U, E, U, U, W, W, W, W, W, U, E, H, W, E, W, T, T, W, W, + W, T, T, W, W, E, W, W, W, W, W, W, W, W, W, W, E, X, G, X, E, W, W, E, W, E, W, W, E, G, E, G, E, W, W, W, W, W, S, W, W, W, E, W, T, T, W, W, + W, T, T, W, W, E, W, W, W, W, W, W, W, W, W, W, E, C, G, C, E, W, W, E, W, E, W, W, C, G, E, G, C, W, W, H, H, E, E, W, W, W, E, W, T, T, W, W, + W, T, T, W, W, E, W, W, W, W, W, W, W, W, W, W, W, W, D, W, W, W, W, E, W, E, W, W, W, W, S, W, W, W, W, E, E, X, E, W, W, W, E, W, T, T, W, W, + W, T, T, W, W, E, W, W, W, U, U, U, C, L, E, W, W, W, F, W, W, W, W, E, W, E, W, W, W, W, F, W, W, W, W, U, E, U, U, W, W, W, E, W, T, T, W, W, + W, T, T, W, W, E, W, W, W, H, F, G, E, W, E, W, W, W, F, W, W, W, W, E, W, E, W, W, W, W, F, W, W, W, W, E, E, E, E, W, W, W, E, W, T, T, W, W, + W, T, T, W, W, E, W, W, W, U, U, U, B, W, E, W, W, W, G, G, I, W, W, E, W, E, W, W, E, G, F, W, W, W, W, E, E, E, E, W, W, W, E, W, T, T, W, W, + W, T, T, W, W, E, W, W, W, W, W, W, W, W, E, W, W, W, X, E, C, W, W, G, W, G, W, W, C, A, G, W, W, W, W, E, E, E, E, W, W, W, E, W, T, T, W, W, + W, T, T, W, W, E, W, W, W, E, U, U, F, D, E, W, W, W, E, E, C, E, G, X, C, X, G, E, E, C, E, W, W, W, W, E, E, E, E, W, W, W, E, W, T, T, W, W, + W, T, T, W, W, E, W, W, W, I, C, E, F, W, E, W, W, W, W, W, W, W, W, C, E, C, W, W, W, W, W, W, E, W, W, W, W, E, W, W, W, W, E, W, T, T, W, W, + W, T, T, W, W, E, W, W, W, G, X, E, E, W, X, E, E, E, E, E, E, E, G, X, C, X, G, E, E, E, E, E, X, E, W, W, W, L, W, W, W, W, E, W, T, T, W, W, + W, T, T, W, W, E, W, W, W, E, U, U, E, W, E, W, W, W, W, W, W, W, W, G, W, G, W, W, W, W, W, W, W, E, W, E, E, E, E, E, W, W, E, W, T, T, W, W, + W, T, T, W, W, E, W, W, W, W, W, W, W, W, E, W, F, F, F, F, F, U, W, E, W, E, W, W, W, W, W, W, W, E, W, U, U, E, U, U, W, W, E, W, T, T, W, W, + W, T, T, W, W, E, W, W, W, U, U, E, E, W, E, W, F, F, F, F, F, U, W, E, W, E, W, W, W, W, W, W, W, E, W, E, G, X, G, I, S, S, E, W, T, T, W, W, + W, E, T, W, W, E, W, R, L, F, F, X, E, W, E, W, F, F, H, F, F, U, W, E, W, E, W, W, W, W, W, E, E, E, W, U, F, E, F, U, W, W, E, W, T, T, W, W, + W, T, T, W, W, E, W, W, W, H, U, G, G, D, E, W, F, F, F, F, F, U, W, E, W, E, W, W, W, W, W, E, E, E, E, E, E, X, E, E, W, W, E, W, T, T, W, W, + W, T, T, W, W, E, W, W, W, F, U, E, C, W, E, W, F, F, F, F, F, U, W, E, W, E, W, W, W, W, W, E, E, W, W, U, E, X, E, U, W, W, E, W, T, T, W, W, + W, T, T, W, W, E, W, W, W, S, W, W, W, W, E, W, E, X, X, E, E, E, W, E, W, E, W, W, W, W, W, E, W, W, W, E, E, E, E, E, W, W, E, W, T, T, W, W, + W, T, T, W, W, E, W, W, W, A, W, W, W, W, D, W, W, W, W, L, W, W, W, E, W, E, W, W, H, S, I, E, E, W, W, W, W, W, W, W, W, W, E, W, T, T, W, W, + W, T, T, W, W, E, W, W, W, G, W, W, W, W, E, E, E, E, E, E, E, G, W, E, W, E, W, W, W, W, W, L, W, W, W, W, W, W, W, W, W, W, E, W, T, T, W, W, + W, T, T, W, W, E, W, W, E, E, E, W, W, W, E, U, E, U, E, F, X, U, W, E, W, E, W, W, W, W, U, E, U, S, E, W, W, W, W, W, W, W, E, W, T, T, W, W, + W, T, T, W, W, E, W, W, U, F, U, W, W, W, E, E, E, E, E, E, X, G, W, E, W, E, W, W, W, W, E, X, E, W, E, E, E, E, E, W, W, W, E, W, T, T, W, W, + W, T, T, W, W, E, W, W, I, H, C, W, W, W, E, U, E, U, E, U, E, U, W, E, W, E, W, W, W, W, E, E, E, W, W, W, E, R, E, W, W, W, E, W, T, T, W, W, + W, T, T, W, W, E, W, W, W, W, W, W, W, W, E, U, E, U, E, U, E, U, W, E, B, E, W, W, W, W, X, X, X, W, W, W, E, E, E, W, W, W, E, W, T, T, W, W, + W, T, T, W, W, E, W, W, E, E, E, W, W, W, E, E, X, E, E, E, E, B, W, E, W, E, W, W, W, W, E, E, E, W, W, W, W, W, W, W, W, W, E, W, T, T, W, W, + W, T, T, W, W, E, W, W, E, E, E, W, W, W, E, U, E, U, E, U, F, U, W, E, W, E, W, W, W, W, E, X, E, W, W, W, W, W, W, W, W, W, E, W, T, T, W, W, + W, T, T, W, W, E, W, W, X, X, X, W, W, W, E, U, E, U, F, U, F, U, W, E, W, E, W, W, W, W, E, E, E, W, W, W, W, W, W, W, W, W, E, W, T, T, W, W, + W, T, T, W, W, E, W, W, I, H, I, W, W, W, E, E, C, G, F, F, H, I, W, F, W, F, W, W, W, W, E, H, V, W, W, W, W, W, W, W, W, W, E, W, T, T, W, W, + W, T, T, W, W, E, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, H, W, H, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, E, W, W, T, W, W, + W, T, T, W, E, E, E, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, E, E, E, W, T, W, W, + W, T, E, W, F, F, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, F, F, W, T, W, W, + W, T, T, W, H, F, E, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, E, F, H, S, T, W, W, + W, T, T, W, W, W, W, W, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, W, W, W, W, W, T, W, W, + W, W, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W + + }; + + public static final int[] SOKOBAN_TELEPORT_LEVEL = { + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, R, E, E, W, W, W, W, W, W, W, W, H, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, E, F, H, H, F, E, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, E, X, H, W, W, W, W, W, W, W, W, F, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, E, F, F, F, F, E, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, B, F, E, W, W, W, W, W, W, W, W, G, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, E, X, E, E, E, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, C, R, S, E, L, B, W, F, R, W, W, W, W, W, W, W, E, R, W, W, W, W, W, W, W, E, E, E, W, W, W, W, W, + W, W, I, F, R, W, W, W, W, F, H, F, W, W, W, W, W, W, W, W, W, W, F, F, F, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, A, X, E, W, W, W, W, W, + W, W, E, F, F, W, W, W, W, F, F, F, W, W, W, W, W, W, W, W, W, W, E, E, E, E, W, W, W, W, W, W, W, W, W, W, W, W, W, F, F, F, E, W, W, W, W, W, + W, W, E, E, E, W, W, W, W, E, X, E, W, W, W, W, W, W, W, W, W, W, E, E, E, R, W, W, W, W, W, W, W, W, W, W, W, W, W, F, F, F, R, W, W, W, W, W, + W, W, E, E, H, W, W, W, W, E, R, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, H, F, W, W, W, W, W, W, W, + W, W, R, E, E, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, E, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, C, G, G, G, G, F, F, F, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, E, E, X, A, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, V, E, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, E, X, E, E, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, F, W, W, E, E, E, E, W, W, E, E, E, I, W, W, W, W, + W, W, W, W, W, W, W, E, E, E, E, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, E, C, W, E, V, X, E, W, W, E, X, V, E, W, W, W, W, + W, W, E, R, W, W, W, E, R, X, E, W, W, W, W, W, E, R, E, W, W, W, W, W, W, W, W, W, W, W, W, G, W, W, E, E, E, R, W, W, R, E, E, E, W, W, W, W, + W, W, E, X, W, W, W, E, E, I, E, W, W, W, W, W, E, X, E, W, W, W, W, W, W, W, W, W, W, W, W, E, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, C, G, W, W, W, E, E, E, E, W, W, W, W, W, F, F, F, W, W, W, W, H, W, W, W, W, W, W, W, E, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, C, G, W, W, W, W, W, W, W, W, W, W, W, W, E, H, E, W, W, W, W, S, W, W, W, W, W, W, W, E, W, W, E, E, E, R, W, W, R, E, E, E, W, W, W, W, + W, W, C, G, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, R, E, U, F, W, W, W, W, W, W, E, W, W, E, V, X, E, W, W, E, X, V, E, W, W, W, W, + W, W, U, F, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, U, A, R, W, W, W, W, W, E, W, W, I, E, E, E, W, W, E, E, E, H, W, W, W, W, + W, W, U, F, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, E, E, E, W, W, W, W, W, W, E, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, U, F, W, W, W, W, W, W, W, W, W, E, C, R, W, W, W, W, W, E, E, E, W, W, W, W, W, W, W, E, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, U, E, E, E, E, E, W, E, E, W, W, E, X, E, W, W, W, W, W, E, E, W, W, W, W, W, W, W, W, E, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, U, E, U, E, E, E, L, E, H, W, W, G, G, G, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, E, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, U, I, U, I, E, E, W, E, E, W, W, E, E, I, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, L, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, L, W, W, W, W, W, W, W, W, W, W, H, E, E, E, E, F, F, F, E, E, E, E, E, E, E, E, E, E, E, R, H, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, I, W, W, W, W, W, W, W, W, W, W, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, E, W, W, W, W, W, W, W, W, W, W, E, U, E, E, E, U, E, U, E, E, U, E, U, E, E, E, E, E, E, U, E, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, E, W, W, W, W, W, W, W, W, W, W, E, E, E, E, E, U, E, U, E, E, U, E, U, E, E, E, E, E, E, E, E, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, E, W, W, W, W, W, W, W, W, W, W, E, U, E, U, U, U, E, U, F, F, U, E, U, U, U, E, E, E, E, U, E, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, E, W, W, W, W, W, W, W, W, W, W, E, E, E, F, F, F, F, F, F, F, F, F, F, F, F, E, E, E, E, E, E, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, L, W, W, W, W, W, W, W, W, W, W, E, U, G, U, F, E, E, E, E, E, E, E, E, F, U, G, E, E, E, U, I, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, E, F, F, F, E, W, W, W, W, W, W, W, W, E, E, G, F, E, E, X, E, X, X, E, X, E, E, F, G, E, E, E, E, E, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, E, E, E, E, E, W, W, W, W, W, W, W, W, E, U, G, U, F, V, E, V, E, E, V, E, V, F, U, G, E, E, E, U, E, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, E, E, H, E, E, W, W, W, W, W, W, W, W, E, E, E, F, F, E, E, E, E, E, E, E, E, F, F, E, E, E, E, E, E, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, E, U, E, U, U, U, U, U, U, U, U, U, U, U, U, E, E, E, E, U, E, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, E, E, E, E, E, E, E, X, E, E, X, E, E, E, E, E, E, E, E, E, E, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, I, U, E, E, E, E, E, X, E, E, X, E, E, E, E, E, E, E, E, U, I, W, W, + W, W, W, E, E, H, E, H, E, E, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, E, E, V, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, W, W, + W, W, W, F, F, F, F, F, F, F, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, E, U, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, U, E, W, W, + W, W, W, F, F, F, F, F, F, F, W, W, W, W, W, W, W, W, W, H, E, W, W, W, W, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, W, W, + W, W, W, E, X, X, R, C, E, E, W, W, W, W, W, W, W, W, W, H, E, E, E, R, S, E, U, E, U, E, U, E, U, E, U, E, U, E, U, E, U, E, U, E, U, E, W, W, + W, W, W, E, E, G, G, G, I, W, W, W, W, W, W, W, W, W, W, H, E, W, W, W, W, H, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, H, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W + + + }; + + public static final int[] SOKOBAN_PUZZLE_LEVEL = { + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, E, E, R, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, U, E, E, E, E, U, S, R, W, W, W, E, A, E, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, C, C, U, H, U, C, C, W, W, W, W, W, W, W, W, W, W, W, E, E, H, H, E, E, W, W, W, W, W, U, I, U, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, G, G, U, F, U, G, G, W, W, W, W, W, W, W, W, W, W, W, E, E, H, H, E, E, W, W, W, W, W, U, I, U, W, W, W, W, + W, W, W, W, W, W, W, W, E, E, S, E, G, G, U, F, U, G, G, V, S, E, E, U, W, W, W, W, W, W, U, E, E, E, E, U, W, W, W, W, W, U, I, U, W, W, W, W, + W, W, W, W, W, W, W, W, G, U, W, W, C, I, U, F, U, I, C, W, W, W, W, G, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, U, I, U, W, W, W, W, + W, W, W, W, W, W, W, W, W, V, W, W, G, G, U, F, U, G, G, W, W, W, W, E, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, U, I, U, W, W, W, W, + W, W, W, W, W, W, W, W, W, E, W, W, C, E, U, F, U, E, C, W, W, W, W, G, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, U, I, U, W, W, W, W, + W, W, W, W, W, W, W, W, W, E, S, R, G, G, U, F, U, G, G, V, S, E, E, U, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, U, I, U, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, E, E, A, E, A, E, I, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, U, I, U, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, U, G, C, U, C, G, U, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, U, H, U, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, L, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, H, E, E, E, W, B, E, E, E, B, W, E, E, E, E, W, W, W, W, W, W, W, W, W, W, W, W, W, W, E, E, E, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, F, F, F, F, W, G, G, E, G, G, W, E, E, F, F, W, W, W, W, W, W, W, E, E, R, W, W, W, E, E, U, E, H, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, H, E, E, E, S, E, E, G, E, E, S, E, G, F, H, W, W, W, W, W, W, W, E, H, E, W, W, W, E, E, E, E, H, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, F, F, F, F, W, E, F, F, F, E, W, E, E, F, F, W, W, W, W, W, W, W, E, E, E, W, W, W, E, E, U, E, H, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, H, E, E, E, W, E, F, H, F, E, W, E, E, E, E, W, W, W, W, W, W, W, W, W, W, W, W, W, W, R, E, E, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, L, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, E, C, G, C, E, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, X, G, X, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, F, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, F, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, E, E, E, E, E, E, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, F, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, E, W, W, W, W, E, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, F, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, E, W, W, W, W, E, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, C, C, C, C, C, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, E, W, W, W, W, E, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, I, E, G, G, G, G, G, E, I, W, W, W, W, W, W, W, W, W, W, W, W, W, F, F, H, H, E, L, E, W, W, W, W, E, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, E, E, U, U, U, U, U, E, E, W, W, W, W, W, W, W, W, W, E, H, E, W, F, U, U, U, U, W, T, W, W, W, W, E, W, W, W, + W, W, W, W, W, W, W, W, W, W, C, G, U, F, E, E, E, F, U, G, C, W, W, W, W, W, W, W, W, E, E, E, W, A, X, B, I, E, W, T, W, W, W, E, E, W, W, W, + W, W, W, W, W, W, W, W, W, W, C, G, U, E, F, F, F, E, U, G, C, W, W, W, W, W, W, W, W, E, E, E, W, E, E, E, E, E, W, T, W, W, W, U, A, W, W, W, + W, W, W, W, W, W, W, W, W, W, C, G, U, E, U, F, U, E, U, G, C, W, W, W, W, W, W, W, W, W, E, W, W, E, E, E, E, E, W, T, W, W, W, T, T, W, W, W, + W, W, W, W, W, W, W, W, W, W, C, G, U, E, U, F, U, E, U, G, C, W, W, W, W, W, W, W, W, W, E, W, W, L, W, W, W, W, W, T, W, W, W, T, F, W, W, W, + W, W, W, W, W, W, W, W, W, W, C, G, U, F, U, H, U, F, U, G, C, W, W, W, W, W, W, W, E, E, E, E, A, F, F, E, W, W, W, T, W, W, W, T, F, R, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, F, U, U, U, U, U, F, W, W, W, W, W, W, W, W, W, G, W, W, W, W, W, W, E, W, W, W, T, W, W, W, T, F, W, W, W, + W, W, W, W, W, W, W, W, W, H, F, S, E, B, E, B, E, B, E, S, F, H, W, W, W, W, W, E, E, W, W, W, W, W, W, E, W, W, W, T, W, W, W, T, T, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, L, W, W, W, W, W, W, W, W, W, W, W, W, E, W, W, W, W, W, W, E, W, W, W, T, W, W, W, T, T, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, E, G, V, W, W, W, W, W, W, W, W, W, W, W, E, W, W, W, W, W, W, E, W, W, W, T, T, T, T, T, T, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, B, G, G, G, G, G, F, F, E, W, W, W, W, W, W, W, E, W, W, W, W, W, W, E, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, C, C, G, C, C, W, W, W, W, W, W, W, W, W, W, E, E, E, E, E, E, E, E, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, U, U, G, U, U, W, W, W, W, W, E, E, R, W, W, E, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, C, C, E, C, C, W, W, W, W, W, X, E, E, W, W, E, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, U, G, E, G, U, W, W, W, W, W, F, E, E, W, W, I, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, B, C, E, C, E, W, W, W, W, W, W, W, W, W, W, E, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, U, U, E, U, U, W, W, W, W, E, E, E, W, W, W, G, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, B, F, F, F, F, F, F, F, L, E, B, E, F, H, D, C, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, E, E, E, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + }; + + +} diff --git a/java/com/hmdzl/spspd/levels/SokobanLayouts2.java b/java/com/hmdzl/spspd/levels/SokobanLayouts2.java new file mode 100644 index 00000000..b0faf051 --- /dev/null +++ b/java/com/hmdzl/spspd/levels/SokobanLayouts2.java @@ -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 + */ +package com.hmdzl.spspd.levels; + +import com.watabou.utils.Random; + +public class SokobanLayouts2 { + + //32X32 + private static final int W = Terrain.WALL_DECO; + private static final int T = Terrain.SHRUB; + private static final int Z = Terrain.HIGH_GRASS; + private static final int D = Terrain.DOOR; + private static final int L = Terrain.LOCKED_DOOR; + + //private static final int T = Terrain.INACTIVE_TRAP; + + private static final int E = Terrain.EMPTY; + //private static final int X = Terrain.EXIT; + + //private static final int M = Terrain.WALL_DECO; + //private static final int P = Terrain.PEDESTAL; + + private static final int A = Terrain.WALL; + private static final int C = Terrain.EMPTY_DECO; + private static final int X = Terrain.EMPTY_SP; + private static final int B = Terrain.BOOKSHELF; + private static final int H = Terrain.SOKOBAN_HEAP; + private static final int I = Terrain.EMBERS; + private static final int F = Terrain.FLEECING_TRAP; + private static final int U = Terrain.STATUE; + private static final int G = Terrain.TENT; + private static final int S = Terrain.SECRET_DOOR; + private static final int R = Terrain.BED; + private static final int V = Terrain.ALCHEMY; + + private static final int J = Terrain.STATUE_SP; + private static final int K = Terrain.WATER; + // M N O P + + + public static final int[] SOKOBAN_VAULT_LEVEL = { + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, I, I, I, I, I, E, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, E, E, I, I, I, I, I, E, W, W, W, W, A, A, A, A, A, A, A, W, W, W, W, A, A, A, A, A, A, A, A, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, X, X, X, X, X, I, I, I, E, E, E, W, W, W, A, B, B, B, B, B, A, W, W, A, A, A, X, X, X, J, Z, Z, A, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, E, X, K, K, K, X, E, E, E, E, E, E, E, A, A, A, X, X, X, X, R, A, W, W, A, X, X, X, X, X, J, Z, Z, A, A, W, W, W, W, W, + W, W, W, W, W, W, W, E, E, X, K, U, K, X, E, E, E, E, E, E, E, A, X, X, X, X, X, X, X, A, W, W, A, X, X, J, X, X, J, Z, Z, Z, A, W, W, W, W, W, + W, W, W, W, W, W, W, E, E, X, K, K, K, X, E, E, E, E, E, E, E, A, V, X, X, X, X, X, X, A, W, W, A, X, X, J, J, J, J, Z, Z, Z, A, W, W, W, W, W, + W, W, W, W, W, W, W, G, E, X, X, X, X, X, E, E, E, E, E, E, E, A, A, A, X, X, X, X, X, A, W, W, A, X, X, X, X, X, J, Z, Z, Z, A, W, W, W, W, W, + W, W, W, W, W, W, W, X, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, A, A, A, D, A, A, A, W, W, A, X, X, X, X, X, J, D, A, A, A, A, W, W, W, W, + W, W, W, W, W, W, W, X, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, X, X, X, X, X, X, X, A, K, K, A, W, W, W, W, + W, W, W, W, W, W, W, E, E, E, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, E, E, E, E, E, E, X, X, X, X, X, X, X, A, K, K, A, W, W, W, W, + W, W, W, W, E, E, E, E, E, E, K, J, J, J, K, J, J, J, K, J, J, J, K, J, J, J, K, E, E, E, E, E, E, X, X, X, X, X, X, X, J, K, K, A, W, W, W, W, + W, W, E, E, E, E, E, E, E, E, K, K, K, J, K, J, K, J, K, K, K, J, K, J, K, J, K, E, E, E, E, E, E, X, X, X, X, X, X, X, A, K, K, A, W, W, W, W, + W, W, E, E, E, E, E, E, E, E, K, J, J, J, K, J, K, J, K, J, J, J, K, J, K, J, K, E, E, E, E, E, A, A, A, D, A, J, J, A, A, D, A, A, W, W, W, W, + W, W, E, E, E, E, E, E, E, E, K, J, K, K, K, J, K, J, K, J, K, K, K, J, K, J, K, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, W, W, W, W, + W, W, E, E, E, E, E, E, E, E, K, J, J, J, K, J, J, J, K, J, J, J, K, J, J, J, K, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, W, W, W, W, + W, W, W, E, E, E, E, E, E, E, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, W, W, W, W, W, + W, W, W, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, W, W, W, W, W, W, + W, W, W, E, E, E, E, E, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, E, E, E, E, E, E, E, W, W, W, W, W, W, + W, W, W, E, E, E, E, E, C, C, T, T, C, T, T, C, C, T, T, C, C, T, T, T, C, T, C, C, T, C, C, T, T, T, C, E, E, E, E, E, E, E, W, W, Z, Z, W, W, + W, W, W, W, E, E, E, E, C, T, C, C, C, T, C, T, C, T, C, T, C, C, T, C, C, T, T, C, T, C, T, C, C, C, C, E, E, E, E, E, E, Z, Z, Z, Z, Z, W, W, + W, W, W, W, E, E, E, E, C, C, T, C, C, T, T, C, C, T, T, C, C, C, T, C, C, T, T, T, T, C, T, C, T, T, C, E, E, E, E, E, E, Z, Z, Z, Z, Z, W, W, + W, W, W, W, E, E, E, E, C, C, C, T, C, T, C, C, C, T, T, C, C, C, T, C, C, T, C, T, T, C, T, C, C, T, C, E, E, E, E, E, E, Z, Z, Z, Z, Z, Z, W, + W, W, W, E, E, E, E, E, C, T, T, C, C, T, C, C, C, T, C, T, C, T, T, T, C, T, C, C, T, C, T, T, T, T, C, E, E, E, X, X, X, X, X, Z, Z, Z, Z, W, + W, W, W, E, E, E, E, E, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, E, E, E, X, G, X, G, X, Z, Z, Z, W, W, + W, W, W, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, X, X, X, X, X, Z, Z, W, W, W, + W, W, E, E, E, E, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, E, X, G, X, G, X, Z, W, W, W, W, + W, W, E, E, E, E, C, T, T, T, C, T, T, T, C, C, T, T, C, T, T, T, C, T, T, T, C, T, C, T, C, C, T, C, C, T, C, E, X, X, X, X, X, Z, W, W, W, W, + W, W, E, E, E, E, C, T, C, C, C, T, C, C, C, T, C, C, C, C, T, C, C, C, T, C, C, T, C, T, C, T, C, T, C, T, C, E, E, E, E, E, E, E, E, E, E, W, + W, W, E, E, E, E, C, T, T, C, C, T, T, T, C, C, T, C, C, C, T, C, C, C, T, C, C, T, C, T, C, T, T, T, C, T, C, E, E, E, E, E, E, E, E, E, E, W, + W, W, E, E, E, E, C, T, C, C, C, T, C, C, C, C, C, T, C, C, T, C, C, C, T, C, C, T, C, T, C, T, C, T, C, T, C, C, C, E, E, E, E, E, E, E, E, W, + W, W, E, E, E, E, C, T, C, C, C, T, T, T, C, T, T, C, C, C, T, C, C, T, T, T, C, C, T, C, C, T, C, T, C, T, T, T, C, E, E, E, E, E, E, E, E, W, + W, W, E, E, E, E, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, E, E, E, E, E, E, E, E, W, + W, W, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, W, + W, W, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, X, X, X, X, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, W, + W, W, W, W, W, A, D, A, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, E, E, E, W, W, W, W, W, W, W, W, W, E, E, E, E, E, W, W, W, W, W, W, W, + W, W, W, W, W, A, E, A, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, T, W, W, W, W, W, W, W, W, W, E, E, E, W, W, W, W, W, W, W, W, + W, W, W, W, W, A, E, A, W, W, W, W, W, W, W, W, W, W, W, A, A, A, A, A, W, W, T, W, W, W, A, A, A, A, A, A, A, A, D, A, A, A, A, W, W, W, W, W, + W, W, W, W, W, A, E, A, W, W, W, W, W, W, W, W, W, Z, Z, J, B, B, X, A, W, T, W, W, W, W, A, B, B, B, B, A, X, X, X, X, R, B, A, W, W, W, W, W, + W, W, W, T, T, S, K, S, T, T, W, W, W, W, W, W, W, U, Z, A, R, X, X, A, T, W, W, W, W, W, A, B, X, X, X, A, X, X, X, X, X, B, A, W, W, W, W, W, + W, W, W, T, W, A, K, A, W, T, W, W, W, W, T, T, T, Z, Z, D, X, X, X, D, W, W, W, W, W, W, A, B, X, X, X, D, X, X, X, X, X, B, A, W, W, W, W, W, + W, W, W, W, A, A, L, A, A, W, T, T, T, W, T, W, W, U, Z, A, X, X, V, A, W, W, W, W, W, W, A, B, X, X, X, A, X, X, X, X, X, A, A, W, W, W, W, W, + W, W, W, W, A, K, K, K, A, W, W, W, T, T, T, W, W, Z, Z, A, X, X, X, A, W, W, W, W, W, W, A, B, X, G, A, A, A, A, A, A, A, A, W, W, W, W, W, W, + W, W, W, W, A, K, K, K, A, W, W, W, W, W, W, W, W, W, W, A, A, A, A, A, W, W, W, W, W, W, A, A, A, A, A, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, A, U, E, U, A, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, A, A, A, A, A, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W + }; + + public static final int[] DRAGON_CAVE = { + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, E, W, W, E, W, W, W, W, W, W, W, W, W, W, W, F, F, F, F, F, F, F, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, E, E, E, E, E, W, E, E, W, W, W, W, E, W, W, W, W, W, W, F, F, F, F, F, F, F, F, F, F, F, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, H, W, E, E, E, W, W, W, W, W, W, E, H, W, W, W, W, W, F, F, F, F, F, F, F, F, F, F, F, F, F, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, E, E, E, E, W, W, W, W, W, E, W, W, W, W, W, W, F, F, F, F, F, F, F, F, F, F, F, F, F, F, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, E, E, E, W, W, W, W, W, E, W, W, W, W, W, W, F, F, F, F, F, F, F, F, F, F, F, F, F, F, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, E, W, W, W, W, W, W, E, W, W, W, W, W, W, W, F, F, F, F, F, F, F, F, F, F, F, F, F, F, W, W, W, W, W, W, W, H, H, W, W, W, W, W, W, + W, W, W, W, E, W, W, W, W, E, E, E, E, W, W, W, W, W, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, W, W, W, W, W, H, H, H, H, W, W, W, W, W, + W, W, W, W, E, W, W, W, W, E, W, W, E, W, W, W, W, W, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, W, W, W, H, H, H, H, W, W, W, W, W, + W, W, W, W, E, W, W, W, W, E, W, W, E, E, W, W, W, W, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, W, W, W, E, H, H, E, W, W, W, W, W, + W, W, W, W, E, E, W, W, E, E, W, W, W, E, W, W, W, W, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, W, W, W, E, E, W, W, W, W, W, W, W, + W, W, W, W, W, E, W, W, E, W, W, W, W, E, W, W, W, W, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, W, W, W, E, W, W, W, W, W, W, W, W, + W, W, W, W, W, E, E, E, E, W, W, W, W, E, E, W, W, W, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, W, W, W, E, E, W, W, W, W, W, W, W, + W, W, W, W, W, W, E, E, W, W, W, W, W, W, E, E, W, W, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, W, W, W, W, E, W, W, W, W, W, W, W, + W, W, W, W, W, W, E, W, W, W, W, W, W, W, W, E, W, W, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, W, W, W, E, E, W, W, W, W, W, W, + W, W, W, W, W, E, E, W, W, W, W, W, W, W, W, E, W, W, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, W, W, W, W, E, E, W, W, W, W, W, + W, W, W, W, W, E, W, W, W, W, W, W, W, W, W, E, W, W, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, W, W, W, W, W, E, W, W, W, W, W, + W, W, E, W, W, E, W, W, W, W, W, W, W, W, W, E, W, W, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, W, W, W, W, W, E, W, W, W, W, W, + W, W, H, E, W, E, W, W, W, W, W, W, W, W, W, E, E, E, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, W, W, W, W, W, E, E, W, W, W, W, + W, W, E, E, E, E, E, W, W, W, W, W, W, W, W, W, W, W, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, W, W, W, W, W, W, E, W, W, W, W, + W, W, W, W, W, W, E, W, W, W, W, W, W, W, W, W, W, W, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, W, W, W, W, W, W, E, W, W, W, W, + W, W, W, W, W, W, E, W, W, W, W, E, W, W, W, W, W, W, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, W, W, W, W, W, E, E, W, W, W, W, + W, W, W, W, W, W, E, W, W, W, E, E, E, W, W, W, W, W, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, W, W, W, W, W, E, E, W, W, W, W, + W, W, W, W, W, W, E, W, W, W, E, H, E, W, W, W, W, W, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, W, W, W, W, W, E, E, W, W, W, W, + W, W, W, W, W, E, E, W, W, W, W, E, E, W, W, W, W, W, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, W, W, W, W, W, E, W, S, W, W, W, + W, W, W, W, E, E, W, E, E, E, E, E, E, W, W, W, W, W, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, W, W, W, W, E, E, W, W, E, W, W, + W, W, W, W, E, W, W, W, W, W, W, W, W, W, W, E, W, W, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, W, W, W, W, E, E, W, W, W, E, W, W, + W, W, W, W, E, W, W, W, W, W, W, W, W, W, E, W, W, W, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, W, W, W, E, E, W, W, W, W, E, W, W, + W, W, W, W, W, E, W, W, W, W, W, W, W, W, W, E, H, W, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, E, E, E, W, W, W, W, E, E, W, W, + W, W, W, W, W, E, W, W, W, W, W, W, W, W, W, E, E, W, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, W, W, W, W, W, W, W, E, W, W, W, + W, W, W, W, W, E, E, E, E, E, E, W, W, W, W, E, W, W, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, W, W, W, W, W, W, W, E, W, W, W, + W, W, W, W, W, W, W, W, E, W, W, E, W, W, W, E, W, W, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, W, W, W, W, W, E, E, E, W, W, W, + W, W, W, W, W, W, W, E, E, W, W, W, E, W, W, E, W, W, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, W, W, W, W, W, H, E, E, W, W, W, W, + W, W, W, W, W, W, E, E, H, W, W, W, W, E, E, E, W, W, W, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, W, W, W, W, W, H, E, E, E, W, W, W, + W, W, W, W, W, E, E, H, E, E, W, W, W, W, W, W, W, W, W, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, W, W, W, W, W, W, E, E, E, W, W, W, + W, W, W, W, W, E, E, E, E, E, W, W, W, W, W, W, W, W, W, W, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, E, E, E, E, E, W, W, W, W, W, W, W, W, W, W, W, F, F, F, F, F, F, F, F, F, F, F, F, F, F, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, + W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W + }; + +} diff --git a/java/com/hmdzl/spspd/levels/SokobanPuzzlesLevel.java b/java/com/hmdzl/spspd/levels/SokobanPuzzlesLevel.java new file mode 100644 index 00000000..3fcd61e6 --- /dev/null +++ b/java/com/hmdzl/spspd/levels/SokobanPuzzlesLevel.java @@ -0,0 +1,678 @@ +/* + * 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 + */ +package com.hmdzl.spspd.levels; + +import java.util.Collection; +import java.util.HashSet; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.WellWater; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.actors.mobs.SokobanSentinel; +import com.hmdzl.spspd.actors.mobs.npcs.Sheep; +import com.hmdzl.spspd.actors.mobs.npcs.SheepSokoban; +import com.hmdzl.spspd.actors.mobs.npcs.SheepSokobanBlack; +import com.hmdzl.spspd.actors.mobs.npcs.SheepSokobanCorner; +import com.hmdzl.spspd.actors.mobs.npcs.SheepSokobanSwitch; +import com.hmdzl.spspd.items.eggs.Egg; +import com.hmdzl.spspd.items.Gold; +import com.hmdzl.spspd.items.Heap; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.Whistle; +import com.hmdzl.spspd.items.artifacts.TimekeepersHourglass; +import com.hmdzl.spspd.items.keys.IronKey; +import com.hmdzl.spspd.items.potions.PotionOfLiquidFlame; +import com.hmdzl.spspd.items.scrolls.ScrollOfMagicalInfusion; +import com.hmdzl.spspd.items.scrolls.ScrollOfUpgrade; + +import com.hmdzl.spspd.items.wands.WandOfFlock; +import com.hmdzl.spspd.levels.features.Chasm; +import com.hmdzl.spspd.levels.features.Door; +import com.hmdzl.spspd.levels.features.HighGrass; +import com.hmdzl.spspd.levels.traps.ActivatePortalTrap; +import com.hmdzl.spspd.levels.traps.ChangeSheepTrap; +import com.hmdzl.spspd.levels.traps.FleecingTrap; +import com.hmdzl.spspd.levels.traps.HeapGenTrap; +import com.hmdzl.spspd.levels.traps.SokobanPortalTrap; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.plants.Flytrap; +import com.hmdzl.spspd.plants.Phaseshift; +import com.hmdzl.spspd.plants.Plant; +import com.hmdzl.spspd.plants.Starflower; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Bundlable; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public class SokobanPuzzlesLevel extends Level { + + + { + color1 = 0x534f3e; + color2 = 0xb9d661; + WIDTH = 48; + HEIGHT = 48; + LENGTH = HEIGHT*WIDTH; + } + + + public HashSet heapstogen; + public int[] heapgenspots; + public int[] teleportspots; + public int[] portswitchspots; + public int[] teleportassign; + public int[] destinationspots; + public int[] destinationassign; + public int prizeNo; + + private static final String HEAPSTOGEN = "heapstogen"; + private static final String HEAPGENSPOTS = "heapgenspots"; + private static final String TELEPORTSPOTS = "teleportspots"; + private static final String PORTSWITCHSPOTS = "portswitchspots"; + private static final String DESTINATIONSPOTS = "destinationspots"; + private static final String TELEPORTASSIGN = "teleportassign"; + private static final String DESTINATIONASSIGN= "destinationassign"; + private static final String PRIZENO = "prizeNo"; + + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(HEAPSTOGEN, heapstogen); + bundle.put(HEAPGENSPOTS, heapgenspots); + bundle.put(TELEPORTSPOTS, teleportspots); + bundle.put(PORTSWITCHSPOTS, portswitchspots); + bundle.put(DESTINATIONSPOTS, destinationspots); + bundle.put(DESTINATIONASSIGN, destinationassign); + bundle.put(TELEPORTASSIGN, teleportassign); + bundle.put(PRIZENO, prizeNo); + } + + + @Override + public String tileName(int tile) { + switch (tile) { + case Terrain.SOKOBAN_SHEEP: + case Terrain.SWITCH_SOKOBAN_SHEEP: + case Terrain.CORNER_SOKOBAN_SHEEP: + case Terrain.BLACK_SOKOBAN_SHEEP: + return Messages.get(Level.class, "floor_name"); + case Terrain.WATER: + return Messages.get(Level.class, "water_name"); + case Terrain.WOOL_RUG: + return Messages.get(Level.class, "wool_rug_name"); + case Terrain.FLEECING_TRAP: + return Messages.get(Level.class, "fleecing_trap_name"); + case Terrain.CHANGE_SHEEP_TRAP: + return Messages.get(Level.class, "change_sheep_trap_name"); + case Terrain.SOKOBAN_ITEM_REVEAL: + return Messages.get(Level.class, "sokoban_item_reveal_name"); + case Terrain.SOKOBAN_PORT_SWITCH: + return Messages.get(Level.class, "sokoban_port_switch_name"); + case Terrain.PORT_WELL: + return Messages.get(Level.class, "port_well_name"); + default: + return super.tileName(tile); + } + } + + + @Override + public String tileDesc(int tile) { + switch (tile) { + case Terrain.SOKOBAN_SHEEP: + case Terrain.SWITCH_SOKOBAN_SHEEP: + case Terrain.CORNER_SOKOBAN_SHEEP: + case Terrain.BLACK_SOKOBAN_SHEEP: + return Messages.get(Level.class, "default_desc"); + case Terrain.EMPTY_DECO: + return Messages.get(PrisonLevel.class, "empty_deco_desc"); + case Terrain.BOOKSHELF: + return Messages.get(PrisonLevel.class, "bookshelf_desc"); + case Terrain.WOOL_RUG: + return Messages.get(Level.class, "wool_rug_desc"); + case Terrain.FLEECING_TRAP: + return Messages.get(Level.class, "fleecing_trap_desc"); + case Terrain.CHANGE_SHEEP_TRAP: + return Messages.get(Level.class, "change_sheep_trap_desc"); + case Terrain.SOKOBAN_ITEM_REVEAL: + return Messages.get(Level.class, "sokoban_item_reveal_desc"); + case Terrain.SOKOBAN_PORT_SWITCH: + return Messages.get(Level.class, "sokoban_port_switch_desc"); + case Terrain.PORT_WELL: + return Messages.get(Level.class, "port_well_desc"); + default: + return super.tileDesc(tile); + } + } + + + @Override + public void restoreFromBundle(Bundle bundle) { + + super.restoreFromBundle(bundle); + + heapgenspots = bundle.getIntArray(HEAPGENSPOTS); + teleportspots = bundle.getIntArray(TELEPORTSPOTS); + portswitchspots = bundle.getIntArray(PORTSWITCHSPOTS); + destinationspots = bundle.getIntArray(DESTINATIONSPOTS); + destinationassign = bundle.getIntArray(DESTINATIONASSIGN); + teleportassign = bundle.getIntArray(TELEPORTASSIGN); + prizeNo = bundle.getInt(PRIZENO); + + heapstogen = new HashSet(); + + Collection collectionheap = bundle.getCollection(HEAPSTOGEN); + for (Bundlable i : collectionheap) { + Item item = (Item) i; + if (item != null) { + heapstogen.add(item); + } + } + } + + @Override + public void create() { + heapstogen = new HashSet(); + heapgenspots = new int[20]; + teleportspots = new int[10]; + portswitchspots = new int[10]; + destinationspots = new int[10]; + destinationassign = new int[10]; + teleportassign = new int[10]; + super.create(); + } + + public void addItemToGen(Item item, int arraypos, int pos) { + if (item != null) { + heapstogen.add(item); + heapgenspots[arraypos]=pos; + } + } + + + public Item genPrizeItem() { + return genPrizeItem(null); + } + + + public Item genPrizeItem(Class match) { + + boolean keysLeft = false; + + if (heapstogen.size() == 0) + return null; + + for (Item item : heapstogen) { + if (match.isInstance(item)) { + heapstogen.remove(item); + keysLeft=true; + return item; + } + } + + if (match == null || !keysLeft) { + Item item = Random.element(heapstogen); + heapstogen.remove(item); + return item; + } + + return null; + } + + @Override + public void press(int cell, Char ch) { + + if (pit[cell] && ch == Dungeon.hero) { + Chasm.heroFall(cell); + return; + } + + TimekeepersHourglass.timeFreeze timeFreeze = null; + + if (ch != null) + timeFreeze = ch.buff(TimekeepersHourglass.timeFreeze.class); + + boolean trap = false; + + switch (map[cell]) { + + case Terrain.FLEECING_TRAP: + + if (ch != null && ch==Dungeon.hero){ + trap = true; + FleecingTrap.trigger(cell, ch); + } + break; + + case Terrain.CHANGE_SHEEP_TRAP: + + if (ch instanceof SheepSokoban || ch instanceof SheepSokobanSwitch || ch instanceof SheepSokobanCorner || ch instanceof Sheep || ch instanceof WandOfFlock.MagicSheep){ + trap = true; + ChangeSheepTrap.trigger(cell, ch); + } + break; + + case Terrain.PORT_WELL: + + if (ch != null && ch==Dungeon.hero){ + + int portarray=-1; + int destinationspot=cell; + + for(int i = 0; i < teleportspots.length; i++) { + if(teleportspots[i] == cell) { + portarray = i; + break; + } + } + + if(portarray != -1) { + destinationspot=destinationspots[portarray]; + if (destinationspot>0){ + SokobanPortalTrap.trigger(cell, ch, destinationspot); + } + } + } + break; + + case Terrain.SOKOBAN_PORT_SWITCH: + trap=false; + ActivatePortalTrap.trigger(cell, ch); + + /* + int arraypos = -1; //position in array of teleport switch + int portpos = -1; //position on map of teleporter + int portarraypos = -1; //position in array of teleporter + int destpos = -1; //destination position assigned to switch + + for(int i = 0; i < portswitchspots.length; i++) { + if(portswitchspots[i] == cell) { + arraypos = i; + //GLog.i("Pos1 %s", arraypos); + break; + } + } + + portpos = teleportassign[arraypos]; + destpos = destinationassign[arraypos]; + + // Stepping on switch deactivates the portal + destpos = -1; + + //GLog.i("ass2 %s", portpos); + //GLog.i("dest3 %s", destpos); + + for(int i = 0; i < teleportspots.length; i++) { + if(teleportspots[i] == portpos) { + portarraypos = i; + // GLog.i("Pos4 %s", portarraypos); + break; + } + } + + if (map[portpos] == Terrain.PORT_WELL){ + destinationspots[portarraypos]=destpos; + GLog.i("Portal Deactivated!"); + } + + + */ + break; + + + case Terrain.HIGH_GRASS: + HighGrass.trample(this, cell, ch); + break; + + case Terrain.WELL: + WellWater.affectCell(cell); + break; + + /*case Terrain.ALCHEMY: + if (ch == null) { + Alchemy.transmute(cell); + } + break;*/ + + case Terrain.DOOR: + Door.enter(cell); + break; + } + + if (trap){ + + if (Dungeon.visible[cell]) + Sample.INSTANCE.play(Assets.SND_TRAP); + + if (ch == Dungeon.hero) + Dungeon.hero.interrupt(); + + set(cell, Terrain.INACTIVE_TRAP); + GameScene.updateMap(cell); + } + + Plant plant = plants.get(cell); + if (plant != null) { + plant.activate(ch); + } + } + + + + @Override + public void mobPress(Mob mob) { + + int cell = mob.pos; + + if (pit[cell] && !mob.flying) { + Chasm.mobFall(mob); + return; + } + + boolean trap = true; + boolean fleece = false; + boolean sheep = false; + switch (map[cell]) { + + case Terrain.FLEECING_TRAP: + if (mob instanceof SheepSokoban || mob instanceof SheepSokobanSwitch || mob instanceof SheepSokobanCorner || mob instanceof SheepSokobanBlack || mob instanceof Sheep || mob instanceof WandOfFlock.MagicSheep){ + fleece=true; + } + FleecingTrap.trigger(cell, mob); + break; + + case Terrain.CHANGE_SHEEP_TRAP: + trap=false; + if (mob instanceof SheepSokoban || mob instanceof SheepSokobanSwitch || mob instanceof SheepSokobanCorner || mob instanceof Sheep || mob instanceof WandOfFlock.MagicSheep){ + trap=true; + ChangeSheepTrap.trigger(cell, mob); + } + break; + + case Terrain.SOKOBAN_ITEM_REVEAL: + trap=false; + if (mob instanceof SheepSokoban || mob instanceof SheepSokobanSwitch || mob instanceof SheepSokobanCorner || mob instanceof SheepSokobanBlack || mob instanceof Sheep || mob instanceof WandOfFlock.MagicSheep){ + HeapGenTrap.trigger(cell, mob); + drop(genPrizeItem(IronKey.class),heapgenspots[prizeNo]); + prizeNo++; + sheep=true; + trap=true; + } + break; + + case Terrain.SOKOBAN_PORT_SWITCH: + trap=false; + if (mob instanceof SheepSokoban || mob instanceof SheepSokobanSwitch || mob instanceof SheepSokobanCorner || mob instanceof SheepSokobanBlack || mob instanceof Sheep || mob instanceof WandOfFlock.MagicSheep){ + ActivatePortalTrap.trigger(cell, mob); + + /* + public int[] teleportspots; location of teleports + public int[] portswitchspots; location of switches + public int[] teleportassign; assignment of teleports to switches + public int[] destinationspots; current assignment of destination spots to teleports + public int[] destinationassign; assignemnt of destination spots to switches + */ + + int arraypos = -1; //position in array of teleport switch + int portpos = -1; //position on map of teleporter + int portarray = -1; //position in array of teleporter + int destpos = -1; //destination position assigned to switch + + for(int i = 0; i < portswitchspots.length; i++) { + if(portswitchspots[i] == cell) { + arraypos = i; + //GLog.i("Pos1 %s", arraypos); + break; + } + } + + portpos = teleportassign[arraypos]; + destpos = destinationassign[arraypos]; + + //GLog.i("ass2 %s", portpos); + //GLog.i("dest3 %s", destpos); + + for(int i = 0; i < teleportspots.length; i++) { + if(teleportspots[i] == portpos) { + portarray = i; + // GLog.i("Pos4 %s", portarray); + break; + } + } + + if (map[portpos] == Terrain.PORT_WELL){ + destinationspots[portarray]=destpos; + GLog.i("Click!"); + } + + sheep=true; + } + break; + + case Terrain.DOOR: + Door.enter(cell); + + default: + trap = false; + } + + if (trap && !fleece && !sheep) { + if (Dungeon.visible[cell]) { + Sample.INSTANCE.play(Assets.SND_TRAP); + } + set(cell, Terrain.INACTIVE_TRAP); + GameScene.updateMap(cell); + } + + if (trap && fleece) { + if (Dungeon.visible[cell]) { + Sample.INSTANCE.play(Assets.SND_TRAP); + } + set(cell, Terrain.WOOL_RUG); + GameScene.updateMap(cell); + } + + if (trap && sheep) { + if (Dungeon.visible[cell]) { + Sample.INSTANCE.play(Assets.SND_TRAP); + } + set(cell, Terrain.EMPTY); + GameScene.updateMap(cell); + } + + + Plant plant = plants.get(cell); + if (plant != null) { + plant.activate(mob); + } + + Dungeon.observe(); + } + + @Override + public String tilesTex() { + return Assets.TILES_PUZZLE; + } + + @Override + public String waterTex() { + return Assets.WATER_PRISON; + } + + @Override + protected boolean build() { + + map = SokobanLayouts.SOKOBAN_PUZZLE_LEVEL.clone(); + decorate(); + + buildFlagMaps(); + cleanWalls(); + createSwitches(); + createSheep(); + + entrance = 15 + WIDTH * 11; + exit = 0 ; + + + return true; + } + @Override + protected void decorate() { + //do nothing, all decorations are hard-coded. + } + + @Override + protected void createMobs() { + + /* + SokobanSentinel mob = new SokobanSentinel(); + mob.pos = 38 + WIDTH * 21; + mobs.add(mob); + Actor.occupyCell(mob); + */ + SokobanSentinel mob2 = new SokobanSentinel(); + mob2.pos = 33 + WIDTH * 30; + mobs.add(mob2); + Actor.occupyCell(mob2); + /* + SokobanSentinel mob3 = new SokobanSentinel(); + mob3.pos = 2 + WIDTH * 43; + mobs.add(mob3); + Actor.occupyCell(mob3); + */ + } + + + + protected void createSheep() { + for (int i = 0; i < LENGTH; i++) { + if (map[i]==Terrain.SOKOBAN_SHEEP){SheepSokoban npc = new SheepSokoban(); mobs.add(npc); npc.pos = i; Actor.occupyCell(npc);} + else if (map[i]==Terrain.CORNER_SOKOBAN_SHEEP){SheepSokobanCorner npc = new SheepSokobanCorner(); mobs.add(npc); npc.pos = i; Actor.occupyCell(npc);} + else if (map[i]==Terrain.SWITCH_SOKOBAN_SHEEP){SheepSokobanSwitch npc = new SheepSokobanSwitch(); mobs.add(npc); npc.pos = i; Actor.occupyCell(npc);} + else if (map[i]==Terrain.BLACK_SOKOBAN_SHEEP){SheepSokobanBlack npc = new SheepSokobanBlack(); mobs.add(npc); npc.pos = i; Actor.occupyCell(npc);} + else if (map[i]==Terrain.PORT_WELL){ + /* + Portal portal = new Portal(); + portal.seed(i, 1); + blobs.put(Portal.class, portal); + */ + } + + } + } + + + protected void createSwitches(){ + + //spots where your portals are + teleportspots[0] = 11 + WIDTH * 10; + teleportspots[1] = 32 + WIDTH * 15; + teleportspots[2] = 25 + WIDTH * 40; + teleportspots[3] = 37 + WIDTH * 18; + teleportspots[4] = 45 + WIDTH * 33; + teleportspots[5] = 37 + WIDTH * 3; + teleportspots[6] = 43 + WIDTH * 2; + + //spots where your portal switches are + portswitchspots[0] = 19 + WIDTH * 10; + portswitchspots[1] = 19 + WIDTH * 6; + portswitchspots[2] = 9 + WIDTH * 8; + portswitchspots[3] = 16 + WIDTH * 37; + + + + //assign each switch to a portal + teleportassign[0] = 11 + WIDTH * 10; + teleportassign[1] = 11 + WIDTH * 10; + teleportassign[2] = 15 + WIDTH * 32; + teleportassign[3] = 37 + WIDTH * 3; + + + + //assign each switch to a destination spot + destinationassign[0] = 30 + WIDTH * 16; + destinationassign[1] = 23 + WIDTH * 40; + destinationassign[2] = 37 + WIDTH * 16; + destinationassign[3] = 42 + WIDTH * 2; + + + + //set the original destination of portals + destinationspots[0] = 0; + destinationspots[1] = 23 + WIDTH * 8; + destinationspots[2] = 23 + WIDTH * 8; + destinationspots[3] = 23 + WIDTH * 8; + destinationspots[4] = 34 + WIDTH * 6; + destinationspots[5] = 23 + WIDTH * 8; + destinationspots[6] = 23 + WIDTH * 8; + + + + + } + + + @Override + protected void createItems() { + int goldmin=300; int goldmax=500; + if (first){ + goldmin=300; goldmax=500; + } + for (int i = 0; i < LENGTH; i++) { + if (map[i]==Terrain.SOKOBAN_HEAP){ + if (first && Random.Int(5)==0){drop(new ScrollOfUpgrade(), i).type = Heap.Type.CHEST;} + else {drop(new Gold(Random.Int(goldmin, goldmax)), i).type = Heap.Type.CHEST;} + } + } + + addItemToGen(new IronKey(Dungeon.depth) , 0, 15 + WIDTH * 11); + addItemToGen(new IronKey(Dungeon.depth) , 1, 16 + WIDTH * 17); + addItemToGen(new IronKey(Dungeon.depth) , 2, 16 + WIDTH * 35); + addItemToGen(new IronKey(Dungeon.depth) , 3, 20 + WIDTH * 38); + addItemToGen(new IronKey(Dungeon.depth) , 4, 27 + WIDTH * 35); + addItemToGen(new IronKey(Dungeon.depth) , 5, 33 + WIDTH * 31); + + + if (first){ + addItemToGen(new ScrollOfMagicalInfusion() , 6, 11 + WIDTH * 10); + addItemToGen(new ScrollOfMagicalInfusion() , 7, 41 + WIDTH * 2); + addItemToGen(new Egg() , 8, 41 + WIDTH * 2); + addItemToGen(new Phaseshift.Seed() , 9, 41 + WIDTH * 2); + addItemToGen(new Starflower.Seed() , 10, 41 + WIDTH * 2); + addItemToGen(new Flytrap.Seed() , 11, 41 + WIDTH * 2); + addItemToGen(new Phaseshift.Seed() , 12, 41 + WIDTH * 2); + addItemToGen(new Flytrap.Seed() , 13, 41 + WIDTH * 2); + addItemToGen(new Whistle() , 14, 41 + WIDTH * 2); + } + + drop(new PotionOfLiquidFlame(), 9 + WIDTH * 24).type = Heap.Type.CHEST; + } + + @Override + public int randomRespawnCell() { + return -1; + } + + +} diff --git a/java/com/hmdzl/spspd/levels/SokobanSPLevel.java b/java/com/hmdzl/spspd/levels/SokobanSPLevel.java new file mode 100644 index 00000000..85939eb9 --- /dev/null +++ b/java/com/hmdzl/spspd/levels/SokobanSPLevel.java @@ -0,0 +1,482 @@ +package com.hmdzl.spspd.levels; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.Alter; +import com.hmdzl.spspd.actors.blobs.WellWater; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.actors.mobs.TestMob; +import com.hmdzl.spspd.actors.mobs.UIcecorps; +import com.hmdzl.spspd.actors.mobs.YearBeast2; +import com.hmdzl.spspd.actors.mobs.npcs.AFly; +import com.hmdzl.spspd.actors.mobs.npcs.ARealMan; +import com.hmdzl.spspd.actors.mobs.npcs.Apostle; +import com.hmdzl.spspd.actors.mobs.npcs.Coconut2; +import com.hmdzl.spspd.actors.mobs.npcs.DreamPlayer; +import com.hmdzl.spspd.actors.mobs.npcs.Evan; +import com.hmdzl.spspd.actors.mobs.npcs.FruitCat; +import com.hmdzl.spspd.actors.mobs.npcs.G2159687; +import com.hmdzl.spspd.actors.mobs.npcs.GoblinPlayer; +import com.hmdzl.spspd.actors.mobs.npcs.HBB; +import com.hmdzl.spspd.actors.mobs.npcs.HateSokoban; +import com.hmdzl.spspd.actors.mobs.npcs.Hmdzl001; +import com.hmdzl.spspd.actors.mobs.npcs.HoneyPoooot; +import com.hmdzl.spspd.actors.mobs.npcs.Ice13; +import com.hmdzl.spspd.actors.mobs.npcs.Jinkeloid; +import com.hmdzl.spspd.actors.mobs.npcs.Kostis12345; +import com.hmdzl.spspd.actors.mobs.npcs.LaJi; +import com.hmdzl.spspd.actors.mobs.npcs.Lery; +import com.hmdzl.spspd.actors.mobs.npcs.Lyn; +import com.hmdzl.spspd.actors.mobs.npcs.Lynn; +import com.hmdzl.spspd.actors.mobs.npcs.MemoryOfSand; +import com.hmdzl.spspd.actors.mobs.npcs.Millilitre; +import com.hmdzl.spspd.actors.mobs.npcs.NewPlayer; +import com.hmdzl.spspd.actors.mobs.npcs.Omicronrg9; +import com.hmdzl.spspd.actors.mobs.npcs.RENnpc; +import com.hmdzl.spspd.actors.mobs.npcs.Rustyblade; +import com.hmdzl.spspd.actors.mobs.npcs.SFB; +import com.hmdzl.spspd.actors.mobs.npcs.SaidbySun; +import com.hmdzl.spspd.actors.mobs.npcs.Shower; +import com.hmdzl.spspd.actors.mobs.npcs.StormAndRain; +import com.hmdzl.spspd.actors.mobs.npcs.Tempest102; +import com.hmdzl.spspd.actors.mobs.npcs.ThankList; +import com.hmdzl.spspd.actors.mobs.npcs.Tinkerer5; +import com.hmdzl.spspd.actors.mobs.npcs.UncleS; +import com.hmdzl.spspd.actors.mobs.npcs.XixiZero; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.items.Heap; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.artifacts.TimekeepersHourglass; +import com.hmdzl.spspd.items.food.completefood.PetFood; +import com.hmdzl.spspd.items.scrolls.ScrollOfUpgrade; +import com.hmdzl.spspd.levels.features.Chasm; +import com.hmdzl.spspd.levels.features.Door; +import com.hmdzl.spspd.levels.features.HighGrass; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.plants.Plant; +import com.hmdzl.spspd.scenes.GameScene; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public class SokobanSPLevel extends Level { + + + { + color1 = 0x534f3e; + color2 = 0xb9d661; + WIDTH = 48; + HEIGHT = 48; + LENGTH = HEIGHT*WIDTH; + cleared=false; + } + + public int mineDepth=0; + + public int[] storespots; + public int[] bombpots; + + + + private static final String MINEDEPTH = "mineDepth"; + private static final String STORESPOTS = "storespots"; + private static final String BOMBPOTS = "bombpots"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(MINEDEPTH, mineDepth); + bundle.put(STORESPOTS, storespots); + bundle.put(BOMBPOTS, bombpots); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + mineDepth = bundle.getInt(MINEDEPTH); + storespots = bundle.getIntArray(STORESPOTS); + bombpots = bundle.getIntArray(BOMBPOTS); + } + + public void storeStock (){ + + + for (int i : bombpots) { + Heap heap = heaps.get(i); + if (heap == null){ + Item storeitem2 = storeItem2(); + drop(storeitem2, i).type = Heap.Type.FOR_SALE; + } + } + for (int i : storespots) { + Heap heap = heaps.get(i); + if (heap == null){ + Item storeitem = storeItem(); + drop(storeitem, i).type = Heap.Type.FOR_SALE; + } + } + } + + + public Item storeItem (){ + Item prize; + switch (Random.Int(2)) { + case 0: + prize = Generator.random(Generator.Category.ARTIFACT);; + break; + case 1: + prize = Generator.random(Generator.Category.RING); + break; + default: + prize = new PetFood(); + break; + } + + return prize; + + } + + public Item storeItem2 (){ + Item prize; + switch (Random.Int(6)) { + case 0: + prize = Generator.random(Generator.Category.WEAPON); + break; + case 1: + prize = Generator.random(Generator.Category.ARMOR); + break; + case 2: + prize = Generator.random(Generator.Category.POTION); + break; + case 3: + prize = Generator.random(Generator.Category.WAND); + break; + case 4: + prize = Generator.random(Generator.Category.SCROLL); + break; + case 5: + prize = Generator.random(Generator.Category.HIGHFOOD); + break; + default: + prize = new ScrollOfUpgrade(); + break; + } + + return prize; + + } + + @Override + public void create() { + super.create(); + } + + @Override + protected void createItems() { + + Mob g2159687 = new G2159687(); + g2159687.pos = 36 + WIDTH * 6; + mobs.add(g2159687); + + Mob evan = new Evan(); + evan.pos = 40 + WIDTH * 42; + mobs.add(evan); + + Mob hbb = new HBB(); + hbb.pos = 38 + WIDTH * 13; + mobs.add(hbb); + + Mob sfb = new SFB(); + sfb.pos = 34 + WIDTH * 11; + mobs.add(sfb); + + Mob jinkeloid = new Jinkeloid(); + jinkeloid.pos = 38 + WIDTH * 41; + mobs.add(jinkeloid); + + Mob rustyblade = new Rustyblade(); + rustyblade.pos = 36 + WIDTH * 15; + mobs.add(rustyblade); + + Mob lyn = new Lyn(); + lyn.pos = 37 + WIDTH * 9; + mobs.add(lyn); + + Mob lery = new Lery(); + lery.pos = 33 + WIDTH * 9; + mobs.add(lery); + + Mob fruitcat = new FruitCat(); + fruitcat.pos = 37 + WIDTH * 4; + mobs.add(fruitcat); + + Mob coconut2 = new Coconut2(); + coconut2.pos = 20 + WIDTH * 35; + mobs.add(coconut2); + + Mob hmdzl = new Hmdzl001(); + hmdzl.pos = 20 + WIDTH * 42; + mobs.add(hmdzl); + + Mob xixizero = new XixiZero(); + xixizero.pos = 25 + WIDTH * 11; + mobs.add(xixizero); + + Mob omi = new Omicronrg9(); + omi.pos = 36 + WIDTH * 11; + mobs.add(omi); + + Mob mill = new Millilitre(); + mill.pos = 42 + WIDTH * 26; + mobs.add(mill); + + Mob honey = new HoneyPoooot(); + honey.pos = 39 + WIDTH * 15; + mobs.add(honey); + + Mob uncles = new UncleS(); + uncles.pos = 43 + WIDTH * 22; + mobs.add(uncles); + + Mob realman = new ARealMan(); + realman.pos = 36 + WIDTH * 42; + mobs.add(realman); + + Mob saidbysun = new SaidbySun(); + saidbysun.pos = 36 + WIDTH * 39; + mobs.add(saidbysun); + + Mob dp = new DreamPlayer(); + dp.pos = 43 + WIDTH * 24; + mobs.add(dp); + + Mob ice13 = new Ice13(); + ice13.pos = 29 + WIDTH * 35; + mobs.add(ice13); + + Mob goblin = new GoblinPlayer(); + goblin.pos = 8 + WIDTH * 14; + mobs.add(goblin); + + Mob Afly = new AFly(); + Afly.pos = 27 + WIDTH * 17; + mobs.add(Afly); + + Mob apos = new Apostle(); + apos.pos = 20 + WIDTH * 8; + mobs.add(apos); + + Mob shower = new Shower(); + shower.pos = 30 + WIDTH * 19; + mobs.add(shower); + + //Mob ice = new UIcecorps(); + // ice.pos = 6 + WIDTH * 34; + // mobs.add(ice); + + Mob year2 = new YearBeast2(); + year2.pos = 6 + WIDTH * 44; + mobs.add(year2); + + Mob tempest102 = new Tempest102(); + tempest102.pos = 33 + WIDTH * 42; + mobs.add(tempest102); + + Mob MOS = new MemoryOfSand(); + MOS.pos = 26 + WIDTH * 5; + mobs.add(MOS); + + Mob HS = new HateSokoban(); + HS.pos = 28 + WIDTH * 8; + mobs.add(HS); + + Mob LJ = new LaJi(); + LJ.pos = 23 + WIDTH * 10; + mobs.add(LJ); + + Mob NP = new NewPlayer(); + NP.pos = 23 + WIDTH * 11; + mobs.add(NP); + + Mob TL = new ThankList(); + TL.pos = 39 + WIDTH * 37; + mobs.add(TL); + + Mob SAR = new StormAndRain(); + SAR.pos = 24 + WIDTH * 6; + mobs.add(SAR); + + Mob LYNN = new Lynn(); + LYNN.pos = 40 + WIDTH * 28; + mobs.add(LYNN); + + Mob REN = new RENnpc(); + REN.pos = 40 + WIDTH * 26; + mobs.add(REN); + + Mob KOSTIS = new Kostis12345(); + KOSTIS.pos = 7 + WIDTH * 9;; + mobs.add(KOSTIS); + + TestMob test4 = new TestMob(); + test4.pos = 15 + WIDTH * 3; + mobs.add(test4); + + Mob tinkerer5 = new Tinkerer5(); + tinkerer5.pos = 10 + WIDTH * 34; + mobs.add(tinkerer5); + + storespots = new int[1]; + storespots[0] = 7 + WIDTH * 10; + + bombpots = new int[1]; + bombpots[0] = 21 + WIDTH * 35; + + } + + @Override + public void press(int cell, Char ch) { + + if(!special){ + storeStock(); + special=true; + } + + if (pit[cell] && ch == Dungeon.hero) { + Chasm.heroFall(cell); + return; + } + + TimekeepersHourglass.timeFreeze timeFreeze = null; + + if (ch != null) + timeFreeze = ch.buff(TimekeepersHourglass.timeFreeze.class); + + boolean trap = false; + boolean interrupt = false; + + + + switch (map[cell]) { + + + case Terrain.HIGH_GRASS: + HighGrass.trample(this, cell, ch); + break; + + case Terrain.WELL: + WellWater.affectCell(cell); + break; + + //case Terrain.ALCHEMY: + // Alchemy alchemy = new Alchemy(); + //level.blobs.put( Alchemy.class, alchemy ); + // break; + + case Terrain.PEDESTAL: + if (ch == null ) { + Alter.transmute(cell); + } + break; + + /*case Terrain.BED: + if(ch == null){ + BedLight.transmute(cell); + } + break;*/ + + case Terrain.DOOR: + Door.enter(cell); + break; + } + + if (trap){ + + if (Dungeon.visible[cell]) + Sample.INSTANCE.play(Assets.SND_TRAP); + + if (ch == Dungeon.hero) + Dungeon.hero.interrupt(); + + set(cell, Terrain.INACTIVE_TRAP); + GameScene.updateMap(cell); + } + + if (interrupt){ + + Dungeon.hero.interrupt(); + GameScene.updateMap(cell); + } + + Plant plant = plants.get(cell); + if (plant != null) { + plant.activate(ch); + } + } + + @Override + public String tilesTex() { + return Assets.TILES_SP; + } + + @Override + public String waterTex() { + return Assets.WATER_SEWERS; + } + + @Override + protected boolean build() { + + map = SokobanLayouts2.SOKOBAN_VAULT_LEVEL.clone(); + decorate(); + + buildFlagMaps(); + cleanWalls(); + + entrance = 8 + WIDTH * 5; + exit = 0; + + + return true; + } + @Override + protected void decorate() { + } + + @Override + protected void createMobs() { + + } + + @Override + public String tileName( int tile ) { + switch (tile) { + case Terrain.WATER: + return Messages.get(PrisonLevel.class, "water_name"); + default: + return super.tileName( tile ); + } + } + + @Override + public String tileDesc(int tile) { + switch (tile) { + case Terrain.EMPTY_DECO: + return Messages.get(PrisonLevel.class, "empty_deco_desc"); + case Terrain.BOOKSHELF: + return Messages.get(PrisonLevel.class, "bookshelf_desc"); + default: + return super.tileDesc( tile ); + } + } + + + @Override + public int randomRespawnCell() { + return -1; + } + + + +} diff --git a/java/com/hmdzl/spspd/levels/SokobanTeleportLevel.java b/java/com/hmdzl/spspd/levels/SokobanTeleportLevel.java new file mode 100644 index 00000000..e17920b8 --- /dev/null +++ b/java/com/hmdzl/spspd/levels/SokobanTeleportLevel.java @@ -0,0 +1,720 @@ +/* + * 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 + */ +package com.hmdzl.spspd.levels; + +import java.util.Collection; +import java.util.HashSet; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.WellWater; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.actors.mobs.SokobanSentinel; +import com.hmdzl.spspd.actors.mobs.npcs.Sheep; +import com.hmdzl.spspd.actors.mobs.npcs.SheepSokoban; +import com.hmdzl.spspd.actors.mobs.npcs.SheepSokobanBlack; +import com.hmdzl.spspd.actors.mobs.npcs.SheepSokobanCorner; +import com.hmdzl.spspd.actors.mobs.npcs.SheepSokobanSwitch; +import com.hmdzl.spspd.items.Gold; +import com.hmdzl.spspd.items.Heap; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.artifacts.TimekeepersHourglass; +import com.hmdzl.spspd.items.keys.IronKey; +import com.hmdzl.spspd.items.misc.AutoPotion; +import com.hmdzl.spspd.items.scrolls.ScrollOfMagicalInfusion; +import com.hmdzl.spspd.items.scrolls.ScrollOfRegrowth; +import com.hmdzl.spspd.items.scrolls.ScrollOfUpgrade; + +import com.hmdzl.spspd.items.wands.WandOfFlock; +import com.hmdzl.spspd.levels.features.Chasm; +import com.hmdzl.spspd.levels.features.Door; +import com.hmdzl.spspd.levels.features.HighGrass; +import com.hmdzl.spspd.levels.traps.ActivatePortalTrap; +import com.hmdzl.spspd.levels.traps.ChangeSheepTrap; +import com.hmdzl.spspd.levels.traps.FleecingTrap; +import com.hmdzl.spspd.levels.traps.HeapGenTrap; +import com.hmdzl.spspd.levels.traps.SokobanPortalTrap; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.plants.Phaseshift; +import com.hmdzl.spspd.plants.Plant; +import com.hmdzl.spspd.plants.Starflower; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Bundlable; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public class SokobanTeleportLevel extends Level { + + + { + color1 = 0x534f3e; + color2 = 0xb9d661; + WIDTH = 48; + HEIGHT = 48; + LENGTH = HEIGHT*WIDTH; + } + + + public HashSet heapstogen; + public int[] heapgenspots; + public int[] teleportspots; + public int[] portswitchspots; + public int[] teleportassign; + public int[] destinationspots; + public int[] destinationassign; + public int prizeNo; + + private static final String HEAPSTOGEN = "heapstogen"; + private static final String HEAPGENSPOTS = "heapgenspots"; + private static final String TELEPORTSPOTS = "teleportspots"; + private static final String PORTSWITCHSPOTS = "portswitchspots"; + private static final String DESTINATIONSPOTS = "destinationspots"; + private static final String TELEPORTASSIGN = "teleportassign"; + private static final String DESTINATIONASSIGN= "destinationassign"; + private static final String PRIZENO = "prizeNo"; + + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(HEAPSTOGEN, heapstogen); + bundle.put(HEAPGENSPOTS, heapgenspots); + bundle.put(TELEPORTSPOTS, teleportspots); + bundle.put(PORTSWITCHSPOTS, portswitchspots); + bundle.put(DESTINATIONSPOTS, destinationspots); + bundle.put(DESTINATIONASSIGN, destinationassign); + bundle.put(TELEPORTASSIGN, teleportassign); + bundle.put(PRIZENO, prizeNo); + } + + + @Override + public String tileName(int tile) { + switch (tile) { + case Terrain.SOKOBAN_SHEEP: + case Terrain.SWITCH_SOKOBAN_SHEEP: + case Terrain.CORNER_SOKOBAN_SHEEP: + case Terrain.BLACK_SOKOBAN_SHEEP: + return Messages.get(Level.class, "floor_name"); + case Terrain.WATER: + return Messages.get(Level.class, "water_name"); + case Terrain.WOOL_RUG: + return Messages.get(Level.class, "wool_rug_name"); + case Terrain.FLEECING_TRAP: + return Messages.get(Level.class, "fleecing_trap_name"); + case Terrain.CHANGE_SHEEP_TRAP: + return Messages.get(Level.class, "change_sheep_trap_name"); + case Terrain.SOKOBAN_ITEM_REVEAL: + return Messages.get(Level.class, "sokoban_item_reveal_name"); + case Terrain.SOKOBAN_PORT_SWITCH: + return Messages.get(Level.class, "sokoban_port_switch_name"); + case Terrain.PORT_WELL: + return Messages.get(Level.class, "port_well_name"); + default: + return super.tileName(tile); + } + } + + + @Override + public String tileDesc(int tile) { + switch (tile) { + case Terrain.SOKOBAN_SHEEP: + case Terrain.SWITCH_SOKOBAN_SHEEP: + case Terrain.CORNER_SOKOBAN_SHEEP: + case Terrain.BLACK_SOKOBAN_SHEEP: + return Messages.get(Level.class, "default_desc"); + case Terrain.EMPTY_DECO: + return Messages.get(PrisonLevel.class, "empty_deco_desc"); + case Terrain.BOOKSHELF: + return Messages.get(PrisonLevel.class, "bookshelf_desc"); + case Terrain.WOOL_RUG: + return Messages.get(Level.class, "wool_rug_desc"); + case Terrain.FLEECING_TRAP: + return Messages.get(Level.class, "fleecing_trap_desc"); + case Terrain.CHANGE_SHEEP_TRAP: + return Messages.get(Level.class, "change_sheep_trap_desc"); + case Terrain.SOKOBAN_ITEM_REVEAL: + return Messages.get(Level.class, "sokoban_item_reveal_desc"); + case Terrain.SOKOBAN_PORT_SWITCH: + return Messages.get(Level.class, "sokoban_port_switch_desc"); + case Terrain.PORT_WELL: + return Messages.get(Level.class, "port_well_desc"); + default: + return super.tileDesc(tile); + } + } + + + @Override + public void restoreFromBundle(Bundle bundle) { + + super.restoreFromBundle(bundle); + + heapgenspots = bundle.getIntArray(HEAPGENSPOTS); + teleportspots = bundle.getIntArray(TELEPORTSPOTS); + portswitchspots = bundle.getIntArray(PORTSWITCHSPOTS); + destinationspots = bundle.getIntArray(DESTINATIONSPOTS); + destinationassign = bundle.getIntArray(DESTINATIONASSIGN); + teleportassign = bundle.getIntArray(TELEPORTASSIGN); + prizeNo = bundle.getInt(PRIZENO); + + heapstogen = new HashSet(); + + Collection collectionheap = bundle.getCollection(HEAPSTOGEN); + for (Bundlable i : collectionheap) { + Item item = (Item) i; + if (item != null) { + heapstogen.add(item); + } + } + } + + @Override + public void create() { + heapstogen = new HashSet(); + heapgenspots = new int[30]; + teleportspots = new int[30]; + portswitchspots = new int[30]; + destinationspots = new int[30]; + destinationassign = new int[30]; + teleportassign = new int[30]; + super.create(); + } + + public void addItemToGen(Item item, int arraypos, int pos) { + if (item != null) { + heapstogen.add(item); + heapgenspots[arraypos]=pos; + } + } + + + public Item genPrizeItem() { + return genPrizeItem(null); + } + + + public Item genPrizeItem(Class match) { + + boolean keysLeft = false; + + if (heapstogen.size() == 0) + return null; + + for (Item item : heapstogen) { + if (match.isInstance(item)) { + heapstogen.remove(item); + keysLeft=true; + return item; + } + } + + if (match == null || !keysLeft) { + Item item = Random.element(heapstogen); + heapstogen.remove(item); + return item; + } + + return null; + } + + @Override + public void press(int cell, Char ch) { + + if (pit[cell] && ch == Dungeon.hero) { + Chasm.heroFall(cell); + return; + } + + TimekeepersHourglass.timeFreeze timeFreeze = null; + + if (ch != null) + timeFreeze = ch.buff(TimekeepersHourglass.timeFreeze.class); + + boolean trap = false; + + switch (map[cell]) { + + case Terrain.FLEECING_TRAP: + + if (ch != null && ch==Dungeon.hero){ + trap = true; + FleecingTrap.trigger(cell, ch); + } + break; + + case Terrain.CHANGE_SHEEP_TRAP: + + if (ch instanceof SheepSokoban || ch instanceof SheepSokobanSwitch || ch instanceof SheepSokobanCorner || ch instanceof Sheep || ch instanceof WandOfFlock.MagicSheep){ + trap = true; + ChangeSheepTrap.trigger(cell, ch); + } + break; + + case Terrain.SOKOBAN_PORT_SWITCH: + trap=false; + ActivatePortalTrap.trigger(cell, ch); + + /* + int arraypos = -1; //position in array of teleport switch + int portpos = -1; //position on map of teleporter + int portarraypos = -1; //position in array of teleporter + int destpos = -1; //destination position assigned to switch + + for(int i = 0; i < portswitchspots.length; i++) { + if(portswitchspots[i] == cell) { + arraypos = i; + //GLog.i("Pos1 %s", arraypos); + break; + } + } + + portpos = teleportassign[arraypos]; + destpos = destinationassign[arraypos]; + + // Stepping on switch deactivates the portal + destpos = -1; + + //GLog.i("ass2 %s", portpos); + //GLog.i("dest3 %s", destpos); + + for(int i = 0; i < teleportspots.length; i++) { + if(teleportspots[i] == portpos) { + portarraypos = i; + //GLog.i("Pos4 %s", portarraypos); + break; + } + } + + if (map[portpos] == Terrain.PORT_WELL){ + destinationspots[portarraypos]=destpos; + GLog.i("Portal Deactivated!"); + } + + */ + + break; + + + case Terrain.PORT_WELL: + + if (ch != null && ch==Dungeon.hero){ + + int portarray=-1; + int destinationspot=cell; + + for(int i = 0; i < teleportspots.length; i++) { + if(teleportspots[i] == cell) { + portarray = i; + break; + } + } + + //GLog.i("hero %s", portarray); + + if(portarray != -1) { + //GLog.i("portar %s", portarray); + destinationspot=destinationspots[portarray]; + //GLog.i("destspot %s", destinationspot); + if (destinationspot>0){ + SokobanPortalTrap.trigger(cell, ch, destinationspot); + } + } + } + break; + + case Terrain.HIGH_GRASS: + HighGrass.trample(this, cell, ch); + break; + + case Terrain.WELL: + WellWater.affectCell(cell); + break; + + /*case Terrain.ALCHEMY: + if (ch == null) { + Alchemy.transmute(cell); + } + break;*/ + + case Terrain.DOOR: + Door.enter(cell); + break; + } + + if (trap){ + + if (Dungeon.visible[cell]) + Sample.INSTANCE.play(Assets.SND_TRAP); + + if (ch == Dungeon.hero) + Dungeon.hero.interrupt(); + + set(cell, Terrain.INACTIVE_TRAP); + GameScene.updateMap(cell); + } + + Plant plant = plants.get(cell); + if (plant != null) { + plant.activate(ch); + } + } + + + + @Override + public void mobPress(Mob mob) { + + int cell = mob.pos; + + if (pit[cell] && !mob.flying) { + Chasm.mobFall(mob); + return; + } + + boolean trap = true; + boolean fleece = false; + boolean sheep = false; + switch (map[cell]) { + + case Terrain.FLEECING_TRAP: + if (mob instanceof SheepSokoban || mob instanceof SheepSokobanSwitch || mob instanceof SheepSokobanCorner || mob instanceof SheepSokobanBlack || mob instanceof Sheep || mob instanceof WandOfFlock.MagicSheep){ + fleece=true; + } + FleecingTrap.trigger(cell, mob); + break; + + case Terrain.CHANGE_SHEEP_TRAP: + trap=false; + if (mob instanceof SheepSokoban || mob instanceof SheepSokobanSwitch || mob instanceof SheepSokobanCorner || mob instanceof Sheep || mob instanceof WandOfFlock.MagicSheep){ + trap=true; + ChangeSheepTrap.trigger(cell, mob); + } + break; + + case Terrain.SOKOBAN_ITEM_REVEAL: + trap=false; + if (mob instanceof SheepSokoban || mob instanceof SheepSokobanSwitch || mob instanceof SheepSokobanCorner || mob instanceof SheepSokobanBlack || mob instanceof Sheep || mob instanceof WandOfFlock.MagicSheep){ + HeapGenTrap.trigger(cell, mob); + drop(genPrizeItem(IronKey.class),heapgenspots[prizeNo]); + prizeNo++; + sheep=true; + trap=true; + } + break; + + case Terrain.SOKOBAN_PORT_SWITCH: + trap=false; + if (mob instanceof SheepSokoban || mob instanceof SheepSokobanSwitch || mob instanceof SheepSokobanCorner || mob instanceof SheepSokobanBlack || mob instanceof Sheep || mob instanceof WandOfFlock.MagicSheep){ + ActivatePortalTrap.trigger(cell, mob); + + /* + public int[] teleportspots; location of teleports + public int[] portswitchspots; location of switches + public int[] teleportassign; assignment of teleports to switches + public int[] destinationspots; current assignment of destination spots to teleports + public int[] destinationassign; assignemnt of destination spots to switches + */ + + int arraypos = -1; //position in array of teleport switch + int portpos = -1; //position on map of teleporter + int portarray = -1; //position in array of teleporter + int destpos = -1; //destination position assigned to switch + + for(int i = 0; i < portswitchspots.length; i++) { + if(portswitchspots[i] == cell) { + arraypos = i; + //GLog.i("Pos1 %s", arraypos); + break; + } + } + + portpos = teleportassign[arraypos]; + destpos = destinationassign[arraypos]; + + //GLog.i("ass2 %s", portpos); + //GLog.i("dest3 %s", destpos); + + for(int i = 0; i < teleportspots.length; i++) { + if(teleportspots[i] == portpos) { + portarray = i; + //GLog.i("Pos4 %s", portarray); + break; + } + } + + if (map[portpos] == Terrain.PORT_WELL){ + destinationspots[portarray]=destpos; + GLog.i("Click!"); + } + + sheep=true; + } + break; + + case Terrain.DOOR: + Door.enter(cell); + + default: + trap = false; + } + + if (trap && !fleece && !sheep) { + if (Dungeon.visible[cell]) { + Sample.INSTANCE.play(Assets.SND_TRAP); + } + set(cell, Terrain.INACTIVE_TRAP); + GameScene.updateMap(cell); + } + + if (trap && fleece) { + if (Dungeon.visible[cell]) { + Sample.INSTANCE.play(Assets.SND_TRAP); + } + set(cell, Terrain.WOOL_RUG); + GameScene.updateMap(cell); + } + + if (trap && sheep) { + if (Dungeon.visible[cell]) { + Sample.INSTANCE.play(Assets.SND_TRAP); + } + set(cell, Terrain.EMPTY); + GameScene.updateMap(cell); + } + + + Plant plant = plants.get(cell); + if (plant != null) { + plant.activate(mob); + } + + Dungeon.observe(); + } + + @Override + public String tilesTex() { + return Assets.TILES_PUZZLE; + } + + @Override + public String waterTex() { + return Assets.WATER_PRISON; + } + + @Override + protected boolean build() { + + map = SokobanLayouts.SOKOBAN_TELEPORT_LEVEL.clone(); + decorate(); + + buildFlagMaps(); + cleanWalls(); + createSwitches(); + createSheep(); + + entrance = 8 + WIDTH * 16; + exit = 0 ; + + + return true; + } + @Override + protected void decorate() { + //do nothing, all decorations are hard-coded. + } + + @Override + protected void createMobs() { + + + SokobanSentinel mob = new SokobanSentinel(); + mob.pos = 21 + WIDTH * 25; + mobs.add(mob); + Actor.occupyCell(mob); + + SokobanSentinel mob2 = new SokobanSentinel(); + mob2.pos = 42 + WIDTH * 42; + mobs.add(mob2); + Actor.occupyCell(mob2); + + } + + + + protected void createSheep() { + for (int i = 0; i < LENGTH; i++) { + if (map[i]==Terrain.SOKOBAN_SHEEP){SheepSokoban npc = new SheepSokoban(); mobs.add(npc); npc.pos = i; Actor.occupyCell(npc);} + else if (map[i]==Terrain.CORNER_SOKOBAN_SHEEP){SheepSokobanCorner npc = new SheepSokobanCorner(); mobs.add(npc); npc.pos = i; Actor.occupyCell(npc);} + else if (map[i]==Terrain.SWITCH_SOKOBAN_SHEEP){SheepSokobanSwitch npc = new SheepSokobanSwitch(); mobs.add(npc); npc.pos = i; Actor.occupyCell(npc);} + else if (map[i]==Terrain.BLACK_SOKOBAN_SHEEP){SheepSokobanBlack npc = new SheepSokobanBlack(); mobs.add(npc); npc.pos = i; Actor.occupyCell(npc);} + else if (map[i]==Terrain.PORT_WELL){ + /* + Portal portal = new Portal(); + portal.seed(i, 1); + blobs.put(Portal.class, portal); + */ + } + + } + } + + + protected void createSwitches(){ + + //spots where your portals are + teleportspots[0] = 4 + WIDTH * 2; + teleportspots[1] = 16 + WIDTH * 5; + teleportspots[2] = 23 + WIDTH * 5; + teleportspots[3] = 32 + WIDTH * 5; + teleportspots[4] = 4 + WIDTH * 6; + teleportspots[5] = 25 + WIDTH * 7; + teleportspots[6] = 42 + WIDTH * 8; + teleportspots[7] = 10 + WIDTH * 9; + teleportspots[8] = 2 + WIDTH * 10; + teleportspots[9] = 3 + WIDTH * 17; + teleportspots[10] = 8 + WIDTH * 17; + teleportspots[11] = 17 + WIDTH * 17; + teleportspots[12] = 37 + WIDTH * 17; + teleportspots[13] = 40 + WIDTH * 17; + teleportspots[14] = 37 + WIDTH * 20; + teleportspots[15] = 40 + WIDTH * 20; + teleportspots[16] = 21 + WIDTH * 21; + teleportspots[17] = 25 + WIDTH * 22; + teleportspots[18] = 15 + WIDTH * 24; + teleportspots[19] = 6 + WIDTH * 44; + teleportspots[20] = 23 + WIDTH * 44; + teleportspots[21] = 44 + WIDTH * 28; + + + + //spots where your portal switches are + portswitchspots[0] = 30 + WIDTH * 14; + portswitchspots[1] = 35 + WIDTH * 16; + portswitchspots[2] = 42 + WIDTH * 16; + portswitchspots[3] = 35 + WIDTH * 21; + portswitchspots[4] = 42 + WIDTH * 21; + portswitchspots[5] = 30 + WIDTH * 36; + portswitchspots[6] = 32 + WIDTH * 36; + portswitchspots[7] = 35 + WIDTH * 36; + portswitchspots[8] = 37 + WIDTH * 36; + portswitchspots[9] = 27 + WIDTH * 41; + + + + //assign each switch to a portal + teleportassign[0] = 8 + WIDTH * 17; + teleportassign[1] = 44 + WIDTH * 28; + teleportassign[2] = 40 + WIDTH * 17; + teleportassign[3] = 40 + WIDTH * 17; + teleportassign[4] = 8 + WIDTH * 17; + teleportassign[5] = 40 + WIDTH * 20; + teleportassign[6] = 15 + WIDTH * 24; + teleportassign[7] = 8 + WIDTH * 17; + teleportassign[8] = 23 + WIDTH * 44; + teleportassign[9] = 6 + WIDTH * 44; + + + //assign each switch to a destination spot + destinationassign[0] = 9 + WIDTH * 9; + destinationassign[1] = 25 + WIDTH * 44; + destinationassign[2] = 36 + WIDTH * 20; + destinationassign[3] = 41 + WIDTH * 20; + destinationassign[4] = 2 + WIDTH * 17; + destinationassign[5] = 22 + WIDTH * 21; + destinationassign[6] = 16 + WIDTH * 17; + destinationassign[7] = 13 + WIDTH * 24; + destinationassign[8] = 0; + destinationassign[9] = 42 + WIDTH * 7; + + //set the original destination of portals + destinationspots[0] = 2 + WIDTH * 9; + destinationspots[1] = 24 + WIDTH * 8; + destinationspots[2] = 8 + WIDTH * 44; + destinationspots[3] = 37 + WIDTH * 16; + destinationspots[4] = 31 + WIDTH * 5; + destinationspots[5] = 9 + WIDTH * 16; + destinationspots[6] = 9 + WIDTH * 16; + destinationspots[7] = 5 + WIDTH * 2; + destinationspots[8] = 9 + WIDTH * 16; + destinationspots[9] = 9 + WIDTH * 16; + destinationspots[10] = 0; + destinationspots[11] = 9 + WIDTH * 16; + destinationspots[12] = 40 + WIDTH * 16; + destinationspots[13] = 36 + WIDTH * 20; + destinationspots[14] = 36 + WIDTH * 17; + destinationspots[15] = 24 + WIDTH * 23; + destinationspots[16] = 18 + WIDTH * 5; + destinationspots[17] = 9 + WIDTH * 16; + destinationspots[18] = 9 + WIDTH * 16; + destinationspots[19] = 9 + WIDTH * 16; + destinationspots[20] = 9 + WIDTH * 16; + destinationspots[21] = 0; + + + + } + + + @Override + protected void createItems() { + int goldmin=300; int goldmax=500; + if (first){ + goldmin=300; goldmax=500; + } + for (int i = 0; i < LENGTH; i++) { + if (map[i]==Terrain.SOKOBAN_HEAP){ + if (first && Random.Int(5)==0){drop(new ScrollOfUpgrade(), i).type = Heap.Type.CHEST;} + else {drop(new Gold(Random.Int(goldmin, goldmax)), i).type = Heap.Type.CHEST;} + } + } + + addItemToGen(new IronKey(Dungeon.depth) , 0, 8 + WIDTH * 18); + addItemToGen(new IronKey(Dungeon.depth) , 1, 8 + WIDTH * 18); + addItemToGen(new IronKey(Dungeon.depth) , 2, 8 + WIDTH * 18); + addItemToGen(new IronKey(Dungeon.depth) , 3, 8 + WIDTH * 18); + addItemToGen(new IronKey(Dungeon.depth) , 4, 8 + WIDTH * 18); + addItemToGen(new IronKey(Dungeon.depth) , 5, 8 + WIDTH * 18); + + + if (first){ + addItemToGen(new Phaseshift.Seed(), 6, 36 + WIDTH * 28); + addItemToGen(new Starflower.Seed(), 7, 36 + WIDTH * 28); + addItemToGen(new AutoPotion(), 8, 36 + WIDTH * 28); + addItemToGen(new ScrollOfMagicalInfusion(), 9, 36 + WIDTH * 28); + addItemToGen(new ScrollOfMagicalInfusion(), 10, 36 + WIDTH * 28); + addItemToGen(new ScrollOfRegrowth(), 11, 36 + WIDTH * 28); + addItemToGen(new Starflower.Seed(), 12, 36 + WIDTH * 28); + } + + //drop(new PotionOfLiquidFlame(), 9 + WIDTH * 24).type = Heap.Type.CHEST; + } + + @Override + public int randomRespawnCell() { + return -1; + } + + + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/levels/SokobanVaultLevel.java b/java/com/hmdzl/spspd/levels/SokobanVaultLevel.java new file mode 100644 index 00000000..dd6bdf43 --- /dev/null +++ b/java/com/hmdzl/spspd/levels/SokobanVaultLevel.java @@ -0,0 +1,496 @@ +/* + * 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 + */ +package com.hmdzl.spspd.levels; + +import java.util.Collection; +import java.util.HashSet; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.WellWater; +import com.hmdzl.spspd.actors.mobs.npcs.Sheep; +import com.hmdzl.spspd.actors.mobs.npcs.SheepSokoban; +import com.hmdzl.spspd.actors.mobs.npcs.SheepSokobanBlack; +import com.hmdzl.spspd.actors.mobs.npcs.SheepSokobanCorner; +import com.hmdzl.spspd.actors.mobs.npcs.SheepSokobanSwitch; +import com.hmdzl.spspd.items.Gold; +import com.hmdzl.spspd.items.Heap; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.artifacts.TimekeepersHourglass; +import com.hmdzl.spspd.items.misc.LuckyBadge; +import com.hmdzl.spspd.items.scrolls.ScrollOfUpgrade; + +import com.hmdzl.spspd.items.wands.WandOfFlock; +import com.hmdzl.spspd.levels.features.Chasm; +import com.hmdzl.spspd.levels.features.Door; +import com.hmdzl.spspd.levels.features.HighGrass; +import com.hmdzl.spspd.levels.traps.ActivatePortalTrap; +import com.hmdzl.spspd.levels.traps.ChangeSheepTrap; +import com.hmdzl.spspd.levels.traps.FleecingTrap; +import com.hmdzl.spspd.levels.traps.SokobanPortalTrap; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.plants.Plant; +import com.hmdzl.spspd.scenes.GameScene; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Bundlable; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public class SokobanVaultLevel extends Level { + + + { + color1 = 0x534f3e; + color2 = 0xb9d661; + WIDTH = 48; + HEIGHT = 48; + LENGTH = HEIGHT*WIDTH; + cleared=true; + } + + + public HashSet heapstogen; + public int[] heapgenspots; + public int[] teleportspots; + public int[] portswitchspots; + public int[] teleportassign; + public int[] destinationspots; + public int[] destinationassign; + public int prizeNo; + + private static final String HEAPSTOGEN = "heapstogen"; + private static final String HEAPGENSPOTS = "heapgenspots"; + private static final String TELEPORTSPOTS = "teleportspots"; + private static final String PORTSWITCHSPOTS = "portswitchspots"; + private static final String DESTINATIONSPOTS = "destinationspots"; + private static final String TELEPORTASSIGN = "teleportassign"; + private static final String DESTINATIONASSIGN= "destinationassign"; + private static final String PRIZENO = "prizeNo"; + + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(HEAPSTOGEN, heapstogen); + bundle.put(HEAPGENSPOTS, heapgenspots); + bundle.put(TELEPORTSPOTS, teleportspots); + bundle.put(PORTSWITCHSPOTS, portswitchspots); + bundle.put(DESTINATIONSPOTS, destinationspots); + bundle.put(DESTINATIONASSIGN, destinationassign); + bundle.put(TELEPORTASSIGN, teleportassign); + bundle.put(PRIZENO, prizeNo); + } + + + + @Override + public void restoreFromBundle(Bundle bundle) { + + super.restoreFromBundle(bundle); + + heapgenspots = bundle.getIntArray(HEAPGENSPOTS); + teleportspots = bundle.getIntArray(TELEPORTSPOTS); + portswitchspots = bundle.getIntArray(PORTSWITCHSPOTS); + destinationspots = bundle.getIntArray(DESTINATIONSPOTS); + destinationassign = bundle.getIntArray(DESTINATIONASSIGN); + teleportassign = bundle.getIntArray(TELEPORTASSIGN); + prizeNo = bundle.getInt(PRIZENO); + + heapstogen = new HashSet(); + + Collection collectionheap = bundle.getCollection(HEAPSTOGEN); + for (Bundlable i : collectionheap) { + Item item = (Item) i; + if (item != null) { + heapstogen.add(item); + } + } + } + + @Override + public void create() { + heapstogen = new HashSet(); + heapgenspots = new int[10]; + teleportspots = new int[10]; + portswitchspots = new int[10]; + destinationspots = new int[10]; + destinationassign = new int[10]; + teleportassign = new int[10]; + super.create(); + } + + public void addItemToGen(Item item, int arraypos, int pos) { + if (item != null) { + heapstogen.add(item); + heapgenspots[arraypos]=pos; + } + } + + + public Item genPrizeItem() { + return genPrizeItem(null); + } + + + public Item genPrizeItem(Class match) { + + boolean keysLeft = false; + + if (heapstogen.size() == 0) + return null; + + for (Item item : heapstogen) { + if (match.isInstance(item)) { + heapstogen.remove(item); + keysLeft=true; + return item; + } + } + + if (match == null || !keysLeft) { + Item item = Random.element(heapstogen); + heapstogen.remove(item); + return item; + } + + return null; + } + + @Override + public void press(int cell, Char ch) { + + if (pit[cell] && ch == Dungeon.hero) { + Chasm.heroFall(cell); + return; + } + + TimekeepersHourglass.timeFreeze timeFreeze = null; + + if (ch != null) + timeFreeze = ch.buff(TimekeepersHourglass.timeFreeze.class); + + boolean trap = false; + boolean interrupt = false; + + switch (map[cell]) { + + case Terrain.FLEECING_TRAP: + + if (ch==null){ + interrupt=true; + } + + if (ch != null && ch==Dungeon.hero){ + trap = true; + FleecingTrap.trigger(cell, ch); + } + break; + + case Terrain.CHANGE_SHEEP_TRAP: + + if (ch instanceof SheepSokoban || ch instanceof SheepSokobanSwitch || ch instanceof SheepSokobanCorner || ch instanceof Sheep || ch instanceof WandOfFlock.MagicSheep){ + trap = true; + ChangeSheepTrap.trigger(cell, ch); + } + break; + + case Terrain.WOOL_RUG: + + break; + + case Terrain.SOKOBAN_PORT_SWITCH: + trap=false; + if (ch!=null){ + ActivatePortalTrap.trigger(cell, ch); + + + int arraypos = -1; //position in array of teleport switch + int portpos = -1; //position on map of teleporter + int portarraypos = -1; //position in array of teleporter + int destpos = -1; //destination position assigned to switch + + for(int i = 0; i < portswitchspots.length; i++) { + if(portswitchspots[i] == cell) { + arraypos = i; + break; + } + } + + portpos = teleportassign[arraypos]; + destpos = destinationassign[arraypos]; + + /* Stepping on switch deactivates the portal */ + destpos = -1; + + for(int i = 0; i < teleportspots.length; i++) { + if(teleportspots[i] == portpos) { + portarraypos = i; + break; + } + } + + if (map[portpos] == Terrain.PORT_WELL){ + destinationspots[portarraypos]=destpos; + } + + + } + break; + + + case Terrain.PORT_WELL: + + if (ch != null && ch==Dungeon.hero){ + + int portarray=-1; + int destinationspot=cell; + + for(int i = 0; i < teleportspots.length; i++) { + if(teleportspots[i] == cell) { + portarray = i; + break; + } + } + + if(portarray != -1) { + destinationspot=destinationspots[portarray]; + if (destinationspot>0){ + SokobanPortalTrap.trigger(cell, ch, destinationspot); + } + } + } + break; + + case Terrain.HIGH_GRASS: + HighGrass.trample(this, cell, ch); + break; + + case Terrain.WELL: + WellWater.affectCell(cell); + break; + + /*case Terrain.ALCHEMY: + if (ch == null) { + Alchemy.transmute(cell); + } + break;*/ + + case Terrain.DOOR: + Door.enter(cell); + break; + } + + if (trap){ + + if (Dungeon.visible[cell]) + Sample.INSTANCE.play(Assets.SND_TRAP); + + if (ch == Dungeon.hero) + Dungeon.hero.interrupt(); + + set(cell, Terrain.INACTIVE_TRAP); + GameScene.updateMap(cell); + } + + if (interrupt){ + + Dungeon.hero.interrupt(); + GameScene.updateMap(cell); + } + + Plant plant = plants.get(cell); + if (plant != null) { + plant.activate(ch); + } + } + + @Override + public String tilesTex() { + return Assets.TILES_PUZZLE; + } + + @Override + public String waterTex() { + return Assets.WATER_PRISON; + } + + @Override + protected boolean build() { + + map = SokobanLayouts2.SOKOBAN_VAULT_LEVEL.clone(); + decorate(); + + buildFlagMaps(); + cleanWalls(); + createSwitches(); + createSheep(); + + entrance = 8 + WIDTH * 5; + exit = 0 + WIDTH * 47; + + + return true; + } + @Override + protected void decorate() { + for (int i = 0; i < getLength(); i++) { + + if (map[i]==Terrain.EMPTY && heaps.get(i) == null && Random.Float()<.20){map[i] = Terrain.HIGH_GRASS;} + if (map[i]==Terrain.EMPTY && heaps.get(i) == null && Random.Float()<.25){map[i] = Terrain.GRASS;} + if (map[i]==Terrain.EMPTY && heaps.get(i) == null && Random.Float()<.30){map[i] = Terrain.SHRUB;} + } + } + + @Override + protected void createMobs() { + /* + SokobanSentinel mob = new SokobanSentinel(); + mob.pos = 38 + WIDTH * 21; + mobs.add(mob); + Actor.occupyCell(mob); + + SokobanSentinel mob2 = new SokobanSentinel(); + mob2.pos = 25 + WIDTH * 36; + mobs.add(mob2); + Actor.occupyCell(mob2); + */ + } + + + + protected void createSheep() { + for (int i = 0; i < LENGTH; i++) { + if (map[i]==Terrain.SOKOBAN_SHEEP){SheepSokoban npc = new SheepSokoban(); mobs.add(npc); npc.pos = i; Actor.occupyCell(npc);} + else if (map[i]==Terrain.CORNER_SOKOBAN_SHEEP){SheepSokobanCorner npc = new SheepSokobanCorner(); mobs.add(npc); npc.pos = i; Actor.occupyCell(npc);} + else if (map[i]==Terrain.SWITCH_SOKOBAN_SHEEP){SheepSokobanSwitch npc = new SheepSokobanSwitch(); mobs.add(npc); npc.pos = i; Actor.occupyCell(npc);} + else if (map[i]==Terrain.BLACK_SOKOBAN_SHEEP){SheepSokobanBlack npc = new SheepSokobanBlack(); mobs.add(npc); npc.pos = i; Actor.occupyCell(npc);} + else if (map[i]==Terrain.PORT_WELL){ + + /* + Portal portal = new Portal(); + portal.seed(i, 1); + blobs.put(Portal.class, portal); + */ + } + + } + } + + + protected void createSwitches(){ + + //spots where your portals are + + + //spots where your portal switches are + + + //assign each switch to a portal + + + //assign each switch to a destination spot + + + //set the original destination of portals + + } + + + @Override + protected void createItems() { + int goldmin=1; int goldmax=10; + boolean ringDrop = false; + if (first){ + goldmin=300; goldmax=500; + } + for (int i = 0; i < LENGTH; i++) { + if (map[i]==Terrain.EMPTY && heaps.get(i) == null && Random.Int(100)>70){ + if (first && !ringDrop){drop(new LuckyBadge(), i).type = Heap.Type.CHEST; ringDrop=true;} + else if (first && Random.Int(50)==0){drop(new ScrollOfUpgrade(), i).type = Heap.Type.CHEST;} + else {drop(new Gold(Random.Int(goldmin, goldmax)), i).type = Heap.Type.CHEST;} + } + } + + + } + + @Override + public int randomRespawnCell() { + return -1; + } + + @Override + public String tileName(int tile) { + switch (tile) { + case Terrain.SOKOBAN_SHEEP: + case Terrain.SWITCH_SOKOBAN_SHEEP: + case Terrain.CORNER_SOKOBAN_SHEEP: + case Terrain.BLACK_SOKOBAN_SHEEP: + return Messages.get(Level.class, "floor_name"); + case Terrain.WATER: + return Messages.get(Level.class, "water_name"); + case Terrain.WOOL_RUG: + return Messages.get(Level.class, "wool_rug_name"); + case Terrain.FLEECING_TRAP: + return Messages.get(Level.class, "fleecing_trap_name"); + case Terrain.CHANGE_SHEEP_TRAP: + return Messages.get(Level.class, "change_sheep_trap_name"); + case Terrain.SOKOBAN_ITEM_REVEAL: + return Messages.get(Level.class, "sokoban_item_reveal_name"); + case Terrain.SOKOBAN_PORT_SWITCH: + return Messages.get(Level.class, "sokoban_port_switch_name"); + case Terrain.PORT_WELL: + return Messages.get(Level.class, "port_well_name"); + default: + return super.tileName(tile); + } + } + + + @Override + public String tileDesc(int tile) { + switch (tile) { + case Terrain.SOKOBAN_SHEEP: + case Terrain.SWITCH_SOKOBAN_SHEEP: + case Terrain.CORNER_SOKOBAN_SHEEP: + case Terrain.BLACK_SOKOBAN_SHEEP: + return Messages.get(Level.class, "default_desc"); + case Terrain.EMPTY_DECO: + return Messages.get(PrisonLevel.class, "empty_deco_desc"); + case Terrain.BOOKSHELF: + return Messages.get(PrisonLevel.class, "bookshelf_desc"); + case Terrain.WOOL_RUG: + return Messages.get(Level.class, "wool_rug_desc"); + case Terrain.FLEECING_TRAP: + return Messages.get(Level.class, "fleecing_trap_desc"); + case Terrain.CHANGE_SHEEP_TRAP: + return Messages.get(Level.class, "change_sheep_trap_desc"); + case Terrain.SOKOBAN_ITEM_REVEAL: + return Messages.get(Level.class, "sokoban_item_reveal_desc"); + case Terrain.SOKOBAN_PORT_SWITCH: + return Messages.get(Level.class, "sokoban_port_switch_desc"); + case Terrain.PORT_WELL: + return Messages.get(Level.class, "port_well_desc"); + default: + return super.tileDesc(tile); + } + } + +} diff --git a/java/com/hmdzl/spspd/levels/TenguDenLevel.java b/java/com/hmdzl/spspd/levels/TenguDenLevel.java new file mode 100644 index 00000000..57b9cbab --- /dev/null +++ b/java/com/hmdzl/spspd/levels/TenguDenLevel.java @@ -0,0 +1,310 @@ +/* + * 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 + */ +package com.hmdzl.spspd.levels; + +import java.util.ArrayList; +import java.util.List; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.mobs.Bestiary; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.levels.Room.Type; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.GameScene; +import com.watabou.noosa.Scene; +import com.watabou.utils.Bundle; +import com.watabou.utils.Graph; +import com.watabou.utils.Random; + +public class TenguDenLevel extends RegularLevel { + + { + color1 = 0x48763c; + color2 = 0x59994a; + cleared=true; + } + + private int stairs = 0; + + @Override + public String tilesTex() { + return Assets.TILES_CAVES; + } + + @Override + public String waterTex() { + return Assets.WATER_CAVES; + } + + @Override + protected boolean build() { + + initRooms(); + + int distance; + // if we ever need to try 20 or more times to find a room, better to + // give up and try again. + int retry = 0; + + // start with finding an entrance room (will also contain exit) + // the room must be at least 4x4 and be nearer the top of the map(so + // that it is less likely something connects to the top) + do { + if (retry++ > 20) { + return false; + } + roomEntrance = Random.element(rooms); + } while (roomEntrance.width() < 4 || roomEntrance.height() < 4 + || roomEntrance.top == 0 || roomEntrance.top >= 12); + + roomEntrance.type = Type.ENTRANCE; + roomExit = roomEntrance; + + // now find the rest of the rooms for this boss mini-maze + Room curRoom = null; + Room lastRoom = roomEntrance; + // we make 4 rooms, last iteration is tieing the final room to the start + for (int i = 0; i <= 4; i++) { + retry = 0; + // find a suitable room the first four times + // suitable room should be empty, have a distance of 2 from the + // current room, and not touch the entrance. + if (i < 4) { + do { + if (retry++ > 20) { + return false; + } + curRoom = Random.element(rooms); + Graph.buildDistanceMap(rooms, curRoom); + distance = lastRoom.distance(); + } while (curRoom.type != Type.NULL || distance != 2 + || !curRoom.intersect(roomEntrance).isEmpty()); + + curRoom.type = Type.STANDARD; + + // otherwise, we're on the last iteration. + } else { + // set the current room to the entrance, so we can build a + // connection to it. + curRoom = roomEntrance; + } + + // now build a connection between the current room and the last one. + Graph.buildDistanceMap(rooms, curRoom); + List path = Graph.buildPath(rooms, lastRoom, curRoom); + + Graph.setPrice(path, lastRoom.distance); + + path = Graph.buildPath(rooms, lastRoom, curRoom); + + Room room = lastRoom; + for (Room next : path) { + room.connect(next); + room = next; + } + + if (i == 4) { + + // we must find a room for his royal highness! + // look at rooms adjacent to the final found room (likely to be + // furthest from start) + ArrayList candidates = new ArrayList(); + for (Room r : lastRoom.neigbours) { + if (r.type == Type.NULL && r.connected.size() == 0 + && !r.neigbours.contains(roomEntrance)) { + candidates.add(r); + } + } + + // if we have candidates, pick a room and put the king there + if (candidates.size() > 0) { + Room kingsRoom = Random.element(candidates); + kingsRoom.connect(lastRoom); + kingsRoom.type = Room.Type.RAT_KING2; + + + // unacceptable! make a new level... + } else { + return false; + } + } + lastRoom = curRoom; + } + + // the connection structure ensures that (most of the time) there is a + // nice loop for the player to kite the + // boss around. What's nice is that there is enough chaos such that the + // loop is rarely straightforward + // and boring. + + // fills our connection rooms in with tunnel + for (Room r : rooms) { + if (r.type == Type.NULL && r.connected.size() > 0) { + r.type = Type.TUNNEL; + } + } + + // make sure nothing is connecting at the top of the entrance, this + // would be bad. + for (Room r : roomEntrance.neigbours) { + if (r.bottom == roomEntrance.top && r.type != Type.NULL) + return false; + } + + paint(); + + // TODO: not handling this through a painter is kinda iffy, separate + // into a painter if you use it again. + // sticks the exit in the room entrance. + exit = roomEntrance.top * Level.getWidth() + + (roomEntrance.left + roomEntrance.right) / 2; + + + map[exit] = Terrain.WALL; + map[entrance] = Terrain.PEDESTAL; + + + paintWater(); + paintGrass(); + + return true; + } + + @Override + protected boolean[] water() { + return Patch.generate(0.5f, 5); + } + + @Override + protected boolean[] grass() { + return Patch.generate(0.40f, 4); + } + + @Override + protected void decorate() { + int start = roomExit.top * getWidth() + roomExit.left + 1; + int end = start + roomExit.width() - 1; + for (int i = start; i < end; i++) { + if (i != exit) { + map[i] = Terrain.WALL_DECO; + map[i + getWidth()] = Terrain.WATER; + } else { + map[i + getWidth()] = Terrain.EMPTY; + } + } + } + + @Override + public void addVisuals(Scene scene) { + SewerLevel.addVisuals(this, scene); + } + + @Override + protected void createMobs() { + if (Dungeon.tengudenkilled){ + return; + } + Mob mob = Bestiary.mob(Dungeon.depth); + Room room; + do { + room = Random.element(rooms); + } while (room.type != Type.STANDARD); + mob.pos = room.random(); + mobs.add(mob); + } + + @Override + public Actor respawner() { + return null; + } + + @Override + protected void createItems() { + + } + + @Override + public int randomRespawnCell() { + return -1; + } + public void seal() { + if (entrance != 0) { + + //locked = true; + + set(entrance, Terrain.WATER_TILES); + GameScene.updateMap(entrance); + GameScene.ripple(entrance); + + stairs = entrance; + entrance = 0; + } + } + + public void unseal() { + if (stairs != 0) { + + locked = false; + + entrance = stairs; + stairs = 0; + + set(entrance, Terrain.ENTRANCE); + GameScene.updateMap(entrance); + + } + } + + private static final String STAIRS = "stairs"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(STAIRS, stairs); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + stairs = bundle.getInt(STAIRS); + } + + @Override + public String tileName( int tile ) { + switch (tile) { + case Terrain.WATER: + return Messages.get(SewerLevel.class, "water_name"); + default: + return super.tileName( tile ); + } + } + + @Override + public String tileDesc(int tile) { + switch (tile) { + case Terrain.EMPTY_DECO: + return Messages.get(SewerLevel.class, "empty_deco_desc"); + case Terrain.BOOKSHELF: + return Messages.get(SewerLevel.class, "bookshelf_desc"); + default: + return super.tileDesc( tile ); + } + } +} diff --git a/java/com/hmdzl/spspd/levels/Terrain.java b/java/com/hmdzl/spspd/levels/Terrain.java new file mode 100644 index 00000000..2ee1e26b --- /dev/null +++ b/java/com/hmdzl/spspd/levels/Terrain.java @@ -0,0 +1,228 @@ +/* + * 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 + */ +package com.hmdzl.spspd.levels; + +import com.hmdzl.spspd.levels.traps.*; +import com.watabou.utils.SparseArray; + +public class Terrain { + + public static final int CHASM = 0; + public static final int EMPTY = 1; + public static final int GRASS = 2; + public static final int EMPTY_WELL = 3; + public static final int WALL = 4; + public static final int DOOR = 5; + public static final int OPEN_DOOR = 6; + public static final int ENTRANCE = 7; + public static final int EXIT = 8; + public static final int EMBERS = 9; + public static final int LOCKED_DOOR = 10; + public static final int PEDESTAL = 11; + public static final int WALL_DECO = 12; + public static final int BARRICADE = 13; + public static final int EMPTY_SP = 14; + public static final int HIGH_GRASS = 15; + + public static final int SECRET_DOOR = 16; + public static final int SECRET_TRAP = 18; + public static final int TRAP = 20; + public static final int INACTIVE_TRAP = 22; + + public static final int UNBREAK_WALL = 28; + + public static final int EMPTY_DECO = 24; + public static final int LOCKED_EXIT = 25; + public static final int UNLOCKED_EXIT = 26; + public static final int SIGN = 29; + + public static final int TRAP_AIR = 30; + public static final int EMPTY_AIR = 31; + + public static final int WELL = 34; + public static final int STATUE = 35; + public static final int STATUE_SP = 36; + public static final int STATUE_SSP = 37; + public static final int TENT = 38; + public static final int BED = 40; + public static final int BOOKSHELF = 41; + public static final int ALCHEMY = 42; + public static final int CHASM_FLOOR = 43; + public static final int CHASM_FLOOR_SP = 44; + public static final int CHASM_WALL = 45; + public static final int CHASM_WATER = 46; + public static final int SHRUB = 47; + + /*public static final int SECRET_DOOR = 16; + public static final int TOXIC_TRAP = 17; + public static final int SECRET_TOXIC_TRAP = 18; + public static final int FIRE_TRAP = 19; + public static final int SECRET_FIRE_TRAP = 20; + public static final int PARALYTIC_TRAP = 21; + public static final int SECRET_PARALYTIC_TRAP = 22; + public static final int INACTIVE_TRAP = 23; + public static final int POISON_TRAP = 27; + public static final int SECRET_POISON_TRAP = 28; + public static final int ALARM_TRAP = 30; + public static final int SECRET_ALARM_TRAP = 31; + public static final int LIGHTNING_TRAP = 32; + public static final int SECRET_LIGHTNING_TRAP = 33; + public static final int GRIPPING_TRAP = 37; + public static final int SECRET_GRIPPING_TRAP = 38; + public static final int SUMMONING_TRAP = 39; + public static final int SECRET_SUMMONING_TRAP = 40;*/ + public static final int FLEECING_TRAP = 65; + public static final int WOOL_RUG = 66; + public static final int SOKOBAN_SHEEP = 67; + public static final int CORNER_SOKOBAN_SHEEP = 68; + public static final int SWITCH_SOKOBAN_SHEEP = 69; + public static final int CHANGE_SHEEP_TRAP = 70; + public static final int SOKOBAN_ITEM_REVEAL = 71; + public static final int SOKOBAN_HEAP = 72; + public static final int BLACK_SOKOBAN_SHEEP = 73; + public static final int SOKOBAN_PORT_SWITCH = 75; + public static final int PORT_WELL = 74; + + public static final int WATER_TILES = 48; + public static final int WATER = 63; + + public static final int PASSABLE = 0x01; + public static final int LOS_BLOCKING = 0x02; + public static final int FLAMABLE = 0x04; + public static final int SECRET = 0x08; + public static final int SOLID = 0x10; + public static final int AVOID = 0x20; + public static final int LIQUID = 0x40; + public static final int PIT = 0x80; + //public static final int SHOCKABLE = 0x200; + + public static final int UNSTITCHABLE = 0x100; + + public static final int[] flags = new int[256]; + static { + flags[CHASM] = AVOID | PIT | UNSTITCHABLE; + flags[EMPTY] = PASSABLE; + flags[GRASS] = PASSABLE | FLAMABLE; + flags[EMPTY_WELL] = PASSABLE; + flags[WATER] = PASSABLE | LIQUID | UNSTITCHABLE /*SHOCKABLE*/; + flags[WALL] = LOS_BLOCKING | SOLID | UNSTITCHABLE; + flags[UNBREAK_WALL] = flags[WALL]; + flags[DOOR] = PASSABLE | LOS_BLOCKING | FLAMABLE | SOLID | UNSTITCHABLE; + flags[OPEN_DOOR] = PASSABLE | FLAMABLE | UNSTITCHABLE; + flags[ENTRANCE] = PASSABLE/* | SOLID */; + flags[EXIT] = PASSABLE; + flags[EMBERS] = PASSABLE; + flags[LOCKED_DOOR] = LOS_BLOCKING | SOLID | UNSTITCHABLE; + flags[PEDESTAL] = PASSABLE | UNSTITCHABLE; + flags[TENT] = PASSABLE | UNSTITCHABLE; + flags[BED] = PASSABLE | UNSTITCHABLE; + flags[WALL_DECO] = flags[WALL]; + flags[BARRICADE] = FLAMABLE | SOLID | LOS_BLOCKING; + flags[EMPTY_SP] = flags[EMPTY] | UNSTITCHABLE; + flags[HIGH_GRASS] = PASSABLE | LOS_BLOCKING | FLAMABLE; + + flags[SECRET_DOOR] = flags[WALL] | SECRET | UNSTITCHABLE; + flags[SECRET_TRAP] = flags[EMPTY] | SECRET; + flags[TRAP] = AVOID; + flags[INACTIVE_TRAP]= flags[EMPTY]; + + flags[TRAP_AIR] = AVOID; + + flags[EMPTY_DECO] = flags[EMPTY]; + flags[LOCKED_EXIT] = SOLID; + flags[UNLOCKED_EXIT] = PASSABLE; + flags[SIGN] = PASSABLE | FLAMABLE; + flags[WELL] = AVOID; + flags[STATUE] = SOLID; + flags[STATUE_SP] = flags[STATUE] | UNSTITCHABLE; + flags[STATUE_SSP] = flags[STATUE] | UNSTITCHABLE; + flags[BOOKSHELF] = flags[BARRICADE] | UNSTITCHABLE; + flags[ALCHEMY] = PASSABLE; + //flags[ALCHEMY] = SOLID; + flags[SHRUB] = FLAMABLE | SOLID | LOS_BLOCKING;; + + flags[CHASM_WALL] = flags[CHASM]; + flags[CHASM_FLOOR] = flags[CHASM]; + flags[CHASM_FLOOR_SP] = flags[CHASM]; + flags[CHASM_WATER] = flags[CHASM]; + + //flags[SECRET_DOOR] = flags[WALL] | SECRET | UNSTITCHABLE; + //flags[TOXIC_TRAP] = AVOID; + //flags[SECRET_TOXIC_TRAP] = flags[EMPTY] | SECRET; + //flags[FIRE_TRAP] = AVOID; + //flags[SECRET_FIRE_TRAP] = flags[EMPTY] | SECRET; + //flags[PARALYTIC_TRAP] = AVOID; + //flags[SECRET_PARALYTIC_TRAP] = flags[EMPTY] | SECRET; + //flags[POISON_TRAP] = AVOID; + //flags[SECRET_POISON_TRAP] = flags[EMPTY] | SECRET; + //flags[ALARM_TRAP] = AVOID; + //flags[SECRET_ALARM_TRAP] = flags[EMPTY] | SECRET; + //flags[LIGHTNING_TRAP] = AVOID; + //flags[SECRET_LIGHTNING_TRAP] = flags[EMPTY] | SECRET; + //flags[GRIPPING_TRAP] = AVOID; + //flags[SECRET_GRIPPING_TRAP] = flags[EMPTY] | SECRET; + //flags[SUMMONING_TRAP] = AVOID; + //flags[SECRET_SUMMONING_TRAP] = flags[EMPTY] | SECRET; + //flags[INACTIVE_TRAP] = flags[EMPTY]; + flags[FLEECING_TRAP] = AVOID ; + flags[WOOL_RUG] = PASSABLE; + flags[SOKOBAN_SHEEP] = PASSABLE; + flags[CORNER_SOKOBAN_SHEEP] = PASSABLE; + flags[SWITCH_SOKOBAN_SHEEP] = PASSABLE; + flags[CHANGE_SHEEP_TRAP] = PASSABLE; + flags[SOKOBAN_ITEM_REVEAL] = PASSABLE; + flags[SOKOBAN_HEAP] = PASSABLE; + flags[BLACK_SOKOBAN_SHEEP] = PASSABLE; + flags[SOKOBAN_PORT_SWITCH] = PASSABLE; + flags[PORT_WELL] = PASSABLE; + + + for (int i = WATER_TILES; i < WATER_TILES + 16; i++) { + flags[i] = flags[WATER]; + } + }; + + public static int discover(int terr) { + switch (terr) { + case SECRET_DOOR: + return DOOR; + /*case SECRET_FIRE_TRAP: + return FIRE_TRAP; + case SECRET_PARALYTIC_TRAP: + return PARALYTIC_TRAP; + case SECRET_TOXIC_TRAP: + return TOXIC_TRAP; + case SECRET_POISON_TRAP: + return POISON_TRAP; + case SECRET_ALARM_TRAP: + return ALARM_TRAP; + case SECRET_LIGHTNING_TRAP: + return LIGHTNING_TRAP; + case SECRET_GRIPPING_TRAP: + return GRIPPING_TRAP; + case SECRET_SUMMONING_TRAP: + return SUMMONING_TRAP;*/ + case SECRET_TRAP: + return TRAP; + default: + return terr; + } + } + + +} diff --git a/java/com/hmdzl/spspd/levels/ThiefBossLevel.java b/java/com/hmdzl/spspd/levels/ThiefBossLevel.java new file mode 100644 index 00000000..db637990 --- /dev/null +++ b/java/com/hmdzl/spspd/levels/ThiefBossLevel.java @@ -0,0 +1,269 @@ +/* + * 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 + */ +package com.hmdzl.spspd.levels; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.mobs.BanditKing; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.actors.mobs.ThiefKing; +import com.hmdzl.spspd.items.Heap; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.keys.SkeletonKey; +import com.hmdzl.spspd.levels.painters.Painter; +import com.hmdzl.spspd.scenes.GameScene; +import com.watabou.noosa.Scene; +import com.watabou.noosa.tweeners.AlphaTweener; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public class ThiefBossLevel extends Level { + + { + color1 = 0x4b6636; + color2 = 0xf2f2f2; + cleared=true; + } + + protected static final int DROP_TIMER = 5; + + private static final int TOP = 2; + private static final int HALL_WIDTH = 13; + private static final int HALL_HEIGHT = 15; + private static final int CHAMBER_HEIGHT = 3; + + private static final int LEFT = (getWidth() - HALL_WIDTH) / 2; + private static final int CENTER = LEFT + HALL_WIDTH / 2; + + private int arenaDoor; + private boolean enteredArena = false; + private boolean keyDropped = false; + + @Override + public String tilesTex() { + return Assets.TILES_VAULT; + } + + @Override + public String waterTex() { + return Assets.WATER_PRISON; + } + + private static final String DOOR = "door"; + private static final String ENTERED = "entered"; + private static final String DROPPED = "droppped"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(DOOR, arenaDoor); + bundle.put(ENTERED, enteredArena); + bundle.put(DROPPED, keyDropped); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + arenaDoor = bundle.getInt(DOOR); + enteredArena = bundle.getBoolean(ENTERED); + keyDropped = bundle.getBoolean(DROPPED); + } + + @Override + protected boolean build() { + + Painter.fill(this, LEFT, TOP, HALL_WIDTH, HALL_HEIGHT, Terrain.EMPTY); + Painter.fill(this, CENTER, TOP, 1, HALL_HEIGHT, Terrain.EMPTY); + + int y = TOP + 1; + while (y < TOP + HALL_HEIGHT) { + map[y * getWidth() + CENTER - 2] = Terrain.TRAP_AIR; + map[y * getWidth() + CENTER + 2] = Terrain.TRAP_AIR; + y += 2; + } + + exit = (TOP - 1) * getWidth() + CENTER; + map[exit] = Terrain.LOCKED_EXIT; + + arenaDoor = (TOP + HALL_HEIGHT) * getWidth() + CENTER; + map[arenaDoor] = Terrain.DOOR; + + Painter.fill(this, LEFT, TOP + HALL_HEIGHT + 1, HALL_WIDTH, + CHAMBER_HEIGHT, Terrain.EMPTY); + Painter.fill(this, LEFT, TOP + HALL_HEIGHT + 1, 1, CHAMBER_HEIGHT, + Terrain.WATER); + Painter.fill(this, LEFT + HALL_WIDTH - 1, TOP + HALL_HEIGHT + 1, 1, + CHAMBER_HEIGHT, Terrain.WATER); + + entrance = (TOP + HALL_HEIGHT + 2 + Random.Int(CHAMBER_HEIGHT - 1)) + * getWidth() + LEFT + (/* 1 + */Random.Int(HALL_WIDTH - 2)); + map[entrance] = Terrain.PEDESTAL; + + map[exit] = Terrain.WALL; + + return true; + } + + @Override + protected void decorate() { + + for (int i = 0; i < getLength(); i++) { + if (map[i] == Terrain.EMPTY && Random.Int(10) == 0) { + map[i] = Terrain.EMPTY_DECO; + } else if (map[i] == Terrain.WALL && Random.Int(8) == 0) { + map[i] = Terrain.WALL_DECO; + } + } + + //int sign = arenaDoor + WIDTH + 1; + //map[sign] = Terrain.SIGN; + } + + public static int pedestal(boolean left) { + if (left) { + return (TOP + HALL_HEIGHT / 2) * getWidth() + CENTER - 2; + } else { + return (TOP + HALL_HEIGHT / 2) * getWidth() + CENTER + 2; + } + } + + @Override + protected void createMobs() { + } + + @Override + public Actor respawner() { + return null; + } + + @Override + protected void createItems() { + + } + + @Override + public int randomRespawnCell() { + return -1; + } + + @Override + public void press(int cell, Char hero) { + + super.press(cell, hero); + + if (!enteredArena && outsideEntraceRoom(cell) && hero == Dungeon.hero) { + + enteredArena = true; + //locked = true; + + Mob boss = new ThiefKing(); + Mob bandit1 = new BanditKing(); + Mob bandit2 = new BanditKing(); + boss.state = boss.HUNTING; + bandit1.state = bandit1.HUNTING; + bandit2.state = bandit2.HUNTING; + int count = 0; + do { + boss.pos = Random.Int(getLength()); + bandit1.pos = (TOP + 1) * getWidth() + CENTER+1; + bandit2.pos = (TOP + 1) * getWidth() + CENTER-1; + + } while (!passable[boss.pos] + || !outsideEntraceRoom(boss.pos) + || (Dungeon.visible[boss.pos] && count++ < 20)); + + GameScene.add(boss); + + + GameScene.add(bandit1); + GameScene.add(bandit2); + + + if (Dungeon.visible[boss.pos]) { + boss.notice(); + boss.sprite.alpha(0); + boss.sprite.parent.add(new AlphaTweener(boss.sprite, 1, 0.1f)); + } + + //set(arenaDoor, Terrain.WALL); + //GameScene.updateMap(arenaDoor); + Dungeon.observe(); + } + } + + @Override + public Heap drop(Item item, int cell) { + + if (!keyDropped && item instanceof SkeletonKey) { + + keyDropped = true; + locked = false; + + set(arenaDoor, Terrain.DOOR); + GameScene.updateMap(arenaDoor); + Dungeon.observe(); + } + + return super.drop(item, cell); + } + + private boolean outsideEntraceRoom(int cell) { + return cell / getWidth() < arenaDoor / getWidth(); + } + + @Override + public String tileName(int tile) { + switch (tile) { + case Terrain.WATER: + return "Suspiciously colored water"; + case Terrain.HIGH_GRASS: + return "Flowers with little gem-shaped leaves"; + default: + return super.tileName(tile); + } + } + + @Override + public String tileDesc(int tile) { + switch (tile) { + case Terrain.ENTRANCE: + return "A ramp leads up to the upper depth."; + case Terrain.EXIT: + return "A ramp leads down to the lower depth."; + case Terrain.WALL_DECO: + case Terrain.EMPTY_DECO: + return "Rough-hewn gold ore adorns the dungeon."; + case Terrain.EMPTY_SP: + return "Thick carpet covers the floor."; + case Terrain.STATUE: + case Terrain.STATUE_SP: + return "The statue is made of solid gold."; + case Terrain.BOOKSHELF: + return "The rows of books on different disciplines fill the bookshelf."; + default: + return super.tileDesc(tile); + } + } + + @Override + public void addVisuals(Scene scene) { + CityLevel.addVisuals(this, scene); + } +} diff --git a/java/com/hmdzl/spspd/levels/ThiefCatchLevel.java b/java/com/hmdzl/spspd/levels/ThiefCatchLevel.java new file mode 100644 index 00000000..03638c3c --- /dev/null +++ b/java/com/hmdzl/spspd/levels/ThiefCatchLevel.java @@ -0,0 +1,305 @@ +/* + * 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 + */ +package com.hmdzl.spspd.levels; + +import java.util.ArrayList; +import java.util.List; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.mobs.Bestiary; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.levels.Room.Type; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.GameScene; +import com.watabou.noosa.Scene; +import com.watabou.utils.Bundle; +import com.watabou.utils.Graph; +import com.watabou.utils.Random; + +public class ThiefCatchLevel extends RegularLevel { + + { + color1 = 0x48763c; + color2 = 0x59994a; + cleared=true; + } + + private int stairs = 0; + + @Override + public String tilesTex() { + return Assets.TILES_CAVES; + } + + @Override + public String waterTex() { + return Assets.WATER_CAVES; + } + + @Override + protected boolean build() { + + initRooms(); + + int distance; + // if we ever need to try 20 or more times to find a room, better to + // give up and try again. + int retry = 0; + + // start with finding an entrance room (will also contain exit) + // the room must be at least 4x4 and be nearer the top of the map(so + // that it is less likely something connects to the top) + do { + if (retry++ > 20) { + return false; + } + roomEntrance = Random.element(rooms); + } while (roomEntrance.width() < 4 || roomEntrance.height() < 4 + || roomEntrance.top == 0 || roomEntrance.top >= 12); + + roomEntrance.type = Type.ENTRANCE; + roomExit = roomEntrance; + + // now find the rest of the rooms for this boss mini-maze + Room curRoom = null; + Room lastRoom = roomEntrance; + // we make 4 rooms, last iteration is tieing the final room to the start + for (int i = 0; i <= 4; i++) { + retry = 0; + // find a suitable room the first four times + // suitable room should be empty, have a distance of 2 from the + // current room, and not touch the entrance. + if (i < 4) { + do { + if (retry++ > 20) { + return false; + } + curRoom = Random.element(rooms); + Graph.buildDistanceMap(rooms, curRoom); + distance = lastRoom.distance(); + } while (curRoom.type != Type.NULL || distance != 2 + || !curRoom.intersect(roomEntrance).isEmpty()); + + curRoom.type = Type.STANDARD; + + // otherwise, we're on the last iteration. + } else { + // set the current room to the entrance, so we can build a + // connection to it. + curRoom = roomEntrance; + } + + // now build a connection between the current room and the last one. + Graph.buildDistanceMap(rooms, curRoom); + List path = Graph.buildPath(rooms, lastRoom, curRoom); + + Graph.setPrice(path, lastRoom.distance); + + path = Graph.buildPath(rooms, lastRoom, curRoom); + + Room room = lastRoom; + for (Room next : path) { + room.connect(next); + room = next; + } + + if (i == 4) { + + // we must find a room for his royal highness! + // look at rooms adjacent to the final found room (likely to be + // furthest from start) + ArrayList candidates = new ArrayList(); + for (Room r : lastRoom.neigbours) { + if (r.type == Type.NULL && r.connected.size() == 0 + && !r.neigbours.contains(roomEntrance)) { + candidates.add(r); + } + } + + // if we have candidates, pick a room and put the king there + if (candidates.size() > 0) { + Room kingsRoom = Random.element(candidates); + kingsRoom.connect(lastRoom); + + kingsRoom.type = Room.Type.STANDARD; + + + // unacceptable! make a new level... + } else { + return false; + } + } + lastRoom = curRoom; + } + + // the connection structure ensures that (most of the time) there is a + // nice loop for the player to kite the + // boss around. What's nice is that there is enough chaos such that the + // loop is rarely straightforward + // and boring. + + // fills our connection rooms in with tunnel + for (Room r : rooms) { + if (r.type == Type.NULL && r.connected.size() > 0) { + r.type = Type.TUNNEL; + } + } + + // make sure nothing is connecting at the top of the entrance, this + // would be bad. + for (Room r : roomEntrance.neigbours) { + if (r.bottom == roomEntrance.top && r.type != Type.NULL) + return false; + } + + paint(); + + // TODO: not handling this through a painter is kinda iffy, separate + // into a painter if you use it again. + // sticks the exit in the room entrance. + exit = roomEntrance.top * Level.getWidth() + + (roomEntrance.left + roomEntrance.right) / 2; + + + map[exit] = Terrain.EMPTY_SP; + + + paintWater(); + paintGrass(); + + return true; + } + + @Override + protected boolean[] water() { + return Patch.generate(0.5f, 5); + } + + @Override + protected boolean[] grass() { + return Patch.generate(0.40f, 4); + } + + @Override + protected void decorate() { + int start = roomExit.top * getWidth() + roomExit.left + 1; + int end = start + roomExit.width() - 1; + for (int i = start; i < end; i++) { + if (i != exit) { + map[i] = Terrain.WALL_DECO; + map[i + getWidth()] = Terrain.WATER; + } else { + map[i + getWidth()] = Terrain.EMPTY; + } + } + } + + @Override + public void addVisuals(Scene scene) { + SewerLevel.addVisuals(this, scene); + } + + @Override + protected void createMobs() { + if (Dungeon.tengudenkilled){ + return; + } + Mob mob = Bestiary.mob(Dungeon.depth); + Room room; + do { + room = Random.element(rooms); + } while (room.type != Type.STANDARD); + mob.pos = room.random(); + mobs.add(mob); + } + + @Override + public Actor respawner() { + return null; + } + + //@Override + //public int randomRespawnCell() { + // return -1; + //} + public void seal() { + if (entrance != 0) { + + locked = true; + + set(entrance, Terrain.WATER_TILES); + GameScene.updateMap(entrance); + GameScene.ripple(entrance); + + stairs = entrance; + entrance = 0; + } + } + + public void unseal() { + if (stairs != 0) { + + locked = false; + + entrance = stairs; + stairs = 0; + + set(entrance, Terrain.ENTRANCE); + GameScene.updateMap(entrance); + + } + } + + private static final String STAIRS = "stairs"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(STAIRS, stairs); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + stairs = bundle.getInt(STAIRS); + } + + @Override + public String tileName( int tile ) { + switch (tile) { + case Terrain.WATER: + return Messages.get(SewerLevel.class, "water_name"); + default: + return super.tileName( tile ); + } + } + + @Override + public String tileDesc(int tile) { + switch (tile) { + case Terrain.EMPTY_DECO: + return Messages.get(SewerLevel.class, "empty_deco_desc"); + case Terrain.BOOKSHELF: + return Messages.get(SewerLevel.class, "bookshelf_desc"); + default: + return super.tileDesc( tile ); + } + } +} diff --git a/java/com/hmdzl/spspd/levels/TownLayouts.java b/java/com/hmdzl/spspd/levels/TownLayouts.java new file mode 100644 index 00000000..3182ea56 --- /dev/null +++ b/java/com/hmdzl/spspd/levels/TownLayouts.java @@ -0,0 +1,106 @@ +/* + * 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 + */ +package com.hmdzl.spspd.levels; + +import com.watabou.utils.Random; + +public class TownLayouts { + + //32X32 + private static final int W = Terrain.WALL; + private static final int T = Terrain.SHRUB; + private static final int Z = Terrain.HIGH_GRASS; + private static final int D = Terrain.DOOR; + private static final int L = Terrain.LOCKED_DOOR; + + private static final int E = Terrain.EMPTY; + private static final int X = Terrain.EXIT; + + private static final int M = Terrain.WALL_DECO; + private static final int P = Terrain.PEDESTAL; + private static final int F = Terrain.EMPTY_DECO; + private static final int O = Terrain.EMPTY_SP; + private static final int A = Terrain.WELL; + private static final int B = Terrain.BOOKSHELF; + + private static final int U = Terrain.STATUE; + private static final int S = Terrain.SECRET_DOOR; + private static final int R = Terrain.WATER; + private static final int Y = Terrain.ALCHEMY; + private static final int G = Terrain.STATUE_SP; + private static final int C = Terrain.TENT; + private static final int H = Terrain.BED; + private static final int I = Terrain.EMBERS; + + //private static final int V = Terrain.TRAP_AIR; + + + public static final int[] TOWN_LAYOUT = { + M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, + M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, O, O, O, M, + M, M, M, M, E, M, T, M, M, M, M, M, E, E, M, M, M, M, M, R, R, R, A, W, W, W, W, W, W, E, E, W, W, W, W, W, W, W, W, M, M, M, M, M, O, E, O, M, + M, M, M, E, E, E, W, S, W, W, W, E, E, E, E, E, E, E, T, C, E, E, E, W, O, O, O, O, W, E, E, G, O, O, G, O, O, O, W, W, W, W, W, W, O, O, O, M, + M, M, O, E, E, E, L, O, O, O, W, E, E, E, E, E, E, E, T, E, E, E, E, W, O, O, O, O, W, E, E, W, O, O, G, G, G, O, W, O, O, O, O, W, M, M, D, M, + M, M, O, E, T, E, G, O, O, O, W, E, E, E, E, E, E, E, T, W, W, S, W, W, O, G, G, G, W, E, E, D, O, O, O, O, O, O, W, O, O, O, H, W, M, M, E, M, + M, M, O, E, E, E, W, W, W, W, W, W, W, W, W, W, E, E, E, W, O, O, O, O, O, O, O, O, E, E, E, W, O, O, O, O, O, O, L, O, O, O, O, W, M, M, E, M, + M, M, M, E, E, E, W, O, O, O, O, O, O, O, O, W, E, E, E, W, O, O, O, O, O, O, O, O, E, E, E, W, O, O, O, O, O, O, W, W, W, G, W, W, M, M, E, M, + M, M, M, E, E, E, W, O, O, O, O, G, G, G, O, W, E, E, E, W, O, O, O, O, O, O, O, O, E, E, E, W, W, W, O, O, O, O, W, R, R, R, R, R, R, M, E, M, + M, M, M, E, E, E, W, O, O, O, O, G, O, O, O, W, E, E, E, W, O, O, O, O, O, O, O, O, E, E, E, E, E, W, O, O, O, O, G, R, R, R, R, R, R, M, E, M, + M, M, M, E, E, E, W, O, O, O, O, G, O, O, O, G, E, E, E, W, O, O, O, O, O, O, O, O, W, E, E, E, E, W, W, W, D, W, W, R, R, R, R, R, U, T, E, M, + M, M, M, M, E, E, W, W, W, D, W, W, O, O, O, W, E, E, E, W, O, O, O, O, O, O, O, O, W, E, E, E, E, W, O, O, O, O, W, E, E, E, R, R, R, M, M, M, + M, M, M, M, E, E, E, E, E, E, E, W, O, O, O, W, E, E, E, W, E, E, E, W, O, O, O, O, W, E, E, E, E, W, O, O, O, O, G, E, E, E, R, R, R, M, M, M, + M, M, M, M, E, E, E, E, E, E, E, W, O, O, O, W, E, E, E, E, E, E, E, W, W, Y, O, O, W, E, E, E, E, W, O, H, O, H, W, W, D, W, W, W, W, M, M, M, + M, M, M, E, E, E, E, E, E, E, E, W, W, W, W, W, E, E, E, E, E, E, E, E, W, W, W, W, W, E, E, E, E, W, W, W, W, W, W, W, O, O, O, O, W, M, M, M, + M, M, M, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, W, O, O, O, O, W, M, M, M, + M, M, M, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, G, O, P, P, O, W, M, M, M, + M, M, M, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, U, W, O, O, O, O, W, M, M, M, + M, M, M, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, D, O, O, O, O, W, M, M, M, + M, M, M, M, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, U, W, O, O, O, O, W, M, M, M, + M, M, M, M, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, W, O, O, O, O, W, M, M, M, + M, M, M, W, W, W, W, W, G, W, W, W, E, E, E, E, O, O, O, O, O, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, W, W, W, W, W, W, M, M, M, + M, M, M, W, O, O, G, O, O, O, O, W, E, E, E, E, O, R, R, R, O, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, W, O, O, O, O, W, M, M, M, + M, M, M, W, O, O, O, O, O, O, O, W, E, E, E, E, O, R, U, R, O, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, W, O, O, O, O, W, M, M, M, + M, M, M, W, O, O, G, G, G, G, G, W, E, E, E, E, O, R, R, R, O, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, G, O, O, O, O, W, M, M, M, + M, M, M, W, O, O, O, O, O, O, O, W, E, E, E, E, O, O, O, O, O, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, G, O, O, O, O, W, M, M, M, + M, M, M, W, O, O, O, O, O, O, O, W, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, U, O, U, W, W, W, W, W, E, E, E, E, W, O, O, O, O, W, M, M, M, + M, M, M, W, O, O, O, O, O, O, O, W, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, O, O, O, W, B, B, B, W, E, E, E, E, W, O, O, O, O, W, M, M, M, + M, M, M, W, W, W, W, W, D, W, W, W, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, U, O, U, W, O, O, O, W, E, E, E, E, W, W, D, W, W, W, M, M, M, + M, M, M, M, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, W, W, W, W, W, W, W, W, W, O, O, O, W, W, E, E, E, E, E, E, E, E, E, M, M, M, + M, M, M, M, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, W, O, O, O, O, O, O, O, O, O, O, O, O, W, W, E, E, E, E, E, E, E, E, M, M, M, + M, M, M, M, M, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, W, O, O, O, O, O, O, O, O, O, O, O, O, B, W, E, E, E, E, E, E, E, E, M, M, M, + M, M, M, M, M, M, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, D, O, O, O, O, O, O, O, O, O, O, P, O, B, W, E, E, E, E, O, O, O, O, M, M, M, + M, M, M, M, M, M, M, M, E, E, E, E, E, E, E, E, E, E, E, E, E, E, W, O, O, O, O, O, O, O, O, O, O, O, O, B, W, E, E, E, E, O, R, R, R, M, M, M, + M, M, M, M, M, M, M, M, M, E, E, E, E, E, E, E, E, E, E, E, E, E, W, O, O, O, O, O, O, O, O, O, O, O, O, W, W, E, E, E, E, O, R, R, R, M, M, M, + M, M, W, W, W, W, W, W, M, E, E, E, E, E, E, E, E, E, E, E, E, E, W, W, W, W, W, W, W, W, W, O, O, O, W, W, E, E, E, E, E, O, R, R, R, M, M, M, + M, M, W, I, F, F, F, W, T, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, W, O, O, O, W, E, E, E, E, E, E, O, R, R, R, M, M, M, + M, M, W, F, F, I, F, T, T, T, M, M, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, W, B, B, B, W, E, E, E, E, E, E, O, R, R, R, M, M, M, + M, M, W, F, F, F, F, T, T, T, M, M, M, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, W, W, W, W, W, E, E, E, E, E, E, O, O, O, O, M, M, M, + M, M, W, F, F, F, F, W, W, W, W, W, M, M, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, Z, Z, Z, Z, Z, Z, W, M, M, M, + M, M, W, F, F, U, F, F, W, F, F, W, M, M, M, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, Z, Z, Z, Z, Z, Z, W, M, M, M, + M, M, W, I, F, F, F, F, W, F, F, W, M, M, M, M, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, U, E, U, E, E, Z, Z, Z, Z, Z, Z, W, W, W, M, + M, M, W, F, F, F, F, I, F, F, F, S, T, T, T, T, M, I, I, I, I, I, I, E, E, E, E, E, E, E, E, E, G, O, O, O, G, E, Z, Z, Z, Z, W, S, W, Z, W, M, + M, M, W, F, F, F, F, F, W, F, F, W, M, M, M, M, M, O, I, I, I, I, O, E, E, E, M, M, E, E, E, E, W, O, O, O, W, E, Z, Z, Z, Z, S, Z, Z, Z, W, M, + M, M, W, F, F, F, F, F, W, F, I, W, M, M, M, M, M, O, I, I, I, I, O, E, E, M, M, M, M, M, E, E, W, O, O, O, W, W, W, W, W, W, W, Z, O, O, W, M, + M, M, W, W, W, W, W, W, W, W, W, W, M, M, M, M, M, O, O, O, O, O, O, E, M, M, M, M, M, M, M, M, W, W, W, W, W, M, M, M, M, W, Z, Z, O, O, W, M, + M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, W, W, W, W, W, W, M, + M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M + + + }; + +} diff --git a/java/com/hmdzl/spspd/levels/TownLevel.java b/java/com/hmdzl/spspd/levels/TownLevel.java new file mode 100644 index 00000000..4e4969e7 --- /dev/null +++ b/java/com/hmdzl/spspd/levels/TownLevel.java @@ -0,0 +1,1101 @@ +/* + * 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 + */ +package com.hmdzl.spspd.levels; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.Challenges; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.Statistics; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.Alchemy; +import com.hmdzl.spspd.actors.blobs.Alter; +import com.hmdzl.spspd.actors.blobs.WellWater; +import com.hmdzl.spspd.actors.mobs.AdultDragonViolet; +import com.hmdzl.spspd.actors.mobs.BombBug; +import com.hmdzl.spspd.actors.mobs.Piranha; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.actors.mobs.TestMob; +import com.hmdzl.spspd.actors.mobs.TestMob2; +import com.hmdzl.spspd.actors.mobs.npcs.AFly; +import com.hmdzl.spspd.actors.mobs.npcs.ARealMan; +import com.hmdzl.spspd.actors.mobs.npcs.Apostle; +import com.hmdzl.spspd.actors.mobs.npcs.DreamPlayer; +import com.hmdzl.spspd.actors.mobs.npcs.GoblinPlayer; +import com.hmdzl.spspd.actors.mobs.npcs.HoneyPoooot; +import com.hmdzl.spspd.actors.mobs.npcs.Ice13; +import com.hmdzl.spspd.actors.mobs.npcs.Juh9870; +import com.hmdzl.spspd.actors.mobs.npcs.Kostis12345; +import com.hmdzl.spspd.actors.mobs.npcs.Lynn; +import com.hmdzl.spspd.actors.mobs.npcs.Millilitre; +import com.hmdzl.spspd.actors.mobs.npcs.NutPainter; +import com.hmdzl.spspd.actors.mobs.npcs.OldNewStwist; +import com.hmdzl.spspd.actors.mobs.npcs.Omicronrg9; +import com.hmdzl.spspd.actors.mobs.npcs.OtilukeNPC; +import com.hmdzl.spspd.actors.mobs.npcs.RENnpc; +import com.hmdzl.spspd.actors.mobs.npcs.RainTrainer; +import com.hmdzl.spspd.actors.mobs.npcs.SadSaltan; +import com.hmdzl.spspd.actors.mobs.npcs.SaidbySun; +import com.hmdzl.spspd.actors.mobs.npcs.Shopkeeper; +import com.hmdzl.spspd.actors.mobs.npcs.Shower; +import com.hmdzl.spspd.actors.mobs.npcs.Tinkerer4; +import com.hmdzl.spspd.actors.mobs.npcs.Tinkerer5; +import com.hmdzl.spspd.actors.mobs.npcs.Udawos; +import com.hmdzl.spspd.actors.mobs.npcs.TypedScroll; +import com.hmdzl.spspd.actors.mobs.npcs.G2159687; +import com.hmdzl.spspd.actors.mobs.npcs.ConsideredHamster; +import com.hmdzl.spspd.actors.mobs.npcs.NYRDS; +import com.hmdzl.spspd.actors.mobs.npcs.Evan; +import com.hmdzl.spspd.actors.mobs.npcs.UncleS; +import com.hmdzl.spspd.actors.mobs.npcs.Watabou; +import com.hmdzl.spspd.actors.mobs.npcs.Bilboldev; +import com.hmdzl.spspd.actors.mobs.npcs.HBB; +import com.hmdzl.spspd.actors.mobs.npcs.SFB; +import com.hmdzl.spspd.actors.mobs.npcs.Jinkeloid; +import com.hmdzl.spspd.actors.mobs.npcs.Rustyblade; +import com.hmdzl.spspd.actors.mobs.npcs.HeXA; +import com.hmdzl.spspd.actors.mobs.npcs.SP931; +import com.hmdzl.spspd.actors.mobs.npcs.Lery; +import com.hmdzl.spspd.actors.mobs.npcs.Lyn; +import com.hmdzl.spspd.actors.mobs.npcs.Coconut; +import com.hmdzl.spspd.actors.mobs.npcs.FruitCat; +import com.hmdzl.spspd.actors.mobs.npcs.Locastan; +import com.hmdzl.spspd.actors.mobs.npcs.Tempest102; +import com.hmdzl.spspd.actors.mobs.npcs.Dachhack; +import com.hmdzl.spspd.actors.mobs.npcs.MemoryOfSand; +import com.hmdzl.spspd.actors.mobs.npcs.StormAndRain; +import com.hmdzl.spspd.actors.mobs.npcs.HateSokoban; +import com.hmdzl.spspd.actors.mobs.npcs.AliveFish; +import com.hmdzl.spspd.actors.mobs.npcs.LaJi; +import com.hmdzl.spspd.actors.mobs.npcs.WhiteGhost; +import com.hmdzl.spspd.actors.mobs.npcs.XixiZero; +import com.hmdzl.spspd.items.food.Nut; +import com.hmdzl.spspd.items.food.vegetable.NutVegetable; +import com.hmdzl.spspd.items.eggs.Egg; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.items.Heap; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.Ankh; +import com.hmdzl.spspd.items.AdamantArmor; +import com.hmdzl.spspd.items.AdamantRing; +import com.hmdzl.spspd.items.AdamantWand; +import com.hmdzl.spspd.items.AdamantWeapon; +import com.hmdzl.spspd.items.food.completefood.PetFood; +import com.hmdzl.spspd.items.misc.SkillOfAtk; +import com.hmdzl.spspd.items.misc.SkillOfDef; +import com.hmdzl.spspd.items.misc.SkillOfMig; +import com.hmdzl.spspd.items.quest.DarkGold; + + +import com.hmdzl.spspd.items.artifacts.TimekeepersHourglass; +import com.hmdzl.spspd.items.scrolls.ScrollOfUpgrade; +import com.hmdzl.spspd.items.scrolls.ScrollOfMagicalInfusion; +import com.hmdzl.spspd.items.scrolls.ScrollOfRegrowth; +import com.hmdzl.spspd.items.weapon.guns.ToyGun; +import com.hmdzl.spspd.items.weapon.melee.special.Brick; +import com.hmdzl.spspd.items.weapon.melee.special.FireCracker; +import com.hmdzl.spspd.items.weapon.melee.special.HookHam; +import com.hmdzl.spspd.items.weapon.melee.special.KeyWeapon; +import com.hmdzl.spspd.items.weapon.melee.special.Lollipop; +import com.hmdzl.spspd.items.weapon.melee.special.Pumpkin; +import com.hmdzl.spspd.items.weapon.melee.special.RunicBlade; +import com.hmdzl.spspd.items.weapon.melee.special.SJRBMusic; +import com.hmdzl.spspd.items.weapon.melee.special.TestWeapon; +import com.hmdzl.spspd.items.weapon.melee.special.Tree; +import com.hmdzl.spspd.items.weapon.missiles.MiniMoai; +import com.hmdzl.spspd.items.weapon.missiles.MoneyPack; +import com.hmdzl.spspd.items.weapon.missiles.PocketBall; +import com.hmdzl.spspd.levels.features.Chasm; +import com.hmdzl.spspd.levels.features.Door; +import com.hmdzl.spspd.levels.features.HighGrass; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.plants.Phaseshift; +import com.hmdzl.spspd.plants.Plant; +import com.hmdzl.spspd.plants.Starflower; +import com.hmdzl.spspd.scenes.GameScene; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +import static com.hmdzl.spspd.Dungeon.level; + +public class TownLevel extends Level { + + + { + color1 = 0x534f3e; + color2 = 0xb9d661; + WIDTH = 48; + HEIGHT = 48; + LENGTH = HEIGHT*WIDTH; + special=false; + } + + + public int mineDepth=0; + + public int[] scrollspots; + public int[] storespots; + public int[] bombpots; + public int[] foodpots; + public int[] sppots; + public int[] eggpots; + public int[] gnollpots; + public int[] skillpots; + public int[] pillpots; + + private static final String MINEDEPTH = "mineDepth"; + private static final String SCROLLSPOTS = "scrollspots"; + private static final String STORESPOTS = "storespots"; + private static final String BOMBPOTS = "bombpots"; + private static final String FOODPOTS = "foodpots"; + private static final String SPPOTS = "sppots"; + private static final String EGGPOTS = "eggpots"; + private static final String GNOLLPOTS = "gnollpots"; + private static final String SKILLPOTS = "skillpots"; + private static final String PILLPOTS = "pillpots"; + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(MINEDEPTH, mineDepth); + bundle.put(SCROLLSPOTS, scrollspots); + bundle.put(STORESPOTS, storespots); + bundle.put(BOMBPOTS, bombpots); + bundle.put(FOODPOTS, foodpots); + bundle.put(SPPOTS, sppots); + bundle.put(EGGPOTS, eggpots); + bundle.put(GNOLLPOTS, gnollpots); + bundle.put(SKILLPOTS, skillpots); + bundle.put(PILLPOTS, pillpots); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + mineDepth = bundle.getInt(MINEDEPTH); + scrollspots = bundle.getIntArray(SCROLLSPOTS); + storespots = bundle.getIntArray(STORESPOTS); + bombpots = bundle.getIntArray(BOMBPOTS); + foodpots = bundle.getIntArray(FOODPOTS); + sppots = bundle.getIntArray(SPPOTS); + eggpots = bundle.getIntArray(EGGPOTS); + gnollpots = bundle.getIntArray(GNOLLPOTS); + skillpots = bundle.getIntArray(SKILLPOTS); + pillpots = bundle.getIntArray(PILLPOTS); + } + + private boolean checkOtiluke(){ + boolean check=false; + for (Mob mob : mobs) { + if (mob instanceof OtilukeNPC ) { + check=true; + } + } + return check; + } + + public void storeStock (){ + + + if(Actor.findChar(13 + WIDTH * 10) == null){ + Mob shopkeeper = new Shopkeeper(); + shopkeeper.pos = 13 + WIDTH * 10; + mobs.add(shopkeeper); + } + if(Actor.findChar(8 + WIDTH * 23) == null){ + Mob shopkeeper2 = new Shopkeeper(); + shopkeeper2.pos = 8 + WIDTH * 23; + mobs.add(shopkeeper2); + } + + if(Badges.checkOtilukeRescued()&&!checkOtiluke()){ + if(Actor.findChar(32 + WIDTH * 15) == null){ + Mob otiluke = new OtilukeNPC(); + otiluke.pos = 32 + WIDTH * 15; + mobs.add(otiluke); + } + + map[exit] = Terrain.STATUE; + } + + if(storeRefresh()){ + if (Badges.checkSARRescued()|| Dungeon.isChallenged(Challenges.TEST_TIME)){ + for (int i : sppots) { + Heap heap = heaps.get(i); + if (heap == null){ + Item storeitem5 = storeItem5(); + drop(storeitem5, i).type = Heap.Type.FOR_SALE; + } + } + } + + if (Badges.checkMOSRescued()|| Dungeon.isChallenged(Challenges.TEST_TIME)){ + for (int i : foodpots) { + Heap heap = heaps.get(i); + if (heap == null){ + Item storeitem4 = storeItem4(); + drop(storeitem4, i).type = Heap.Type.FOR_SALE; + } + } + } + + if (Badges.checkCoconutRescued()|| Dungeon.isChallenged(Challenges.TEST_TIME)){ + for (int i : bombpots) { + Heap heap = heaps.get(i); + if (heap == null){ + Item storeitem3 = storeItem3(); + drop(storeitem3, i).type = Heap.Type.FOR_SALE; + } + } + } + + if (Badges.checkItemRescued()|| Dungeon.isChallenged(Challenges.TEST_TIME)){ + for (int i : scrollspots) { + Heap heap = heaps.get(i); + if (heap == null){ + Item storeitem2 = storeItem2(); + drop(storeitem2, i).type = Heap.Type.FOR_SALE; + } + } + for (int i : storespots) { + Heap heap = heaps.get(i); + if (heap == null){ + Item storeitem = storeItem(); + drop(storeitem, i).type = Heap.Type.FOR_SALE; + } + } + } + + if (Badges.checkEggRescued()|| Dungeon.isChallenged(Challenges.TEST_TIME)){ + for (int i : eggpots) { + Heap heap = heaps.get(i); + if (heap == null){ + Item storeitem6 = storeItem6(); + drop(storeitem6, i).type = Heap.Type.FOR_SALE; + } + } + } + if (Dungeon.gnollmission==true|| Dungeon.isChallenged(Challenges.TEST_TIME)){ + for (int i : gnollpots) { + Heap heap = heaps.get(i); + if (heap == null){ + Item storeitem7 = storeItem7(); + drop(storeitem7, i).type = Heap.Type.FOR_SALE; + } + } + } + if (Badges.checkRainRescued() || Dungeon.isChallenged(Challenges.TEST_TIME)) { + for (int i : skillpots) { + Heap heap = heaps.get(i); + if (heap == null) { + Item storeitem8 = storeItem8(); + drop(storeitem8, i).type = Heap.Type.FOR_SALE; + } + } + } + if (Badges.checkUncleRescued()|| Dungeon.isChallenged(Challenges.TEST_TIME)) { + for (int i : pillpots) { + Heap heap = heaps.get(i); + if (heap == null) { + Item storeitem9 = storeItem9(); + drop(storeitem9, i).type = Heap.Type.FOR_SALE; + } + } + } + } + } + + public Item storeItem (){ + Item prize; + switch (Random.Int(10)) { + case 0: + prize = Generator.random(Generator.Category.MUSHROOM); + break; + case 1: + prize = Generator.random(Generator.Category.POTION); + break; + case 2: + prize = new PocketBall(); + break; + case 3: + prize = Generator.random(Generator.Category.SCROLL); + break; + case 4: + prize = Generator.random(Generator.Category.SEED); + break; + case 5: + prize = Generator.random(Generator.Category.BERRY); + break; + case 6: + prize = Generator.random(Generator.Category.SUMMONED); + break; + case 7: + prize = new PetFood(); + break; + case 8: + prize = new NutVegetable(); + break; + default: + prize = new Nut(); + break; + } + + return prize; + + } + + public Item storeItem2 (){ + Item prize; + switch (Random.Int(12)) { + case 0: + prize = new ScrollOfUpgrade(); + break; + case 1: + prize = new ScrollOfMagicalInfusion(); + break; + case 2: + prize = Generator.random(Generator.Category.RANGEWEAPON); + break; + case 3: + prize = Generator.random(Generator.Category.WAND); + break; + case 4: + prize = Generator.random(Generator.Category.RING); + break; + case 5: + prize = Generator.random(Generator.Category.WEAPON); + break; + case 6: + prize = Generator.random(Generator.Category.NORNSTONE); + break; + case 7: + prize = Generator.random(Generator.Category.ARMOR); + break; + case 8: + prize = new RunicBlade(); + break; + case 9: + prize = Generator.random(Generator.Category.RANGEWEAPON); + break; + default: + prize = new ScrollOfUpgrade(); + break; + } + + return prize; + + } + + public Item storeItem3 (){ + Item prize; + switch (Random.Int(12)) { + case 0: + prize = new Ankh(); + break; + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + prize = Generator.random(Generator.Category.BOMBS); + break; + case 11: + prize = new ScrollOfRegrowth(); + break; + default: + prize = new Ankh(); + break; + } + + return prize; + + } + + public Item storeItem4 (){ + Item prize; + switch (Random.Int(3)) { + case 0: + prize = Generator.random(Generator.Category.HIGHFOOD); + break; + case 1: + prize = Generator.random(Generator.Category.FOOD); + break; + default: + prize = Generator.random(Generator.Category.HIGHFOOD); + break; + } + return prize; + } + + public Item storeItem5 (){ + Item prize; + switch (Random.Int(6)) { + case 0: + prize = new AdamantArmor(); + break; + case 1: + prize = new AdamantRing(); + break; + case 2: + prize = new AdamantWand(); + break; + case 3: + prize = new AdamantWeapon(); + break; + default: + prize = new DarkGold().quantity(10); + break; + } + return prize; + } + + public Item storeItem6 (){ + Item prize; + switch (Random.Int(2)) { + case 0: + case 1: + prize = Generator.random(Generator.Category.EGGS); + break; + default: + prize = new Egg(); + break; + } + return prize; + } + + public Item storeItem7 (){ + Item prize; + switch (Random.Int(12)) { + case 0: + prize = new Pumpkin(); + break; + case 1: + prize = new Tree(); + break; + case 2: + prize = new FireCracker(); + break; + case 3: + prize = new MiniMoai(); + break; + case 4: + prize = new TestWeapon(); + break; + case 5: + prize = new ToyGun(); + break; + case 6: + prize = new HookHam(); + break; + case 7: + prize = new Brick(); + break; + case 8: + prize = new Lollipop(); + break; + case 9: + prize = new SJRBMusic(); + break; + case 10: + prize = new MoneyPack(5); + break; + case 11: + prize = new KeyWeapon(); + break; + default: + prize = new PetFood(); + break; + } + return prize; + } + + public Item storeItem8 (){ + Item prize; + switch (Random.Int(6)) { + case 0: + prize = new SkillOfAtk(); + break; + case 1: + prize = new SkillOfDef(); + break; + case 2: + prize = new SkillOfMig(); + break; + default: + prize = Generator.random(Generator.Category.MUSICWEAPON); + break; + } + return prize; + } + + public Item storeItem9 (){ + Item prize; + prize = Generator.random(Generator.Category.PILL); + return prize; + } + + public boolean storeRefresh(){ + boolean check=false; + if (Statistics.realdeepestFloor>mineDepth || Dungeon.oneDay==true){ + //mineDepth=Statistics.realdeepestFloor; + check=true; + Dungeon.oneDay=false; + } + return check; + } + + @Override + public void create() { + + super.create(); + } + + + @Override + protected void createItems() { + + /*Mob bluecat = new BlueCat(); + bluecat.pos = 35 + WIDTH * 5; + mobs.add(bluecat);*/ + + Mob udawos = new Udawos(); + udawos.pos = 33 + WIDTH * 34; + mobs.add(udawos); + + Mob typedscroll = new TypedScroll(); + typedscroll.pos = 9 + WIDTH * 23; + mobs.add(typedscroll); + + Mob g2159687 = new G2159687(); + g2159687.pos = 35 + WIDTH * 3; + mobs.add(g2159687); + + Mob consideredhamster = new ConsideredHamster(); + consideredhamster.pos = 26 + WIDTH * 10; + mobs.add(consideredhamster); + + Mob bilboldev = new Bilboldev(); + bilboldev.pos = 24 + WIDTH * 10; + mobs.add(bilboldev); + + Mob xixizero = new XixiZero(); + xixizero.pos = 25 + WIDTH * 11; + mobs.add(xixizero); + + if(Badges.checkTombRescued() || Dungeon.isChallenged(Challenges.TEST_TIME)){ + Mob watabou = new Watabou(); + watabou.pos = 42 + WIDTH * 42; + mobs.add(watabou); + + Mob wg = new WhiteGhost(); + wg.pos = 45 + WIDTH * 44; + mobs.add(wg); + + } + + Mob mill = new Millilitre(); + mill.pos = 45 + WIDTH * 42; + mobs.add(mill); + + Mob nyrds = new NYRDS(); + nyrds.pos = 13 + WIDTH * 11; + mobs.add(nyrds); + + Mob hbb = new HBB(); + hbb.pos = 43 + WIDTH * 15; + mobs.add(hbb); + + Mob sfb = new SFB(); + sfb.pos = 34 + WIDTH * 11; + mobs.add(sfb); + + Mob omi = new Omicronrg9(); + omi.pos = 36 + WIDTH * 11; + mobs.add(omi); + + Mob honey = new HoneyPoooot(); + honey.pos = 40 + WIDTH * 15; + mobs.add(honey); + + Mob jinkeloid = new Jinkeloid(); + jinkeloid.pos = 43 + WIDTH * 14; + mobs.add(jinkeloid); + + if (Badges.checkUncleRescued() || Dungeon.isChallenged(Challenges.TEST_TIME)) { + Mob uncles = new UncleS(); + uncles.pos = 43 + WIDTH * 22; + mobs.add(uncles); + + Mob realman = new ARealMan(); + realman.pos = 44 + WIDTH * 45; + mobs.add(realman); + + Mob lyn = new Lyn(); + lyn.pos = 40 + WIDTH * 22; + mobs.add(lyn); + + Mob saidbysun = new SaidbySun(); + saidbysun.pos = 42 + WIDTH * 45;; + mobs.add(saidbysun); + } + + Mob sp931 = new SP931(); + sp931.pos = 40 + WIDTH * 16; + mobs.add(sp931); + + Mob dp = new DreamPlayer(); + dp.pos = 43 + WIDTH * 24; + mobs.add(dp); + + if (Badges.checkEggRescued()|| Dungeon.isChallenged(Challenges.TEST_TIME)){ + Mob lery = new Lery(); + lery.pos = 41 + WIDTH * 9; + mobs.add(lery); + } + Mob evan = new Evan(); + evan.pos = 27 + WIDTH * 31; + mobs.add(evan); + + Mob ice13 = new Ice13(); + ice13.pos = 29 + WIDTH * 32; + mobs.add(ice13); + + Mob hexa = new HeXA(); + hexa.pos = 33 + WIDTH * 30; + mobs.add(hexa); + + if (Badges.checkCoconutRescued()){ + Mob fruitcat = new FruitCat(); + fruitcat.pos = 45 + WIDTH * 2; + mobs.add(fruitcat); + } else { + Mob coconut = new Coconut(); + coconut.pos = 45 + WIDTH * 2; + mobs.add(coconut); + } + + Mob locastan = new Locastan(); + locastan.pos = 5 + WIDTH * 5; + mobs.add(locastan); + + Mob goblin = new GoblinPlayer(); + goblin.pos = 2 + WIDTH * 5; + mobs.add(goblin); + + Mob dachhack = new Dachhack(); + dachhack.pos = 37 + WIDTH * 3; + mobs.add(dachhack); + + if (Badges.checkMOSRescued() || Dungeon.isChallenged(Challenges.TEST_TIME)){ + Mob MOS = new MemoryOfSand(); + MOS.pos = 26 + WIDTH * 4; + mobs.add(MOS); + + Mob Afly = new AFly(); + Afly.pos = 27 + WIDTH * 17; + mobs.add(Afly); + + + } + + Mob ONS = new OldNewStwist(); + ONS.pos = 20 + WIDTH * 3; + mobs.add(ONS); + + Mob HS = new HateSokoban(); + HS.pos = 23 + WIDTH * 10; + mobs.add(HS); + + Mob LJ = new LaJi(); + LJ.pos = 23 + WIDTH * 12; + mobs.add(LJ); + + if (Badges.checkSARRescued()|| Dungeon.isChallenged(Challenges.TEST_TIME)){ + Mob SAR = new StormAndRain(); + SAR.pos = 21 + WIDTH * 6; + mobs.add(SAR); + } + + if (Dungeon.dewNorn == true || Dungeon.isChallenged(Challenges.TEST_TIME)) { + Mob LYNN = new Lynn(); + LYNN.pos = 31 + WIDTH * 32; + mobs.add(LYNN); + } + + Mob REN = new RENnpc(); + REN.pos = 28 + WIDTH * 27; + mobs.add(REN); + + Mob KOSTIS = new Kostis12345(); + KOSTIS.pos = 20 + WIDTH * 25; + mobs.add(KOSTIS); + + Mob apos = new Apostle(); + apos.pos = 20 + WIDTH * 21; + mobs.add(apos); + + Mob painter = new NutPainter(); + painter.pos = 16 + WIDTH * 21; + mobs.add(painter); + + Mob JUH = new Juh9870(); + JUH.pos = 35 + WIDTH * 6; + mobs.add(JUH); + + Mob SADS = new SadSaltan(); + SADS.pos = 42 + WIDTH * 38; + mobs.add(SADS); + + Mob tinkerer4 = new Tinkerer4(); + tinkerer4.pos = 31 + WIDTH * 20; + mobs.add(tinkerer4); + + Mob shower = new Shower(); + shower.pos = 30 + WIDTH * 19; + mobs.add(shower); + + Mob tinkerer5 = new Tinkerer5(); + tinkerer5.pos = 14 + WIDTH * 33; + mobs.add(tinkerer5); + + AdultDragonViolet mob3 = new AdultDragonViolet(); + mob3.pos = 5 + WIDTH * 43; + mobs.add(mob3); + + BombBug test = new BombBug(); + test.pos = 14 + WIDTH * 32; + mobs.add(test); + + /*Guard test2 = new Guard(); + test2.pos = 14 + WIDTH * 31; + mobs.add(test2);*/ + + /*TrollWarrior test3 = new TrollWarrior(); + test3.pos = 14 + WIDTH * 30; + mobs.add(test3);*/ + if (Badges.checkRainRescued() || Dungeon.isChallenged(Challenges.TEST_TIME)) { + TestMob test4 = new TestMob(); + test4.pos = 18 + WIDTH * 44; + mobs.add(test4); + + RainTrainer rain = new RainTrainer(); + rain.pos = 17 + WIDTH * 42; + mobs.add(rain); + + Mob rustyblade = new Rustyblade(); + rustyblade.pos = 22 + WIDTH * 42; + mobs.add(rustyblade); + + Mob tempest102 = new Tempest102(); + tempest102.pos = 33 + WIDTH * 42; + mobs.add(tempest102); + } + + TestMob2 test5 = new TestMob2(); + test5.pos = 21 + WIDTH * 44; + mobs.add(test5); + + /*Assassin test5 = new Assassin(); + test5.pos = 14 + WIDTH * 28; + mobs.add(test5);*/ + + if (Badges.checkFishRescued() || Dungeon.isChallenged(Challenges.TEST_TIME)){ + Piranha mob4 = new Piranha(); + mob4.pos = 42 + WIDTH * 37; + mobs.add(mob4); + Piranha mob5 = new Piranha(); + mob5.pos = 42 + WIDTH * 36; + mobs.add(mob5); + Mob alivefish = new AliveFish(); + alivefish.pos = 42 + WIDTH * 9; + mobs.add(alivefish); + } + + /*Golem mob6 = new Golem(); + mob6.pos = 42 + WIDTH * 36; + mobs.add(mob6);*/ + + scrollspots = new int[11]; + scrollspots[0] = 4 + WIDTH * 27; + scrollspots[1] = 4 + WIDTH * 26; + scrollspots[2] = 4 + WIDTH * 25; + scrollspots[3] = 4 + WIDTH * 24; + scrollspots[4] = 4 + WIDTH * 23; + scrollspots[5] = 4 + WIDTH * 22; + + scrollspots[6] = 6 + WIDTH * 25; + scrollspots[7] = 7 + WIDTH * 25; + scrollspots[8] = 8 + WIDTH * 25; + scrollspots[9] = 9 + WIDTH * 25; + scrollspots[10] = 10 + WIDTH * 25; + + storespots = new int[9]; + storespots[0] = 7 + WIDTH * 10; + storespots[1] = 7 + WIDTH * 9; + storespots[2] = 7 + WIDTH * 8; + storespots[3] = 7 + WIDTH * 7; + + storespots[4] = 12 + WIDTH * 13; + storespots[5] = 12 + WIDTH * 12; + storespots[6] = 12 + WIDTH * 11; + storespots[7] = 12 + WIDTH * 10; + storespots[8] = 12 + WIDTH * 9; + + bombpots = new int[8]; + bombpots[0] = 45 + WIDTH * 1; + bombpots[1] = 45 + WIDTH * 3; + bombpots[2] = 44 + WIDTH * 1; + bombpots[3] = 44 + WIDTH * 2; + + bombpots[4] = 44 + WIDTH * 3; + bombpots[5] = 46 + WIDTH * 1; + bombpots[6] = 46 + WIDTH * 2; + bombpots[7] = 46 + WIDTH * 3; + + foodpots = new int[4]; + foodpots[0] = 24 + WIDTH * 6; + foodpots[1] = 25 + WIDTH * 6; + foodpots[2] = 26 + WIDTH * 6; + foodpots[3] = 27 + WIDTH * 6; + + sppots = new int[1]; + sppots[0] = 20 + WIDTH * 6; + + eggpots = new int[1]; + eggpots[0] = 41 + WIDTH * 10; + + gnollpots = new int[1]; + gnollpots[0] = 21 + WIDTH * 3; + + skillpots = new int[3]; + skillpots[0] = 33 + WIDTH * 44; + skillpots[1] = 34 + WIDTH * 44; + skillpots[2] = 35 + WIDTH * 44; + + pillpots = new int[1]; + pillpots[0] = 43 + WIDTH * 23; + + storeStock(); + if (Dungeon.dewNorn == true) { + Alter alter = new Alter(); + alter.seed(33 + WIDTH * 32, 1); + blobs.put(Alter.class, alter); + } + + addChest(39 + WIDTH * 4); + addChest(40 + WIDTH * 4); + addChest(41 + WIDTH * 4); + addChest(42 + WIDTH * 4); + + if(Badges.checkTombRescued()){ + addChest(41 + WIDTH * 18); + addChest(42 + WIDTH * 18); + } + + addChest(7 + WIDTH * 5); + addChest(8 + WIDTH * 5); + addChest(9 + WIDTH * 5); + + if(Badges.checkFishRescued()){ + addChest(27 + WIDTH * 11); + addChest(27 + WIDTH * 12); + } + + if(Badges.checkTombRescued()){ + addTomb(41 + WIDTH * 41); + } + } + + private void addChest(int pos) { + + Item prize; + switch (Random.Int(10)) { + case 0: + prize = Generator.random(Generator.Category.BERRY); + break; + case 1: + prize = new Starflower.Seed(); + break; + default: + prize = new DarkGold(); + break; + } + + drop(prize, pos).type = Heap.Type.CHEST; + } + + private void addTomb(int pos) { + + Item prize; + switch (Random.Int(10)) { + case 0: + prize = new Phaseshift.Seed(); + break; + case 1: + prize = Generator.random(Generator.Category.MUSHROOM); + break; + default: + prize = new DarkGold(); + break; + } + + drop(prize, pos).type = Heap.Type.TOMB; + } + + @Override + public void press(int cell, Char ch) { + + if(!special){ + storeStock(); + special=true; + } + + if (pit[cell] && ch == Dungeon.hero) { + Chasm.heroFall(cell); + return; + } + + TimekeepersHourglass.timeFreeze timeFreeze = null; + + if (ch != null) + timeFreeze = ch.buff(TimekeepersHourglass.timeFreeze.class); + + boolean trap = false; + boolean interrupt = false; + + + + switch (map[cell]) { + + + case Terrain.HIGH_GRASS: + HighGrass.trample(this, cell, ch); + break; + + case Terrain.WELL: + WellWater.affectCell(cell); + break; + + case Terrain.ALCHEMY: + Alchemy alchemy = new Alchemy(); + level.blobs.put( Alchemy.class, alchemy ); + break; + + case Terrain.PEDESTAL: + if (ch == null ) { + Alter.transmute(cell); + } + break; + + case Terrain.DOOR: + Door.enter(cell); + break; + } + + if (trap){ + + if (Dungeon.visible[cell]) + Sample.INSTANCE.play(Assets.SND_TRAP); + + if (ch == Dungeon.hero) + Dungeon.hero.interrupt(); + + set(cell, Terrain.INACTIVE_TRAP); + GameScene.updateMap(cell); + } + + if (interrupt){ + + Dungeon.hero.interrupt(); + GameScene.updateMap(cell); + } + + Plant plant = plants.get(cell); + if (plant != null) { + plant.activate(ch); + } + } + + @Override + public String tilesTex() { + return Assets.TILES_TOWN; + } + + @Override + public String waterTex() { + return Assets.WATER_PRISON; + } + + @Override + protected boolean build() { + + map = TownLayouts.TOWN_LAYOUT.clone(); + decorate(); + + buildFlagMaps(); + cleanWalls(); + + entrance = 25 + WIDTH * 21; + exit = 5 + WIDTH * 40; + + + return true; + } + @Override + protected void decorate() { + + } + + @Override + protected void createMobs() { + + } + @Override + public String tileName( int tile ) { + switch (tile) { + case Terrain.WATER: + return Messages.get(PrisonLevel.class, "water_name"); + default: + return super.tileName( tile ); + } + } + + @Override + public String tileDesc(int tile) { + switch (tile) { + case Terrain.EMPTY_DECO: + return Messages.get(PrisonLevel.class, "empty_deco_desc"); + case Terrain.BOOKSHELF: + return Messages.get(PrisonLevel.class, "bookshelf_desc"); + default: + return super.tileDesc( tile ); + } + } + + @Override + public int randomRespawnCell() { + return -1; + } + +} diff --git a/java/com/hmdzl/spspd/levels/VaultLevel.java b/java/com/hmdzl/spspd/levels/VaultLevel.java new file mode 100644 index 00000000..b31c6823 --- /dev/null +++ b/java/com/hmdzl/spspd/levels/VaultLevel.java @@ -0,0 +1,249 @@ +/* + * 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 + */ +package com.hmdzl.spspd.levels; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.Statistics; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.mobs.Bestiary; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.items.Gold; +import com.hmdzl.spspd.levels.painters.Painter; +import com.hmdzl.spspd.scenes.GameScene; +import com.watabou.noosa.Scene; +import com.watabou.utils.Random; + +public class VaultLevel extends Level { + + { + color1 = 0x4b6636; + color2 = 0xf2f2f2; + cleared=true; + + } + + private static final int ROOM_LEFT = getWidth() / 2 - 2; + private static final int ROOM_RIGHT = getWidth() / 2 + 2; + private static final int ROOM_TOP = HEIGHT / 2 - 2; + private static final int ROOM_BOTTOM = HEIGHT / 2 + 2; + + protected static final float TIME_TO_RESPAWN = 20; + protected static final int REGROW_TIMER = 4; + @Override + public String tilesTex() { + return Assets.TILES_VAULT; + } + + @Override + public String waterTex() { + return Assets.WATER_CITY; + } + + + + @Override + protected boolean build() { + + int topMost = Integer.MAX_VALUE; + + for (int i = 0; i < 8; i++) { + int left, right, top, bottom; + if (Random.Int(2) == 0) { + left = Random.Int(1, ROOM_LEFT - 3); + right = ROOM_RIGHT + 3; + } else { + left = ROOM_LEFT - 3; + right = Random.Int(ROOM_RIGHT + 3, getWidth() - 1); + } + if (Random.Int(2) == 0) { + top = Random.Int(2, ROOM_TOP - 3); + bottom = ROOM_BOTTOM + 3; + } else { + top = ROOM_LEFT - 3; + bottom = Random.Int(ROOM_TOP + 3, HEIGHT - 1); + } + + Painter.fill(this, left, top, right - left + 1, bottom - top + 1, + Terrain.EMPTY); + + if (top < topMost) { + topMost = top; + exit = Random.Int(left, right) + (top - 1) * getWidth(); + } + } + + map[exit] = Terrain.WALL; + + + + Painter.fill(this, ROOM_LEFT, ROOM_TOP + 1, ROOM_RIGHT - ROOM_LEFT + 1, + ROOM_BOTTOM - ROOM_TOP, Terrain.EMPTY); + + + entrance = Random.Int(ROOM_LEFT + 1, ROOM_RIGHT - 1) + + Random.Int(ROOM_TOP + 1, ROOM_BOTTOM - 1) * getWidth(); + map[entrance] = Terrain.EMPTY; + + return true; + } + + @Override + protected void decorate() { + + for (int i = getWidth() + 1; i < getLength() - getWidth(); i++) { + if (map[i] == Terrain.EMPTY) { + int n = 0; + if (map[i + 1] == Terrain.WALL) { + n++; + } + if (map[i - 1] == Terrain.WALL) { + n++; + } + if (map[i + getWidth()] == Terrain.WALL) { + n++; + } + if (map[i - getWidth()] == Terrain.WALL) { + n++; + } + if (Random.Int(8) <= n) { + map[i] = Terrain.EMPTY_DECO; + } + } + } + + for (int i = 0; i < getLength(); i++) { + if (map[i] == Terrain.WALL && Random.Int(8) == 0) { + map[i] = Terrain.WALL_DECO; + } + if (map[i]==Terrain.ENTRANCE){map[i] = Terrain.EMPTY;} + if (map[i]==Terrain.EMPTY && heaps.get(i) == null && Random.Float()<.15){map[i] = Terrain.STATUE;} + if (map[i]==Terrain.EMPTY && heaps.get(i) == null && Random.Float()<.10){map[i] = Terrain.HIGH_GRASS;} + if (map[i]==Terrain.EMPTY && heaps.get(i) == null && Random.Float()<.10){map[i] = Terrain.GRASS;} + } + + } + + //@Override + //protected void createMobs() { + //} + + //@Override + //public Actor respawner() { + // return null; + //} + + @Override + protected void createItems() { + + for (int i = 0; i < 50; i++) { + int pos = randomDestination(); + drop(new Gold(Random.Int(100,300)), pos); + } + + } + + + + //@Override + //public int randomRespawnCell() { + // return -1; + //} + + + + + @Override + public String tileName(int tile) { + switch (tile) { + case Terrain.WATER: + return "Suspiciously colored water"; + case Terrain.HIGH_GRASS: + return "Flowers with little gem-shaped leaves"; + default: + return super.tileName(tile); + } + } + + @Override + public String tileDesc(int tile) { + switch (tile) { + case Terrain.ENTRANCE: + return "A ramp leads up to the upper depth."; + case Terrain.EXIT: + return "A ramp leads down to the lower depth."; + case Terrain.WALL_DECO: + case Terrain.EMPTY_DECO: + return "Rough-hewn gold ore adorns the dungeon."; + case Terrain.EMPTY_SP: + return "Thick carpet covers the floor."; + case Terrain.STATUE: + case Terrain.STATUE_SP: + return "The statue is made of solid gold."; + case Terrain.BOOKSHELF: + return "The rows of books on different disciplines fill the bookshelf."; + default: + return super.tileDesc(tile); + } + } + + + @Override + public void addVisuals(Scene scene) { + CavesLevel.addVisuals(this, scene); + } + @Override + public int nMobs() { + return 16; + } + + @Override + protected void createMobs() { + int nMobs = nMobs(); + for (int i = 0; i < nMobs; i++) { + Mob mob = Bestiary.mob(Dungeon.depth); + do { + mob.pos = randomRespawnCellMob(); + } while (mob.pos == -1); + mobs.add(mob); + Actor.occupyCell(mob); + } + } + + @Override + public Actor respawner() { + return new Actor() { + @Override + protected boolean act() { + if (mobs.size() < nMobs()) { + + Mob mob = Bestiary.mutable(Dungeon.depth); + mob.state = mob.WANDERING; + mob.pos = randomRespawnCellMob(); + if (Dungeon.hero.isAlive() && mob.pos != -1) { + GameScene.add(mob); + } + } + spend(Dungeon.level.feeling == Feeling.DARK + || Statistics.amuletObtained ? TIME_TO_RESPAWN / 2 + : TIME_TO_RESPAWN); + return true; + } + }; + } +} diff --git a/java/com/hmdzl/spspd/levels/ZotBossLevel.java b/java/com/hmdzl/spspd/levels/ZotBossLevel.java new file mode 100644 index 00000000..8d602cbc --- /dev/null +++ b/java/com/hmdzl/spspd/levels/ZotBossLevel.java @@ -0,0 +1,271 @@ +/* + * 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 + */ +package com.hmdzl.spspd.levels; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.mobs.Zot; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.levels.painters.Painter; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.noosa.Camera; +import com.watabou.noosa.Scene; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public class ZotBossLevel extends Level { + + { + color1 = 0x534f3e; + color2 = 0xb9d661; + cleared=true; + viewDistance = 6; + } + + private static final int ROOM_LEFT = getWidth() / 2 - 2; + private static final int ROOM_RIGHT = getWidth() / 2 + 2; + private static final int ROOM_TOP = HEIGHT / 2 - 2; + private static final int ROOM_BOTTOM = HEIGHT / 2 + 2; + + private int arenaDoor; + private boolean enteredArena = false; + private boolean keyDropped = false; + + @Override + public String tilesTex() { + return Assets.TILES_SEAL; + } + + @Override + public String waterTex() { + return Assets.WATER_CITY; + } + + + private static final String DOOR = "door"; + private static final String ENTERED = "entered"; + private static final String DROPPED = "droppped"; + + protected static final float TIME_TO_RESPAWN = 20; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(DOOR, arenaDoor); + bundle.put(ENTERED, enteredArena); + bundle.put(DROPPED, keyDropped); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + arenaDoor = bundle.getInt(DOOR); + enteredArena = bundle.getBoolean(ENTERED); + keyDropped = bundle.getBoolean(DROPPED); + } + + @Override + protected boolean build() { + + int topMost = Integer.MAX_VALUE; + + for (int i = 0; i < 8; i++) { + int left, right, top, bottom; + if (Random.Int(2) == 0) { + left = Random.Int(1, ROOM_LEFT - 3); + right = ROOM_RIGHT + 3; + } else { + left = ROOM_LEFT - 3; + right = Random.Int(ROOM_RIGHT + 3, getWidth() - 1); + } + if (Random.Int(2) == 0) { + top = Random.Int(2, ROOM_TOP - 3); + bottom = ROOM_BOTTOM + 3; + } else { + top = ROOM_LEFT - 3; + bottom = Random.Int(ROOM_TOP + 3, HEIGHT - 1); + } + + Painter.fill(this, left, top, right - left + 1, bottom - top + 1, + Terrain.EMPTY); + + if (top < topMost) { + topMost = top; + exit = Random.Int(left, right) + (top - 1) * getWidth(); + } + } + + map[exit] = Terrain.WALL; + + Painter.fill(this, ROOM_LEFT - 1, ROOM_TOP - 1, ROOM_RIGHT - ROOM_LEFT + + 3, ROOM_BOTTOM - ROOM_TOP + 3, Terrain.WALL); + Painter.fill(this, ROOM_LEFT, ROOM_TOP + 1, ROOM_RIGHT - ROOM_LEFT + 1, + ROOM_BOTTOM - ROOM_TOP, Terrain.EMPTY); + + Painter.fill(this, ROOM_LEFT, ROOM_TOP, ROOM_RIGHT - ROOM_LEFT + 1, 1, + Terrain.TRAP); + + arenaDoor = Random.Int(ROOM_LEFT, ROOM_RIGHT) + (ROOM_BOTTOM + 1) + * getWidth(); + map[arenaDoor] = Terrain.DOOR; + + entrance = Random.Int(ROOM_LEFT + 1, ROOM_RIGHT - 1) + + Random.Int(ROOM_TOP + 1, ROOM_BOTTOM - 1) * getWidth(); + map[entrance] = Terrain.ENTRANCE; + + return true; + } + + @Override + protected void decorate() { + + for (int i = getWidth() + 1; i < getLength() - getWidth(); i++) { + if (map[i] == Terrain.EMPTY) { + int n = 0; + if (map[i + 1] == Terrain.WALL) { + n++; + } + if (map[i - 1] == Terrain.WALL) { + n++; + } + if (map[i + getWidth()] == Terrain.WALL) { + n++; + } + if (map[i - getWidth()] == Terrain.WALL) { + n++; + } + if (Random.Int(8) <= n) { + map[i] = Terrain.EMPTY_DECO; + } + } + } + + for (int i = 0; i < getLength(); i++) { + + if (map[i]==Terrain.ENTRANCE){map[i] = Terrain.PEDESTAL;} + } + + locked=true; + + } + + //@Override + //protected void createMobs() { + //} + + //@Override + //public Actor respawner() { + // return null; + //} + + @Override + protected void createItems() { + } + + //@Override + //public int randomRespawnCell() { + // return -1; + //} + + @Override + public void press(int cell, Char hero) { + + super.press(cell, hero); + + if (!enteredArena && outsideEntraceRoom(cell) && hero == Dungeon.hero) { + + enteredArena = true; + //locked = true; + + Zot boss = new Zot(); + boss.state = boss.HUNTING; + do { + boss.pos = Random.Int(getLength()); + } while (!passable[boss.pos] || !outsideEntraceRoom(boss.pos) + || Dungeon.visible[boss.pos]); + GameScene.add(boss); + GLog.n("..."); + + + //set(arenaDoor, Terrain.WALL); + GameScene.updateMap(arenaDoor); + Dungeon.observe(); + + CellEmitter.get(arenaDoor).start(Speck.factory(Speck.ROCK), 0.07f, 10); + Camera.main.shake(3, 0.7f); + Sample.INSTANCE.play(Assets.SND_ROCKS); + } + } + + + private boolean outsideEntraceRoom(int cell) { + int cx = cell % getWidth(); + int cy = cell / getWidth(); + return cx < ROOM_LEFT - 1 || cx > ROOM_RIGHT + 1 || cy < ROOM_TOP - 1 + || cy > ROOM_BOTTOM + 1; + } + + @Override + public String tileName(int tile) { + switch (tile) { + case Terrain.WATER: + return Messages.get(BossRushLevel.class, "water_name"); + case Terrain.GRASS: + return Messages.get(BossRushLevel.class, "grass_name"); + case Terrain.HIGH_GRASS: + return Messages.get(BossRushLevel.class, "high_grass_name"); + case Terrain.STATUE: + case Terrain.STATUE_SP: + return Messages.get(BossRushLevel.class, "statue_sp_name"); + default: + return super.tileName(tile); + } + } + + @Override + public String tileDesc(int tile) { + switch (tile) { + case Terrain.WATER: + return Messages.get(BossRushLevel.class, "water_desc"); + case Terrain.STATUE: + case Terrain.STATUE_SP: + return Messages.get(BossRushLevel.class, "statue_sp_desc"); + default: + return super.tileDesc(tile); + } + } + + @Override + public void addVisuals(Scene scene) { + CavesLevel.addVisuals(this, scene); + } + @Override + public int nMobs() { + return 0; + } + + @Override + protected void createMobs() { } + + +} diff --git a/java/com/hmdzl/spspd/levels/features/AlchemyPot.java b/java/com/hmdzl/spspd/levels/features/AlchemyPot.java new file mode 100644 index 00000000..1a3d2489 --- /dev/null +++ b/java/com/hmdzl/spspd/levels/features/AlchemyPot.java @@ -0,0 +1,85 @@ +/* + * 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 + */ +package com.hmdzl.spspd.levels.features; + +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.windows.WndAlchemy; + +public class AlchemyPot { + + public static void cook(int pos) { + GameScene.show(new WndAlchemy()); + } + + /*private static final String TXT_SELECT_SEED = "Select a seed to throw"; + private static final String TXT_POT = "Alchemy Pot"; + private static final String TXT_FRUIT = "Cook a Blandfruit"; + private static final String TXT_POTION = "Brew a Potion"; + private static final String TXT_OPTIONS = "Do you want to cook a Blandfruit with a seed, or brew a Potion from seeds?"; + + public static Hero hero; + public static int pos; + + public static boolean foundFruit; + public static Item curItem = null; + + public static void operate(Hero hero, int pos) { + + AlchemyPot.hero = hero; + AlchemyPot.pos = pos; + + Iterator items = hero.belongings.iterator(); + foundFruit = false; + Heap heap = Dungeon.level.heaps.get(pos); + + if (heap == null) + while (items.hasNext() && !foundFruit) { + curItem = items.next(); + if (curItem instanceof Blandfruit + && ((Blandfruit) curItem).potionAttrib == null) { + GameScene.show(new WndOptions(Messages.get(AlchemyPot.class, "pot"), + Messages.get(AlchemyPot.class, "options"), + Messages.get(AlchemyPot.class, "fruit"), + Messages.get(AlchemyPot.class, "potion")) { + @Override + protected void onSelect(int index) { + if (index == 0) { + curItem.cast(AlchemyPot.hero, AlchemyPot.pos); + } else + GameScene.selectItem(itemSelector, + WndBag.Mode.SEED, Messages.get(AlchemyPot.class, "select_seed")); + } + }); + foundFruit = true; + } + } + + if (!foundFruit) + GameScene.selectItem(itemSelector, WndBag.Mode.SEED, + Messages.get(AlchemyPot.class, "select_seed")); + } + + private static final WndBag.Listener itemSelector = new WndBag.Listener() { + @Override + public void onSelect(Item item) { + if (item != null) { + item.cast(hero, pos); + } + } + };*/ +} diff --git a/java/com/hmdzl/spspd/levels/features/Chasm.java b/java/com/hmdzl/spspd/levels/features/Chasm.java new file mode 100644 index 00000000..f17b1f16 --- /dev/null +++ b/java/com/hmdzl/spspd/levels/features/Chasm.java @@ -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 + */ +package com.hmdzl.spspd.levels.features; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.ResultDescriptions; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Cripple; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.items.artifacts.TimekeepersHourglass; +import com.hmdzl.spspd.levels.RegularLevel; +import com.hmdzl.spspd.levels.Room; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.scenes.InterlevelScene; +import com.hmdzl.spspd.sprites.MobSprite; +import com.hmdzl.spspd.windows.WndOptions; +import com.watabou.noosa.Camera; +import com.watabou.noosa.Game; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Random; + +public class Chasm { + + private static final String TXT_CHASM = "Chasm"; + private static final String TXT_YES = "Yes, I know what I'm doing"; + private static final String TXT_NO = "No, I changed my mind"; + private static final String TXT_JUMP = "Do you really want to jump into the chasm? You can probably die."; + + public static boolean jumpConfirmed = false; + + public static void heroJump(final Hero hero) { + GameScene.show(new WndOptions(Messages.get(Chasm.class, "chasm"), + Messages.get(Chasm.class, "jump"), + Messages.get(Chasm.class, "yes"), + Messages.get(Chasm.class, "no") ) { + @Override + protected void onSelect(int index) { + if (index == 0) { + jumpConfirmed = true; + hero.resume(); + } + }; + }); + } + + + + public static void heroFall(int pos) { + + jumpConfirmed = false; + + Sample.INSTANCE.play(Assets.SND_FALLING); + + Buff buff = Dungeon.hero.buff(TimekeepersHourglass.timeFreeze.class); + if (buff != null) + buff.detach(); + + if (Dungeon.hero.isAlive()) { + Dungeon.hero.interrupt(); + InterlevelScene.mode = InterlevelScene.Mode.FALL; + if (Dungeon.level instanceof RegularLevel) { + Room room = ((RegularLevel) Dungeon.level).room(pos); + InterlevelScene.fallIntoPit = room != null + && room.type == Room.Type.WEAK_FLOOR; + } else { + InterlevelScene.fallIntoPit = false; + } + Game.switchScene(InterlevelScene.class); + } else { + Dungeon.hero.sprite.visible = false; + } + } + + + public static void heroLand() { + + Hero hero = Dungeon.hero; + + hero.sprite.burst(hero.sprite.blood(), 10); + Camera.main.shake(4, 0.2f); + + Buff.prolong(hero, Cripple.class, Cripple.DURATION); + + + hero.damage(Random.IntRange(hero.HT/3, hero.HT/2), new Hero.Doom() { + @Override + public void onDeath() { + Badges.validateDeathFromFalling(); + + Dungeon.fail(Messages.format(ResultDescriptions.FALL)); + //GLog.n("You fell to death..."); + } + }); + } + + public static void mobFall(Mob mob) { + mob.die(null); + + ((MobSprite) mob.sprite).fall(); + } +} diff --git a/java/com/hmdzl/spspd/levels/features/Door.java b/java/com/hmdzl/spspd/levels/features/Door.java new file mode 100644 index 00000000..ac09d167 --- /dev/null +++ b/java/com/hmdzl/spspd/levels/features/Door.java @@ -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 + */ +package com.hmdzl.spspd.levels.features; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.Terrain; +import com.hmdzl.spspd.scenes.GameScene; +import com.watabou.noosa.audio.Sample; + +public class Door { + + public static void enter(int pos) { + Level.set(pos, Terrain.OPEN_DOOR); + GameScene.updateMap(pos); + Dungeon.observe(); + + if (Dungeon.visible[pos]) { + Sample.INSTANCE.play(Assets.SND_OPEN); + } + } + + public static void leave(int pos) { + if (Dungeon.level.heaps.get(pos) == null) { + Level.set(pos, Terrain.DOOR); + GameScene.updateMap(pos); + Dungeon.observe(); + } + } +} diff --git a/java/com/hmdzl/spspd/levels/features/HighGrass.java b/java/com/hmdzl/spspd/levels/features/HighGrass.java new file mode 100644 index 00000000..a4b28e4d --- /dev/null +++ b/java/com/hmdzl/spspd/levels/features/HighGrass.java @@ -0,0 +1,107 @@ +/* + * 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 + */ +package com.hmdzl.spspd.levels.features; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Invisibility; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.hero.HeroSubClass; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.particles.LeafParticle; +import com.hmdzl.spspd.items.Dewdrop; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.RedDewdrop; +import com.hmdzl.spspd.items.VioletDewdrop; +import com.hmdzl.spspd.items.YellowDewdrop; +import com.hmdzl.spspd.items.artifacts.SandalsOfNature; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.Terrain; +import com.hmdzl.spspd.plants.NutPlant; +import com.hmdzl.spspd.scenes.GameScene; +import com.watabou.utils.Random; + +public class HighGrass { + + public static void trample(Level level, int pos, Char ch) { + + Level.set(pos, Terrain.GRASS); + GameScene.updateMap(pos); + + //if (!Dungeon.isChallenged(Challenges.NO_HERBALISM)) { + int naturalismLevel = 0; + + if (ch != null) { + SandalsOfNature.Naturalism naturalism = ch + .buff(SandalsOfNature.Naturalism.class); + if (naturalism != null) { + if (!naturalism.isCursed()) { + naturalismLevel = naturalism.level() + 1; + naturalism.charge(); + } else { + naturalismLevel = -1; + } + } + } + + if (naturalismLevel >= 0) { + // Seed + if (Random.Int(20 - ((int) (naturalismLevel * 3.34))) == 0) { + Item seed = Generator.random(Generator.Category.SEED); + level.drop(seed, pos).sprite.drop(); + } + + // Vegetable + //if (Dungeon.growLevel(Dungeon.depth) && Random.Int(40 - ((int) (naturalismLevel * 3.34))) == 0) { + //level.drop(new NutVegetable(), pos).sprite.drop(); + //} + + if (Dungeon.growLevel(Dungeon.depth) && Random.Int(15 - ((int) (naturalismLevel * 3.34))) == 0) { + level.drop(new NutPlant.Seed(), pos).sprite.drop(); + } + + // Dew + if (Random.Int(3 - naturalismLevel) == 0) { + if (Random.Int(30 - naturalismLevel) == 0 && naturalismLevel>0) { + level.drop(new YellowDewdrop(), pos).sprite.drop(); + } else if (Random.Int(50 - naturalismLevel) == 0 && naturalismLevel>2) { + level.drop(new RedDewdrop(), pos).sprite.drop(); + } else if (Random.Int(100 - naturalismLevel) == 0 && naturalismLevel>4){ + level.drop(new VioletDewdrop(), pos).sprite.drop(); + } else { + level.drop(new Dewdrop(), pos).sprite.drop(); + } + } + } + // } + + int leaves = 4; + + // Barkskin + if (ch instanceof Hero && ((Hero) ch).subClass == HeroSubClass.WARDEN) { + //Buff.affect(ch, Barkskin.class).level(ch.HT / 3); + Buff.affect(ch, Invisibility.class,2f); + //leaves = 8; + } + + CellEmitter.get(pos).burst(LeafParticle.LEVEL_SPECIFIC, leaves); + Dungeon.observe(); + } +} diff --git a/java/com/hmdzl/spspd/levels/features/Sign.java b/java/com/hmdzl/spspd/levels/features/Sign.java new file mode 100644 index 00000000..e11e5b98 --- /dev/null +++ b/java/com/hmdzl/spspd/levels/features/Sign.java @@ -0,0 +1,128 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 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 + */ +package com.hmdzl.spspd.levels.features; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.particles.ElmoParticle; +import com.hmdzl.spspd.levels.DeadEndLevel; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.Terrain; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.utils.GLog; +import com.hmdzl.spspd.windows.WndMessage; +import com.watabou.noosa.audio.Sample; + +public class Sign { + + private static final String TXT_DEAD_END = "What are you doing here?!"; + + private static final String[] TIPS = { + "Almost all equipment has a strength requirement. Don't overestimate your strength, using equipment you can't " + + "handle has big penalties!\n\nRaising your strength is not the only way to access better equipment, " + + "you can also lower equipment strength requirements with Scrolls of Upgrade.\n\n\n" + + "Items found in the dungeon will often be unidentified. Some items will have unknown effects, others " + + "may be upgraded, or degraded and cursed! Unidentified items are unpredictable, so be careful!", + "Charging forward recklessly is a great way to get killed.\n\n" + + "Slowing down a bit to examine enemies and use the environment and items to your advantage can make a" + + " big difference.\n\nThe dungeon is full of traps and hidden passageways as well, keep your eyes open!", + "Levelling up is important!\n\nBeing about the same level as the floor you are on is a good idea. " + + "Hunger may keep you moving in search of more food, but don't be afraid to slow down a little and train." + + "\n\n\nHunger and health are both resources, and using them well can mean starving yourself in order" + + " to help conserve food, if you have some health to spare.", + "The rogue isn't the only character that benefits from being sneaky. You can retreat to the other side of a " + + "door to ambush a chasing opponent for a guaranteed hit!" + + "\n\nAny attack on an unaware opponent is guaranteed to hit them.", + + "Note to all sewer maintenance & cleaning crews: TURN BACK NOW. Some sort of sludge monster has made its home" + + " here and several crews have been lost trying to deal with it.\n\n" + + "Approval has been given to seal off the lower sewers, this area has been condemned, LEAVE NOW.", + + "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 unblessed 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!", + + // hmm.. I wonder what this is? + "standOfF roW", "fraCtion doWnpOur", "gaffe MaSts" }; + + + private static final String PIT = "Note to self: Always leave a teleport scroll in the vault."; + //private static final String BOOKLVL = "Note to self: Always leave a teleport scroll in the vault."; + + + private static final String TXT_BURN = "As you try to read the sign it bursts into greenish flames."; + + public static void read(int pos) { + + if (Dungeon.level instanceof DeadEndLevel) { + + GameScene.show(new WndMessage(Messages.get(Sign.class, "dead_end"))); + + } else { + + int index = Dungeon.depth - 1; + + if (index < TIPS.length) { + GameScene.show(new WndMessage(Messages.get(Sign.class, "tip_"+Dungeon.depth))); + + if (index >= 21) { + + Level.set(pos, Terrain.EMBERS); + GameScene.updateMap(pos); + GameScene.discoverTile(pos, Terrain.SIGN); + + GLog.w(Messages.get(Sign.class, "burn")); + + CellEmitter.get(pos).burst(ElmoParticle.FACTORY, 6); + Sample.INSTANCE.play(Assets.SND_BURNING); + } + + } + } + } + + public static void readPit(int pos) { + GameScene.show(new WndMessage(Messages.get(Sign.class,"pit_message"))); + } + + +} diff --git a/java/com/hmdzl/spspd/levels/painters/ArmoryPainter.java b/java/com/hmdzl/spspd/levels/painters/ArmoryPainter.java new file mode 100644 index 00000000..90785dc7 --- /dev/null +++ b/java/com/hmdzl/spspd/levels/painters/ArmoryPainter.java @@ -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 + */ +package com.hmdzl.spspd.levels.painters; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.items.bombs.Bomb; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.keys.IronKey; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.Room; +import com.hmdzl.spspd.levels.Terrain; +import com.watabou.utils.Point; +import com.watabou.utils.Random; + +public class ArmoryPainter extends Painter { + + public static void paint(Level level, Room room) { + + fill(level, room, Terrain.WALL); + fill(level, room, 1, Terrain.EMPTY); + + Room.Door entrance = room.entrance(); + Point statue = null; + if (entrance.x == room.left) { + statue = new Point(room.right - 1, + Random.Int(2) == 0 ? room.top + 1 : room.bottom - 1); + } else if (entrance.x == room.right) { + statue = new Point(room.left + 1, Random.Int(2) == 0 ? room.top + 1 + : room.bottom - 1); + } else if (entrance.y == room.top) { + statue = new Point(Random.Int(2) == 0 ? room.left + 1 + : room.right - 1, room.bottom - 1); + } else if (entrance.y == room.bottom) { + statue = new Point(Random.Int(2) == 0 ? room.left + 1 + : room.right - 1, room.top + 1); + } + if (statue != null) { + set(level, statue, Terrain.STATUE); + } + + int n = Random.IntRange(2, 3); + for (int i = 0; i < n; i++) { + int pos; + do { + pos = room.random(); + } while (level.map[pos] != Terrain.EMPTY + || level.heaps.get(pos) != null); + level.drop(prize(level), pos); + } + + entrance.set(Room.Door.Type.LOCKED); + level.addItemToSpawn(new IronKey(Dungeon.depth)); + } + + private static Item prize(Level level) { + return Random.Int(6) == 0 ? new Bomb().random() : Generator + .random(Random.oneOf(Generator.Category.ARMOR, + Generator.Category.WEAPON)); + } +} diff --git a/java/com/hmdzl/spspd/levels/painters/BarricadedPainter.java b/java/com/hmdzl/spspd/levels/painters/BarricadedPainter.java new file mode 100644 index 00000000..6c9267f4 --- /dev/null +++ b/java/com/hmdzl/spspd/levels/painters/BarricadedPainter.java @@ -0,0 +1,79 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Yet Another Pixel Dungeon + * Copyright (C) 2015-2016 Considered Hamster + * + * 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 + */ +package com.hmdzl.spspd.levels.painters; + +import com.watabou.utils.Random; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.items.Heap; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.potions.PotionOfLiquidFlame; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.Room; +import com.hmdzl.spspd.levels.Terrain; + +public class BarricadedPainter extends Painter { + + public static void paint( Level level, Room room ) { + + final int floor = Terrain.EMPTY_SP; + + fill( level, room, Terrain.WALL ); + fill( level, room, 1, floor ); + + if (room.width() > room.height()) { + for (int i=room.left + 2; i < room.right; i += 2) { + fill( level, i, room.top + 2, 1, room.height() - 3, Terrain.BOOKSHELF ); + } + } else { + for (int i=room.top + 2; i < room.bottom; i += 2) { + fill( level, room.left + 2, i, room.width() - 3, 1, Terrain.BOOKSHELF); + } + } + + int n = 2 + Random.Int( 0,2 ); + for (int i=0; i < n; i++) { + int pos; + do { + pos = room.random(); + } while (level.map[pos] != floor); + level.drop( prize( level ), pos ).type = Heap.Type.SKELETON; + } + + room.entrance().set( Room.Door.Type.BARRICADE ); + level.addItemToSpawn( new PotionOfLiquidFlame() ); + } + + private static Item prize( Level level ) { + + Item prize = Generator.random(); + + if (prize != null) { + return prize; + } + + return Generator.random( Random.oneOf( + Generator.Category.POTION, + Generator.Category.SCROLL, + Generator.Category.GOLD, + Generator.Category.NORNSTONE + ) ); + } +} diff --git a/java/com/hmdzl/spspd/levels/painters/BlacksmithPainter.java b/java/com/hmdzl/spspd/levels/painters/BlacksmithPainter.java new file mode 100644 index 00000000..44baecd8 --- /dev/null +++ b/java/com/hmdzl/spspd/levels/painters/BlacksmithPainter.java @@ -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 + */ +package com.hmdzl.spspd.levels.painters; + +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.mobs.npcs.Blacksmith; +import com.hmdzl.spspd.actors.mobs.npcs.Blacksmith2; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.Room; +import com.hmdzl.spspd.levels.Terrain; +import com.hmdzl.spspd.levels.traps.FireTrap; +import com.watabou.utils.Random; + +public class BlacksmithPainter extends Painter { + + public static void paint(Level level, Room room) { + + fill(level, room, Terrain.WALL); + fill(level, room, 1, Terrain.TRAP); + fill(level, room, 2, Terrain.EMPTY_SP); + + + for (int i = 0; i < 2; i++) { + int pos; + do { + pos = room.random(); + } while (level.map[pos] != Terrain.EMPTY_SP); + level.drop(Generator.random(Random.oneOf(Generator.Category.ARMOR, + Generator.Category.WEAPON)), pos); + } + + + for (Room.Door door : room.connected.values()) { + door.set(Room.Door.Type.UNLOCKED); + drawInside(level, room, door, 1, Terrain.EMPTY); + } + + Blacksmith npc = new Blacksmith(); + do { + npc.pos = room.random(1); + } while (level.heaps.get(npc.pos) != null); + level.mobs.add(npc); + Actor.occupyCell(npc); + + + Blacksmith2 npc2 = new Blacksmith2(); + do { + npc2.pos = room.random(1); + } while (level.heaps.get(npc2.pos) != null || Actor.findChar(npc2.pos) != null); + level.mobs.add(npc2); + Actor.occupyCell(npc2); + + for(int cell : room.getCells()) { + if (level.map[cell] == Terrain.TRAP){ + level.setTrap(new FireTrap().reveal(), cell); + } + } + } +} diff --git a/java/com/hmdzl/spspd/levels/painters/BossExitPainter.java b/java/com/hmdzl/spspd/levels/painters/BossExitPainter.java new file mode 100644 index 00000000..95e133c3 --- /dev/null +++ b/java/com/hmdzl/spspd/levels/painters/BossExitPainter.java @@ -0,0 +1,39 @@ +/* + * 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 + */ +package com.hmdzl.spspd.levels.painters; + +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.Room; +import com.hmdzl.spspd.levels.Terrain; + +public class BossExitPainter extends Painter { + + public static void paint(Level level, Room room) { + + fill(level, room, Terrain.WALL); + fill(level, room, 1, Terrain.EMPTY); + + for (Room.Door door : room.connected.values()) { + door.set(Room.Door.Type.REGULAR); + } + + level.exit = room.top * Level.getWidth() + (room.left + room.right) / 2; + set(level, level.exit, Terrain.LOCKED_EXIT); + } + +} diff --git a/java/com/hmdzl/spspd/levels/painters/CryptPainter.java b/java/com/hmdzl/spspd/levels/painters/CryptPainter.java new file mode 100644 index 00000000..d67d4471 --- /dev/null +++ b/java/com/hmdzl/spspd/levels/painters/CryptPainter.java @@ -0,0 +1,100 @@ +/* + * 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 + */ +package com.hmdzl.spspd.levels.painters; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.blobs.weather.WeatherOfDead; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.items.Heap.Type; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.keys.IronKey; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.Room; +import com.hmdzl.spspd.levels.Terrain; +import com.watabou.utils.Point; +import com.watabou.utils.Random; + +public class CryptPainter extends Painter { + + public static void paint(Level level, Room room) { + + fill(level, room, Terrain.WALL); + fill(level, room, 1, Terrain.EMPTY); + + Point c = room.center(); + int cx = c.x; + int cy = c.y; + + Room.Door entrance = room.entrance(); + + entrance.set(Room.Door.Type.LOCKED); + level.addItemToSpawn(new IronKey(Dungeon.depth)); + + if (entrance.x == room.left) { + set(level, new Point(room.right - 1, room.top + 1), Terrain.STATUE); + set(level, new Point(room.right - 1, room.bottom - 1), + Terrain.STATUE); + cx = room.right - 2; + } else if (entrance.x == room.right) { + set(level, new Point(room.left + 1, room.top + 1), Terrain.STATUE); + set(level, new Point(room.left + 1, room.bottom - 1), + Terrain.STATUE); + cx = room.left + 2; + } else if (entrance.y == room.top) { + set(level, new Point(room.left + 1, room.bottom - 1), + Terrain.STATUE); + set(level, new Point(room.right - 1, room.bottom - 1), + Terrain.STATUE); + cy = room.bottom - 2; + } else if (entrance.y == room.bottom) { + set(level, new Point(room.left + 1, room.top + 1), Terrain.STATUE); + set(level, new Point(room.right - 1, room.top + 1), Terrain.STATUE); + cy = room.top + 2; + } + + level.drop(prize(level), cx + cy * Level.getWidth()).type = Type.TOMB; + + if (Random.Int(10) > 5) { + WeatherOfDead light = (WeatherOfDead) level.blobs.get(WeatherOfDead.class); + if (light == null) { + light = new WeatherOfDead(); + } + for (int i = room.top + 1; i < room.bottom; i++) { + for (int j = room.left + 1; j < room.right; j++) { + light.seed(j + Level.getWidth() * i, 1); + } + } + level.blobs.put(WeatherOfDead.class, light); + } + + } + + private static Item prize(Level level) { + + Item prize = Generator.random(Generator.Category.ARMOR); + + for (int i = 0; i < 3; i++) { + Item another = Generator.random(Generator.Category.ARMOR); + if (another.level > prize.level) { + prize = another; + } + } + + return prize; + } +} diff --git a/java/com/hmdzl/spspd/levels/painters/EntrancePainter.java b/java/com/hmdzl/spspd/levels/painters/EntrancePainter.java new file mode 100644 index 00000000..e8b23e3f --- /dev/null +++ b/java/com/hmdzl/spspd/levels/painters/EntrancePainter.java @@ -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 + */ +package com.hmdzl.spspd.levels.painters; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.mobs.GoldCollector; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.Room; +import com.hmdzl.spspd.levels.Terrain; + +public class EntrancePainter extends Painter { + + public static void paint(Level level, Room room) { + + fill(level, room, Terrain.WALL); + fill(level, room, 1, Terrain.EMPTY); + + for (Room.Door door : room.connected.values()) { + door.set(Room.Door.Type.REGULAR); + } + + level.entrance = room.random(1); + set(level, level.entrance, Terrain.ENTRANCE); + + if (Dungeon.gold > (2000000/(Math.max(1,20-Dungeon.depth))) && Dungeon.depth < 25){ + GoldCollector gc = new GoldCollector(); + gc.pos = room.random(); + level.mobs.add(gc); + Actor.occupyCell(gc); + } + + } + +} diff --git a/java/com/hmdzl/spspd/levels/painters/ExitPainter.java b/java/com/hmdzl/spspd/levels/painters/ExitPainter.java new file mode 100644 index 00000000..0cef5aaf --- /dev/null +++ b/java/com/hmdzl/spspd/levels/painters/ExitPainter.java @@ -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 + */ +package com.hmdzl.spspd.levels.painters; + +import com.hmdzl.spspd.Challenges; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.mobs.LevelChecker; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.Room; +import com.hmdzl.spspd.levels.Terrain; + +public class ExitPainter extends Painter { + + public static void paint(Level level, Room room) { + + fill(level, room, Terrain.WALL); + fill(level, room, 1, Terrain.EMPTY); + + for (Room.Door door : room.connected.values()) { + door.set(Room.Door.Type.REGULAR); + } + + if ((Dungeon.hero.lvl > 14 + Dungeon.depth) && Dungeon.depth < 25 && !Dungeon.isChallenged(Challenges.TEST_TIME)){ + LevelChecker lc = new LevelChecker(); + lc.pos = room.random(); + level.mobs.add(lc); + Actor.occupyCell(lc); + } + + level.exit = room.random(1); + if (Dungeon.isChallenged(Challenges.TEST_TIME)) { + set(level, level.exit, Terrain.STATUE); + } else + set(level, level.exit, Terrain.EXIT); + } + +} diff --git a/java/com/hmdzl/spspd/levels/painters/GardenPainter.java b/java/com/hmdzl/spspd/levels/painters/GardenPainter.java new file mode 100644 index 00000000..6b82416b --- /dev/null +++ b/java/com/hmdzl/spspd/levels/painters/GardenPainter.java @@ -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 + */ +package com.hmdzl.spspd.levels.painters; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.blobs.Foliage; +import com.hmdzl.spspd.items.Ankh; +import com.hmdzl.spspd.items.eggs.EasterEgg; +import com.hmdzl.spspd.items.summon.Honeypot; +import com.hmdzl.spspd.items.bags.ShoppingCart; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.Room; +import com.hmdzl.spspd.levels.Terrain; +import com.hmdzl.spspd.plants.BlandfruitBush; +import com.hmdzl.spspd.plants.Seedpod; +import com.watabou.utils.Random; + +public class GardenPainter extends Painter { + + public static void paint(Level level, Room room) { + + fill(level, room, Terrain.WALL); + fill(level, room, 1, Terrain.HIGH_GRASS); + fill(level, room, 2, Terrain.WATER); + + room.entrance().set(Room.Door.Type.REGULAR); + + //if (Dungeon.isChallenged(Challenges.NO_FOOD)) { + //if (Random.Int(2) == 0) { + //level.plant(new Seedpod.Seed(), room.random()); + //} + //} else { + int bushes = Random.Int(3); + if (bushes == 0) { + level.plant(new Seedpod.Seed(), room.random()); + } else if (bushes == 1) { + level.plant(new BlandfruitBush.Seed(), room.random()); + } else if (Random.Int(5) == 0) { + level.plant(new Seedpod.Seed(), room.random()); + level.plant(new BlandfruitBush.Seed(), room.random()); + } + //} + + + if (!Dungeon.limitedDrops.shopcart.dropped()){ + int pos; + do {pos = room.random();} + while (level.heaps.get(pos) != null); + level.drop(new ShoppingCart(), pos); + Dungeon.limitedDrops.shopcart.drop(); + } + + if (Random.Int(100)==0 && (Dungeon.getMonth()==4 || Dungeon.getMonth()==5)){ + int pos; + do {pos = room.random();} + while (level.heaps.get(pos) != null); + level.drop(new EasterEgg(), pos); + } + + if (Dungeon.depth==32 && Random.Float() < 0.75f){ + int pos; + do {pos = room.random();} + while (level.heaps.get(pos) != null); + level.drop(new Honeypot(), pos); + + do {pos = room.random();} + while (level.heaps.get(pos) != null); + level.drop(new Honeypot(), pos); + + do {pos = room.random();} + while (level.heaps.get(pos) != null); + level.drop(new Honeypot(), pos); + } + + if (Dungeon.depth==32 && Random.Float() < 0.75f){ + int pos; + do {pos = room.random();} + while (level.heaps.get(pos) != null); + level.drop(new Ankh(), pos); + } + + Foliage light = (Foliage) level.blobs.get(Foliage.class); + if (light == null) { + light = new Foliage(); + } + for (int i = room.top + 1; i < room.bottom; i++) { + for (int j = room.left + 1; j < room.right; j++) { + light.seed(j + Level.getWidth() * i, 1); + } + } + level.blobs.put(Foliage.class, light); + } +} diff --git a/java/com/hmdzl/spspd/levels/painters/LaboratoryPainter.java b/java/com/hmdzl/spspd/levels/painters/LaboratoryPainter.java new file mode 100644 index 00000000..643e9091 --- /dev/null +++ b/java/com/hmdzl/spspd/levels/painters/LaboratoryPainter.java @@ -0,0 +1,85 @@ +/* + * 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 + */ +package com.hmdzl.spspd.levels.painters; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.blobs.Alchemy; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.keys.IronKey; +import com.hmdzl.spspd.items.potions.Potion; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.Room; +import com.hmdzl.spspd.levels.Terrain; +import com.watabou.utils.Point; +import com.watabou.utils.Random; + +public class LaboratoryPainter extends Painter { + + public static void paint(Level level, Room room) { + + fill(level, room, Terrain.WALL); + fill(level, room, 1, Terrain.EMPTY_SP); + + Room.Door entrance = room.entrance(); + + Point pot = null; + if (entrance.x == room.left) { + pot = new Point(room.right - 1, Random.Int(2) == 0 ? room.top + 1 + : room.bottom - 1); + } else if (entrance.x == room.right) { + pot = new Point(room.left + 1, Random.Int(2) == 0 ? room.top + 1 + : room.bottom - 1); + } else if (entrance.y == room.top) { + pot = new Point( + Random.Int(2) == 0 ? room.left + 1 : room.right - 1, + room.bottom - 1); + } else if (entrance.y == room.bottom) { + pot = new Point( + Random.Int(2) == 0 ? room.left + 1 : room.right - 1, + room.top + 1); + } + set(level, pot, Terrain.ALCHEMY); + + Alchemy alchemy = new Alchemy(); + alchemy.seed(pot.x + Level.getWidth() * pot.y, 1); + level.blobs.put(Alchemy.class, alchemy); + + int n = Random.IntRange(2, 3); + for (int i = 0; i < n; i++) { + int pos; + do { + pos = room.random(); + } while (level.map[pos] != Terrain.EMPTY_SP + || level.heaps.get(pos) != null); + level.drop(prize(level), pos); + } + + entrance.set(Room.Door.Type.LOCKED); + level.addItemToSpawn(new IronKey(Dungeon.depth)); + } + + private static Item prize(Level level) { + + Item prize = level.findPrizeItem(Potion.class); + if (prize == null) + prize = Generator.random(Generator.Category.POTION); + + return prize; + } +} diff --git a/java/com/hmdzl/spspd/levels/painters/LibraryPainter.java b/java/com/hmdzl/spspd/levels/painters/LibraryPainter.java new file mode 100644 index 00000000..bde14248 --- /dev/null +++ b/java/com/hmdzl/spspd/levels/painters/LibraryPainter.java @@ -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 + */ +package com.hmdzl.spspd.levels.painters; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.blobs.weather.WeatherOfQuite; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.keys.IronKey; +import com.hmdzl.spspd.items.scrolls.Scroll; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.Room; +import com.hmdzl.spspd.levels.Terrain; +import com.watabou.utils.Point; +import com.watabou.utils.Random; + +public class LibraryPainter extends Painter { + + public static void paint(Level level, Room room) { + + fill(level, room, Terrain.WALL); + fill(level, room, 1, Terrain.EMPTY); + + Room.Door entrance = room.entrance(); + Point a = null; + Point b = null; + + if (entrance.x == room.left) { + a = new Point(room.left + 1, entrance.y - 1); + b = new Point(room.left + 1, entrance.y + 1); + fill(level, room.right - 1, room.top + 1, 1, room.height() - 1, + Terrain.BOOKSHELF); + } else if (entrance.x == room.right) { + a = new Point(room.right - 1, entrance.y - 1); + b = new Point(room.right - 1, entrance.y + 1); + fill(level, room.left + 1, room.top + 1, 1, room.height() - 1, + Terrain.BOOKSHELF); + } else if (entrance.y == room.top) { + a = new Point(entrance.x + 1, room.top + 1); + b = new Point(entrance.x - 1, room.top + 1); + fill(level, room.left + 1, room.bottom - 1, room.width() - 1, 1, + Terrain.BOOKSHELF); + } else if (entrance.y == room.bottom) { + a = new Point(entrance.x + 1, room.bottom - 1); + b = new Point(entrance.x - 1, room.bottom - 1); + fill(level, room.left + 1, room.top + 1, room.width() - 1, 1, + Terrain.BOOKSHELF); + } + if (a != null && level.map[a.x + a.y * Level.getWidth()] == Terrain.EMPTY) { + set(level, a, Terrain.STATUE); + } + if (b != null && level.map[b.x + b.y * Level.getWidth()] == Terrain.EMPTY) { + set(level, b, Terrain.STATUE); + } + + int n = Random.IntRange(2, 3); + for (int i = 0; i < n; i++) { + int pos; + do { + pos = room.random(); + } while (level.map[pos] != Terrain.EMPTY + || level.heaps.get(pos) != null); + level.drop(prize(level), pos); + } + + entrance.set(Room.Door.Type.LOCKED); + level.addItemToSpawn(new IronKey(Dungeon.depth)); + + if (Random.Int(10) > 5){ + WeatherOfQuite light = (WeatherOfQuite) level.blobs.get(WeatherOfQuite.class); + if (light == null) { + light = new WeatherOfQuite(); + } + for (int i = room.top + 1; i < room.bottom; i++) { + for (int j = room.left + 1; j < room.right; j++) { + light.seed(j + Level.getWidth() * i, 1); + } + } + level.blobs.put(WeatherOfQuite.class, light);} + } + + private static Item prize(Level level) { + + Item prize = level.findPrizeItem(Scroll.class); + if (prize == null) + prize = Generator.random(Generator.Category.SCROLL); + + return prize; + } +} diff --git a/java/com/hmdzl/spspd/levels/painters/MagicWellPainter.java b/java/com/hmdzl/spspd/levels/painters/MagicWellPainter.java new file mode 100644 index 00000000..36e42ce9 --- /dev/null +++ b/java/com/hmdzl/spspd/levels/painters/MagicWellPainter.java @@ -0,0 +1,73 @@ +/* + * 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 + */ +package com.hmdzl.spspd.levels.painters; + +import com.hmdzl.spspd.actors.blobs.WaterOfAwareness; +import com.hmdzl.spspd.actors.blobs.WaterOfHealth; +import com.hmdzl.spspd.actors.blobs.WaterOfTransmutation; +import com.hmdzl.spspd.actors.blobs.WellWater; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.Room; +import com.hmdzl.spspd.levels.Terrain; +import com.hmdzl.spspd.plants.BlandfruitBush; +import com.hmdzl.spspd.plants.Flytrap; +import com.hmdzl.spspd.plants.Phaseshift; +import com.watabou.utils.Point; +import com.watabou.utils.Random; + +public class MagicWellPainter extends Painter { + + private static final Class[] WATERS = { WaterOfAwareness.class, + WaterOfHealth.class, WaterOfTransmutation.class }; + + public static void paint(Level level, Room room) { + + fill(level, room, Terrain.WALL); + fill(level, room, 1, Terrain.EMPTY); + + Point c = room.center(); + set(level, c.x, c.y, Terrain.WELL); + + @SuppressWarnings("unchecked") + Class waterClass = (Class) Random.element(WATERS); + + + WellWater water = (WellWater) level.blobs.get(waterClass); + if (water == null) { + try { + water = waterClass.newInstance(); + } catch (Exception e) { + water = null; + } + } + + int bushes = Random.Int(3); + if (bushes == 0) { + level.plant(new Flytrap.Seed(), room.random()); + } else if (bushes == 1) { + level.plant(new BlandfruitBush.Seed(), room.random()); + } else if (bushes == 2) { + level.plant(new Phaseshift.Seed(), room.random()); + } + + water.seed(c.x + Level.getWidth() * c.y, 1); + level.blobs.put(waterClass, water); + + room.entrance().set(Room.Door.Type.REGULAR); + } +} diff --git a/java/com/hmdzl/spspd/levels/painters/MemoryPainter.java b/java/com/hmdzl/spspd/levels/painters/MemoryPainter.java new file mode 100644 index 00000000..d9a3be1e --- /dev/null +++ b/java/com/hmdzl/spspd/levels/painters/MemoryPainter.java @@ -0,0 +1,60 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 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 + */ +package com.hmdzl.spspd.levels.painters; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.blobs.MemoryFire; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.Room; +import com.hmdzl.spspd.levels.Terrain; +import com.watabou.utils.Point; + +public class MemoryPainter extends Painter { + + public static void paint( Level level, Room room ) { + + fill( level, room, Terrain.WALL ); + fill( level, room, 1, Dungeon.bossLevel( Dungeon.depth + 1 ) ? Terrain.HIGH_GRASS : Terrain.CHASM ); + + Point c = room.center(); + Room.Door door = room.entrance(); + if (door.x == room.left || door.x == room.right) { + Point p = drawInside( level, room, door, Math.abs( door.x - c.x ) - 2, Terrain.EMPTY_SP ); + for (; p.y != c.y; p.y += p.y < c.y ? +1 : -1) { + set( level, p, Terrain.EMPTY_SP ); + } + } else { + Point p = drawInside( level, room, door, Math.abs( door.y - c.y ) - 2, Terrain.EMPTY_SP ); + for (; p.x != c.x; p.x += p.x < c.x ? +1 : -1) { + set( level, p, Terrain.EMPTY_SP ); + } + } + + fill( level, c.x - 1, c.y - 1, 3, 3, Terrain.EMBERS ); + set( level, c, Terrain.PEDESTAL ); + + MemoryFire fire = (MemoryFire)level.blobs.get( MemoryFire.class ); + if (fire == null) { + fire = new MemoryFire(); + } + fire.seed( c.x + c.y * Level.WIDTH, 5 + Dungeon.depth * 5 ); + level.blobs.put(MemoryFire.class, fire ); + + door.set( Room.Door.Type.HIDDEN ); + } +} diff --git a/java/com/hmdzl/spspd/levels/painters/Painter.java b/java/com/hmdzl/spspd/levels/painters/Painter.java new file mode 100644 index 00000000..5de59351 --- /dev/null +++ b/java/com/hmdzl/spspd/levels/painters/Painter.java @@ -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 + */ +package com.hmdzl.spspd.levels.painters; + +import java.util.Arrays; + +import com.hmdzl.spspd.actors.blobs.Foliage; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.Room; +import com.watabou.utils.Point; +import com.watabou.utils.Rect; + +public class Painter { + + public static void set(Level level, int cell, int value) { + level.map[cell] = value; + } + + public static void set(Level level, int x, int y, int value) { + set(level, x + y * Level.getWidth(), value); + } + + public static void set(Level level, Point p, int value) { + set(level, p.x, p.y, value); + } + + public static void fill(Level level, int x, int y, int w, int h, int value) { + + int width = Level.getWidth(); + + int pos = y * width + x; + for (int i = y; i < y + h; i++, pos += width) { + Arrays.fill(level.map, pos, pos + w, value); + } + } + + public static void fill(Level level, Rect rect, int value) { + fill(level, rect.left, rect.top, rect.width() + 1, rect.height() + 1, + value); + } + + public static void fill(Level level, Rect rect, int m, int value) { + fill(level, rect.left + m, rect.top + m, rect.width() + 1 - m * 2, + rect.height() + 1 - m * 2, value); + } + + public static void fill(Level level, Rect rect, int l, int t, int r, int b, + int value) { + fill(level, rect.left + l, rect.top + t, rect.width() + 1 - (l + r), + rect.height() + 1 - (t + b), value); + } + + public static Point drawInside(Level level, Room room, Point from, int n, + int value) { + + Point step = new Point(); + if (from.x == room.left) { + step.set(+1, 0); + } else if (from.x == room.right) { + step.set(-1, 0); + } else if (from.y == room.top) { + step.set(0, +1); + } else if (from.y == room.bottom) { + step.set(0, -1); + } + + Point p = new Point(from).offset(step); + for (int i = 0; i < n; i++) { + if (value != -1) { + set(level, p, value); + } + p.offset(step); + } + + return p; + } + +} diff --git a/java/com/hmdzl/spspd/levels/painters/PassagePainter.java b/java/com/hmdzl/spspd/levels/painters/PassagePainter.java new file mode 100644 index 00000000..a6802b7f --- /dev/null +++ b/java/com/hmdzl/spspd/levels/painters/PassagePainter.java @@ -0,0 +1,118 @@ +/* + * 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 + */ +package com.hmdzl.spspd.levels.painters; + +import java.util.ArrayList; +import java.util.Collections; + +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.Room; +import com.watabou.utils.Point; + +public class PassagePainter extends Painter { + + private static int pasWidth; + private static int pasHeight; + + public static void paint(Level level, Room room) { + + pasWidth = room.width() - 2; + pasHeight = room.height() - 2; + + int floor = level.tunnelTile(); + + ArrayList joints = new ArrayList(); + for (Point door : room.connected.values()) { + joints.add(xy2p(room, door)); + } + Collections.sort(joints); + + int nJoints = joints.size(); + int perimeter = pasWidth * 2 + pasHeight * 2; + + int start = 0; + int maxD = joints.get(0) + perimeter - joints.get(nJoints - 1); + for (int i = 1; i < nJoints; i++) { + int d = joints.get(i) - joints.get(i - 1); + if (d > maxD) { + maxD = d; + start = i; + } + } + + int end = (start + nJoints - 1) % nJoints; + + int p = joints.get(start); + do { + set(level, p2xy(room, p), floor); + p = (p + 1) % perimeter; + } while (p != joints.get(end)); + + set(level, p2xy(room, p), floor); + + for (Room.Door door : room.connected.values()) { + door.set(Room.Door.Type.TUNNEL); + } + } + + private static int xy2p(Room room, Point xy) { + if (xy.y == room.top) { + + return (xy.x - room.left - 1); + + } else if (xy.x == room.right) { + + return (xy.y - room.top - 1) + pasWidth; + + } else if (xy.y == room.bottom) { + + return (room.right - xy.x - 1) + pasWidth + pasHeight; + + } else { + + if (xy.y == room.top + 1) { + return 0; + } else { + return (room.bottom - xy.y - 1) + pasWidth * 2 + pasHeight; + } + + } + } + + private static Point p2xy(Room room, int p) { + if (p < pasWidth) { + + return new Point(room.left + 1 + p, room.top + 1); + + } else if (p < pasWidth + pasHeight) { + + return new Point(room.right - 1, room.top + 1 + (p - pasWidth)); + + } else if (p < pasWidth * 2 + pasHeight) { + + return new Point(room.right - 1 - (p - (pasWidth + pasHeight)), + room.bottom - 1); + + } else { + + return new Point(room.left + 1, room.bottom - 1 + - (p - (pasWidth * 2 + pasHeight))); + + } + } +} diff --git a/java/com/hmdzl/spspd/levels/painters/PitPainter.java b/java/com/hmdzl/spspd/levels/painters/PitPainter.java new file mode 100644 index 00000000..e438c285 --- /dev/null +++ b/java/com/hmdzl/spspd/levels/painters/PitPainter.java @@ -0,0 +1,101 @@ +/* + * 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 + */ +package com.hmdzl.spspd.levels.painters; + +import com.hmdzl.spspd.items.Ankh; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.items.Heap.Type; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.scrolls.ScrollOfTeleportation; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.Room; +import com.hmdzl.spspd.levels.Terrain; +import com.hmdzl.spspd.plants.Fadeleaf; +import com.watabou.utils.Point; +import com.watabou.utils.Random; + +public class PitPainter extends Painter { + + public static void paint(Level level, Room room) { + + fill(level, room, Terrain.WALL); + fill(level, room, 1, Terrain.EMPTY); + + Room.Door entrance = room.entrance(); + entrance.set(Room.Door.Type.ONEWAY); + + Point well = null; + if (entrance.x == room.left) { + well = new Point(room.right - 1, Random.Int(2) == 0 ? room.top + 1 + : room.bottom - 1); + } else if (entrance.x == room.right) { + well = new Point(room.left + 1, Random.Int(2) == 0 ? room.top + 1 + : room.bottom - 1); + } else if (entrance.y == room.top) { + well = new Point(Random.Int(2) == 0 ? room.left + 1 + : room.right - 1, room.bottom - 1); + } else if (entrance.y == room.bottom) { + well = new Point(Random.Int(2) == 0 ? room.left + 1 + : room.right - 1, room.top + 1); + } + set(level, well, Terrain.EMPTY_WELL); + + int remains = room.random(); + while (level.map[remains] == Terrain.EMPTY_WELL) { + remains = room.random(); + } + + int sign = room.random(); + while (level.map[sign] == Terrain.EMPTY_WELL || sign == remains) { + sign = room.random(); + } + + level.map[sign] = Terrain.SIGN; + level.pitSign=sign; + + level.drop(new ScrollOfTeleportation(), remains).type = Type.SKELETON; + int loot = Random.Int(3); + if (loot == 0) { + level.drop(Generator.random(Generator.Category.RING), remains); + } else if (loot == 1) { + level.drop(Generator.random(Generator.Category.ARTIFACT), remains); + } else { + level.drop(Generator.random(Random.oneOf(Generator.Category.WEAPON, + Generator.Category.ARMOR)), remains); + } + level.drop(new Ankh(), remains); + level.drop(new Fadeleaf.Seed(), remains); + int n = Random.IntRange(1, 2); + for (int i = 0; i < n; i++) { + level.drop(prize(level), remains); + } + } + + private static Item prize(Level level) { + + if (Random.Int(2) != 0) { + Item prize = level.findPrizeItem(); + if (prize != null) + return prize; + } + + return Generator.random(Random.oneOf(Generator.Category.POTION, + Generator.Category.SCROLL, Generator.Category.FOOD, + Generator.Category.GOLD)); + } +} diff --git a/java/com/hmdzl/spspd/levels/painters/PoolPainter.java b/java/com/hmdzl/spspd/levels/painters/PoolPainter.java new file mode 100644 index 00000000..4d01428f --- /dev/null +++ b/java/com/hmdzl/spspd/levels/painters/PoolPainter.java @@ -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 + */ +package com.hmdzl.spspd.levels.painters; + +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.mobs.Piranha; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.items.Heap; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.potions.PotionOfInvisibility; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.Room; +import com.hmdzl.spspd.levels.Terrain; +import com.watabou.utils.Random; + +public class PoolPainter extends Painter { + + private static final int NPIRANHAS = 4; + + public static void paint(Level level, Room room) { + + fill(level, room, Terrain.WALL); + fill(level, room, 1, Terrain.WATER); + + Room.Door door = room.entrance(); + door.set(Room.Door.Type.REGULAR); + + int x = -1; + int y = -1; + if (door.x == room.left) { + + x = room.right - 1; + y = room.top + room.height() / 2; + + } else if (door.x == room.right) { + + x = room.left + 1; + y = room.top + room.height() / 2; + + } else if (door.y == room.top) { + + x = room.left + room.width() / 2; + y = room.bottom - 1; + + } else if (door.y == room.bottom) { + + x = room.left + room.width() / 2; + y = room.top + 1; + + } + + int pos = x + y * Level.getWidth(); + level.drop(prize(level), pos).type = Random.Int(3) == 0 ? Heap.Type.CHEST + : Heap.Type.HEAP; + set(level, pos, Terrain.PEDESTAL); + + level.addItemToSpawn(new PotionOfInvisibility()); + + for (int i = 0; i < NPIRANHAS; i++) { + Piranha piranha = new Piranha(); + do { + piranha.pos = room.random(); + } while (level.map[piranha.pos] != Terrain.WATER + || Actor.findChar(piranha.pos) != null); + level.mobs.add(piranha); + Actor.occupyCell(piranha); + } + } + + private static Item prize(Level level) { + + Item prize; + + if (Random.Int(3) != 0) { + prize = level.findPrizeItem(); + if (prize != null) + return prize; + } + + prize = Generator.random(Random.oneOf(Generator.Category.WEAPON, + Generator.Category.ARMOR)); + + for (int i = 0; i < 4; i++) { + Item another = Generator.random(Random.oneOf( + Generator.Category.WEAPON, Generator.Category.ARMOR)); + if (another.level > prize.level) { + prize = another; + } + } + + return prize; + } +} diff --git a/java/com/hmdzl/spspd/levels/painters/RatKingPainter.java b/java/com/hmdzl/spspd/levels/painters/RatKingPainter.java new file mode 100644 index 00000000..206326a5 --- /dev/null +++ b/java/com/hmdzl/spspd/levels/painters/RatKingPainter.java @@ -0,0 +1,107 @@ +/* + * 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 + */ +package com.hmdzl.spspd.levels.painters; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.Statistics; +import com.hmdzl.spspd.actors.mobs.npcs.RatKing; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.items.Gold; +import com.hmdzl.spspd.items.Heap; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.journalpages.Town; +import com.hmdzl.spspd.items.weapon.missiles.MissileWeapon; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.Room; +import com.hmdzl.spspd.levels.Terrain; +import com.watabou.utils.Random; + +public class RatKingPainter extends Painter { + + static boolean page = false; + + public static void paint(Level level, Room room) { + + fill(level, room, Terrain.WALL); + fill(level, room, 1, Terrain.EMPTY_SP); + + Room.Door entrance = room.entrance(); + entrance.set(Room.Door.Type.HIDDEN); + int door = entrance.x + entrance.y * Level.getWidth(); + + Dungeon.ratChests=0; + + for (int i = room.left + 1; i < room.right; i++) { + addChest(level, (room.top + 1) * Level.getWidth() + i, door); + addChest(level, (room.bottom - 1) * Level.getWidth() + i, door); + } + + for (int i = room.top + 2; i < room.bottom - 1; i++) { + addChest(level, i * Level.getWidth() + room.left + 1, door); + addChest(level, i * Level.getWidth() + room.right - 1, door); + } + + while (true) { + Heap chest = level.heaps.get(room.random()); + if (chest != null) { + chest.type = Heap.Type.MIMIC; + break; + } + } + + RatKing king = new RatKing(); + king.pos = room.random(1); + level.mobs.add(king); + } + + private static void addChest(Level level, int pos, int door) { + + if (pos == door - 1 || pos == door + 1 || pos == door - Level.getWidth() + || pos == door + Level.getWidth()) { + return; + } + + Item prize; + switch (Random.Int(10)) { + case 0: + prize = Generator.random(Generator.Category.WEAPON); + if (prize instanceof MissileWeapon) { + prize.quantity(1); + } else { + prize.degrade(Random.Int(3)); + } + break; + case 1: + prize = Generator.random(Generator.Category.ARMOR).degrade( + Random.Int(3)); + break; + default: + prize = new Gold(Random.IntRange(1, 5)); + break; + } + + if (!page && Statistics.enemiesSlain<21 && Dungeon.limitedDrops.journal.dropped()){ + level.drop(new Town(), pos); + page=true; + } else { + level.drop(prize, pos).type = Heap.Type.CHEST; + Dungeon.ratChests++; + } + + } +} diff --git a/java/com/hmdzl/spspd/levels/painters/RatKingPainter2.java b/java/com/hmdzl/spspd/levels/painters/RatKingPainter2.java new file mode 100644 index 00000000..667f8ea3 --- /dev/null +++ b/java/com/hmdzl/spspd/levels/painters/RatKingPainter2.java @@ -0,0 +1,106 @@ +/* + * 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 + */ +package com.hmdzl.spspd.levels.painters; + +import com.hmdzl.spspd.actors.mobs.npcs.RatKingDen; +import com.hmdzl.spspd.items.summon.ActiveMrDestructo; +import com.hmdzl.spspd.items.eggs.Egg; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.items.Gold; +import com.hmdzl.spspd.items.Heap; +import com.hmdzl.spspd.items.Item; + +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.Room; +import com.hmdzl.spspd.levels.Terrain; +import com.hmdzl.spspd.plants.Phaseshift; +import com.hmdzl.spspd.plants.Starflower; +import com.watabou.utils.Random; + +public class RatKingPainter2 extends Painter { + + public static void paint(Level level, Room room) { + + fill(level, room, Terrain.WALL); + fill(level, room, 1, Terrain.EMPTY_SP); + + Room.Door entrance = room.entrance(); + entrance.set(Room.Door.Type.HIDDEN); + int door = entrance.x + entrance.y * Level.getWidth(); + + //Dungeon.ratChests=0; + + for (int i = room.left + 1; i < room.right; i++) { + addChest(level, (room.top + 1) * Level.getWidth() + i, door); + addChest(level, (room.bottom - 1) * Level.getWidth() + i, door); + } + + for (int i = room.top + 2; i < room.bottom - 1; i++) { + addChest(level, i * Level.getWidth() + room.left + 1, door); + addChest(level, i * Level.getWidth() + room.right - 1, door); + } + + while (true) { + Heap chest = level.heaps.get(room.random()); + if (chest != null) { + chest.type = Heap.Type.MIMIC; + break; + } + } + + RatKingDen king = new RatKingDen(); + king.pos = room.random(1); + level.mobs.add(king); + } + + private static void addChest(Level level, int pos, int door) { + + if (pos == door - 1 || pos == door + 1 || pos == door - Level.getWidth() + || pos == door + Level.getWidth()) { + return; + } + + Item prize; + switch (Random.Int(10)) { + case 0: + prize = new Egg(); + break; + case 1: + prize = new Phaseshift.Seed(); + break; + case 2: + prize = Generator.random(Generator.Category.BERRY); + break; + case 3: + prize = new Starflower.Seed(); + break; + case 5: + prize = new ActiveMrDestructo(); + break; + case 6: + prize = Generator.random(Generator.Category.BOMBS); + break; + default: + prize = new Gold(Random.IntRange(1, 5)); + break; + } + + level.drop(prize, pos).type = Heap.Type.CHEST; + //Dungeon.ratChests++; + } +} diff --git a/java/com/hmdzl/spspd/levels/painters/ShopPainter.java b/java/com/hmdzl/spspd/levels/painters/ShopPainter.java new file mode 100644 index 00000000..f722d1a7 --- /dev/null +++ b/java/com/hmdzl/spspd/levels/painters/ShopPainter.java @@ -0,0 +1,400 @@ +/* + * 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 + */ +package com.hmdzl.spspd.levels.painters; + +import java.util.ArrayList; +import java.util.Collections; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.hero.Belongings; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.actors.mobs.npcs.ImpShopkeeper; +import com.hmdzl.spspd.actors.mobs.npcs.Shopkeeper; +import com.hmdzl.spspd.items.Ankh; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.items.Heap; +import com.hmdzl.spspd.items.armor.normalarmor.PlateArmor; +import com.hmdzl.spspd.items.summon.ActiveMrDestructo; +import com.hmdzl.spspd.items.summon.FairyCard; +import com.hmdzl.spspd.items.summon.Honeypot; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.DolyaSlate; +import com.hmdzl.spspd.items.Stylus; +import com.hmdzl.spspd.items.Torch; +import com.hmdzl.spspd.items.Weightstone; +import com.hmdzl.spspd.items.challengelists.CourageChallenge; +import com.hmdzl.spspd.items.challengelists.PowerChallenge; +import com.hmdzl.spspd.items.challengelists.WisdomChallenge; +import com.hmdzl.spspd.items.food.staplefood.Pasty; +import com.hmdzl.spspd.items.journalpages.Town; +import com.hmdzl.spspd.items.journalpages.SafeSpotPage; +import com.hmdzl.spspd.items.armor.normalarmor.DiscArmor; +import com.hmdzl.spspd.items.armor.normalarmor.MailArmor; +import com.hmdzl.spspd.items.armor.normalarmor.ScaleArmor; +import com.hmdzl.spspd.items.artifacts.TimekeepersHourglass; +import com.hmdzl.spspd.items.bags.PotionBandolier; +import com.hmdzl.spspd.items.bags.ScrollHolder; +import com.hmdzl.spspd.items.bags.SeedPouch; +import com.hmdzl.spspd.items.bags.WandHolster; +import com.hmdzl.spspd.items.potions.Potion; +import com.hmdzl.spspd.items.potions.PotionOfHealing; +import com.hmdzl.spspd.items.scrolls.Scroll; +import com.hmdzl.spspd.items.scrolls.ScrollOfMagicMapping; +import com.hmdzl.spspd.items.summon.Mobile; +import com.hmdzl.spspd.items.wands.Wand; +import com.hmdzl.spspd.items.weapon.guns.GunA; +import com.hmdzl.spspd.items.weapon.guns.GunB; +import com.hmdzl.spspd.items.weapon.guns.GunC; +import com.hmdzl.spspd.items.weapon.guns.GunD; +import com.hmdzl.spspd.items.weapon.guns.GunE; +import com.hmdzl.spspd.items.weapon.melee.special.KeyWeapon; +import com.hmdzl.spspd.items.weapon.missiles.PocketBall; +import com.hmdzl.spspd.levels.LastShopLevel; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.Room; +import com.hmdzl.spspd.levels.Terrain; +import com.hmdzl.spspd.plants.Plant; +import com.watabou.utils.Point; +import com.watabou.utils.Random; + +public class ShopPainter extends Painter { + + private static int pasWidth; + private static int pasHeight; + + private static ArrayList itemsToSpawn; + + public static void paint(Level level, Room room) { + + fill(level, room, Terrain.WALL); + fill(level, room, 1, Terrain.EMPTY_SP); + + pasWidth = room.width() - 2; + pasHeight = room.height() - 2; + int per = pasWidth * 2 + pasHeight * 2; + + if (itemsToSpawn == null) + generateItems(); + + int pos = xy2p(room, room.entrance()) + (per - itemsToSpawn.size()) / 2; + for (Item item : itemsToSpawn) { + + Point xy = p2xy(room, (pos + per) % per); + int cell = xy.x + xy.y * Level.getWidth(); + + if (level.heaps.get(cell) != null) { + do { + cell = room.random(); + } while (level.heaps.get(cell) != null); + } + + level.drop(item, cell).type = Heap.Type.FOR_SALE; + + pos++; + } + + placeShopkeeper(level, room); + + for (Room.Door door : room.connected.values()) { + door.set(Room.Door.Type.REGULAR); + } + + itemsToSpawn = null; + } + + private static void generateItems() { + + itemsToSpawn = new ArrayList(); + + switch (Dungeon.depth) { + case 1: + itemsToSpawn.add(new GunA().identify()); + //itemsToSpawn.add(new MiniMoai().identify()); + itemsToSpawn.add(new KeyWeapon()); + itemsToSpawn.add(new DolyaSlate().identify()); + itemsToSpawn.add(new Pasty()); + //itemsToSpawn.add(new UnstableSpellbook()); + Dungeon.limitedDrops.journal.drop(); + break; + + case 6: + itemsToSpawn.add(new SafeSpotPage().identify()); + Dungeon.limitedDrops.safespotpage.drop(); + itemsToSpawn.add(new GunB().identify()); + itemsToSpawn.add(new DiscArmor().identify()); + break; + + case 11: + itemsToSpawn.add(new Town().identify()); + Dungeon.limitedDrops.town.drop(); + itemsToSpawn.add(new GunC().identify()); + itemsToSpawn.add(new MailArmor().identify()); + break; + + case 16: + itemsToSpawn.add(new GunD().identify()); + itemsToSpawn.add(new ScaleArmor().identify()); + break; + + case 21: + //itemsToSpawn.add(Random.Int(2) == 0 ? new Glaive().identify() + // : new WarHammer().identify()); + //itemsToSpawn.add(Random.Int(2) == 0 ? new Bola().quantity(Random + // .NormalIntRange(4, 7)) : new Tamahawk().quantity(Random + // .NormalIntRange(4, 7))); + //itemsToSpawn.add(new PlateArmor().identify()); + //itemsToSpawn.add(new Torch()); + itemsToSpawn.add(new GunE().identify()); + itemsToSpawn.add(new PlateArmor().identify()); + itemsToSpawn.add(new CourageChallenge()); + itemsToSpawn.add(new PowerChallenge()); + itemsToSpawn.add(new WisdomChallenge()); + break; + } + + ChooseBag(Dungeon.hero.belongings); + + itemsToSpawn.add(new PotionOfHealing()); + for (int i = 0; i < 2; i++) + itemsToSpawn.add(Generator.random(Generator.Category.POTION)); + + //itemsToSpawn.add(new ScrollOfIdentify()); + //itemsToSpawn.add(new ScrollOfRemoveCurse()); + itemsToSpawn.add(new ScrollOfMagicMapping()); + for (int i = 0; i < 2; i++) + itemsToSpawn.add(Generator.random(Generator.Category.SCROLL)); + itemsToSpawn.add(new PocketBall()); + itemsToSpawn.add(Generator.random(Generator.Category.BOMBS)); + //for (int i = 0; i < 2; i++) + itemsToSpawn.add(Random.Int(2) == 0 ? + Generator.random(Generator.Category.POTION): + Generator.random(Generator.Category.SCROLL)); + for (int i = 0; i < 2; i++) + itemsToSpawn.add(Generator.random(Generator.Category.RANGEWEAPON)); + itemsToSpawn.add(Generator.random(Generator.Category.MELEEWEAPON)); + //itemsToSpawn.add(new DungeonBomb().random()); + switch (Random.Int(8)) { + case 1: + itemsToSpawn.add(new ActiveMrDestructo()); + break; + case 2: + itemsToSpawn.add(new FairyCard()); + break; + case 3: + itemsToSpawn.add(new Mobile()); + break; + case 4: + itemsToSpawn.add(new Honeypot()); + break; + case 5: + case 6: + case 7: + itemsToSpawn.add(new Torch()); + break; + } + + //if (Dungeon.depth == 6) { + itemsToSpawn.add(new Ankh()); + itemsToSpawn.add(new Weightstone()); + //} else { + //itemsToSpawn.add(Random.Int(2) == 0 ? new Ankh() + //: new Weightstone()); + //} + + TimekeepersHourglass hourglass = Dungeon.hero.belongings + .getItem(TimekeepersHourglass.class); + if (hourglass != null) { + int bags = 0; + // creates the given float percent of the remaining bags to be + // dropped. + // this way players who get the hourglass late can still max it, + // usually. + switch (Dungeon.depth) { + case 6: + bags = (int) Math.ceil((5 - hourglass.sandBags) * 0.20f); + break; + case 11: + bags = (int) Math.ceil((5 - hourglass.sandBags) * 0.25f); + break; + case 16: + bags = (int) Math.ceil((5 - hourglass.sandBags) * 0.50f); + break; + case 21: + bags = (int) Math.ceil((5 - hourglass.sandBags) * 0.80f); + break; + } + + for (int i = 1; i <= bags; i++) { + itemsToSpawn.add(new TimekeepersHourglass.sandBag()); + hourglass.sandBags++; + } + } + + Item rare; + switch (Random.Int(4)) { + case 0: + rare = Generator.random(Generator.Category.WAND); + rare.level = 0; + break; + case 1: + rare = Generator.random(Generator.Category.RING); + rare.level = 1; + break; + case 2: + rare = Generator.random(Generator.Category.ARTIFACT).identify(); + break; + default: + rare = new Stylus(); + } + rare.cursed = rare.cursedKnown = false; + itemsToSpawn.add(rare); + + // this is a hard limit, level gen allows for at most an 8x5 room, can't + // fit more than 39 items + 1 shopkeeper. + if (itemsToSpawn.size() > 39) + throw new RuntimeException( + "Shop attempted to carry more than 39 items!"); + + Collections.shuffle(itemsToSpawn); + } + + private static void ChooseBag(Belongings pack) { + // FIXME: this whole method is pretty messy to accomplish a fairly + // simple logic goal. Should be a better way. + + // there is a bias towards giving certain bags earlier, seen here + int seeds = 10, scrolls = 1, potions = 1, wands = 0; + + // we specifically only want to look at items in the main bag, none of + // the sub-bags. + for (Item item : pack.backpack.items) { + if (item instanceof Plant.Seed) + seeds++; + else if (item instanceof Scroll) + scrolls++; + else if (item instanceof Potion) + potions++; + else if (item instanceof Wand) + wands++; + } + // kill our counts for bags that have already been dropped. + if (Dungeon.limitedDrops.seedBag.dropped()) + seeds = 0; + if (Dungeon.limitedDrops.scrollBag.dropped()) + scrolls = 0; + if (Dungeon.limitedDrops.potionBag.dropped()) + potions = 0; + if (Dungeon.limitedDrops.wandBag.dropped()) + wands = 0; + + // then pick whichever valid bag has the most items available to put + // into it. + if (seeds >= scrolls && seeds >= potions && seeds >= wands + && !Dungeon.limitedDrops.seedBag.dropped()) { + Dungeon.limitedDrops.seedBag.drop(); + itemsToSpawn.add(new SeedPouch()); + } else if (scrolls >= potions && scrolls >= wands + && !Dungeon.limitedDrops.scrollBag.dropped()) { + Dungeon.limitedDrops.scrollBag.drop(); + itemsToSpawn.add(new ScrollHolder()); + } else if (potions >= wands + && !Dungeon.limitedDrops.potionBag.dropped()) { + Dungeon.limitedDrops.potionBag.drop(); + itemsToSpawn.add(new PotionBandolier()); + } else if (!Dungeon.limitedDrops.wandBag.dropped()) { + Dungeon.limitedDrops.wandBag.drop(); + itemsToSpawn.add(new WandHolster()); + } + } + + public static int spaceNeeded() { + if (itemsToSpawn == null) + generateItems(); + + // plus one for the shopkeeper + return itemsToSpawn.size() + 1; + } + + private static void placeShopkeeper(Level level, Room room) { + + int pos; + do { + pos = room.random(); + } while (level.heaps.get(pos) != null); + + Mob shopkeeper = level instanceof LastShopLevel ? new ImpShopkeeper() + : new Shopkeeper(); + shopkeeper.pos = pos; + level.mobs.add(shopkeeper); + + if (level instanceof LastShopLevel) { + for (int i = 0; i < Level.NEIGHBOURS9.length; i++) { + int p = shopkeeper.pos + Level.NEIGHBOURS9[i]; + if (level.map[p] == Terrain.EMPTY_SP) { + level.map[p] = Terrain.WATER; + } + } + } + } + + private static int xy2p(Room room, Point xy) { + if (xy.y == room.top) { + + return (xy.x - room.left - 1); + + } else if (xy.x == room.right) { + + return (xy.y - room.top - 1) + pasWidth; + + } else if (xy.y == room.bottom) { + + return (room.right - xy.x - 1) + pasWidth + pasHeight; + + } else { + + if (xy.y == room.top + 1) { + return 0; + } else { + return (room.bottom - xy.y - 1) + pasWidth * 2 + pasHeight; + } + + } + } + + private static Point p2xy(Room room, int p) { + if (p < pasWidth) { + + return new Point(room.left + 1 + p, room.top + 1); + + } else if (p < pasWidth + pasHeight) { + + return new Point(room.right - 1, room.top + 1 + (p - pasWidth)); + + } else if (p < pasWidth * 2 + pasHeight) { + + return new Point(room.right - 1 - (p - (pasWidth + pasHeight)), + room.bottom - 1); + + } else { + + return new Point(room.left + 1, room.bottom - 1 + - (p - (pasWidth * 2 + pasHeight))); + + } + } +} diff --git a/java/com/hmdzl/spspd/levels/painters/StandardPainter.java b/java/com/hmdzl/spspd/levels/painters/StandardPainter.java new file mode 100644 index 00000000..1cfc89e5 --- /dev/null +++ b/java/com/hmdzl/spspd/levels/painters/StandardPainter.java @@ -0,0 +1,453 @@ +/* + * 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 + */ +package com.hmdzl.spspd.levels.painters; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.blobs.weather.WeatherOfDead; +import com.hmdzl.spspd.actors.blobs.weather.WeatherOfQuite; +import com.hmdzl.spspd.actors.blobs.weather.WeatherOfRain; +import com.hmdzl.spspd.actors.blobs.weather.WeatherOfSand; +import com.hmdzl.spspd.actors.blobs.weather.WeatherOfSnow; +import com.hmdzl.spspd.actors.blobs.weather.WeatherOfSun; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.items.Gold; +import com.hmdzl.spspd.items.Heap; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.Room; +import com.hmdzl.spspd.levels.Terrain; +import com.hmdzl.spspd.levels.traps.FireTrap; +import com.watabou.utils.Point; +import com.watabou.utils.Random; + +public class StandardPainter extends Painter { + + public static void paint(Level level, Room room) { + + fill(level, room, Terrain.WALL); + for (Room.Door door : room.connected.values()) { + door.set(Room.Door.Type.REGULAR); + } + + if (Dungeon.depth==31){ + if (Math.min(room.width(), room.height()) >= 4 + && Math.max(room.width(), room.height()) >= 6) { + paintGraveyard(level, room); + return; + } + } + if (Dungeon.depth==32){ + if (Math.min(room.width(), room.height()) >= 4 + && Math.max(room.width(), room.height()) >= 6) { + paintStriped(level, room); + return; + } + } + if (Dungeon.depth==33){ + if (Math.min(room.width(), room.height()) >= 4 + && Math.max(room.width(), room.height()) >= 6) { + paintStudy(level, room); + return; + } + } + + if (!Dungeon.bossLevel() && Random.Int(5) == 0) { + switch (Random.Int(7)) { + case 0: + if (level.feeling != Level.Feeling.GRASS) { + if (Math.min(room.width(), room.height()) >= 4 + && Math.max(room.width(), room.height()) >= 6) { + paintGraveyard(level, room); + return; + } + break; + } else { + // Burned room + } + case 1: + if (Dungeon.depth > 1) { + paintBurned(level, room); + return; + } + break; + case 2: + if (Math.max(room.width(), room.height()) >= 4) { + paintStriped(level, room); + return; + } + break; + case 3: + if (room.width() >= 6 && room.height() >= 6) { + paintStudy(level, room); + return; + } + break; + case 4: + if (room.width() >= 6 && room.height() >= 6) { + paintStudy2(level, room); + return; + } + break; + case 5: + if (level.feeling != Level.Feeling.WATER) { + if (room.connected.size() == 2 && room.width() >= 4 + && room.height() >= 4) { + paintBridge(level, room); + return; + } + break; + } else { + // Fissure + } + case 6: + if (!Dungeon.bossLevel() + && !Dungeon.bossLevel(Dungeon.depth + 1) + && (Dungeon.depth < 22 || Dungeon.depth > 100) + && !Dungeon.townCheck(Dungeon.depth) + && Math.min(room.width(), room.height()) >= 5) { + paintFissure(level, room); + return; + } + break; + } + } + + fill(level, room, 1, Terrain.EMPTY); + + if (!Dungeon.bossLevel() && Random.Int(5) == 0) { + switch (Random.Int(4)) { + case 0: + WeatherOfRain rain = (WeatherOfRain) level.blobs.get(WeatherOfRain.class); + if (rain == null) { + rain = new WeatherOfRain(); + } + for (int i = room.top + 1; i < room.bottom; i++) { + for (int j = room.left + 1; j < room.right; j++) { + rain.seed(j + Level.getWidth() * i, 1); + } + } + level.blobs.put(WeatherOfRain.class, rain); + break; + case 1: + WeatherOfSand sand = (WeatherOfSand) level.blobs.get(WeatherOfSand.class); + if (sand == null) { + sand = new WeatherOfSand(); + } + for (int i = room.top + 1; i < room.bottom; i++) { + for (int j = room.left + 1; j < room.right; j++) { + sand.seed(j + Level.getWidth() * i, 1); + } + } + level.blobs.put(WeatherOfSand.class, sand); + break; + case 2: + WeatherOfSnow snow = (WeatherOfSnow) level.blobs.get(WeatherOfSnow.class); + if (snow == null) { + snow = new WeatherOfSnow(); + } + for (int i = room.top + 1; i < room.bottom; i++) { + for (int j = room.left + 1; j < room.right; j++) { + snow.seed(j + Level.getWidth() * i, 1); + } + } + level.blobs.put(WeatherOfSnow.class, snow); + break; + case 3: + WeatherOfSun sun = (WeatherOfSun) level.blobs.get(WeatherOfSun.class); + if (sun == null) { + sun = new WeatherOfSun(); + } + for (int i = room.top + 1; i < room.bottom; i++) { + for (int j = room.left + 1; j < room.right; j++) { + sun.seed(j + Level.getWidth() * i, 1); + } + } + level.blobs.put(WeatherOfSun.class, sun); + break; + + } + } + } + + private static void paintBurned(Level level, Room room) { + for (int i = room.top + 1; i < room.bottom; i++) { + for (int j = room.left + 1; j < room.right; j++) { + int cell = i * Level.WIDTH + j; + int t = Terrain.EMBERS; + switch (Random.Int(5)) { + case 0: + t = Terrain.EMPTY; + break; + case 1: + t = Terrain.TRAP; + level.setTrap(new FireTrap().reveal(), cell); + break; + case 2: + t = Terrain.SECRET_TRAP; + level.setTrap(new FireTrap().hide(), cell); + break; + case 3: + t = Terrain.INACTIVE_TRAP; + FireTrap trap = new FireTrap(); + trap.reveal().active = false; + level.setTrap(trap, cell); + break; + } + level.map[i * Level.getWidth() + j] = t; + } + } + } + + private static void paintGraveyard(Level level, Room room) { + fill(level, room.left + 1, room.top + 1, room.width() - 1, + room.height() - 1, Terrain.GRASS); + + int w = room.width() - 1; + int h = room.height() - 1; + int nGraves = Math.max(w, h) / 2; + + int index = Random.Int(nGraves); + + int shift = Random.Int(2); + for (int i = 0; i < nGraves; i++) { + int pos = w > h ? room.left + 1 + shift + i * 2 + + (room.top + 2 + Random.Int(h - 2)) * Level.getWidth() + : (room.left + 2 + Random.Int(w - 2)) + + (room.top + 1 + shift + i * 2) * Level.getWidth(); + level.drop(i == index ? Generator.random() : new Gold().random(), + pos).type = Heap.Type.TOMB; + } + + if (Random.Int(10)==0){ + WeatherOfDead light = (WeatherOfDead) level.blobs.get(WeatherOfDead.class); + if (light == null) { + light = new WeatherOfDead(); + } + for (int i = room.top + 1; i < room.bottom; i++) { + for (int j = room.left + 1; j < room.right; j++) { + light.seed(j + Level.getWidth() * i, 1); + } + } + level.blobs.put(WeatherOfDead.class, light); + } + + } + + private static void paintStriped(Level level, Room room) { + fill(level, room.left + 1, room.top + 1, room.width() - 1, + room.height() - 1, Terrain.EMPTY_SP); + + if (room.width() > room.height()) { + for (int i = room.left + 2; i < room.right; i += 2) { + fill(level, i, room.top + 1, 1, room.height() - 1, + Terrain.HIGH_GRASS); + } + } else { + for (int i = room.top + 2; i < room.bottom; i += 2) { + fill(level, room.left + 1, i, room.width() - 1, 1, + Terrain.HIGH_GRASS); + } + } + } + + // TODO: this is almost a special room type now, consider moving this into + // its own painter if/when you address room gen significantly. + private static void paintStudy(Level level, Room room) { + fill(level, room.left + 1, room.top + 1, room.width() - 1, + room.height() - 1, Terrain.BOOKSHELF); + fill(level, room.left + 2, room.top + 2, room.width() - 3, + room.height() - 3, Terrain.EMPTY_SP); + + for (Point door : room.connected.values()) { + if (door.x == room.left) { + set(level, door.x + 1, door.y, Terrain.EMPTY); + } else if (door.x == room.right) { + set(level, door.x - 1, door.y, Terrain.EMPTY); + } else if (door.y == room.top) { + set(level, door.x, door.y + 1, Terrain.EMPTY); + } else if (door.y == room.bottom) { + set(level, door.x, door.y - 1, Terrain.EMPTY); + } + } + Point center = room.center(); + set(level, center, Terrain.PEDESTAL); + if (Random.Int(2) != 0) { + Item prize = level.findPrizeItem(); + if (prize != null) { + level.drop(prize, (room.center().x + center.y * Level.getWidth())); + return; + } + } + + level.drop(Generator.random(Random.oneOf(Generator.Category.POTION, + Generator.Category.SCROLL)), (room.center().x + center.y + * Level.getWidth())); + + if (Random.Int(5)==0){ + WeatherOfQuite light = (WeatherOfQuite) level.blobs.get(WeatherOfQuite.class); + if (light == null) { + light = new WeatherOfQuite(); + } + for (int i = room.top + 1; i < room.bottom; i++) { + for (int j = room.left + 1; j < room.right; j++) { + light.seed(j + Level.getWidth() * i, 1); + } + } + level.blobs.put(WeatherOfQuite.class, light); } + + } + + private static void paintStudy2( Level level, Room room ) { + + fill( level, room.left + 1, room.top + 1, room.width() - 1, room.height() - 1 , Terrain.EMPTY_SP ); + + if (room.width() > room.height()) { + for (int i=room.left + 2; i < room.right; i += 2) { + fill( level, i, room.top + 2, 1, room.height() - 3, Terrain.BOOKSHELF ); + } + } else { + for (int i=room.top + 2; i < room.bottom; i += 2) { + fill( level, room.left + 2, i, room.width() - 3, 1, Terrain.BOOKSHELF ); + } + } + +// fill( bonus, room.left + 1, room.top + 1, room.width() - 1, room.height() - 1 , Terrain.SHELF_EMPTY ); +// fill( bonus, room.left + 2, room.top + 2, room.width() - 3, room.height() - 3 , Terrain.EMPTY_SP ); +// + for (Point door : room.connected.values()) { + if (door.x == room.left) { + set( level, door.x + 1, door.y, Terrain.EMPTY_SP ); + } else if (door.x == room.right) { + set( level, door.x - 1, door.y, Terrain.EMPTY_SP ); + } else if (door.y == room.top) { + set( level, door.x, door.y + 1, Terrain.EMPTY_SP ); + } else if (door.y == room.bottom) { + set( level, door.x , door.y - 1, Terrain.EMPTY_SP ); + } + } + + if (Random.Int(5)==0){ + WeatherOfQuite light = (WeatherOfQuite) level.blobs.get(WeatherOfQuite.class); + if (light == null) { + light = new WeatherOfQuite(); + } + for (int i = room.top + 1; i < room.bottom; i++) { + for (int j = room.left + 1; j < room.right; j++) { + light.seed(j + Level.getWidth() * i, 1); + } + } + level.blobs.put(WeatherOfQuite.class, light);} + +// set( bonus, room.center(), Terrain.PEDESTAL ); + } + + private static void paintBridge(Level level, Room room) { + + if( room.connected.size() == 2 ) { + + fill(level, room.left + 1, room.top + 1, room.width() - 1, + room.height() - 1, + !Dungeon.bossLevel() && !Dungeon.bossLevel(Dungeon.depth + 1) && (Dungeon.depth < 22 || Dungeon.depth > 26) + && !Dungeon.townCheck(Dungeon.depth) + && Random.Int(3) == 0 ? Terrain.TRAP_AIR : Terrain.WATER); + + Point door1 = null; + Point door2 = null; + for (Point p : room.connected.values()) { + if (door1 == null) { + door1 = p; + } else { + door2 = p; + } + } + + if ((door1.x == room.left && door2.x == room.right) + || (door1.x == room.right && door2.x == room.left)) { + + int s = room.width() / 2; + + drawInside(level, room, door1, s, Terrain.EMPTY_SP); + drawInside(level, room, door2, s, Terrain.EMPTY_SP); + fill(level, room.center().x, Math.min(door1.y, door2.y), 1, + Math.abs(door1.y - door2.y) + 1, Terrain.EMPTY_SP); + + } else if ((door1.y == room.top && door2.y == room.bottom) + || (door1.y == room.bottom && door2.y == room.top)) { + + int s = room.height() / 2; + + drawInside(level, room, door1, s, Terrain.EMPTY_SP); + drawInside(level, room, door2, s, Terrain.EMPTY_SP); + fill(level, Math.min(door1.x, door2.x), room.center().y, + Math.abs(door1.x - door2.x) + 1, 1, Terrain.EMPTY_SP); + + } else if (door1.x == door2.x) { + + fill(level, door1.x == room.left ? room.left + 1 : room.right - 1, + Math.min(door1.y, door2.y), 1, + Math.abs(door1.y - door2.y) + 1, Terrain.EMPTY_SP); + + } else if (door1.y == door2.y) { + + fill(level, Math.min(door1.x, door2.x), + door1.y == room.top ? room.top + 1 : room.bottom - 1, + Math.abs(door1.x - door2.x) + 1, 1, Terrain.EMPTY_SP); + + } else if (door1.y == room.top || door1.y == room.bottom) { + + drawInside(level, room, door1, Math.abs(door1.y - door2.y), + Terrain.EMPTY_SP); + drawInside(level, room, door2, Math.abs(door1.x - door2.x), + Terrain.EMPTY_SP); + + } else if (door1.x == room.left || door1.x == room.right) { + + drawInside(level, room, door1, Math.abs(door1.x - door2.x), + Terrain.EMPTY_SP); + drawInside(level, room, door2, Math.abs(door1.y - door2.y), + Terrain.EMPTY_SP); + + } + } else { + fill( level, room.left + 1, room.top + 1, room.width() - 1, room.height() - 1, Terrain.EMPTY_SP ); + + fill( level, room.left + 2, room.top + 2, room.width() - 3, room.height() - 3, + level.feeling == Level.Feeling.WATER ? + Terrain.WATER : Terrain.CHASM ); + } + + for (Room.Door door : room.connected.values()) { + door.set( Room.Door.Type.REGULAR ); + } + } + + private static void paintFissure(Level level, Room room) { + fill(level, room.left + 1, room.top + 1, room.width() - 1, + room.height() - 1, Terrain.EMPTY); + + for (int i = room.top + 2; i < room.bottom - 1; i++) { + for (int j = room.left + 2; j < room.right - 1; j++) { + int v = Math.min(i - room.top, room.bottom - i); + int h = Math.min(j - room.left, room.right - j); + if (Math.min(v, h) > 2 || Random.Int(2) == 0) { + set(level, j, i, Terrain.CHASM); + } + } + } + } +} diff --git a/java/com/hmdzl/spspd/levels/painters/StatuePainter.java b/java/com/hmdzl/spspd/levels/painters/StatuePainter.java new file mode 100644 index 00000000..521a4a0c --- /dev/null +++ b/java/com/hmdzl/spspd/levels/painters/StatuePainter.java @@ -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 + */ +package com.hmdzl.spspd.levels.painters; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.mobs.Statue; +import com.hmdzl.spspd.items.keys.IronKey; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.Room; +import com.hmdzl.spspd.levels.Terrain; +import com.watabou.utils.Point; + +public class StatuePainter extends Painter { + + public static void paint(Level level, Room room) { + + fill(level, room, Terrain.WALL); + fill(level, room, 1, Terrain.EMPTY); + + Point c = room.center(); + int cx = c.x; + int cy = c.y; + + Room.Door door = room.entrance(); + + door.set(Room.Door.Type.LOCKED); + level.addItemToSpawn(new IronKey(Dungeon.depth)); + + if (door.x == room.left) { + + fill(level, room.right - 1, room.top + 1, 1, room.height() - 1, + Terrain.STATUE); + cx = room.right - 2; + + } else if (door.x == room.right) { + + fill(level, room.left + 1, room.top + 1, 1, room.height() - 1, + Terrain.STATUE); + cx = room.left + 2; + + } else if (door.y == room.top) { + + fill(level, room.left + 1, room.bottom - 1, room.width() - 1, 1, + Terrain.STATUE); + cy = room.bottom - 2; + + } else if (door.y == room.bottom) { + + fill(level, room.left + 1, room.top + 1, room.width() - 1, 1, + Terrain.STATUE); + cy = room.top + 2; + + } + + Statue statue = new Statue(); + statue.pos = cx + cy * Level.getWidth(); + level.mobs.add(statue); + Actor.occupyCell(statue); + } +} diff --git a/java/com/hmdzl/spspd/levels/painters/StoragePainter.java b/java/com/hmdzl/spspd/levels/painters/StoragePainter.java new file mode 100644 index 00000000..f31ed8ab --- /dev/null +++ b/java/com/hmdzl/spspd/levels/painters/StoragePainter.java @@ -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 + */ +package com.hmdzl.spspd.levels.painters; + +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.items.Heap; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.potions.PotionOfLiquidFlame; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.Room; +import com.hmdzl.spspd.levels.Terrain; +import com.watabou.utils.Random; + +public class StoragePainter extends Painter { + + public static void paint( Level level, Room room ) { + + final int floor = Terrain.EMPTY_SP; + + fill( level, room, Terrain.WALL ); + fill( level, room, 1, floor ); + + Room.Door entrance = room.entrance(); + + if (entrance.x == room.left) { + fill( level, room.right - 1, room.top + 1, 1, room.height() - 1 , Terrain.EMPTY ); + fill( level, room.right - 2, room.top + 1, 1, room.height() - 1 , Terrain.BOOKSHELF ); + } else if (entrance.x == room.right) { + fill( level, room.left + 1, room.top + 1, 1, room.height() - 1 , Terrain.EMPTY ); + fill( level, room.left + 2, room.top + 1, 1, room.height() - 1 , Terrain.BOOKSHELF ); + } else if (entrance.y == room.top) { + fill( level, room.left + 1, room.bottom - 1, room.width() - 1, 1 , Terrain.EMPTY ); + fill( level, room.left + 1, room.bottom - 2, room.width() - 1, 1 , Terrain.BOOKSHELF ); + } else if (entrance.y == room.bottom) { + fill( level, room.left + 1, room.top + 1, room.width() - 1, 1 , Terrain.EMPTY ); + fill( level, room.left + 1, room.top + 2, room.width() - 1, 1 , Terrain.BOOKSHELF ); + } + + int n = 2 + Random.Int( 3 ); + for (int i=0; i < n; i++) { + int pos; + do { + pos = room.random(); + } while (level.map[pos] != Terrain.EMPTY); + level.drop( prize( level ), pos ).type = Heap.Type.SKELETON; + } + + int pos; + do { + pos = room.random(); + } while (level.map[pos] != floor); + level.drop( prize( level ), pos ).type = Heap.Type.CHEST; + + room.entrance().set( Room.Door.Type.REGULAR ); + level.addItemToSpawn( new PotionOfLiquidFlame() ); + } + + private static Item prize( Level level ) { + + Item prize = Generator.random(); + + if (prize != null) { + return prize; + } + + return Generator.random( Random.oneOf( + Generator.Category.POTION, + Generator.Category.SCROLL, + Generator.Category.GOLD, + Generator.Category.WAND + ) ); + } +} diff --git a/java/com/hmdzl/spspd/levels/painters/TrapsPainter.java b/java/com/hmdzl/spspd/levels/painters/TrapsPainter.java new file mode 100644 index 00000000..207ab1e5 --- /dev/null +++ b/java/com/hmdzl/spspd/levels/painters/TrapsPainter.java @@ -0,0 +1,153 @@ +/* + * 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 + */ +package com.hmdzl.spspd.levels.painters; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.ShatteredPixelDungeon; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.items.Heap; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.potions.PotionOfLevitation; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.Room; +import com.hmdzl.spspd.levels.Terrain; +import com.hmdzl.spspd.levels.traps.*; +import com.watabou.utils.Random; + +public class TrapsPainter extends Painter { + + public static void paint(Level level, Room room) { + + fill( level, room, Terrain.WALL ); + + Class trapClass; + switch (Random.Int(5)){ + case 0: default: + trapClass = SpearTrap.class; + break; + case 1: + trapClass = !Dungeon.bossLevel(Dungeon.depth + 1)? null : SummoningTrap.class; + break; + case 2: case 3: case 4: + trapClass = Random.oneOf(trapType); + break; + } + + if (trapClass == null){ + Painter.fill(level, room, 1, Terrain.CHASM); + } else { + Painter.fill(level, room, 1, Terrain.TRAP); + } + + Room.Door door = room.entrance(); + door.set(Room.Door.Type.REGULAR); + + int lastRow = level.map[room.left + 1 + (room.top + 1) * Level.getWidth()] == Terrain.CHASM ? Terrain.CHASM + : Terrain.EMPTY; + + int x = -1; + int y = -1; + if (door.x == room.left) { + x = room.right - 1; + y = room.top + room.height() / 2; + fill(level, x, room.top + 1, 1, room.height() - 1, lastRow); + } else if (door.x == room.right) { + x = room.left + 1; + y = room.top + room.height() / 2; + fill(level, x, room.top + 1, 1, room.height() - 1, lastRow); + } else if (door.y == room.top) { + x = room.left + room.width() / 2; + y = room.bottom - 1; + fill(level, room.left + 1, y, room.width() - 1, 1, lastRow); + } else if (door.y == room.bottom) { + x = room.left + room.width() / 2; + y = room.top + 1; + fill(level, room.left + 1, y, room.width() - 1, 1, lastRow); + } + + for(int cell : room.getCells()) { + if (level.map[cell] == Terrain.TRAP){ + try { + level.setTrap(((Trap) trapClass.newInstance()).reveal(), cell); + } catch (Exception e) { + ShatteredPixelDungeon.reportException(e); + } + } + } + + int pos = x + y * Level.getWidth(); + if (Random.Int(3) == 0) { + if (lastRow == Terrain.CHASM) { + set(level, pos, Terrain.EMPTY); + } + level.drop(prize(level), pos).type = Heap.Type.CHEST; + } else { + set(level, pos, Terrain.PEDESTAL); + level.drop(prize(level), pos); + } + + level.addItemToSpawn(new PotionOfLevitation()); + } + + private static Item prize(Level level) { + + Item prize; + + if (Random.Int(4) != 0) { + prize = level.findPrizeItem(); + if (prize != null) + return prize; + } + + prize = Generator.random(Random.oneOf(Generator.Category.WEAPON, + Generator.Category.ARMOR)); + + for (int i = 0; i < 3; i++) { + Item another = Generator.random(Random.oneOf( + Generator.Category.WEAPON, Generator.Category.ARMOR)); + if (another.level > prize.level) { + prize = another; + } + } + + return prize; + } + + /*@SuppressWarnings("unchecked") + private static Class[][] levelTraps = new Class[][]{ + //sewers + {ToxicTrap.class, TeleportationTrap.class, FlockTrap.class}, + //prison + {ConfusionTrap.class, ExplosiveTrap.class, ParalyticTrap.class}, + //caves + {BlazingTrap.class, VenomTrap.class, ExplosiveTrap.class}, + //city + {WarpingTrap.class, VenomTrap.class, DisintegrationTrap.class}, + //halls, muahahahaha + {GrimTrap.class} + };*/ + @SuppressWarnings("unchecked") + private static Class[] trapType = new Class[]{ + ToxicTrap.class, TeleportationTrap.class, FlockTrap.class, + ConfusionTrap.class, ExplosiveTrap.class, ParalyticTrap.class, + BlazingTrap.class, VenomTrap.class, ExplosiveTrap.class, + WarpingTrap.class, DisintegrationTrap.class, + GrimTrap.class,SpearTrap.class, + !Dungeon.bossLevel(Dungeon.depth + 1)? null : SummoningTrap.class}; + +} diff --git a/java/com/hmdzl/spspd/levels/painters/TreasuryPainter.java b/java/com/hmdzl/spspd/levels/painters/TreasuryPainter.java new file mode 100644 index 00000000..e51e4c98 --- /dev/null +++ b/java/com/hmdzl/spspd/levels/painters/TreasuryPainter.java @@ -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 + */ +package com.hmdzl.spspd.levels.painters; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.items.Gold; +import com.hmdzl.spspd.items.Heap; +import com.hmdzl.spspd.items.keys.IronKey; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.Room; +import com.hmdzl.spspd.levels.Terrain; +import com.watabou.utils.Random; + +public class TreasuryPainter extends Painter { + + public static void paint(Level level, Room room) { + + fill(level, room, Terrain.WALL); + fill(level, room, 1, Terrain.EMPTY); + + set(level, room.center(), Terrain.STATUE); + + Heap.Type heapType = Random.Int(2) == 0 ? Heap.Type.CHEST + : Heap.Type.HEAP; + + int n = Random.IntRange(2, 3); + for (int i = 0; i < n; i++) { + int pos; + do { + pos = room.random(); + } while (level.map[pos] != Terrain.EMPTY + || level.heaps.get(pos) != null); + level.drop(new Gold().random(), pos).type = (i == 0 + && heapType == Heap.Type.CHEST ? Heap.Type.MIMIC : heapType); + } + + if (heapType == Heap.Type.HEAP) { + for (int i = 0; i < n; i++) { + int pos; + do { + pos = room.random(); + } while (level.map[pos] != Terrain.EMPTY + || level.heaps.get(pos) != null); + level.drop(new Gold().random(), pos).type = (i == 0 + && heapType == Heap.Type.CHEST ? Heap.Type.MIMIC : heapType); + } + } + + room.entrance().set(Room.Door.Type.LOCKED); + level.addItemToSpawn(new IronKey(Dungeon.depth)); + } +} diff --git a/java/com/hmdzl/spspd/levels/painters/TunnelPainter.java b/java/com/hmdzl/spspd/levels/painters/TunnelPainter.java new file mode 100644 index 00000000..de12a8f3 --- /dev/null +++ b/java/com/hmdzl/spspd/levels/painters/TunnelPainter.java @@ -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 + */ +package com.hmdzl.spspd.levels.painters; + +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.Room; +import com.watabou.utils.Point; +import com.watabou.utils.Random; + +public class TunnelPainter extends Painter { + + public static void paint(Level level, Room room) { + + int floor = level.tunnelTile(); + + Point c = room.center(); + + if (room.width() > room.height() + || (room.width() == room.height() && Random.Int(2) == 0)) { + + int from = room.right - 1; + int to = room.left + 1; + + for (Room.Door door : room.connected.values()) { + + int step = door.y < c.y ? +1 : -1; + + if (door.x == room.left) { + + from = room.left + 1; + for (int i = door.y; i != c.y; i += step) { + set(level, from, i, floor); + } + + } else if (door.x == room.right) { + + to = room.right - 1; + for (int i = door.y; i != c.y; i += step) { + set(level, to, i, floor); + } + + } else { + if (door.x < from) { + from = door.x; + } + if (door.x > to) { + to = door.x; + } + + for (int i = door.y + step; i != c.y; i += step) { + set(level, door.x, i, floor); + } + } + } + + for (int i = from; i <= to; i++) { + set(level, i, c.y, floor); + } + + } else { + + int from = room.bottom - 1; + int to = room.top + 1; + + for (Room.Door door : room.connected.values()) { + + int step = door.x < c.x ? +1 : -1; + + if (door.y == room.top) { + + from = room.top + 1; + for (int i = door.x; i != c.x; i += step) { + set(level, i, from, floor); + } + + } else if (door.y == room.bottom) { + + to = room.bottom - 1; + for (int i = door.x; i != c.x; i += step) { + set(level, i, to, floor); + } + + } else { + if (door.y < from) { + from = door.y; + } + if (door.y > to) { + to = door.y; + } + + for (int i = door.x + step; i != c.x; i += step) { + set(level, i, door.y, floor); + } + } + } + + for (int i = from; i <= to; i++) { + set(level, c.x, i, floor); + } + } + + for (Room.Door door : room.connected.values()) { + door.set(Room.Door.Type.TUNNEL); + } + } +} diff --git a/java/com/hmdzl/spspd/levels/painters/VaultPainter.java b/java/com/hmdzl/spspd/levels/painters/VaultPainter.java new file mode 100644 index 00000000..e0f029de --- /dev/null +++ b/java/com/hmdzl/spspd/levels/painters/VaultPainter.java @@ -0,0 +1,84 @@ +/* + * 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 + */ +package com.hmdzl.spspd.levels.painters; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.items.Heap.Type; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.keys.GoldenKey; +import com.hmdzl.spspd.items.keys.IronKey; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.Room; +import com.hmdzl.spspd.levels.Terrain; +import com.watabou.utils.Random; + +public class VaultPainter extends Painter { + + public static void paint(Level level, Room room) { + + fill(level, room, Terrain.WALL); + fill(level, room, 1, Terrain.EMPTY_SP); + fill( level, room, 2, Terrain.EMPTY ); + + int cx = (room.left + room.right) / 2; + int cy = (room.top + room.bottom) / 2; + int c = cx + cy * Level.getWidth(); + + switch (Random.Int(3)) { + + case 0: case 1: case 2: + Item i1,i2; + do { + i1 = prizeUncursed(level); + i2 = prizeUncursed(level); + } while (i1.getClass() == i2.getClass()); + level.drop(i1, c).type = Type.CRYSTAL_CHEST; + level.drop(i2, c + Level.NEIGHBOURS8[Random.Int(8)]).type = Type.CRYSTAL_CHEST; + level.addItemToSpawn(new GoldenKey(Dungeon.depth)); + break; + + /* + level.drop(prizeUncursed(level), c); + set(level, c, Terrain.PEDESTAL); + break;*/ + } + + room.entrance().set(Room.Door.Type.LOCKED); + level.addItemToSpawn(new IronKey(Dungeon.depth)); + } + + private static Item prize(Level level) { + return Generator.random(Random.oneOf(Generator.Category.WAND, + Generator.Category.RING, Generator.Category.ARTIFACT)); + } + + + private static Item prizeUncursed(Level level) { + + Item item = Generator.random(Random.oneOf(Generator.Category.WAND, Generator.Category.RING, Generator.Category.ARTIFACT)); + + if (item != null && item.cursed && item.isUpgradable()) { + item.cursed = false; + if(item.level<0){item.upgrade(-item.level);} //upgrade to even + } + + return item; + } + +} diff --git a/java/com/hmdzl/spspd/levels/painters/WeakFloorPainter.java b/java/com/hmdzl/spspd/levels/painters/WeakFloorPainter.java new file mode 100644 index 00000000..2be53650 --- /dev/null +++ b/java/com/hmdzl/spspd/levels/painters/WeakFloorPainter.java @@ -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 + */ +package com.hmdzl.spspd.levels.painters; + +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.Room; +import com.hmdzl.spspd.levels.Terrain; +import com.watabou.utils.Point; +import com.watabou.utils.Random; +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.CustomTileVisual; + +public class WeakFloorPainter extends Painter { + + public static void paint(Level level, Room room) { + + fill(level, room, Terrain.WALL); + fill(level, room, 1, Terrain.CHASM); + + Room.Door door = room.entrance(); + door.set(Room.Door.Type.REGULAR); + + if (door.x == room.left) { + for (int i = room.top + 1; i < room.bottom; i++) { + drawInside(level, room, new Point(room.left, i), + Random.IntRange(1, room.width() - 2), Terrain.EMPTY_SP); + } + } else if (door.x == room.right) { + for (int i = room.top + 1; i < room.bottom; i++) { + drawInside(level, room, new Point(room.right, i), + Random.IntRange(1, room.width() - 2), Terrain.EMPTY_SP); + } + } else if (door.y == room.top) { + for (int i = room.left + 1; i < room.right; i++) { + drawInside(level, room, new Point(i, room.top), + Random.IntRange(1, room.height() - 2), Terrain.EMPTY_SP); + } + } else if (door.y == room.bottom) { + for (int i = room.left + 1; i < room.right; i++) { + drawInside(level, room, new Point(i, room.bottom), + Random.IntRange(1, room.height() - 2), Terrain.EMPTY_SP); + } + } + + Point well = null; + if (door.x == room.left) { + well = new Point( room.right-1, Random.Int( 2 ) == 0 ? room.top + 2 : room.bottom - 1 ); + } else if (door.x == room.right) { + well = new Point( room.left+1, Random.Int( 2 ) == 0 ? room.top + 2 : room.bottom - 1 ); + } else if (door.y == room.top) { + well = new Point( Random.Int( 2 ) == 0 ? room.left + 1 : room.right - 1, room.bottom-1 ); + } else if (door.y == room.bottom) { + well = new Point( Random.Int( 2 ) == 0 ? room.left + 1 : room.right - 1, room.top+2 ); + } + set(level, well, Terrain.CHASM); + CustomTileVisual vis = new HiddenWell(); + vis.pos(well.x, well.y); + level.customTiles.add(vis); + } + + public static class HiddenWell extends CustomTileVisual{ + + { + name = Messages.get(this, "name"); + + tx = Assets.WEAK_FLOOR; + txX = Dungeon.depth/5; + txY = 0; + } + + @Override + public String desc() { + return Messages.get(this, "desc"); + } + } +} diff --git a/java/com/hmdzl/spspd/levels/traps/ActivatePortalTrap.java b/java/com/hmdzl/spspd/levels/traps/ActivatePortalTrap.java new file mode 100644 index 00000000..bf2e9930 --- /dev/null +++ b/java/com/hmdzl/spspd/levels/traps/ActivatePortalTrap.java @@ -0,0 +1,39 @@ +/* + * 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 + */ +package com.hmdzl.spspd.levels.traps; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.mobs.npcs.SheepSokoban; +import com.hmdzl.spspd.actors.mobs.npcs.SheepSokobanCorner; +import com.hmdzl.spspd.actors.mobs.npcs.SheepSokobanSwitch; +import com.hmdzl.spspd.items.wands.WandOfFlock; + +public class ActivatePortalTrap { + + public static boolean gen = false; + public static int portPos = 0; + + // 00x66CCEE + + public static void trigger(int pos, Char ch) { + + if (ch instanceof SheepSokoban || ch instanceof SheepSokobanCorner || ch instanceof SheepSokobanSwitch || ch instanceof WandOfFlock.MagicSheep){ + gen = true; + } + } +} diff --git a/java/com/hmdzl/spspd/levels/traps/AirTrap.java b/java/com/hmdzl/spspd/levels/traps/AirTrap.java new file mode 100644 index 00000000..b42c0523 --- /dev/null +++ b/java/com/hmdzl/spspd/levels/traps/AirTrap.java @@ -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 + */ +package com.hmdzl.spspd.levels.traps; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.ResultDescriptions; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Bleeding; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.effects.Wound; + +import com.hmdzl.spspd.messages.Messages; + +import com.watabou.utils.Random; + +public class AirTrap { + + public static void trigger( int pos, Char ch ) { + + if (ch != null) { + int damage = Random.NormalIntRange(Dungeon.depth, Dungeon.depth*2); + //ch.damage(damage,Bleeding.class); + Buff.affect( ch, Bleeding.class).set((int)(damage/2)); + Wound.hit( ch ); + if (ch == Dungeon.hero && !ch.isAlive()) { + Dungeon.fail(Messages.format(ResultDescriptions.TRAP)); + //GLog.n("You bled to death..."); + } + } else { + Wound.hit( pos ); + } + Dungeon.hero.next(); + } + +} diff --git a/java/com/hmdzl/spspd/levels/traps/AlarmTrap.java b/java/com/hmdzl/spspd/levels/traps/AlarmTrap.java new file mode 100644 index 00000000..78e14983 --- /dev/null +++ b/java/com/hmdzl/spspd/levels/traps/AlarmTrap.java @@ -0,0 +1,56 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2015 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.levels.traps; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.TrapSprite; +import com.watabou.noosa.audio.Sample; +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.utils.GLog; + +public class AlarmTrap extends Trap { + + { + color = TrapSprite.RED; + shape = TrapSprite.DOTS; + } + + @Override + public void activate(Char ch) { + super.activate(ch); + + for (Mob mob : Dungeon.level.mobs) { + mob.beckon( pos ); + } + + if (Dungeon.visible[pos]) { + GLog.w( Messages.get(this, "alarm") ); + CellEmitter.center( pos ).start( Speck.factory( Speck.SCREAM ), 0.3f, 3 ); + } + + Sample.INSTANCE.play( Assets.SND_ALERT ); + } +} diff --git a/java/com/hmdzl/spspd/levels/traps/BlazingTrap.java b/java/com/hmdzl/spspd/levels/traps/BlazingTrap.java new file mode 100644 index 00000000..83acd981 --- /dev/null +++ b/java/com/hmdzl/spspd/levels/traps/BlazingTrap.java @@ -0,0 +1,56 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2015 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.levels.traps; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.Blob; +import com.hmdzl.spspd.actors.blobs.Fire; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.particles.FlameParticle; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.TrapSprite; +import com.watabou.noosa.audio.Sample; + +public class BlazingTrap extends Trap { + + { + color = TrapSprite.ORANGE; + shape = TrapSprite.STARS; + } + + + @Override + public void activate(Char ch) { + super.activate(ch); + for (int i : Level.NEIGHBOURS9DIST2){ + if (Level.insideMap(pos+i) && !Level.solid[pos+i]) { + if (Level.pit[pos+i] || Level.water[pos+i]) + GameScene.add(Blob.seed(pos + i, 1, Fire.class)); + else + GameScene.add(Blob.seed(pos + i, 5, Fire.class)); + CellEmitter.get(pos + i).burst(FlameParticle.FACTORY, 5); + } + } + Sample.INSTANCE.play(Assets.SND_BURNING); + } +} diff --git a/java/com/hmdzl/spspd/levels/traps/ChangeSheepTrap.java b/java/com/hmdzl/spspd/levels/traps/ChangeSheepTrap.java new file mode 100644 index 00000000..ce0e2608 --- /dev/null +++ b/java/com/hmdzl/spspd/levels/traps/ChangeSheepTrap.java @@ -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 + */ +package com.hmdzl.spspd.levels.traps; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.mobs.npcs.SheepSokoban; +import com.hmdzl.spspd.actors.mobs.npcs.SheepSokobanCorner; +import com.hmdzl.spspd.actors.mobs.npcs.SheepSokobanStop; +import com.hmdzl.spspd.actors.mobs.npcs.SheepSokobanSwitch; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.particles.ElmoParticle; +import com.hmdzl.spspd.scenes.GameScene; + +public class ChangeSheepTrap { + + private static final float SPAWN_DELAY = 0.2f; + + // 00x66CCEE + + public static void trigger(int pos, Char ch) { + + if (ch instanceof SheepSokoban) { + ch.destroy(); + ch.sprite.killAndErase(); + CellEmitter.get(pos).burst(ElmoParticle.FACTORY, 6); + SheepSokobanCorner s = new SheepSokobanCorner(); + s.pos = pos; + GameScene.add(s, SPAWN_DELAY); + } + + else if (ch instanceof SheepSokobanCorner) { + ch.destroy(); + ch.sprite.killAndErase(); + CellEmitter.get(pos).burst(ElmoParticle.FACTORY, 6); + SheepSokobanStop s = new SheepSokobanStop(); + s.pos = pos; + GameScene.add(s, SPAWN_DELAY); + + } + + else if (ch instanceof SheepSokobanSwitch) { + ch.destroy(); + ch.sprite.killAndErase(); + CellEmitter.get(pos).burst(ElmoParticle.FACTORY, 6); + SheepSokoban s = new SheepSokoban(); + s.pos = pos; + GameScene.add(s, SPAWN_DELAY); + } + } +} diff --git a/java/com/hmdzl/spspd/levels/traps/ChillingTrap.java b/java/com/hmdzl/spspd/levels/traps/ChillingTrap.java new file mode 100644 index 00000000..a010b91d --- /dev/null +++ b/java/com/hmdzl/spspd/levels/traps/ChillingTrap.java @@ -0,0 +1,52 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2015 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.levels.traps; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.Blob; +import com.hmdzl.spspd.actors.blobs.FrostGas; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.particles.SnowParticle; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.TrapSprite; +import com.watabou.noosa.audio.Sample; + +public class ChillingTrap extends Trap{ + + { + color = TrapSprite.WHITE; + shape = TrapSprite.DOTS; + } + + @Override + public void activate(Char ch) { + super.activate(ch); + for (int i : Level.NEIGHBOURS9){ + if (Level.insideMap(pos+i) && !Level.solid[pos+i]) { + GameScene.add(Blob.seed(pos + i, 10, FrostGas.class)); + CellEmitter.get(pos + i).burst(SnowParticle.FACTORY, 5); + } + } + Sample.INSTANCE.play(Assets.SND_SHATTER); + } +} diff --git a/java/com/hmdzl/spspd/levels/traps/ConfusionTrap.java b/java/com/hmdzl/spspd/levels/traps/ConfusionTrap.java new file mode 100644 index 00000000..ef7e300c --- /dev/null +++ b/java/com/hmdzl/spspd/levels/traps/ConfusionTrap.java @@ -0,0 +1,44 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2015 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.levels.traps; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.Blob; +import com.hmdzl.spspd.actors.blobs.ConfusionGas; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.TrapSprite; + +public class ConfusionTrap extends Trap { + + { + color = TrapSprite.TEAL; + shape = TrapSprite.GRILL; + } + + @Override + public void activate(Char ch) { + super.activate(ch); + + GameScene.add(Blob.seed(pos, 300 + 20 * Dungeon.depth, ConfusionGas.class)); + + } +} diff --git a/java/com/hmdzl/spspd/levels/traps/CursingTrap.java b/java/com/hmdzl/spspd/levels/traps/CursingTrap.java new file mode 100644 index 00000000..cfa29592 --- /dev/null +++ b/java/com/hmdzl/spspd/levels/traps/CursingTrap.java @@ -0,0 +1,74 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2015 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.levels.traps; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.particles.ShadowParticle; +import com.hmdzl.spspd.items.*; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.TrapSprite; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.noosa.audio.Sample; + +public class CursingTrap extends Trap { + + { + color = TrapSprite.VIOLET; + shape = TrapSprite.WAVES; + } + + @Override + public void activate(Char ch) { + super.activate(ch); + if (Dungeon.visible[ pos ]) { + CellEmitter.get(pos).burst(ShadowParticle.UP, 5); + Sample.INSTANCE.play(Assets.SND_CURSED); + } + + Heap heap = Dungeon.level.heaps.get( pos ); + if (heap != null){ + for (Item item : heap.items){ + if (item.isUpgradable()) + item.cursed = item.cursedKnown = true; + } + } + + if (Dungeon.hero.pos == pos){ + Hero hero = Dungeon.hero; + KindOfWeapon weapon = hero.belongings.weapon; + KindOfArmor armor = hero.belongings.armor; + KindofMisc misc1 = hero.belongings.misc1; + KindofMisc misc2 = hero.belongings.misc2; + KindofMisc misc3 = hero.belongings.misc3; + if (weapon != null) weapon.cursed = weapon.cursedKnown = true; + if (armor != null) armor.cursed = armor.cursedKnown = true; + if (misc1 != null) misc1.cursed = misc1.cursedKnown = true; + if (misc2 != null) misc2.cursed = misc2.cursedKnown = true; + if (misc3 != null) misc3.cursed = misc3.cursedKnown = true; + EquipableItem.equipCursed(hero); + GLog.n( Messages.get(this, "curse") ); + } + } +} diff --git a/java/com/hmdzl/spspd/levels/traps/DisarmingTrap.java b/java/com/hmdzl/spspd/levels/traps/DisarmingTrap.java new file mode 100644 index 00000000..f3152535 --- /dev/null +++ b/java/com/hmdzl/spspd/levels/traps/DisarmingTrap.java @@ -0,0 +1,94 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2015 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.levels.traps; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.Heap; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.KindOfWeapon; +import com.hmdzl.spspd.items.weapon.melee.FightGloves; +import com.hmdzl.spspd.items.weapon.melee.Knuckles; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.TrapSprite; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.noosa.audio.Sample; + +public class DisarmingTrap extends Trap{ + + { + color = TrapSprite.RED; + shape = TrapSprite.LARGE_DOT; + } + + @Override + public void activate(Char ch) { + super.activate(ch); + Heap heap = Dungeon.level.heaps.get( pos ); + + if (heap != null){ + int cell = Dungeon.level.randomRespawnCell(); + + if (cell != -1) { + Item item = heap.pickUp(); + Dungeon.level.drop( item, cell ).seen = true; + for (int i : Level.NEIGHBOURS9) + Dungeon.level.visited[cell+i] = true; + Dungeon.observe(); + + Sample.INSTANCE.play(Assets.SND_TELEPORT); + CellEmitter.get(pos).burst(Speck.factory(Speck.LIGHT), 4); + } + } + + if (Dungeon.hero.pos == pos){ + Hero hero = Dungeon.hero; + KindOfWeapon weapon = hero.belongings.weapon; + + if (weapon != null && !(weapon instanceof Knuckles || weapon instanceof FightGloves) && !weapon.cursed) { + + int cell = Dungeon.level.randomRespawnCell(); + if (cell != -1) { + hero.belongings.weapon = null; + Dungeon.quickslot.clearItem(weapon); + weapon.updateQuickslot(); + + Dungeon.level.drop(weapon, cell).seen = true; + for (int i : Level.NEIGHBOURS9) + Dungeon.level.visited[cell+i] = true; + Dungeon.observe(); + + GLog.w( Messages.get(this, "disarm") ); + + Sample.INSTANCE.play(Assets.SND_TELEPORT); + CellEmitter.get(pos).burst(Speck.factory(Speck.LIGHT), 4); + + } + + } + } + } +} diff --git a/java/com/hmdzl/spspd/levels/traps/DisintegrationTrap.java b/java/com/hmdzl/spspd/levels/traps/DisintegrationTrap.java new file mode 100644 index 00000000..3fef957e --- /dev/null +++ b/java/com/hmdzl/spspd/levels/traps/DisintegrationTrap.java @@ -0,0 +1,93 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2015 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.levels.traps; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.DungeonTilemap; +import com.hmdzl.spspd.ResultDescriptions; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.Beam; +import com.hmdzl.spspd.items.Heap; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.bags.Bag; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.TrapSprite; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Random; + +public class DisintegrationTrap extends Trap { + + { + color = TrapSprite.VIOLET; + shape = TrapSprite.LARGE_DOT; + } + + @Override + public void activate(Char ch) { + super.activate(ch); + + if (Dungeon.visible[ pos ]) { + sprite.parent.add( new Beam.DeathRay( DungeonTilemap.tileCenterToWorld(pos-1), + DungeonTilemap.tileCenterToWorld(pos+1))); + sprite.parent.add(new Beam.DeathRay(DungeonTilemap.tileCenterToWorld(pos - Level.WIDTH), + DungeonTilemap.tileCenterToWorld(pos + Level.WIDTH))); + Sample.INSTANCE.play( Assets.SND_RAY ); + } + + Heap heap = Dungeon.level.heaps.get(pos); + if (heap != null) heap.explode(); + + //Char ch = Actor.findChar(pos); + if (ch != null){ + ch.damage( Math.max( ch.HT/5, Random.Int(ch.HP / 2, 2 * ch.HP / 3) ), this ); + if (ch == Dungeon.hero){ + Hero hero = (Hero)ch; + if (!hero.isAlive()){ + Dungeon.fail(ResultDescriptions.TRAP); + //GLog.n( Messages.get(this, "ondeath") ); + } else { + Item item = hero.belongings.randomUnequipped(); + Bag bag = hero.belongings.backpack; + //bags do not protect against this trap + if (item instanceof Bag){ + bag = (Bag)item; + item = Random.element(bag.items); + } + if (item == null || item.level > 0 || item.unique ) return; + if (!item.stackable){ + item.detachAll(bag); + GLog.w( Messages.get(this, "one", item.name()) ); + } else { + int n = Random.NormalIntRange(1, (item.quantity()+1)/2); + for(int i = 1; i <= n; i++) + item.detach(bag); + GLog.w( Messages.get(this, "some", item.name()) ); + } + } + } + } + + } +} diff --git a/java/com/hmdzl/spspd/levels/traps/DistortionTrap.java b/java/com/hmdzl/spspd/levels/traps/DistortionTrap.java new file mode 100644 index 00000000..60555dca --- /dev/null +++ b/java/com/hmdzl/spspd/levels/traps/DistortionTrap.java @@ -0,0 +1,50 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2015 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.levels.traps; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.keys.Key; +import com.hmdzl.spspd.scenes.InterlevelScene; +import com.hmdzl.spspd.sprites.TrapSprite; +import com.watabou.noosa.Game; + +public class DistortionTrap extends Trap{ + + { + color = TrapSprite.TEAL; + shape = TrapSprite.LARGE_DOT; + } + + @Override + public void activate(Char ch) { + super.activate(ch); + InterlevelScene.returnDepth = Dungeon.depth; + for (Item item : Dungeon.hero.belongings.backpack.items.toArray( new Item[0])){ + if (item instanceof Key && ((Key)item).depth == Dungeon.depth){ + item.detachAll(Dungeon.hero.belongings.backpack); + } + } + InterlevelScene.mode = InterlevelScene.Mode.RESET; + Game.switchScene(InterlevelScene.class); + } +} diff --git a/java/com/hmdzl/spspd/levels/traps/ExplosiveTrap.java b/java/com/hmdzl/spspd/levels/traps/ExplosiveTrap.java new file mode 100644 index 00000000..502a2a2e --- /dev/null +++ b/java/com/hmdzl/spspd/levels/traps/ExplosiveTrap.java @@ -0,0 +1,42 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2015 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.levels.traps; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.items.bombs.Bomb; +import com.hmdzl.spspd.items.bombs.BuildBomb; +import com.hmdzl.spspd.items.bombs.MiniBomb; +import com.hmdzl.spspd.sprites.TrapSprite; + +public class ExplosiveTrap extends Trap { + + { + color = TrapSprite.ORANGE; + shape = TrapSprite.DIAMOND; + } + + @Override + public void activate(Char ch) { + super.activate(ch); + new BuildBomb().explode(pos); + } + +} diff --git a/java/com/hmdzl/spspd/levels/traps/FireTrap.java b/java/com/hmdzl/spspd/levels/traps/FireTrap.java new file mode 100644 index 00000000..65d09324 --- /dev/null +++ b/java/com/hmdzl/spspd/levels/traps/FireTrap.java @@ -0,0 +1,55 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2015 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.levels.traps; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.Blob; +import com.hmdzl.spspd.actors.blobs.Fire; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.particles.FlameParticle; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.TrapSprite; +import com.watabou.noosa.audio.Sample; + +public class FireTrap extends Trap { + + { + color = TrapSprite.ORANGE; + shape = TrapSprite.DOTS; + } + + @Override + public void activate(Char ch) { + super.activate(ch); + for (int i : Level.NEIGHBOURS9){ + if (Level.insideMap(pos+i) && !Level.solid[pos+i]) { + if (Level.pit[pos+i] || Level.water[pos+i]) + GameScene.add(Blob.seed(pos + i, 1, Fire.class)); + else + GameScene.add(Blob.seed(pos + i, 2, Fire.class)); + CellEmitter.get(pos + i).burst(FlameParticle.FACTORY, 5); + } + } + Sample.INSTANCE.play(Assets.SND_BURNING); + } +} diff --git a/java/com/hmdzl/spspd/levels/traps/FlashingTrap.java b/java/com/hmdzl/spspd/levels/traps/FlashingTrap.java new file mode 100644 index 00000000..aec67404 --- /dev/null +++ b/java/com/hmdzl/spspd/levels/traps/FlashingTrap.java @@ -0,0 +1,72 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2015 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.levels.traps; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Blindness; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Cripple; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.Heap; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.TrapSprite; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Random; + +public class FlashingTrap extends Trap { + + { + color = TrapSprite.YELLOW; + shape = TrapSprite.STARS; + } + + @Override + public void activate(Char ch) { + super.activate(ch); + //Char ch = Actor.findChar(pos); + + Heap heap = Dungeon.level.heaps.get(pos); + if (heap != null) {heap.light();} + + if (ch != null) { + int len = Random.Int(5, 10)+Dungeon.depth; + Buff.prolong( ch, Blindness.class, len ); + Buff.prolong( ch, Cripple.class, len ); + if (ch instanceof Mob) { + if (((Mob)ch).state == ((Mob)ch).HUNTING) ((Mob)ch).state = ((Mob)ch).WANDERING; + ((Mob)ch).beckon( Dungeon.level.randomDestination() ); + } + if (ch == Dungeon.hero){ + Sample.INSTANCE.play( Assets.SND_BLAST ); + } + } + + if (Dungeon.visible[pos]) { + GameScene.flash(0xFFFFFF); + CellEmitter.get(pos).burst( Speck.factory(Speck.LIGHT), 4 ); + } + } + +} diff --git a/java/com/hmdzl/spspd/levels/traps/FleecingTrap.java b/java/com/hmdzl/spspd/levels/traps/FleecingTrap.java new file mode 100644 index 00000000..8621d116 --- /dev/null +++ b/java/com/hmdzl/spspd/levels/traps/FleecingTrap.java @@ -0,0 +1,107 @@ +/* + * 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 + */ +package com.hmdzl.spspd.levels.traps; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.ResultDescriptions; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.mobs.npcs.Sheep; +import com.hmdzl.spspd.actors.mobs.npcs.SheepSokoban; +import com.hmdzl.spspd.actors.mobs.npcs.SheepSokobanBlack; +import com.hmdzl.spspd.actors.mobs.npcs.SheepSokobanCorner; +import com.hmdzl.spspd.actors.mobs.npcs.SheepSokobanSwitch; +import com.hmdzl.spspd.effects.particles.ShadowParticle; +import com.hmdzl.spspd.items.KindOfArmor; +import com.hmdzl.spspd.items.keys.IronKey; + +import com.hmdzl.spspd.items.wands.WandOfFlock; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.InterlevelScene; +import com.hmdzl.spspd.sprites.HeroSprite; +import com.hmdzl.spspd.utils.GLog; + +import com.watabou.noosa.Camera; +import com.watabou.noosa.Game; + +public class FleecingTrap { + + // 00x66CCEE + + public static void trigger(int pos, Char ch) { + + if (ch instanceof SheepSokoban || ch instanceof SheepSokobanCorner || ch instanceof SheepSokobanSwitch || ch instanceof Sheep || ch instanceof WandOfFlock.MagicSheep + || ch instanceof SheepSokobanBlack){ + Camera.main.shake(2, 0.3f); + ch.destroy(); + ch.sprite.killAndErase(); + ch.sprite.emitter().burst(ShadowParticle.UP, 5); + + } else if (ch != null) { + + int dmg = ch.HP; + boolean port=true; + + if (ch == Dungeon.hero) { + + Hero hero = Dungeon.hero; + + KindOfArmor armor = hero.belongings.armor; + if (armor!=null){ + hero.belongings.armor=null; + GLog.n(Messages.get(FleecingTrap.class, "destroy")); + ((HeroSprite) hero.sprite).updateArmor(); + dmg=dmg-1; + port=false; + } + + } + + //Port back to 1,1 or something + + Camera.main.shake(2, 0.3f); + ch.sprite.emitter().burst(ShadowParticle.UP, 5); + + if (ch == Dungeon.hero && port) { + IronKey key = ((Hero)ch).belongings.getKey(IronKey.class, Dungeon.depth); + if (key!=null){key.detachAll(Dungeon.hero.belongings.backpack);} + InterlevelScene.mode = InterlevelScene.Mode.SOKOBANFAIL; + Game.switchScene(InterlevelScene.class); + } + + if (ch == Dungeon.hero) { + + Camera.main.shake(2, 0.3f); + + if (!ch.isAlive()) { + Dungeon.fail(Messages.format(ResultDescriptions.TRAP)); + } + } + } + + Dungeon.hero.next(); + + } + + public static final Fleece FLEECE = new Fleece(); + + public static class Fleece { + } + + +} diff --git a/java/com/hmdzl/spspd/levels/traps/FlockTrap.java b/java/com/hmdzl/spspd/levels/traps/FlockTrap.java new file mode 100644 index 00000000..2b44a932 --- /dev/null +++ b/java/com/hmdzl/spspd/levels/traps/FlockTrap.java @@ -0,0 +1,73 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2015 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.levels.traps; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.mobs.npcs.Sheep; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.Heap; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.TrapSprite; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Random; + +public class FlockTrap extends Trap { + + { + color = TrapSprite.WHITE; + shape = TrapSprite.WAVES; + } + + + @Override + public void activate(Char ch) { + super.activate(ch); + //use an actor as we want to put this on a slight delay so all chars get a chance to act this turn first. + Actor.add(new Actor() { + + protected boolean act() { + int cell; + for (int i : Level.NEIGHBOURS9DIST2) { + cell = pos + i; + if (Level.insideMap(cell) && Actor.findChar(cell) == null && !(Level.solid[cell] || Level.pit[cell])) { + Sheep sheep = new Sheep(); + sheep.lifespan = 2 + Random.Int(Dungeon.depth + 10); + sheep.pos = cell; + GameScene.add(sheep); + } + CellEmitter.get(cell).burst(Speck.factory(Speck.WOOL), 4); + } + Sample.INSTANCE.play(Assets.SND_PUFF); + Actor.remove(this); + return true; + } + }); + + Heap heap = Dungeon.level.heaps.get(pos); + if (heap != null) {heap.summon();} + } + +} diff --git a/java/com/hmdzl/spspd/levels/traps/FrostTrap.java b/java/com/hmdzl/spspd/levels/traps/FrostTrap.java new file mode 100644 index 00000000..3f0fbb0e --- /dev/null +++ b/java/com/hmdzl/spspd/levels/traps/FrostTrap.java @@ -0,0 +1,52 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2015 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.levels.traps; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.Blob; +import com.hmdzl.spspd.actors.blobs.FrostGas; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.particles.SnowParticle; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.TrapSprite; +import com.watabou.noosa.audio.Sample; + +public class FrostTrap extends Trap { + + { + color = TrapSprite.WHITE; + shape = TrapSprite.STARS; + } + + @Override + public void activate(Char ch) { + super.activate(ch); + for (int i : Level.NEIGHBOURS9DIST2){ + if (Level.insideMap(pos+i) && !Level.solid[pos+i]) { + GameScene.add(Blob.seed(pos + i, 20, FrostGas.class)); + CellEmitter.get(pos + i).burst(SnowParticle.FACTORY, 5); + } + } + Sample.INSTANCE.play(Assets.SND_SHATTER); + } +} diff --git a/java/com/hmdzl/spspd/levels/traps/GrimTrap.java b/java/com/hmdzl/spspd/levels/traps/GrimTrap.java new file mode 100644 index 00000000..d51330c8 --- /dev/null +++ b/java/com/hmdzl/spspd/levels/traps/GrimTrap.java @@ -0,0 +1,64 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2015 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.levels.traps; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.ResultDescriptions; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.effects.Wound; +import com.hmdzl.spspd.sprites.TrapSprite; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Random; + +public class GrimTrap extends Trap { + + { + color = TrapSprite.GREY; + shape = TrapSprite.LARGE_DOT; + } + + @Override + public Trap hide() { + //cannot hide this trap + return reveal(); + } + + @Override + public void activate(Char ch) { + + if (Dungeon.visible[pos]){ + Sample.INSTANCE.play(Assets.SND_HIT); + Wound.hit(pos); + } + + //Char ch = Actor.findChar( pos); + if (ch != null){ + int damage = Random.NormalIntRange(ch.HP/2,ch.HP); + damage -= Random.IntRange( ch.drRoll()/2, ch.drRoll()); + ch.damage( Math.max(damage, 0) , this); + if (!ch.isAlive() && ch == Dungeon.hero){ + Dungeon.fail(ResultDescriptions.TRAP); + //GLog.n( Messages.get(this, "ondeath") ); + } + } + } +} diff --git a/java/com/hmdzl/spspd/levels/traps/GrippingTrap.java b/java/com/hmdzl/spspd/levels/traps/GrippingTrap.java new file mode 100644 index 00000000..39735dbe --- /dev/null +++ b/java/com/hmdzl/spspd/levels/traps/GrippingTrap.java @@ -0,0 +1,60 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2015 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.levels.traps; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Bleeding; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Cripple; +import com.hmdzl.spspd.actors.buffs.Roots; +import com.hmdzl.spspd.effects.Wound; +import com.hmdzl.spspd.items.Heap; +import com.hmdzl.spspd.sprites.TrapSprite; +import com.watabou.utils.Random; + +public class GrippingTrap extends Trap { + + { + color = TrapSprite.GREY; + shape = TrapSprite.CROSSHAIR; + } + + @Override + public void activate(Char ch) { + //super.activate(ch); + Char c = Actor.findChar( pos ); + + if (c != null) { + int damage = Math.max( 0, (Dungeon.depth) - Random.IntRange( 0, c.drRoll() / 2 ) ); + Buff.affect( c, Bleeding.class ).set( damage ); + Buff.prolong( c, Cripple.class, 15f); + Buff.prolong( c, Roots.class, 5f); + Wound.hit( c ); + } else { + Wound.hit( pos ); + } + Heap heap = Dungeon.level.heaps.get(pos); + if (heap != null) {heap.poison();} + + } +} diff --git a/java/com/hmdzl/spspd/levels/traps/GuardianTrap.java b/java/com/hmdzl/spspd/levels/traps/GuardianTrap.java new file mode 100644 index 00000000..a7aa499d --- /dev/null +++ b/java/com/hmdzl/spspd/levels/traps/GuardianTrap.java @@ -0,0 +1,113 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2015 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.levels.traps; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.actors.mobs.Statue; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.Heap; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.StatueSprite; +import com.hmdzl.spspd.sprites.TrapSprite; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.noosa.audio.Sample; + +public class GuardianTrap extends Trap { + + { + color = TrapSprite.RED; + shape = TrapSprite.STARS; + } + + @Override + public void activate(Char ch) { + super.activate(ch); + for (Mob mob : Dungeon.level.mobs) { + mob.beckon( pos ); + } + + if (Dungeon.visible[pos]) { + GLog.w( Messages.get(this, "alarm") ); + CellEmitter.center(pos).start( Speck.factory(Speck.SCREAM), 0.3f, 3 ); + } + + Sample.INSTANCE.play( Assets.SND_ALERT ); + + for (int i = 0; i < (Dungeon.depth - 5)/5; i++){ + Guardian guardian = new Guardian(); + guardian.state = guardian.WANDERING; + guardian.pos = Dungeon.level.randomRespawnCell(); + GameScene.add(guardian); + guardian.beckon(Dungeon.hero.pos ); + } + Heap heap = Dungeon.level.heaps.get(pos); + if (heap != null) {heap.summon();} + + } + + public static class Guardian extends Statue { + + { + spriteClass = GuardianSprite.class; + + EXP = 0; + state = WANDERING; + } + + public Guardian(){ + super(); + + //weapon.enchant(null); + //weapon.degrade(weapon.level); + } + + @Override + public void beckon(int cell) { + //Beckon works on these ones, unlike their superclass. + notice(); + + if (state != HUNTING) { + state = WANDERING; + } + target = cell; + } + + } + + public static class GuardianSprite extends StatueSprite { + + public GuardianSprite(){ + super(); + tint(0, 0, 1, 0.2f); + } + + @Override + public void resetColor() { + super.resetColor(); + tint(0, 0, 1, 0.2f); + } + } +} diff --git a/java/com/hmdzl/spspd/levels/traps/HeapGenTrap.java b/java/com/hmdzl/spspd/levels/traps/HeapGenTrap.java new file mode 100644 index 00000000..bead48f4 --- /dev/null +++ b/java/com/hmdzl/spspd/levels/traps/HeapGenTrap.java @@ -0,0 +1,38 @@ +/* + * 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 + */ +package com.hmdzl.spspd.levels.traps; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.mobs.npcs.SheepSokoban; +import com.hmdzl.spspd.actors.mobs.npcs.SheepSokobanCorner; +import com.hmdzl.spspd.actors.mobs.npcs.SheepSokobanSwitch; +import com.hmdzl.spspd.items.wands.WandOfFlock; + +public class HeapGenTrap { + + public static boolean gen = false; + + // 00x66CCEE + + public static void trigger(int pos, Char ch) { + + if (ch instanceof SheepSokoban || ch instanceof SheepSokobanCorner || ch instanceof SheepSokobanSwitch || ch instanceof WandOfFlock.MagicSheep){ + gen = true; + } + } +} diff --git a/java/com/hmdzl/spspd/levels/traps/LightningTrap.java b/java/com/hmdzl/spspd/levels/traps/LightningTrap.java new file mode 100644 index 00000000..4fdf5e70 --- /dev/null +++ b/java/com/hmdzl/spspd/levels/traps/LightningTrap.java @@ -0,0 +1,91 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2015 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.levels.traps; + +import com.hmdzl.spspd.ResultDescriptions; +import com.hmdzl.spspd.items.Heap; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.wands.Wand; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.TrapSprite; +import com.watabou.noosa.Camera; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.Lightning; +import com.hmdzl.spspd.effects.particles.SparkParticle; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Random; + +import java.util.ArrayList; + +public class LightningTrap extends Trap { + + { + color = TrapSprite.TEAL; + shape = TrapSprite.CROSSHAIR; + } + + @Override + public void activate(Char ch) { + super.activate(ch); + + //Char ch = Actor.findChar( pos ); + + if (ch != null) { + ch.damage( Math.max( 1, Random.Int( ch.HP / 3, 2 * ch.HP / 3 ) ), LIGHTNING ); + if (ch == Dungeon.hero) { + + Camera.main.shake( 2, 0.3f ); + + if (!ch.isAlive()) { + Dungeon.fail(ResultDescriptions.TRAP); + GLog.n( Messages.get(this, "ondeath") ); + } + } + + ArrayList arcs = new ArrayList<>(); + arcs.add(new Lightning.Arc(pos - Level.WIDTH, pos + Level.WIDTH)); + arcs.add(new Lightning.Arc(pos - 1, pos + 1)); + + ch.sprite.parent.add( new Lightning( arcs, null ) ); + } + + Heap heap = Dungeon.level.heaps.get(pos); + if (heap != null){ + //TODO: this should probably charge staffs too + Item item = heap.items.peek(); + if (item instanceof Wand){ + Wand wand = (Wand)item; + ((Wand)item).curCharges += (int)Math.ceil((wand.maxCharges - wand.curCharges)/2f); + } + heap.lit(); + } + + CellEmitter.center( pos ).burst( SparkParticle.FACTORY, Random.IntRange( 3, 4 ) ); + } + + //FIXME: this is bad, handle when you rework resistances, make into a category + public static final Electricity LIGHTNING = new Electricity(); + public static class Electricity { + } +} diff --git a/java/com/hmdzl/spspd/levels/traps/OozeTrap.java b/java/com/hmdzl/spspd/levels/traps/OozeTrap.java new file mode 100644 index 00000000..eb0af9bf --- /dev/null +++ b/java/com/hmdzl/spspd/levels/traps/OozeTrap.java @@ -0,0 +1,50 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2015 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.levels.traps; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Ooze; +import com.hmdzl.spspd.effects.Splash; +import com.hmdzl.spspd.items.Heap; +import com.hmdzl.spspd.sprites.TrapSprite; + +public class OozeTrap extends Trap { + + { + color = TrapSprite.GREEN; + shape = TrapSprite.DOTS; + } + + @Override + public void activate(Char ch) { + super.activate(ch); + //Char ch = Actor.findChar( pos ); + + if (ch != null){ + Buff.affect(ch, Ooze.class); + Splash.at(sprite.center(), 0x000000, 5); + } + Heap heap = Dungeon.level.heaps.get(pos); + if (heap != null) {heap.poison();} + } +} diff --git a/java/com/hmdzl/spspd/levels/traps/ParalyticTrap.java b/java/com/hmdzl/spspd/levels/traps/ParalyticTrap.java new file mode 100644 index 00000000..3b4ae516 --- /dev/null +++ b/java/com/hmdzl/spspd/levels/traps/ParalyticTrap.java @@ -0,0 +1,44 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2015 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.levels.traps; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.Blob; +import com.hmdzl.spspd.actors.blobs.ParalyticGas; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.TrapSprite; + +public class ParalyticTrap extends Trap{ + + { + color = TrapSprite.YELLOW; + shape = TrapSprite.GRILL; + } + + @Override + public void activate(Char ch) { + super.activate(ch); + + GameScene.add( Blob.seed( pos, 80 + 5 * Dungeon.depth, ParalyticGas.class ) ); + + } +} diff --git a/java/com/hmdzl/spspd/levels/traps/PitfallTrap.java b/java/com/hmdzl/spspd/levels/traps/PitfallTrap.java new file mode 100644 index 00000000..f49f37a2 --- /dev/null +++ b/java/com/hmdzl/spspd/levels/traps/PitfallTrap.java @@ -0,0 +1,83 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2015 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.levels.traps; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.items.Heap; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.levels.features.Chasm; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.TrapSprite; + +public class PitfallTrap extends Trap { + + { + color = TrapSprite.RED; + shape = TrapSprite.DIAMOND; + } + + @Override + public void activate(Char ch) { + super.activate(ch); + Heap heap = Dungeon.level.heaps.get( pos ); + + if (heap != null){ + for (Item item : heap.items){ + Dungeon.dropToChasm(item); + } + heap.sprite.kill(); + GameScene.discard(heap); + Dungeon.level.heaps.remove( pos ); + } + + //Char ch = Actor.findChar( pos ); + + if (ch == Dungeon.hero){ + Chasm.heroFall( pos ); + } else if (ch != null){ + Chasm.mobFall((Mob)ch); + } + } + + /*@Override + protected void disarm() { + super.disarm(); + + //if making a pit here wouldn't block any paths, make a pit tile instead of a disarmed trap tile. + if (!(Dungeon.level.solid[pos - Level.WIDTH] && Dungeon.level.solid[pos + Level.WIDTH]) + && !(Dungeon.level.solid[pos - 1]&& Dungeon.level.solid[pos + 1])){ + + int c = Dungeon.level.map[pos - Level.WIDTH]; + + if (c == Terrain.WALL || c == Terrain.WALL_DECO) { + Level.set(pos, Terrain.CHASM_WALL); + } else { + Level.set( pos, Terrain.CHASM_FLOOR ); + } + + sprite.parent.add(new WindParticle.Wind(pos)); + sprite.kill(); + GameScene.updateMap( pos ); + } + }*/ +} diff --git a/java/com/hmdzl/spspd/levels/traps/PoisonTrap.java b/java/com/hmdzl/spspd/levels/traps/PoisonTrap.java new file mode 100644 index 00000000..55436fce --- /dev/null +++ b/java/com/hmdzl/spspd/levels/traps/PoisonTrap.java @@ -0,0 +1,54 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2015 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.levels.traps; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Poison; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.particles.PoisonParticle; +import com.hmdzl.spspd.items.Heap; +import com.hmdzl.spspd.sprites.TrapSprite; + +public class PoisonTrap extends Trap{ + + { + color = TrapSprite.VIOLET; + shape = TrapSprite.CROSSHAIR; + } + + @Override + public void activate(Char ch) { + super.activate(ch); + + //Char ch = Actor.findChar( pos ); + + if (ch != null) { + Buff.affect( ch, Poison.class ).set( Poison.durationFactor( ch ) * (4 + Dungeon.depth / 2) ); + } + + CellEmitter.center( pos ).burst( PoisonParticle.SPLASH, 3 ); + Heap heap = Dungeon.level.heaps.get(pos); + if (heap != null) {heap.poison();} + + } +} diff --git a/java/com/hmdzl/spspd/levels/traps/RockfallTrap.java b/java/com/hmdzl/spspd/levels/traps/RockfallTrap.java new file mode 100644 index 00000000..5bae79ac --- /dev/null +++ b/java/com/hmdzl/spspd/levels/traps/RockfallTrap.java @@ -0,0 +1,83 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2015 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.levels.traps; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.ResultDescriptions; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Paralysis; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.TrapSprite; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.noosa.Camera; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Random; + +public class RockfallTrap extends Trap { + + { + color = TrapSprite.GREY; + shape = TrapSprite.DIAMOND; + } + + @Override + public void activate(Char ch) { + super.activate(ch); + + boolean seen = false; + + for (int i : Level.NEIGHBOURS9){ + + if (Level.solid[pos+i]) + continue; + + if (Dungeon.visible[ pos+i ]){ + CellEmitter.get( pos + i - Level.WIDTH ).start(Speck.factory(Speck.ROCK), 0.07f, 10); + if (!seen) { + Camera.main.shake(3, 0.7f); + Sample.INSTANCE.play(Assets.SND_ROCKS); + seen = true; + } + } + + //Char ch = Actor.findChar( pos+i ); + + if (ch != null){ + int damage = Random.NormalIntRange(Dungeon.depth, Dungeon.depth*2); + damage -= Random.IntRange( 0, ch.drRoll()); + ch.damage( Math.max(damage, 0) , this); + + Buff.prolong( ch, Paralysis.class, Paralysis.duration(ch)/2); + + if (!ch.isAlive() && ch == Dungeon.hero){ + Dungeon.fail( ResultDescriptions.TRAP ); + GLog.n( Messages.get(this, "ondeath") ); + } + } + } + + } +} diff --git a/java/com/hmdzl/spspd/levels/traps/ShockTrap.java b/java/com/hmdzl/spspd/levels/traps/ShockTrap.java new file mode 100644 index 00000000..00657dd3 --- /dev/null +++ b/java/com/hmdzl/spspd/levels/traps/ShockTrap.java @@ -0,0 +1,52 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2015 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.levels.traps; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.Blob; +import com.hmdzl.spspd.actors.blobs.ElectriShock; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.particles.EnergyParticle; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.TrapSprite; +import com.watabou.noosa.audio.Sample; + +public class ShockTrap extends Trap { + + { + color = TrapSprite.GREEN; + shape = TrapSprite.DIAMOND; + } + + @Override + public void activate(Char ch) { + super.activate(ch); + for (int i : Level.NEIGHBOURS9){ + if (Level.insideMap(pos+i) && !Level.solid[pos+i]) { + GameScene.add(Blob.seed(pos + i, 10, ElectriShock.class)); + CellEmitter.get(pos + i).burst(EnergyParticle.FACTORY, 5); + } + } + Sample.INSTANCE.play(Assets.SND_ZAP); + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/levels/traps/SokobanPortalTrap.java b/java/com/hmdzl/spspd/levels/traps/SokobanPortalTrap.java new file mode 100644 index 00000000..adc02968 --- /dev/null +++ b/java/com/hmdzl/spspd/levels/traps/SokobanPortalTrap.java @@ -0,0 +1,39 @@ +/* + * 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 + */ +package com.hmdzl.spspd.levels.traps; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.items.scrolls.ScrollOfTeleportation; + +public class SokobanPortalTrap { + + public static int portPos = 0; + + // 00x66CCEE + + public static void trigger(int pos, Char ch, int dest) { + + if (ch instanceof Hero ){ + //teleport ch to dest from pos teleport scroll + ScrollOfTeleportation.teleportHeroLocation((Hero) ch,dest); + //GLog.i("teleport to, %s",dest); + + } + } +} diff --git a/java/com/hmdzl/spspd/levels/traps/SpearTrap.java b/java/com/hmdzl/spspd/levels/traps/SpearTrap.java new file mode 100644 index 00000000..2cc4e8bb --- /dev/null +++ b/java/com/hmdzl/spspd/levels/traps/SpearTrap.java @@ -0,0 +1,69 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2015 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.levels.traps; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.ResultDescriptions; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.effects.Wound; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.Terrain; +import com.hmdzl.spspd.sprites.TrapSprite; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Random; + +public class SpearTrap extends Trap { + + { + color = TrapSprite.GREY; + shape = TrapSprite.DOTS; + } + + public void trigger() { + if (Dungeon.visible[pos]){ + Sample.INSTANCE.play(Assets.SND_TRAP); + } + //this trap is not disarmed by being triggered + reveal(); + Level.set(pos, Terrain.TRAP); + } + + @Override + public void activate(Char ch) { + //super.activate(ch); + if (Dungeon.visible[pos]){ + Sample.INSTANCE.play(Assets.SND_HIT); + Wound.hit(pos); + } + + //Char ch = Actor.findChar( pos); + if (ch != null){ + int damage = Random.NormalIntRange(Dungeon.depth, Dungeon.depth*2); + damage -= Random.IntRange( 0, ch.drRoll()); + ch.damage( Math.max(damage, 0) , this); + if (!ch.isAlive() && ch == Dungeon.hero){ + Dungeon.fail(ResultDescriptions.TRAP); + //GLog.n( Messages.get(this, "ondeath") ); + } + } + } +} diff --git a/java/com/hmdzl/spspd/levels/traps/StormTrap.java b/java/com/hmdzl/spspd/levels/traps/StormTrap.java new file mode 100644 index 00000000..d7fc97c9 --- /dev/null +++ b/java/com/hmdzl/spspd/levels/traps/StormTrap.java @@ -0,0 +1,52 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2015 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.levels.traps; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.Blob; +import com.hmdzl.spspd.actors.blobs.ElectriShock; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.particles.EnergyParticle; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.TrapSprite; +import com.watabou.noosa.audio.Sample; + +public class StormTrap extends Trap { + + { + color = TrapSprite.GREEN; + shape = TrapSprite.LARGE_DOT; + } + + @Override + public void activate(Char ch) { + super.activate(ch); + for (int i : Level.NEIGHBOURS9DIST2){ + if (Level.insideMap(pos+i) && !Level.solid[pos+i]) { + GameScene.add(Blob.seed(pos + i, 20, ElectriShock.class)); + CellEmitter.get(pos + i).burst(EnergyParticle.FACTORY, 5); + } + } + Sample.INSTANCE.play(Assets.SND_ZAP); + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/levels/traps/SummoningTrap.java b/java/com/hmdzl/spspd/levels/traps/SummoningTrap.java new file mode 100644 index 00000000..272c1b7a --- /dev/null +++ b/java/com/hmdzl/spspd/levels/traps/SummoningTrap.java @@ -0,0 +1,99 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2015 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.levels.traps; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.mobs.Bestiary; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.items.Heap; +import com.hmdzl.spspd.items.scrolls.ScrollOfTeleportation; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.TrapSprite; +import com.watabou.utils.Random; + +public class SummoningTrap extends Trap { + + private static final float DELAY = 2f; + + { + color = TrapSprite.TEAL; + shape = TrapSprite.WAVES; + } + + @Override + public void activate(Char ch) { + super.activate(ch); + + if (Dungeon.bossLevel()) { + return; + } + + int nMobs = 1; + if (Random.Int( 2 ) == 0) { + nMobs++; + if (Random.Int( 2 ) == 0) { + nMobs++; + } + } + + ArrayList candidates = new ArrayList<>(); + + 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])) { + candidates.add( p ); + } + } + + ArrayList respawnPoints = new ArrayList<>(); + + while (nMobs > 0 && candidates.size() > 0) { + int index = Random.index( candidates ); + + respawnPoints.add( candidates.remove( index ) ); + nMobs--; + } + + ArrayList mobs = new ArrayList<>(); + + for (Integer point : respawnPoints) { + Mob mob = Bestiary.mob( Dungeon.depth ); + mob.state = mob.WANDERING; + mob.pos = point; + GameScene.add( mob, DELAY ); + mobs.add( mob ); + } + + //important to process the visuals and pressing of cells last, so spawned mobs have a chance to occupy cells first + for (Mob mob : mobs){ + ScrollOfTeleportation.appear(mob, mob.pos); + } + + Heap heap = Dungeon.level.heaps.get(pos); + if (heap != null) {heap.summon();} + + } +} diff --git a/java/com/hmdzl/spspd/levels/traps/TeleportationTrap.java b/java/com/hmdzl/spspd/levels/traps/TeleportationTrap.java new file mode 100644 index 00000000..ca730f32 --- /dev/null +++ b/java/com/hmdzl/spspd/levels/traps/TeleportationTrap.java @@ -0,0 +1,90 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2015 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.levels.traps; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.Heap; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.scrolls.ScrollOfTeleportation; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.TrapSprite; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.noosa.audio.Sample; + +public class TeleportationTrap extends Trap { + + { + color = TrapSprite.TEAL; + shape = TrapSprite.DOTS; + } + + @Override + public void activate(Char ch) { + super.activate(ch); + + CellEmitter.get(pos).start(Speck.factory(Speck.LIGHT), 0.2f, 3); + Sample.INSTANCE.play( Assets.SND_TELEPORT ); + + //Char ch = Actor.findChar( pos); + if (ch instanceof Hero){ + ScrollOfTeleportation.teleportHero((Hero)ch); + ((Hero) ch).curAction = null; + } else if (ch != null){ + int count = 10; + int pos; + do { + pos = Dungeon.level.randomRespawnCell(); + if (count-- <= 0) { + break; + } + } while (pos == -1); + + if (pos == -1 || Dungeon.bossLevel()) { + + GLog.w( Messages.get(ScrollOfTeleportation.class, "no_tele") ); + + } else { + + ch.pos = pos; + ch.sprite.place(ch.pos); + ch.sprite.visible = Dungeon.visible[pos]; + + } + } + + Heap heap = Dungeon.level.heaps.get(pos); + + if (heap != null){ + int cell = Dungeon.level.randomRespawnCell(); + + Item item = heap.pickUp(); + + if (cell != -1) { + Dungeon.level.drop( item, cell ); + } + } + } +} diff --git a/java/com/hmdzl/spspd/levels/traps/ToxicTrap.java b/java/com/hmdzl/spspd/levels/traps/ToxicTrap.java new file mode 100644 index 00000000..297de84e --- /dev/null +++ b/java/com/hmdzl/spspd/levels/traps/ToxicTrap.java @@ -0,0 +1,46 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2015 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.levels.traps; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.Blob; +import com.hmdzl.spspd.actors.blobs.ToxicGas; +import com.hmdzl.spspd.items.Heap; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.TrapSprite; + +public class ToxicTrap extends Trap{ + + { + color = TrapSprite.GREEN; + shape = TrapSprite.GRILL; + } + + @Override + public void activate(Char ch) { + super.activate(ch); + + GameScene.add( Blob.seed( pos, 300 + 20 * Dungeon.depth, ToxicGas.class ) ); + Heap heap = Dungeon.level.heaps.get(pos); + if (heap != null) {heap.poison();} + } +} diff --git a/java/com/hmdzl/spspd/levels/traps/Trap.java b/java/com/hmdzl/spspd/levels/traps/Trap.java new file mode 100644 index 00000000..312f6ece --- /dev/null +++ b/java/com/hmdzl/spspd/levels/traps/Trap.java @@ -0,0 +1,109 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2015 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.levels.traps; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.TrapSprite; +import com.watabou.noosa.audio.Sample; +import com.watabou.noosa.tweeners.AlphaTweener; +import com.watabou.utils.Bundlable; +import com.watabou.utils.Bundle; + +public abstract class Trap implements Bundlable { + + public String name = Messages.get(this, "name"); + + public int color; + public int shape; + + public int pos; + + public TrapSprite sprite; + public boolean visible; + public boolean active = true; + + public Trap set(int pos){ + this.pos = pos; + return this; + } + + public Trap reveal() { + visible = true; + if (sprite != null && sprite.visible == false) { + sprite.visible = true; + sprite.alpha( 0 ); + sprite.parent.add( new AlphaTweener( sprite, 1, 0.6f)); + } + return this; + } + + public Trap hide() { + visible = false; + if (sprite != null) + sprite.visible = false; + return this; + } + + public void activate(Char ch) { + + if (Dungeon.visible[pos]) { + Sample.INSTANCE.play(Assets.SND_TRAP); + } + disarm(); + reveal(); + + } + + protected void disarm(){ + Dungeon.level.disarmTrap(pos); + active = false; + if (sprite != null) { + sprite.reset( this ); + } + } + + private static final String POS = "pos"; + private static final String VISIBLE = "visible"; + private static final String ACTIVE = "active"; + + @Override + public void restoreFromBundle( Bundle bundle ) { + pos = bundle.getInt( POS ); + visible = bundle.getBoolean( VISIBLE ); + if (bundle.contains(ACTIVE)){ + active = bundle.getBoolean(ACTIVE); + } + } + + @Override + public void storeInBundle( Bundle bundle ) { + bundle.put( POS, pos ); + bundle.put( VISIBLE, visible ); + bundle.put( ACTIVE, active ); + } + + public String desc() { + return Messages.get(this, "desc"); + } +} diff --git a/java/com/hmdzl/spspd/levels/traps/VenomTrap.java b/java/com/hmdzl/spspd/levels/traps/VenomTrap.java new file mode 100644 index 00000000..564ac10c --- /dev/null +++ b/java/com/hmdzl/spspd/levels/traps/VenomTrap.java @@ -0,0 +1,50 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2015 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.levels.traps; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.Blob; +import com.hmdzl.spspd.actors.blobs.VenomGas; +import com.hmdzl.spspd.items.Heap; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.TrapSprite; + +public class VenomTrap extends Trap { + + { + color = TrapSprite.VIOLET; + shape = TrapSprite.GRILL; + } + @Override + public void activate(Char ch) { + super.activate(ch); + + VenomGas venomGas = Blob.seed(pos, 80 + 5 * Dungeon.depth, VenomGas.class); + + venomGas.setStrength(1+Dungeon.depth/4); + + GameScene.add(venomGas); + Heap heap = Dungeon.level.heaps.get(pos); + if (heap != null) {heap.poison();} + + } +} diff --git a/java/com/hmdzl/spspd/levels/traps/WarpingTrap.java b/java/com/hmdzl/spspd/levels/traps/WarpingTrap.java new file mode 100644 index 00000000..3a6b5fbb --- /dev/null +++ b/java/com/hmdzl/spspd/levels/traps/WarpingTrap.java @@ -0,0 +1,110 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2015 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.levels.traps; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.Heap; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.artifacts.TimekeepersHourglass; +import com.hmdzl.spspd.items.scrolls.ScrollOfTeleportation; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.InterlevelScene; +import com.hmdzl.spspd.sprites.TrapSprite; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.noosa.Game; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Random; + +import java.util.ArrayList; + +public class WarpingTrap extends Trap { + + { + color = TrapSprite.TEAL; + shape = TrapSprite.STARS; + } + + @Override + public void activate(Char ch) { + super.activate(ch); + CellEmitter.get(pos).start(Speck.factory(Speck.LIGHT), 0.2f, 3); + Sample.INSTANCE.play( Assets.SND_TELEPORT ); + + if (Dungeon.depth > 1 && !Dungeon.bossLevel()) { + + //each depth has 1 more weight than the previous depth. + float[] depths = new float[Dungeon.depth-1]; + for (int i = 1; i < Dungeon.depth; i++) depths[i-1] = i; + int depth = 1+Random.chances(depths); + + Heap heap = Dungeon.level.heaps.get(pos); + if (heap != null) { + ArrayList dropped = Dungeon.droppedItems.get( depth ); + if (dropped == null) { + Dungeon.droppedItems.put( depth, dropped = new ArrayList() ); + } + for (Item item : heap.items){ + dropped.add(item); + } + heap.destroy(); + } + + //Char ch = Actor.findChar( pos ); + if (ch == Dungeon.hero){ + Buff buff = Dungeon.hero.buff(TimekeepersHourglass.timeFreeze.class); + if (buff != null) buff.detach(); + + InterlevelScene.mode = InterlevelScene.Mode.RETURN; + InterlevelScene.returnDepth = depth; + InterlevelScene.returnPos = -1; + Game.switchScene(InterlevelScene.class); + } else if (ch != null) { + int count = 10; + int pos; + do { + pos = Dungeon.level.randomRespawnCell(); + if (count-- <= 0) { + break; + } + } while (pos == -1); + + if (pos == -1 || Dungeon.bossLevel()) { + + GLog.w( Messages.get(ScrollOfTeleportation.class, "no_tele") ); + + } else { + + ch.pos = pos; + ch.sprite.place(ch.pos); + ch.sprite.visible = Dungeon.visible[pos]; + + } + } + + } + + } +} diff --git a/java/com/hmdzl/spspd/levels/traps/WeakeningTrap.java b/java/com/hmdzl/spspd/levels/traps/WeakeningTrap.java new file mode 100644 index 00000000..c0ff114d --- /dev/null +++ b/java/com/hmdzl/spspd/levels/traps/WeakeningTrap.java @@ -0,0 +1,56 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2015 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.levels.traps; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Slow; +import com.hmdzl.spspd.actors.buffs.Weakness; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.particles.ShadowParticle; +import com.hmdzl.spspd.items.Heap; +import com.hmdzl.spspd.sprites.TrapSprite; + +public class WeakeningTrap extends Trap{ + + { + color = TrapSprite.GREEN; + shape = TrapSprite.WAVES; + } + + @Override + public void activate(Char ch) { + super.activate(ch); + if (Dungeon.visible[ pos ]){ + CellEmitter.get(pos).burst(ShadowParticle.UP, 5); + } + + //Char ch = Actor.findChar( pos ); + if (ch == Dungeon.hero){ + Buff.prolong( ch, Weakness.class, Weakness.duration(ch)*2f); + } else if (ch != null) { + Buff.prolong( ch, Slow.class, Slow.duration(ch)); + } + Heap heap = Dungeon.level.heaps.get(pos); + if (heap != null) {heap.poison();} + } +} diff --git a/java/com/hmdzl/spspd/levels/traps/WornTrap.java b/java/com/hmdzl/spspd/levels/traps/WornTrap.java new file mode 100644 index 00000000..70ce31a6 --- /dev/null +++ b/java/com/hmdzl/spspd/levels/traps/WornTrap.java @@ -0,0 +1,49 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2015 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.levels.traps; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.TrapSprite; +import com.hmdzl.spspd.utils.GLog; + +public class WornTrap extends Trap { + + { + color = TrapSprite.BLACK; + shape = TrapSprite.DOTS; + } + + @Override + public Trap hide() { + //this one can't be hidden + return reveal(); + } + + @Override + public void activate(Char ch) { + super.activate(ch); + CellEmitter.get(pos).burst(Speck.factory(Speck.STEAM), 6); + GLog.i(Messages.get(this, "nothing")); + } +} diff --git a/java/com/hmdzl/spspd/mechanics/Ballistica.java b/java/com/hmdzl/spspd/mechanics/Ballistica.java new file mode 100644 index 00000000..72f188af --- /dev/null +++ b/java/com/hmdzl/spspd/mechanics/Ballistica.java @@ -0,0 +1,140 @@ +/* + * 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 + */ +package com.hmdzl.spspd.mechanics; + +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.levels.Level; + +import java.util.ArrayList; +import java.util.List; + +public class Ballistica { + + public ArrayList path = new ArrayList<>(); + public Integer sourcePos = null; + public Integer collisionPos = null; + public Integer dist = 0; + + //parameters to specify the colliding cell + public static final int STOP_TARGET = 1; //ballistica will stop at the target cell + public static final int STOP_CHARS = 2; //ballistica will stop on first char hit + public static final int STOP_TERRAIN = 4; //ballistica will stop on terrain(LOS blocking, impassable, etc.) + + public static final int PROJECTILE = STOP_TARGET | STOP_CHARS | STOP_TERRAIN; + + public static final int MAGIC_BOLT = STOP_CHARS | STOP_TERRAIN; + + public static final int WONT_STOP = 0; + + public static int[] trace = new int[Math.max(Level.getWidth(), Level.HEIGHT)]; + public static int distance; + + public Ballistica( int from, int to, int params ){ + sourcePos = from; + build(from, to, (params & STOP_TARGET) > 0, (params & STOP_CHARS) > 0, (params & STOP_TERRAIN) > 0); + if (collisionPos != null) + dist = path.indexOf( collisionPos ); + else + collisionPos = path.get( dist=path.size()-1 ); + } + + private void build( int from, int to, boolean stopTarget, boolean stopChars, boolean stopTerrain ) { + int w = Level.WIDTH; + + int x0 = from % w; + int x1 = to % w; + int y0 = from / w; + int y1 = to / w; + + int dx = x1 - x0; + int dy = y1 - y0; + + int stepX = dx > 0 ? +1 : -1; + int stepY = dy > 0 ? +1 : -1; + + dx = Math.abs( dx ); + dy = Math.abs( dy ); + + int stepA; + int stepB; + int dA; + int dB; + + if (dx > dy) { + + stepA = stepX; + stepB = stepY * w; + dA = dx; + dB = dy; + + } else { + + stepA = stepY * w; + stepB = stepX; + dA = dy; + dB = dx; + + } + + int cell = from; + + int err = dA / 2; + while (Level.insideMap(cell)) { + + //if we're in a wall, collide with the previous cell along the path. + if (stopTerrain && cell != sourcePos && !Level.passable[cell] && !Level.avoid[cell]) { + collide(path.get(path.size() - 1)); + } + + path.add(cell); + + if ((stopTerrain && cell != sourcePos && Level.losBlockHigh[cell]) + || (cell != sourcePos && stopChars && Actor.findChar( cell ) != null) + || (cell == to && stopTarget)){ + collide(cell); + } + + cell += stepA; + + err += dB; + if (err >= dA) { + err = err - dA; + cell = cell + stepB; + } + } + } + + //we only want to record the first position collision occurs at. + private void collide(int cell){ + if (collisionPos == null) + collisionPos = cell; + } + + //returns a segment of the path from start to end, inclusive. + //if there is an error, returns an empty arraylist instead. + public List subPath(int start, int end){ + try { + end = Math.min( end, path.size()-1); + return path.subList(start, end+1); + } catch (Exception e){ + return new ArrayList<>(); + } + } + + +} diff --git a/java/com/hmdzl/spspd/mechanics/ShadowCaster.java b/java/com/hmdzl/spspd/mechanics/ShadowCaster.java new file mode 100644 index 00000000..edbbfa73 --- /dev/null +++ b/java/com/hmdzl/spspd/mechanics/ShadowCaster.java @@ -0,0 +1,158 @@ +/* + * 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 + */ +package com.hmdzl.spspd.mechanics; + +import java.util.Arrays; + +import com.hmdzl.spspd.levels.Level; + +public final class ShadowCaster { + + private static final int MAX_DISTANCE = 8; + + private static final int WIDTH = Level.getWidth(); + private static final int HEIGHT = Level.HEIGHT; + + private static int distance; + private static int limits[]; + + private static boolean[] losBlocking; + private static boolean[] fieldOfView; + + private static int[][] rounding; + static { + rounding = new int[MAX_DISTANCE + 1][]; + for (int i = 1; i <= MAX_DISTANCE; i++) { + rounding[i] = new int[i + 1]; + for (int j = 1; j <= i; j++) { + rounding[i][j] = (int) Math.min(j, + Math.round(i * Math.cos(Math.asin(j / (i + 0.5))))); + } + } + } + + private static Obstacles obs = new Obstacles(); + + public static void castShadow(int x, int y, boolean[] fieldOfView, + int distance, boolean flying) { + + losBlocking = flying ? Level.losBlockHigh.clone() : Level.losBlockLow.clone() ; + + ShadowCaster.distance = distance; + limits = rounding[distance]; + + ShadowCaster.fieldOfView = fieldOfView; + Arrays.fill(fieldOfView, false); + fieldOfView[y * WIDTH + x] = true; + + scanSector(x, y, +1, +1, 0, 0); + scanSector(x, y, -1, +1, 0, 0); + scanSector(x, y, +1, -1, 0, 0); + scanSector(x, y, -1, -1, 0, 0); + scanSector(x, y, 0, 0, +1, +1); + scanSector(x, y, 0, 0, -1, +1); + scanSector(x, y, 0, 0, +1, -1); + scanSector(x, y, 0, 0, -1, -1); + } + + private static void scanSector(int cx, int cy, int m1, int m2, int m3, + int m4) { + + obs.reset(); + + for (int p = 1; p <= distance; p++) { + + float dq2 = 0.5f / p; + + int pp = limits[p]; + for (int q = 0; q <= pp; q++) { + + int x = cx + q * m1 + p * m3; + int y = cy + p * m2 + q * m4; + + if (y >= 0 && y < HEIGHT && x >= 0 && x < WIDTH) { + + float a0 = (float) q / p; + float a1 = a0 - dq2; + float a2 = a0 + dq2; + + int pos = y * WIDTH + x; + + if (obs.isBlocked(a0) && obs.isBlocked(a1) + && obs.isBlocked(a2)) { + + // Do nothing + } else { + fieldOfView[pos] = true; + } + + if (losBlocking[pos]) { + obs.add(a1, a2); + } + + } + } + + obs.nextRow(); + } + } + + private static final class Obstacles { + + private static int SIZE = (MAX_DISTANCE + 1) * (MAX_DISTANCE + 1) / 2; + private static float[] a1 = new float[SIZE]; + private static float[] a2 = new float[SIZE]; + + private int length; + private int limit; + + public void reset() { + length = 0; + limit = 0; + } + + public void add(float o1, float o2) { + + if (length > limit && o1 <= a2[length - 1]) { + + // Merging several blocking cells + a2[length - 1] = o2; + + } else { + + a1[length] = o1; + a2[length++] = o2; + + } + + } + + public boolean isBlocked(float a) { + for (int i = 0; i < limit; i++) { + if (a >= a1[i] && a <= a2[i]) { + return true; + } + } + return false; + } + + public void nextRow() { + limit = length; + } + } +} diff --git a/java/com/hmdzl/spspd/messages/Languages.java b/java/com/hmdzl/spspd/messages/Languages.java new file mode 100644 index 00000000..08e8479d --- /dev/null +++ b/java/com/hmdzl/spspd/messages/Languages.java @@ -0,0 +1,88 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2016 Evan Debenham + */ +package com.hmdzl.spspd.messages; + +import java.util.Locale; + +public enum Languages { + ENGLISH("english", "", Status.REVIEWED, null, null), + + //RUSSIAN("русский", "ru", Status.INCOMPLETE, new String[]{"ConsideredHamster", "Inevielle", "yarikonline"}, new String[]{"AttHawk46", "HerrGotlieb", "MrXantar", "Shamahan", "roman.yagodin", "un_logic"}), + //KOREAN("한국어", "ko", Status.INCOMPLETE, new String[]{"Flameblast12"}, new String[]{"WondarRabb1t", "ddojin0115", "eeeei", "linterpreteur", "lsiebnie" }), + CHINESE("中文", "zh", Status.INCOMPLETE, new String[]{"Jinkeloid(zdx00793)"}, new String[]{"931451545", "HoofBumpBlurryface", "Lery", "Lyn-0401", "ShatteredFlameBlast", "hmdzl001", "tempest102"}); + //FINNISH("suomi", "fi", Status.INCOMPLETE, new String[]{"TenguTheKnight"}, null ), + //POLISH("polski", "pl", Status.INCOMPLETE, new String[]{"Deksippos", "kuadziw"}, new String[]{"Chasseur", "Darden", "MJedi", "Peperos", "Scharnvirk", "Shmilly", "dusakus", "michaub", "ozziezombie", "szczoteczka22", "szymex73"}), + + //ITALIAN("italiano", "it", Status.INCOMPLETE, new String[]{"bizzolino", "funnydwarf"}, new String[]{"4est", "DaniMare", "Danzl", "andrearubbino00", "nessunluogo", "righi.a", "umby000"}), + //CATALAN("català", "ca", Status.INCOMPLETE, new String[]{"Illyatwo2"}, null), + //SPANISH("español", "es", Status.INCOMPLETE, new String[]{"Kiroto", "Kohru", "grayscales"}, new String[]{"Alesxanderk", "CorvosUtopy", "Dewstend", "Dyrran", "Fervoreking", "Illyatwo2", "airman12", "alfongad", "benzarr410", "ctrijueque", "dhg121", "javifs", "jonismack1"}), + //ESPERANTO("esperanto", "eo", Status.INCOMPLETE, new String[]{"Verdulo"}, null), + //HUNGARIAN("magyar", "hu", Status.INCOMPLETE, new String[]{"dorheim"}, new String[]{"Navetelen", "clarovani", "dhialub", "nanometer", "nardomaa"}), + //TURKISH("türkçe", "tr", Status.INCOMPLETE, new String[]{"LokiofMillenium", "emrebnk"}, new String[]{"AcuriousPotato", "alpekin98", "denizakalin", "melezorus34"}), + + //GERMAN("deutsch", "de", Status.INCOMPLETE, new String[]{"Dallukas", "KrystalCroft", "Wuzzy", "Zap0", "davedude" }, new String[]{"DarkPixel", "ErichME", "LenzB", "Sarius", "Sorpl3x", "ThunfischGott", "Topicranger", "oragothen"}); + //FRENCH("français", "fr", Status.INCOMPLETE, new String[]{"Emether", "canc42", "kultissim", "minikrob"}, new String[]{"Alsydis", "Basttee", "Dekadisk", "Draal", "antoine9298", "go11um", "linterpreteur", "solthaar"}), + //PORTUGUESE("português", "pt", Status.INCOMPLETE, new String[]{"TDF2001", "matheus208"}, new String[]{"ChainedFreaK", "JST", "MadHorus", "Tio_P_", "ancientorange", "danypr23", "ismael.henriques12", "owenreilly", "try31"}), + //INDONESIAN("indonésien","in", Status.INCOMPLETE, new String[]{"rakapratama"}, null); + + public enum Status{ + //below 60% complete languages are not added. + INCOMPLETE, //60-99% complete + UNREVIEWED, //100% complete + REVIEWED //100% reviewed + } + + private String name; + private String code; + private Status status; + private String[] reviewers; + private String[] translators; + + Languages(String name, String code, Status status, String[] reviewers, String[] translators){ + this.name = name; + this.code = code; + this.status = status; + this.reviewers = reviewers; + this.translators = translators; + } + + public String nativeName(){ + return name; + } + + public String code(){ + return code; + } + + public Status status(){ + return status; + } + + public String[] reviewers() { + if (reviewers == null) return new String[]{}; + else return reviewers.clone(); + } + + public String[] translators() { + if (translators == null) return new String[]{}; + else return translators.clone(); + } + + public static Languages matchLocale(Locale locale){ + return matchCode(locale.getLanguage()); + } + + public static Languages matchCode(String code){ + for (Languages lang : Languages.values()){ + if (lang.code().equals(code)) + return lang; + } + return ENGLISH; + } + +} diff --git a/java/com/hmdzl/spspd/messages/Messages.java b/java/com/hmdzl/spspd/messages/Messages.java new file mode 100644 index 00000000..e08876ac --- /dev/null +++ b/java/com/hmdzl/spspd/messages/Messages.java @@ -0,0 +1,185 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2015 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.messages; + +import com.hmdzl.spspd.SPSSettings; +import com.hmdzl.spspd.ShatteredPixelDungeon; +import com.watabou.utils.DeviceCompat; + +import java.util.Arrays; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Locale; +import java.util.ResourceBundle; + +/* + Simple wrapper class for java resource bundles. + + The core idea here is that each string resource's key is a combination of the class definition and a local value. + An object or static method would usually call this with an object/class reference (usually its own) and a local key. + This means that an object can just ask for "name" rather than, say, "items.weapon.enchantments.death.name" + */ +public class Messages { + + /* + use hashmap for two reasons. Firstly because android 2.2 doesn't support resourcebundle.containskey(), + secondly so I can read in and combine multiple properties files, + resulting in a more clean structure for organizing all the strings, instead of one big file. + + ..Yes R.string would do this for me, but that's not multiplatform + */ + private static HashMap strings; + private static Languages lang; + + public static Languages lang(){ + return lang; + } + + + + /** + * Setup Methods + */ + + private static String[] prop_files = new String[]{ + "com.hmdzl.spspd.messages.actors.actors", + "com.hmdzl.spspd.messages.items.items", + "com.hmdzl.spspd.messages.levels.levels", + "com.hmdzl.spspd.messages.plants.plants", + "com.hmdzl.spspd.messages.scenes.scenes", + "com.hmdzl.spspd.messages.ui.ui", + "com.hmdzl.spspd.messages.windows.windows", + "com.hmdzl.spspd.messages.misc.misc" + }; + + static{ + setup(SPSSettings.language()); + } + + public static void setup( Languages lang ){ + strings = new HashMap<>(); + Messages.lang = lang; + Locale locale = new Locale(lang.code()); + + for (String file : prop_files) { + ResourceBundle bundle = ResourceBundle.getBundle( file, locale); + Enumeration keys = bundle.getKeys(); + while (keys.hasMoreElements()) { + String key = keys.nextElement(); + String value = bundle.getString(key); + + //android 2.2 doesn't use UTF-8 by default, need to force it. + if (DeviceCompat.usesISO_8859_1()) { + try { + value = new String(value.getBytes("ISO-8859-1"), "UTF-8"); + } catch (Exception e) { + ShatteredPixelDungeon.reportException(e); + } + } + + strings.put(key, value); + } + } + } + + + + /** + * Resource grabbing methods + */ + + public static String get(String key, Object...args){ + return get(null, key, args); + } + + public static String get(Object o, String k, Object...args){ + return get(o.getClass(), k, args); + } + + public static String get(Class c, String k, Object...args){ + String key; + if (c != null){ + key = c.getName().replace("com.hmdzl.spspd.", ""); + key += "." + k; + } else + key = k; + + if (strings.containsKey(key.toLowerCase(Locale.ENGLISH))){ + if (args.length > 0) return format(strings.get(key.toLowerCase(Locale.ENGLISH)), args); + else return strings.get(key.toLowerCase(Locale.ENGLISH)); + } else { + //this is so child classes can inherit properties from their parents. + //in cases where text is commonly grabbed as a utility from classes that aren't mean to be instantiated + //(e.g. flavourbuff.dispTurns()) using .class directly is probably smarter to prevent unnecessary recursive calls. + if (c != null && c.getSuperclass() != null){ + return get(c.getSuperclass(), k, args); + } else { + return "!!!NO TEXT FOUND!!!"; + } + } + } + + + + /** + * String Utility Methods + */ + + public static String format( String format, Object...args ) { + return String.format( Locale.ENGLISH, format, args ); + } + + public static String capitalize( String str ){ + if (str.length() == 0) return str; + else return Character.toTitleCase( str.charAt( 0 ) ) + str.substring( 1 ); + } + + //Words which should not be capitalized in title case, mostly prepositions which appear ingame + //This list is not comprehensive! + private static final HashSet noCaps = new HashSet<>( + Arrays.asList(new String[]{ + //English + //"a", "of", "by", "to", "the", "x" + "a", "an", "and", "of", "by", "to", "the", "x" + }) + ); + + public static String titleCase( String str ){ + //English capitalizes every word except for a few exceptions + if (lang == Languages.ENGLISH){ + String result = ""; + //split by any unicode space character + for (String word : str.split("(?<=\\p{Zs})")){ + if (noCaps.contains(word.trim().toLowerCase(Locale.ENGLISH).replaceAll(":|[0-9]", ""))){ + result += word; + } else { + result += capitalize(word); + } + } + //first character is always capitalized. + return capitalize(result); + } + + //Otherwise, use sentence case + return capitalize(str); + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/plants/BlandfruitBush.java b/java/com/hmdzl/spspd/plants/BlandfruitBush.java new file mode 100644 index 00000000..3da6a2d5 --- /dev/null +++ b/java/com/hmdzl/spspd/plants/BlandfruitBush.java @@ -0,0 +1,50 @@ +package com.hmdzl.spspd.plants; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.items.food.fruit.Blackberry; +import com.hmdzl.spspd.items.food.fruit.Blandfruit; +import com.hmdzl.spspd.items.food.fruit.Blueberry; +import com.hmdzl.spspd.items.food.fruit.Cloudberry; +import com.hmdzl.spspd.items.food.fruit.Moonberry; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.utils.Random; + +/** + * Created by Evan on 13/08/2014. + */ +public class BlandfruitBush extends Plant { + + { + image = 8; + } + + @Override + public void activate(Char ch) { + super.activate(ch); + Dungeon.level.drop(new Blandfruit(), pos).sprite.drop(); + switch (Random.Int(4)){ + case 0: + Dungeon.level.drop(new Blackberry(), pos).sprite.drop(); + break; + case 1: + Dungeon.level.drop(new Blueberry(), pos).sprite.drop(); + break; + case 2: + Dungeon.level.drop(new Cloudberry(), pos).sprite.drop(); + break; + case 3: + Dungeon.level.drop(new Moonberry(), pos).sprite.drop(); + break; + } + } + + public static class Seed extends Plant.Seed { + { + image = ItemSpriteSheet.SEED_BLANDFRUIT; + + plantClass = BlandfruitBush.class; + alchemyClass = null; + } + } +} diff --git a/java/com/hmdzl/spspd/plants/Blindweed.java b/java/com/hmdzl/spspd/plants/Blindweed.java new file mode 100644 index 00000000..0afb4361 --- /dev/null +++ b/java/com/hmdzl/spspd/plants/Blindweed.java @@ -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 + */ +package com.hmdzl.spspd.plants; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Blindness; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Cripple; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.potions.PotionOfInvisibility; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.utils.Random; + +public class Blindweed extends Plant { + + { + image = 3; + } + + @Override + public void activate(Char ch) { + super.activate(ch); + + if (ch != null) { + int len = Random.Int(5, 10); + Buff.prolong(ch, Blindness.class, len); + Buff.prolong(ch, Cripple.class, len); + if (ch instanceof Mob) { + if (((Mob)ch).state == ((Mob)ch).HUNTING) ((Mob)ch).state = ((Mob)ch).WANDERING; + ((Mob)ch).beckon( Dungeon.level.randomDestination() ); + } + } + + if (Dungeon.visible[pos]) { + CellEmitter.get(pos).burst(Speck.factory(Speck.LIGHT), 4); + } + } + + public static class Seed extends Plant.Seed { + { + image = ItemSpriteSheet.SEED_BLINDWEED; + + plantClass = Blindweed.class; + alchemyClass = PotionOfInvisibility.class; + } + } +} diff --git a/java/com/hmdzl/spspd/plants/Dewcatcher.java b/java/com/hmdzl/spspd/plants/Dewcatcher.java new file mode 100644 index 00000000..dddca7fb --- /dev/null +++ b/java/com/hmdzl/spspd/plants/Dewcatcher.java @@ -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 + */ +package com.hmdzl.spspd.plants; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.items.RedDewdrop; +import com.hmdzl.spspd.items.VioletDewdrop; +import com.hmdzl.spspd.items.YellowDewdrop; +import com.hmdzl.spspd.items.potions.PotionOfOverHealing; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.utils.Random; + +public class Dewcatcher extends Plant { + + { + image = 12; + } + + @Override + public void activate(Char ch) { + + explodeDew(pos); + if (Random.Int(2)==0){super.activate(ch);} + + + } + + public static class Seed extends Plant.Seed { + { + image = ItemSpriteSheet.SEED_DEWCATCHER; + + plantClass = Dewcatcher.class; + alchemyClass = PotionOfOverHealing.class; + } + } + +public void explodeDew(int cell) { + + for (int n : Level.NEIGHBOURS8) { + int c = cell + n; + if (c >= 0 && c < Level.getLength() && Level.passable[c]) { + + if (Random.Int(10)==1){Dungeon.level.drop(new VioletDewdrop(), c).sprite.drop();} + else if (Random.Int(5)==1){Dungeon.level.drop(new RedDewdrop(), c).sprite.drop();} + else if (Random.Int(3)==1){Dungeon.level.drop(new YellowDewdrop(), c).sprite.drop();} + } + } + + } + + +} diff --git a/java/com/hmdzl/spspd/plants/Dreamfoil.java b/java/com/hmdzl/spspd/plants/Dreamfoil.java new file mode 100644 index 00000000..5590d590 --- /dev/null +++ b/java/com/hmdzl/spspd/plants/Dreamfoil.java @@ -0,0 +1,72 @@ +/* + * 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 + */ +package com.hmdzl.spspd.plants; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Bleeding; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Cripple; +import com.hmdzl.spspd.actors.buffs.Drowsy; +import com.hmdzl.spspd.actors.buffs.MagicalSleep; +import com.hmdzl.spspd.actors.buffs.Poison; +import com.hmdzl.spspd.actors.buffs.Slow; +import com.hmdzl.spspd.actors.buffs.Vertigo; +import com.hmdzl.spspd.actors.buffs.Weakness; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.items.food.vegetable.DreamLeaf; +import com.hmdzl.spspd.items.potions.PotionOfPurity; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class Dreamfoil extends Plant { + + { + image = 10; + } + + @Override + public void activate(Char ch) { + super.activate(ch); + Dungeon.level.drop(new DreamLeaf(), pos).sprite.drop(); + if (ch != null) { + if (ch instanceof Mob) + Buff.affect(ch, MagicalSleep.class); + else if (ch instanceof Hero) { + //GLog.i("You feel refreshed."); + Buff.detach(ch, Poison.class); + Buff.detach(ch, Cripple.class); + Buff.detach(ch, Weakness.class); + Buff.detach(ch, Bleeding.class); + Buff.detach(ch, Drowsy.class); + Buff.detach(ch, Slow.class); + Buff.detach(ch, Vertigo.class); + } + } + } + + + public static class Seed extends Plant.Seed { + { + image = ItemSpriteSheet.SEED_DREAMFOIL; + + plantClass = Dreamfoil.class; + alchemyClass = PotionOfPurity.class; + } + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/plants/Earthroot.java b/java/com/hmdzl/spspd/plants/Earthroot.java new file mode 100644 index 00000000..1e129b5e --- /dev/null +++ b/java/com/hmdzl/spspd/plants/Earthroot.java @@ -0,0 +1,135 @@ +/* + * 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 + */ +package com.hmdzl.spspd.plants; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.particles.EarthParticle; +import com.hmdzl.spspd.items.potions.PotionOfParalyticGas; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.ui.BuffIndicator; + +import com.watabou.noosa.Camera; +import com.watabou.utils.Bundle; + +public class Earthroot extends Plant { + + { + image = 5; + } + + @Override + public void activate(Char ch) { + super.activate(ch); + + if (ch != null) { + Buff.affect(ch, Armor.class).level = ch.HT; + } + + if (Dungeon.visible[pos]) { + CellEmitter.bottom(pos).start(EarthParticle.FACTORY, 0.05f, 8); + Camera.main.shake(1, 0.4f); + } + } + + public static class Seed extends Plant.Seed { + { + image = ItemSpriteSheet.SEED_EARTHROOT; + + plantClass = Earthroot.class; + alchemyClass = PotionOfParalyticGas.class; + + + } + } + + public static class Armor extends Buff { + + private static final float STEP = 1f; + + private int pos; + private int level; + + @Override + public boolean attachTo(Char target) { + pos = target.pos; + return super.attachTo(target); + } + + @Override + public boolean act() { + if (target.pos != pos) { + detach(); + } + spend(STEP); + return true; + } + + public int absorb(int damage) { + if (level <= damage - damage / 2) { + detach(); + return damage - level; + } else { + level -= damage - damage / 2; + return damage / 2; + } + } + + public void level(int value) { + if (level < value) { + level = value; + } + } + + @Override + public int icon() { + return BuffIndicator.ARMOR; + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public String desc() { + return Messages.get(this, "desc", level); + } + + + private static final String POS = "pos"; + private static final String LEVEL = "level"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(POS, pos); + bundle.put(LEVEL, level); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + pos = bundle.getInt(POS); + level = bundle.getInt(LEVEL); + } + } +} diff --git a/java/com/hmdzl/spspd/plants/Fadeleaf.java b/java/com/hmdzl/spspd/plants/Fadeleaf.java new file mode 100644 index 00000000..47f7aaad --- /dev/null +++ b/java/com/hmdzl/spspd/plants/Fadeleaf.java @@ -0,0 +1,80 @@ +/* + * 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 + */ +package com.hmdzl.spspd.plants; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.potions.PotionOfMindVision; +import com.hmdzl.spspd.items.scrolls.ScrollOfTeleportation; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class Fadeleaf extends Plant { + + { + image = 6; + } + + @Override + public void activate(Char ch) { + super.activate(ch); + + if (ch instanceof Hero) { + + ScrollOfTeleportation.teleportHero((Hero) ch); + ((Hero) ch).curAction = null; + + } else if (ch instanceof Mob) { + + int count = 10; + int newPos; + do { + newPos = Dungeon.level.randomRespawnCell(); + if (count-- <= 0) { + break; + } + } while (newPos == -1); + + if (newPos != -1) { + + ch.pos = newPos; + ch.sprite.place(ch.pos); + ch.sprite.visible = Dungeon.visible[pos]; + + } + + } + + if (Dungeon.visible[pos]) { + CellEmitter.get(pos).start(Speck.factory(Speck.LIGHT), 0.2f, 3); + } + } + + public static class Seed extends Plant.Seed { + { + image = ItemSpriteSheet.SEED_FADELEAF; + + plantClass = Fadeleaf.class; + alchemyClass = PotionOfMindVision.class; + } + + } +} diff --git a/java/com/hmdzl/spspd/plants/Firebloom.java b/java/com/hmdzl/spspd/plants/Firebloom.java new file mode 100644 index 00000000..fc6d1514 --- /dev/null +++ b/java/com/hmdzl/spspd/plants/Firebloom.java @@ -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 + */ +package com.hmdzl.spspd.plants; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.Blob; +import com.hmdzl.spspd.actors.blobs.Fire; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.particles.FlameParticle; +import com.hmdzl.spspd.items.potions.PotionOfLiquidFlame; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class Firebloom extends Plant { + + { + image = 0; + } + + @Override + public void activate(Char ch) { + super.activate(ch); + + GameScene.add(Blob.seed(pos, 2, Fire.class)); + + if (Dungeon.visible[pos]) { + CellEmitter.get(pos).burst(FlameParticle.FACTORY, 5); + } + } + + public static class Seed extends Plant.Seed { + { + image = ItemSpriteSheet.SEED_FIREBLOOM; + + plantClass = Firebloom.class; + alchemyClass = PotionOfLiquidFlame.class; + } + } +} diff --git a/java/com/hmdzl/spspd/plants/Flytrap.java b/java/com/hmdzl/spspd/plants/Flytrap.java new file mode 100644 index 00000000..f43b8ff5 --- /dev/null +++ b/java/com/hmdzl/spspd/plants/Flytrap.java @@ -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 + */ +package com.hmdzl.spspd.plants; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.items.UpgradeEatBall; +import com.hmdzl.spspd.items.food.fruit.Blackberry; +import com.hmdzl.spspd.items.food.fruit.Blueberry; +import com.hmdzl.spspd.items.food.fruit.Cloudberry; +import com.hmdzl.spspd.items.food.fruit.Moonberry; +import com.hmdzl.spspd.items.potions.PotionOfOverHealing; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.utils.Random; + +public class Flytrap extends Plant { + + { + image = 15; + } + + @Override + public void activate(Char ch) { + super.activate(ch); + Dungeon.level.drop(new UpgradeEatBall(), pos).sprite.drop(); + switch (Random.Int(4)){ + case 0: + Dungeon.level.drop(new Blackberry(), pos).sprite.drop(); + break; + case 1: + Dungeon.level.drop(new Blueberry(), pos).sprite.drop(); + break; + case 2: + Dungeon.level.drop(new Cloudberry(), pos).sprite.drop(); + break; + case 3: + Dungeon.level.drop(new Moonberry(), pos).sprite.drop(); + break; + } + } + + public static class Seed extends Plant.Seed { + { + image = ItemSpriteSheet.SEED_FLYTRAP; + + plantClass = Flytrap.class; + alchemyClass = PotionOfOverHealing.class; + } + + } +} diff --git a/java/com/hmdzl/spspd/plants/Icecap.java b/java/com/hmdzl/spspd/plants/Icecap.java new file mode 100644 index 00000000..6522b468 --- /dev/null +++ b/java/com/hmdzl/spspd/plants/Icecap.java @@ -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 + */ +package com.hmdzl.spspd.plants; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.Fire; +import com.hmdzl.spspd.actors.blobs.Freezing; +import com.hmdzl.spspd.items.potions.PotionOfFrost; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.utils.BArray; +import com.watabou.utils.PathFinder; + +public class Icecap extends Plant { + + { + image = 1; + } + + @Override + public void activate(Char ch) { + super.activate(ch); + + PathFinder + .buildDistanceMap(pos, BArray.not(Level.losBlockLow, null), 1); + + Fire fire = (Fire) Dungeon.level.blobs.get(Fire.class); + + for (int i = 0; i < Level.getLength(); i++) { + if (PathFinder.distance[i] < Integer.MAX_VALUE) { + Freezing.affect(i, fire); + } + } + } + + public static class Seed extends Plant.Seed { + { + image = ItemSpriteSheet.SEED_ICECAP; + + plantClass = Icecap.class; + alchemyClass = PotionOfFrost.class; + } + } +} diff --git a/java/com/hmdzl/spspd/plants/NutPlant.java b/java/com/hmdzl/spspd/plants/NutPlant.java new file mode 100644 index 00000000..f7cb2156 --- /dev/null +++ b/java/com/hmdzl/spspd/plants/NutPlant.java @@ -0,0 +1,34 @@ +package com.hmdzl.spspd.plants; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.items.food.Nut; +import com.hmdzl.spspd.items.food.vegetable.NutVegetable; +import com.hmdzl.spspd.items.potions.PotionOfHealing; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +/** + * Created by Evan on 13/08/2014. + */ +public class NutPlant extends Plant { + + { + image = 17; + } + + @Override + public void activate(Char ch) { + super.activate(ch); + Dungeon.level.drop(new Nut(), pos).sprite.drop(); + Dungeon.level.drop(new NutVegetable(), pos).sprite.drop(); + } + + public static class Seed extends Plant.Seed { + { + image = ItemSpriteSheet.SEED_DUNGEONNUT; + + plantClass = NutPlant.class; + alchemyClass = PotionOfHealing.class;; + } + } +} diff --git a/java/com/hmdzl/spspd/plants/Phaseshift.java b/java/com/hmdzl/spspd/plants/Phaseshift.java new file mode 100644 index 00000000..6c459694 --- /dev/null +++ b/java/com/hmdzl/spspd/plants/Phaseshift.java @@ -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 + */ +package com.hmdzl.spspd.plants; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.items.TransmutationBall; +import com.hmdzl.spspd.items.food.fruit.Blackberry; +import com.hmdzl.spspd.items.food.fruit.Blueberry; +import com.hmdzl.spspd.items.food.fruit.Cloudberry; +import com.hmdzl.spspd.items.food.fruit.Moonberry; +import com.hmdzl.spspd.items.potions.PotionOfMight; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.watabou.utils.Random; + +public class Phaseshift extends Plant { + + { + image = 14; + } + + @Override + public void activate(Char ch) { + super.activate(ch); + Dungeon.level.drop(new TransmutationBall(), pos).sprite.drop(); + switch (Random.Int(4)){ + case 0: + Dungeon.level.drop(new Blackberry(), pos).sprite.drop(); + break; + case 1: + Dungeon.level.drop(new Blueberry(), pos).sprite.drop(); + break; + case 2: + Dungeon.level.drop(new Cloudberry(), pos).sprite.drop(); + break; + case 3: + Dungeon.level.drop(new Moonberry(), pos).sprite.drop(); + break; + } + } + + public static class Seed extends Plant.Seed { + { + image = ItemSpriteSheet.SEED_PHASEPITCHER; + + plantClass = Phaseshift.class; + alchemyClass = PotionOfMight.class; + } + + + } +} diff --git a/java/com/hmdzl/spspd/plants/Plant.java b/java/com/hmdzl/spspd/plants/Plant.java new file mode 100644 index 00000000..78781531 --- /dev/null +++ b/java/com/hmdzl/spspd/plants/Plant.java @@ -0,0 +1,198 @@ +/* + * 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 + */ +package com.hmdzl.spspd.plants; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Barkskin; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.hero.HeroSubClass; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.particles.LeafParticle; +import com.hmdzl.spspd.items.Dewdrop; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.artifacts.SandalsOfNature; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.Terrain; +import com.hmdzl.spspd.sprites.PlantSprite; +import com.hmdzl.spspd.messages.Messages; + +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Bundlable; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +public class Plant implements Bundlable { + + public String plantName = Messages.get(this, "name"); + + public int image; + public int pos; + + public PlantSprite sprite; + + public void activate(Char ch) { + + if (ch instanceof Hero && ((Hero) ch).subClass == HeroSubClass.WARDEN) { + Buff.affect(ch, Barkskin.class).level(ch.HT / 3); + } + wither(); + } + + public static boolean checkPhase(int cell) { + Plant plant = Dungeon.level.plants.get(cell); + if (plant instanceof Phaseshift || plant instanceof Flytrap) { + return true; + } else { + return false; + } + } + + public void wither() { + Dungeon.level.uproot(pos); + + sprite.kill(); + if (Dungeon.visible[pos]) { + CellEmitter.get(pos).burst(LeafParticle.GENERAL, 6); + } + + if (Dungeon.hero.subClass == HeroSubClass.WARDEN) { + + int naturalismLevel = 0; + SandalsOfNature.Naturalism naturalism = Dungeon.hero + .buff(SandalsOfNature.Naturalism.class); + if (naturalism != null) { + naturalismLevel = naturalism.level() + 1; + } + + if (Random.Int(5 - (naturalismLevel / 2)) == 0) { + Item seed = Generator.random(Generator.Category.SEED); + Dungeon.level.drop(seed, pos).sprite.drop(); + } + if (Random.Int(5 - naturalismLevel) == 0) { + Dungeon.level.drop(new Dewdrop(), pos).sprite.drop(); + } + } + } + + private static final String POS = "pos"; + + @Override + public void restoreFromBundle(Bundle bundle) { + pos = bundle.getInt(POS); + } + + @Override + public void storeInBundle(Bundle bundle) { + bundle.put(POS, pos); + } + + public String desc() { + return Messages.get(this, "desc"); + } + + public static class Seed extends Item { + + public static final String AC_PLANT = "PLANT"; + + private static final float TIME_TO_PLANT = 1f; + + { + stackable = true; + defaultAction = AC_THROW; + } + + protected Class plantClass; + + public Class alchemyClass; + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + actions.add(AC_PLANT); + return actions; + } + + @Override + protected void onThrow(int cell) { + if (Dungeon.level.map[cell] == Terrain.ALCHEMY || Level.pit[cell]) { + super.onThrow(cell); + } else { + Dungeon.level.plant(this, cell); + } + } + + @Override + public void execute(Hero hero, String action) { + if (action.equals(AC_PLANT)) { + + hero.spend(TIME_TO_PLANT); + hero.busy(); + ((Seed) detach(hero.belongings.backpack)).onThrow(hero.pos); + + hero.sprite.operate(hero.pos); + + } else { + super.execute(hero, action); + } + } + + public Plant couch(int pos) { + try { + if (Dungeon.visible[pos]) { + Sample.INSTANCE.play(Assets.SND_PLANT); + } + Plant plant = plantClass.newInstance(); + plant.pos = pos; + return plant; + } catch (Exception e) { + return null; + } + } + + @Override + public boolean isUpgradable() { + return false; + } + + @Override + public boolean isIdentified() { + return true; + } + + @Override + public int price() { + return 10 * quantity; + } + + @Override + public String desc() { + return Messages.get(plantClass, "desc"); + } + + @Override + public String info() { + return Messages.get( Seed.class, "info", desc() ); + } + } +} diff --git a/java/com/hmdzl/spspd/plants/Rotberry.java b/java/com/hmdzl/spspd/plants/Rotberry.java new file mode 100644 index 00000000..83b965c4 --- /dev/null +++ b/java/com/hmdzl/spspd/plants/Rotberry.java @@ -0,0 +1,57 @@ +/* + * 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 + */ +package com.hmdzl.spspd.plants; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.blobs.Blob; +import com.hmdzl.spspd.actors.blobs.ToxicGas; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Roots; +import com.hmdzl.spspd.items.potions.PotionOfStrength; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class Rotberry extends Plant { + + { + image = 7; + } + + @Override + public void activate(Char ch) { + super.activate(ch); + + GameScene.add(Blob.seed(pos, 100, ToxicGas.class)); + + Dungeon.level.drop(new Seed(), pos).sprite.drop(); + + if (ch != null) { + Buff.prolong(ch, Roots.class,3); + } + } + + public static class Seed extends Plant.Seed { + { + image = ItemSpriteSheet.SEED_ROTBERRY; + + plantClass = Rotberry.class; + alchemyClass = PotionOfStrength.class; + } + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/plants/Seedpod.java b/java/com/hmdzl/spspd/plants/Seedpod.java new file mode 100644 index 00000000..342bf6d5 --- /dev/null +++ b/java/com/hmdzl/spspd/plants/Seedpod.java @@ -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 + */ +package com.hmdzl.spspd.plants; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.items.potions.PotionOfOverHealing; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.levels.Level; +import com.watabou.utils.Random; +import java.util.ArrayList; + +public class Seedpod extends Plant{ + + { + image = 13; + } + + @Override + public void activate(Char ch) { + super.activate(ch); + + int nSeeds = Random.NormalIntRange(1, 5); + + ArrayList candidates = new ArrayList(); + for (int i : Level.NEIGHBOURS8){ + if (Level.passable[pos+i]){ + candidates.add(pos+i); + } + } + + for (int i = 0; i < nSeeds && !candidates.isEmpty(); i++){ + Integer c = Random.element(candidates); + Dungeon.level.drop(Generator.random(Generator.Category.SEED), c).sprite.drop(pos); + candidates.remove(c); + } + + } + + + public static class Seed extends Plant.Seed { + { + image = ItemSpriteSheet.SEED_SEEDPOD; + + plantClass = Seedpod.class; + alchemyClass = PotionOfOverHealing.class;; + } + } +} + + diff --git a/java/com/hmdzl/spspd/plants/Sorrowmoss.java b/java/com/hmdzl/spspd/plants/Sorrowmoss.java new file mode 100644 index 00000000..ca5cb945 --- /dev/null +++ b/java/com/hmdzl/spspd/plants/Sorrowmoss.java @@ -0,0 +1,57 @@ +/* + * 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 + */ +package com.hmdzl.spspd.plants; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Poison; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.particles.PoisonParticle; +import com.hmdzl.spspd.items.potions.PotionOfToxicGas; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class Sorrowmoss extends Plant { + + { + image = 2; + } + + @Override + public void activate(Char ch) { + super.activate(ch); + + if (ch != null) { + Buff.affect(ch, Poison.class).set( + Poison.durationFactor(ch) * (4 + Dungeon.depth / 2)); + } + + if (Dungeon.visible[pos]) { + CellEmitter.center(pos).burst(PoisonParticle.SPLASH, 3); + } + } + + public static class Seed extends Plant.Seed { + { + image = ItemSpriteSheet.SEED_SORROWMOSS; + + plantClass = Sorrowmoss.class; + alchemyClass = PotionOfToxicGas.class; + } + } +} diff --git a/java/com/hmdzl/spspd/plants/Starflower.java b/java/com/hmdzl/spspd/plants/Starflower.java new file mode 100644 index 00000000..987f9d01 --- /dev/null +++ b/java/com/hmdzl/spspd/plants/Starflower.java @@ -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 + */ +package com.hmdzl.spspd.plants; + + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Strength; +import com.hmdzl.spspd.items.food.vegetable.BattleFlower; +import com.hmdzl.spspd.items.potions.PotionOfExperience; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +public class Starflower extends Plant { + + { + image = 11; + } + + @Override + public void activate(Char ch) { + super.activate(ch); + Dungeon.level.drop(new BattleFlower(), pos).sprite.drop(); + if (ch != null) { + Buff.affect(ch, Strength.class); + } + } + + public static class Seed extends Plant.Seed{ + + { + image = ItemSpriteSheet.SEED_STARFLOWER; + + plantClass = Starflower.class; + alchemyClass = PotionOfExperience.class; + } + } +} diff --git a/java/com/hmdzl/spspd/plants/Stormvine.java b/java/com/hmdzl/spspd/plants/Stormvine.java new file mode 100644 index 00000000..c97ae0c5 --- /dev/null +++ b/java/com/hmdzl/spspd/plants/Stormvine.java @@ -0,0 +1,36 @@ +package com.hmdzl.spspd.plants; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Vertigo; +import com.hmdzl.spspd.items.potions.PotionOfLevitation; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +/** + * Created by Evan on 23/10/2014. + */ +public class Stormvine extends Plant { + + { + image = 9; + } + + @Override + public void activate(Char ch) { + super.activate(ch); + + if (ch != null) { + Buff.affect(ch, Vertigo.class, Vertigo.duration(ch)); + } + } + + + public static class Seed extends Plant.Seed { + { + image = ItemSpriteSheet.SEED_STORMVINE; + + plantClass = Stormvine.class; + alchemyClass = PotionOfLevitation.class; + } + } +} diff --git a/java/com/hmdzl/spspd/plants/Sungrass.java b/java/com/hmdzl/spspd/plants/Sungrass.java new file mode 100644 index 00000000..f5dc79c2 --- /dev/null +++ b/java/com/hmdzl/spspd/plants/Sungrass.java @@ -0,0 +1,157 @@ +/* + * 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 + */ +package com.hmdzl.spspd.plants; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.effects.particles.ShaftParticle; +import com.hmdzl.spspd.items.food.vegetable.HealGrass; +import com.hmdzl.spspd.items.potions.PotionOfHealing; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.BuffIndicator; + +import com.watabou.utils.Bundle; + +public class Sungrass extends Plant { + + + { + image = 4; + } + + @Override + public void activate(Char ch) { + super.activate(ch); + Dungeon.level.drop(new HealGrass(), pos).sprite.drop(); + if (ch != null) { + Buff.affect(ch, Health.class).level = ch.HT; + } + + if (Dungeon.visible[pos]) { + CellEmitter.get(pos).start(ShaftParticle.FACTORY, 0.2f, 3); + } + } + + public static class Seed extends Plant.Seed { + { + + image = ItemSpriteSheet.SEED_SUNGRASS; + + plantClass = Sungrass.class; + alchemyClass = PotionOfHealing.class; + + + } + } + + public static class Health extends Buff { + + private static final float STEP = 1f; + + private int pos; + private int healCurr = 1; + private int count = 0; + private int level; + + @Override + public boolean attachTo(Char target) { + pos = target.pos; + return super.attachTo(target); + } + + @Override + public boolean act() { + if (target.pos != pos) { + detach(); + } + if (count == 5) { + if (level <= healCurr * .025 * target.HT) { + target.HP = Math.min(target.HT, target.HP + level); + target.sprite.emitter().burst(Speck.factory(Speck.HEALING), + 1); + detach(); + } else { + target.HP = Math.min(target.HT, target.HP + + (int) (healCurr * .025 * target.HT)); + level -= (healCurr * .025 * target.HT); + if (healCurr < 6) + healCurr++; + target.sprite.emitter().burst(Speck.factory(Speck.HEALING), + 1); + } + count = 1; + } else { + count++; + } + if (level <= 0) + detach(); + spend(STEP); + return true; + } + + public int absorb(int damage) { + level -= damage; + if (level <= 0) + detach(); + return damage; + } + + @Override + public int icon() { + return BuffIndicator.HEALING; + } + + @Override + public String toString() { + return Messages.get(this, "name"); + } + + @Override + public String desc() { + return Messages.get(this, "desc", level); + } + + private static final String POS = "pos"; + private static final String HEALCURR = "healCurr"; + private static final String COUNT = "count"; + private static final String LEVEL = "level"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(POS, pos); + bundle.put(HEALCURR, healCurr); + bundle.put(COUNT, count); + bundle.put(LEVEL, level); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + pos = bundle.getInt(POS); + healCurr = bundle.getInt(HEALCURR); + count = bundle.getInt(COUNT); + level = bundle.getInt(LEVEL); + + } + } +} diff --git a/java/com/hmdzl/spspd/scenes/AboutScene.java b/java/com/hmdzl/spspd/scenes/AboutScene.java new file mode 100644 index 00000000..2d7d45b9 --- /dev/null +++ b/java/com/hmdzl/spspd/scenes/AboutScene.java @@ -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 + */ +package com.hmdzl.spspd.scenes; + +import android.content.Intent; +import android.net.Uri; + +import com.hmdzl.spspd.ShatteredPixelDungeon; +import com.hmdzl.spspd.effects.Flare; +import com.hmdzl.spspd.ui.Archs; +import com.hmdzl.spspd.ui.ExitButton; +import com.hmdzl.spspd.ui.Icons; +import com.hmdzl.spspd.ui.RenderedTextMultiline; +import com.hmdzl.spspd.ui.Window; +import com.watabou.input.Touchscreen.Touch; +import com.watabou.noosa.Camera; +import com.watabou.noosa.Game; +import com.watabou.noosa.Image; +import com.watabou.noosa.RenderedText; +import com.watabou.noosa.TouchArea; + +public class AboutScene extends PixelScene { + + private static final String TTL_SHPX = "SPecial Surprise Pixel Dungeon"; + + private static final String TXT_SHPX = "Modified from lots of Pixel Dungeon Mods"; + + private static final String LNK_SHPX = "github.com/hmdzl001/SPS-PD"; + + private static final String TTL_WATA = "Original Pixel Dungeon"; + + private static final String TXT_WATA = "Code & Graphics: Watabou\n" + "Music: Cube_Code"; + + private static final String LNK_WATA = "pixeldungeon.watabou.ru"; + + @Override + public void create() { + super.create(); + + final float colWidth = Camera.main.width + / (ShatteredPixelDungeon.landscape() ? 2 : 1); + final float colTop = (Camera.main.height / 2) + - (ShatteredPixelDungeon.landscape() ? 30 : 90); + final float wataOffset = ShatteredPixelDungeon.landscape() ? colWidth + : 0; + + Image shpx = Icons.SHPX.get(); + shpx.x = align((colWidth - shpx.width()) / 2); + shpx.y = align(colTop); + align(shpx); + add(shpx); + + new Flare(7, 64).color(0x225511, true).show(shpx, 0).angularSpeed = +20; + + RenderedText shpxtitle = renderText( TTL_SHPX, 8 ); + shpxtitle.hardlight( Window.SHPX_COLOR ); + add( shpxtitle ); + + shpxtitle.x = (colWidth - shpxtitle.width()) / 2; + shpxtitle.y = shpx.y + shpx.height + 5; + align(shpxtitle); + + RenderedTextMultiline shpxtext = renderMultiline( TXT_SHPX, 8 ); + shpxtext.maxWidth((int)Math.min(colWidth, 120)); + add( shpxtext ); + + shpxtext.setPos((colWidth - shpxtext.width()) / 2, shpxtitle.y + shpxtitle.height() + 12); + align(shpxtext); + + RenderedTextMultiline shpxlink = renderMultiline( LNK_SHPX, 8 ); + shpxlink.maxWidth(shpxtext.maxWidth()); + shpxlink.hardlight( Window.SHPX_COLOR ); + add( shpxlink ); + + shpxlink.setPos((colWidth - shpxlink.width()) / 2, shpxtext.bottom() + 6); + align(shpxlink); + + TouchArea shpxhotArea = new TouchArea( shpxlink.left(), shpxlink.top(), shpxlink.width(), shpxlink.height() ) { + @Override + protected void onClick( Touch touch ) { + Intent intent = new Intent( Intent.ACTION_VIEW, Uri.parse( "https://" + LNK_SHPX ) ); + Game.instance.startActivity( intent ); + } + }; + add(shpxhotArea); + + Image wata = Icons.WATA.get(); + wata.x = wataOffset + (colWidth - wata.width()) / 2; + wata.y = ShatteredPixelDungeon.landscape() ? + colTop: + shpxlink.top() + wata.height + 20; + align(wata); + add( wata ); + + new Flare(7, 64).color(0x112233, true).show(wata, 0).angularSpeed = +20; + + RenderedText wataTitle = renderText( TTL_WATA, 8 ); + wataTitle.hardlight(Window.TITLE_COLOR); + add( wataTitle ); + + wataTitle.x = wataOffset + (colWidth - wataTitle.width()) / 2; + wataTitle.y = wata.y + wata.height + 11; + align(wataTitle); + + RenderedTextMultiline wataText = renderMultiline( TXT_WATA, 8 ); + wataText.maxWidth((int)Math.min(colWidth, 120)); + add( wataText ); + + wataText.setPos(wataOffset + (colWidth - wataText.width()) / 2, wataTitle.y + wataTitle.height() + 12); + align(wataText); + + RenderedTextMultiline wataLink = renderMultiline( LNK_WATA, 8 ); + wataLink.maxWidth((int)Math.min(colWidth, 120)); + wataLink.hardlight(Window.TITLE_COLOR); + add(wataLink); + + wataLink.setPos(wataOffset + (colWidth - wataLink.width()) / 2 , wataText.bottom() + 6); + align(wataLink); + + TouchArea hotArea = new TouchArea( wataLink.left(), wataLink.top(), wataLink.width(), wataLink.height() ) { + @Override + protected void onClick( Touch touch ) { + Intent intent = new Intent( Intent.ACTION_VIEW, Uri.parse( "https://" + LNK_WATA ) ); + Game.instance.startActivity( intent ); + } + }; + add( hotArea ); + + Archs archs = new Archs(); + archs.setSize(Camera.main.width, Camera.main.height); + addToBack(archs); + + ExitButton btnExit = new ExitButton(); + btnExit.setPos(Camera.main.width - btnExit.width(), 0); + add(btnExit); + + fadeIn(); + } + + @Override + protected void onBackPressed() { + ShatteredPixelDungeon.switchNoFade(TitleScene.class); + } +} diff --git a/java/com/hmdzl/spspd/scenes/AmuletScene.java b/java/com/hmdzl/spspd/scenes/AmuletScene.java new file mode 100644 index 00000000..05742f36 --- /dev/null +++ b/java/com/hmdzl/spspd/scenes/AmuletScene.java @@ -0,0 +1,119 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2015 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.scenes; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.ResultDescriptions; +import com.hmdzl.spspd.effects.Flare; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.RedButton; +import com.hmdzl.spspd.ui.RenderedTextMultiline; +import com.watabou.noosa.Camera; +import com.watabou.noosa.Game; +import com.watabou.noosa.Image; +import com.watabou.utils.Random; + +public class AmuletScene extends PixelScene { + + private static final int WIDTH = 120; + private static final int BTN_HEIGHT = 18; + private static final float SMALL_GAP = 2; + private static final float LARGE_GAP = 8; + + private Image amulet; + + @Override + public void create() { + super.create(); + + RenderedTextMultiline text = null; + + text = renderMultiline( Messages.get(this, "text"), 8 ); + text.maxWidth(WIDTH); + add( text ); + + + amulet = new Image( Assets.AMULET ); + add( amulet ); + + RedButton btnExit = new RedButton( Messages.get(this, "exit") ) { + @Override + protected void onClick() { + Dungeon.win(Messages.format(ResultDescriptions.WIN)); + Dungeon.deleteGame( Dungeon.hero.heroClass, true ); + Game.switchScene( RankingsScene.class ); + } + }; + btnExit.setSize( WIDTH, BTN_HEIGHT ); + add( btnExit ); + + RedButton btnStay = new RedButton( Messages.get(this, "stay") ) { + @Override + protected void onClick() { + onBackPressed(); + } + }; + btnStay.setSize( WIDTH, BTN_HEIGHT ); + add( btnStay ); + + float height; + + height = amulet.height + LARGE_GAP + text.height() + LARGE_GAP + btnExit.height() + SMALL_GAP + btnStay.height(); + + amulet.x = (Camera.main.width - amulet.width) / 2; + amulet.y = (Camera.main.height - height) / 2; + align(amulet); + + text.setPos((Camera.main.width - text.width()) / 2, amulet.y + amulet.height + LARGE_GAP); + align(text); + + btnExit.setPos( (Camera.main.width - btnExit.width()) / 2, text.top() + text.height() + LARGE_GAP ); + btnStay.setPos( btnExit.left(), btnExit.bottom() + SMALL_GAP ); + + + new Flare( 8, 48 ).color( 0xFFDDBB, true ).show( amulet, 0 ).angularSpeed = +30; + + fadeIn(); + } + + @Override + protected void onBackPressed() { + InterlevelScene.mode = InterlevelScene.Mode.CONTINUE; + Game.switchScene( InterlevelScene.class ); + } + + private float timer = 0; + + @Override + public void update() { + super.update(); + + if ((timer -= Game.elapsed) < 0) { + timer = Random.Float( 0.5f, 5f ); + + Speck star = (Speck)recycle( Speck.class ); + star.reset( 0, amulet.x + 10.5f, amulet.y + 5.5f, Speck.DISCOVER ); + add( star ); + } + } +} diff --git a/java/com/hmdzl/spspd/scenes/BadgesScene.java b/java/com/hmdzl/spspd/scenes/BadgesScene.java new file mode 100644 index 00000000..43704578 --- /dev/null +++ b/java/com/hmdzl/spspd/scenes/BadgesScene.java @@ -0,0 +1,112 @@ +/* + * 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 + */ +package com.hmdzl.spspd.scenes; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.Chrome; +import com.hmdzl.spspd.ShatteredPixelDungeon; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.Archs; +import com.hmdzl.spspd.ui.BadgesList; +import com.hmdzl.spspd.ui.ExitButton; +import com.hmdzl.spspd.ui.ScrollPane; +import com.hmdzl.spspd.ui.Window; +import com.watabou.noosa.Camera; +import com.watabou.noosa.Game; +import com.watabou.noosa.NinePatch; +import com.watabou.noosa.audio.Music; +import com.watabou.utils.Callback; +import com.watabou.noosa.RenderedText; + +public class BadgesScene extends PixelScene { + + private static final String TXT_TITLE = "Your Badges"; + + private static final int MAX_PANE_WIDTH = 160; + + @Override + public void create() { + + super.create(); + + Music.INSTANCE.play(Assets.THEME, true); + Music.INSTANCE.volume(1f); + + uiCamera.visible = false; + + int w = Camera.main.width; + int h = Camera.main.height; + + Archs archs = new Archs(); + archs.setSize(w, h); + add(archs); + + int pw = Math.min(MAX_PANE_WIDTH, w - 6); + int ph = h - 30; + + NinePatch panel = Chrome.get(Chrome.Type.WINDOW); + panel.size(pw, ph); + panel.x = (w - pw) / 2; + panel.y = (h - ph) / 2; + add(panel); + + RenderedText title = PixelScene.renderText( Messages.get(this, "title"), 9 ); + title.hardlight(Window.TITLE_COLOR); + title.x = align((w - title.width()) / 2); + title.y = align((panel.y - title.baseLine()) / 2); + add(title); + + Badges.loadGlobal(); + + ScrollPane list = new BadgesList(true); + add(list); + + list.setRect(panel.x + panel.marginLeft(), panel.y + panel.marginTop(), + panel.innerWidth(), panel.innerHeight()); + + ExitButton btnExit = new ExitButton(); + btnExit.setPos(Camera.main.width - btnExit.width(), 0); + add(btnExit); + + fadeIn(); + + Badges.loadingListener = new Callback() { + @Override + public void call() { + if (Game.scene() == BadgesScene.this) { + ShatteredPixelDungeon.switchNoFade(BadgesScene.class); + } + } + }; + } + + @Override + public void destroy() { + + Badges.saveGlobal(); + Badges.loadingListener = null; + + super.destroy(); + } + + @Override + protected void onBackPressed() { + ShatteredPixelDungeon.switchNoFade(TitleScene.class); + } +} diff --git a/java/com/hmdzl/spspd/scenes/CellSelector.java b/java/com/hmdzl/spspd/scenes/CellSelector.java new file mode 100644 index 00000000..310e4781 --- /dev/null +++ b/java/com/hmdzl/spspd/scenes/CellSelector.java @@ -0,0 +1,179 @@ +/* + * 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 + */ +package com.hmdzl.spspd.scenes; + +import com.hmdzl.spspd.DungeonTilemap; +import com.hmdzl.spspd.ShatteredPixelDungeon; +import com.watabou.input.Touchscreen.Touch; +import com.watabou.noosa.TouchArea; +import com.watabou.utils.GameMath; +import com.watabou.utils.PointF; + +public class CellSelector extends TouchArea { + + public Listener listener = null; + + public boolean enabled; + + private float dragThreshold; + + public CellSelector(DungeonTilemap map) { + super(map); + camera = map.camera(); + + dragThreshold = PixelScene.defaultZoom * DungeonTilemap.SIZE / 2; + } + + @Override + protected void onClick(Touch touch) { + if (dragging) { + + dragging = false; + + } else { + + select(((DungeonTilemap) target).screenToTile( + (int) touch.current.x, (int) touch.current.y)); + } + } + + public void select(int cell) { + if (enabled && listener != null && cell != -1) { + + listener.onSelect(cell); + GameScene.ready(); + + } else { + + GameScene.cancel(); + + } + } + + private boolean pinching = false; + private Touch another; + private float startZoom; + private float startSpan; + + @Override + protected void onTouchDown(Touch t) { + + if (t != touch && another == null) { + + if (!touch.down) { + touch = t; + onTouchDown(t); + return; + } + + pinching = true; + + another = t; + startSpan = PointF.distance(touch.current, another.current); + startZoom = camera.zoom; + + dragging = false; + } else if (t != touch) { + reset(); + } + } + + @Override + protected void onTouchUp(Touch t) { + if (pinching && (t == touch || t == another)) { + + pinching = false; + + int zoom = Math.round(camera.zoom); + camera.zoom(zoom); + ShatteredPixelDungeon.zoom((int) (zoom - PixelScene.defaultZoom)); + + dragging = true; + if (t == touch) { + touch = another; + } + another = null; + lastPos.set(touch.current); + } + } + + private boolean dragging = false; + private PointF lastPos = new PointF(); + + @Override + protected void onDrag(Touch t) { + + camera.target = null; + + if (pinching) { + + float curSpan = PointF.distance(touch.current, another.current); + camera.zoom(GameMath.gate(PixelScene.minZoom, startZoom * curSpan + / startSpan, PixelScene.maxZoom)); + + } else { + + if (!dragging + && PointF.distance(t.current, t.start) > dragThreshold) { + + dragging = true; + lastPos.set(t.current); + + } else if (dragging) { + camera.scroll.offset(PointF.diff(lastPos, t.current).invScale( + camera.zoom)); + lastPos.set(t.current); + } + } + + } + + public void cancel() { + + if (listener != null) { + listener.onSelect(null); + } + + GameScene.ready(); + } + + @Override + public void reset() { + super.reset(); + another = null; + if (pinching) { + pinching = false; + + int zoom = Math.round(camera.zoom); + camera.zoom(zoom); + ShatteredPixelDungeon.zoom((int) (zoom - PixelScene.defaultZoom)); + } + } + + public void enable(boolean value) { + if (enabled != value) { + enabled = value; + } + } + + public interface Listener { + void onSelect(Integer cell); + + String prompt(); + } +} diff --git a/java/com/hmdzl/spspd/scenes/GameScene.java b/java/com/hmdzl/spspd/scenes/GameScene.java new file mode 100644 index 00000000..80889681 --- /dev/null +++ b/java/com/hmdzl/spspd/scenes/GameScene.java @@ -0,0 +1,866 @@ +/* + * 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 + */ +package com.hmdzl.spspd.scenes; + +import java.io.IOException; +import java.util.ArrayList; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.DungeonTilemap; +import com.hmdzl.spspd.FogOfWar; +import com.hmdzl.spspd.ShatteredPixelDungeon; +import com.hmdzl.spspd.Statistics; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.blobs.Blob; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.effects.BannerSprites; +import com.hmdzl.spspd.effects.BlobEmitter; +import com.hmdzl.spspd.effects.CircleArc; +import com.hmdzl.spspd.effects.EmoIcon; +import com.hmdzl.spspd.effects.Flare; +import com.hmdzl.spspd.effects.FloatingText; +import com.hmdzl.spspd.effects.Ripple; +import com.hmdzl.spspd.effects.SpellSprite; +import com.hmdzl.spspd.items.Heap; +import com.hmdzl.spspd.items.summon.Honeypot; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.bags.PotionBandolier; +import com.hmdzl.spspd.items.bags.ScrollHolder; +import com.hmdzl.spspd.items.bags.SeedPouch; +import com.hmdzl.spspd.items.bags.WandHolster; +import com.hmdzl.spspd.items.potions.Potion; +import com.hmdzl.spspd.items.scrolls.ScrollOfTeleportation; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.RegularLevel; +import com.hmdzl.spspd.levels.features.Chasm; +import com.hmdzl.spspd.levels.traps.Trap; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.plants.Plant; +import com.hmdzl.spspd.sprites.CharSprite; +import com.hmdzl.spspd.sprites.DiscardedItemSprite; +import com.hmdzl.spspd.sprites.HeroSprite; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.sprites.PlantSprite; +import com.hmdzl.spspd.sprites.TrapSprite; +import com.hmdzl.spspd.ui.ActionIndicator; +import com.hmdzl.spspd.ui.AttackIndicator; +import com.hmdzl.spspd.ui.Banner; +import com.hmdzl.spspd.ui.BusyIndicator; +import com.hmdzl.spspd.ui.CharHealthIndicator; +import com.hmdzl.spspd.ui.GameLog; +import com.hmdzl.spspd.ui.HealthIndicator; +import com.hmdzl.spspd.ui.LootIndicator; +import com.hmdzl.spspd.ui.QuickSlotButton; +import com.hmdzl.spspd.ui.ResumeIndicator; +import com.hmdzl.spspd.ui.StatusPane; +import com.hmdzl.spspd.ui.TargetHealthIndicator; +import com.hmdzl.spspd.ui.Toast; +import com.hmdzl.spspd.ui.Toolbar; +import com.hmdzl.spspd.ui.Window; +import com.hmdzl.spspd.utils.GLog; +import com.hmdzl.spspd.windows.WndBag; +import com.hmdzl.spspd.windows.WndBag.Mode; +import com.hmdzl.spspd.windows.WndGame; +import com.hmdzl.spspd.windows.WndHero; +import com.hmdzl.spspd.windows.WndInfoCell; +import com.hmdzl.spspd.windows.WndInfoItem; +import com.hmdzl.spspd.windows.WndInfoMob; +import com.hmdzl.spspd.windows.WndInfoPlant; +import com.hmdzl.spspd.windows.WndInfoTrap; +import com.hmdzl.spspd.windows.WndMessage; +import com.hmdzl.spspd.windows.WndStory; +import com.hmdzl.spspd.windows.WndTradeItem; +import com.watabou.noosa.Camera; +import com.watabou.noosa.Game; +import com.watabou.noosa.Group; +import com.watabou.noosa.SkinnedBlock; +import com.watabou.noosa.Visual; +import com.watabou.noosa.audio.Music; +import com.watabou.noosa.audio.Sample; +import com.watabou.noosa.particles.Emitter; +import com.watabou.utils.Random; + +public class GameScene extends PixelScene { + + private static final String TXT_WELCOME = "Welcome to the level %d of Pixel Dungeon!"; + private static final String TXT_WELCOME_BACK = "Welcome back to the level %d of Pixel Dungeon!"; + + private static final String TXT_CHASM = "Your steps echo across the dungeon."; + private static final String TXT_WATER = "You hear water splashing around you."; + private static final String TXT_GRASS = "The smell of vegetation is thick in the air."; + private static final String TXT_DARK = "You can hear enemies moving in the darkness..."; + private static final String TXT_SECRETS = "The atmosphere hints that this floor hides many secrets."; + + static GameScene scene; + + private SkinnedBlock water; + private DungeonTilemap tiles; + private FogOfWar fog; + private HeroSprite hero; + + private GameLog log; + + private BusyIndicator busy; + private CircleArc counter; + + private static CellSelector cellSelector; + + private Group terrain; + private Group ripples; + private Group plants; + private Group traps; + private Group heaps; + private Group mobs; + private Group emitters; + private Group effects; + private Group gases; + private Group spells; + private Group statuses; + private Group emoicons; + private Group healthIndicators; + + private Toolbar toolbar; + private Toast prompt; + + private AttackIndicator attack; + private LootIndicator loot; + private ActionIndicator action; + private ResumeIndicator resume; + + @Override + public void create() { + + Music.INSTANCE.play(Assets.TUNE, true); + Music.INSTANCE.volume(1f); + + ShatteredPixelDungeon.lastClass(Dungeon.hero.heroClass.ordinal()); + + super.create(); + Camera.main.zoom(defaultZoom + ShatteredPixelDungeon.zoom()); + + scene = this; + + terrain = new Group(); + add(terrain); + + water = new SkinnedBlock(Level.getWidth() * DungeonTilemap.SIZE, + Level.HEIGHT * DungeonTilemap.SIZE, Dungeon.level.waterTex()); + terrain.add(water); + + ripples = new Group(); + terrain.add(ripples); + + tiles = new DungeonTilemap(); + terrain.add(tiles); + + Dungeon.level.addVisuals(this); + + traps = new Group(); + add(traps); + + int size = Dungeon.level.traps.size(); + for (int i=0; i < size; i++) { + addTrapSprite( Dungeon.level.traps.valueAt( i ) ); + } + + plants = new Group(); + add(plants); + + size = Dungeon.level.plants.size(); + for (int i = 0; i < size; i++) { + addPlantSprite(Dungeon.level.plants.valueAt(i)); + } + + heaps = new Group(); + add(heaps); + + size = Dungeon.level.heaps.size(); + for (int i = 0; i < size; i++) { + addHeapSprite(Dungeon.level.heaps.valueAt(i)); + } + + emitters = new Group(); + effects = new Group(); + emoicons = new Group(); + healthIndicators = new Group(); + + mobs = new Group(); + add(mobs); + + for (Mob mob : Dungeon.level.mobs) { + addMobSprite(mob); + } + + add(emitters); + add(effects); + + gases = new Group(); + add(gases); + + for (Blob blob : Dungeon.level.blobs.values()) { + blob.emitter = null; + addBlobSprite(blob); + } + + fog = new FogOfWar(Level.getWidth(), Level.HEIGHT); + fog.updateVisibility(Dungeon.visible, Dungeon.level.visited, + Dungeon.level.mapped); + add(fog); + + brightness(ShatteredPixelDungeon.brightness()); + + spells = new Group(); + add(spells); + + statuses = new Group(); + add(statuses); + + add( healthIndicators ); + //always appears ontop of other health indicators + add( new TargetHealthIndicator() ); + + add(emoicons); + + hero = new HeroSprite(); + hero.place(Dungeon.hero.pos); + hero.updateArmor(); + mobs.add(hero); + + add(new HealthIndicator()); + + add(cellSelector = new CellSelector(tiles)); + + StatusPane sb = new StatusPane(); + sb.camera = uiCamera; + sb.setSize(uiCamera.width, 0); + add(sb); + + toolbar = new Toolbar(); + toolbar.camera = uiCamera; + toolbar.setRect(0, uiCamera.height - toolbar.height(), uiCamera.width, + toolbar.height()); + add(toolbar); + + attack = new AttackIndicator(); + attack.camera = uiCamera; + attack.setPos(uiCamera.width - attack.width(), + toolbar.top() - attack.height()); + add(attack); + + loot = new LootIndicator(); + loot.camera = uiCamera; + add(loot); + + action = new ActionIndicator(); + action.camera = uiCamera; + action.setPos(uiCamera.width - attack.width(), + toolbar.top() -3 * attack.height()); + add( action ); + + resume = new ResumeIndicator(); + resume.camera = uiCamera; + add(resume); + + layoutTags(); + + log = new GameLog(); + log.camera = uiCamera; + log.setRect(0, toolbar.top(), attack.left(), 0); + add(log); + + if (Dungeon.depth < Statistics.deepestFloor) + GLog.i(Messages.get(this, "welcome_back"), Dungeon.depth); + else + GLog.i(Messages.get(this, "welcome"), Dungeon.depth); + Sample.INSTANCE.play(Assets.SND_DESCEND); + switch (Dungeon.level.feeling) { + case CHASM: + GLog.w(Messages.get(this, "chasm")); + break; + case WATER: + GLog.w(Messages.get(this, "water")); + break; + case GRASS: + GLog.w(Messages.get(this, "grass")); + break; + case DARK: + GLog.w(Messages.get(this, "dark")); + break; + default: + } + if (Dungeon.level instanceof RegularLevel + && ((RegularLevel) Dungeon.level).secretDoors > Random + .IntRange(3, 4)) { + GLog.w(Messages.get(this, "secrets")); + } + + busy = new BusyIndicator(); + busy.camera = uiCamera; + busy.x = 1; + busy.y = sb.bottom() + 1; + add(busy); + + /*counter = new CircleArc(18, 4.25f); + counter.color( 0x808080, true ); + counter.camera = uiCamera; + counter.show(this, busy.center(), 0f);*/ + + switch (InterlevelScene.mode) { + case RESURRECT: + ScrollOfTeleportation.appear(Dungeon.hero, Dungeon.level.entrance); + new Flare(8, 32).color(0xFFFF66, true).show(hero, 2f); + break; + case RETURN: + ScrollOfTeleportation.appear(Dungeon.hero, Dungeon.hero.pos); + break; + case FALL: + Chasm.heroLand(); + break; + case PALANTIR: + WndStory.showChapter(WndStory.ID_ZOT); + break; + case DESCEND: + switch (Dungeon.depth) { + case 1: + WndStory.showChapter(WndStory.ID_SEWERS); + break; + case 6: + WndStory.showChapter(WndStory.ID_PRISON); + break; + case 11: + WndStory.showChapter(WndStory.ID_CAVES); + break; + case 16: + WndStory.showChapter(WndStory.ID_CITY); + break; + } + case CHAOS: + switch (Dungeon.depth) { + case 85: + WndStory.showChapter(WndStory.ID_CHAOS); + break; + } + case JOURNAL: + switch (Dungeon.depth) { + case 50: + WndStory.showChapter(WndStory.ID_SAFELEVEL); + break; + case 51: + WndStory.showChapter(WndStory.ID_SOKOBAN1); + break; + case 52: + WndStory.showChapter(WndStory.ID_SOKOBAN2); + break; + case 53: + WndStory.showChapter(WndStory.ID_SOKOBAN3); + break; + case 54: + WndStory.showChapter(WndStory.ID_SOKOBAN4); + break; + case 55: + WndStory.showChapter(WndStory.ID_TOWN); + break; + } + + if (Dungeon.hero.isAlive() && Dungeon.depth != 22) { + Badges.validateNoKilling(); + } + break; + default: + } + + ArrayList dropped = Dungeon.droppedItems.get(Dungeon.depth); + if (dropped != null) { + for (Item item : dropped) { + int pos = Dungeon.level.randomRespawnCell(); + if (item instanceof Potion) { + ((Potion) item).shatter(pos); + } else if (item instanceof Plant.Seed) { + Dungeon.level.plant((Plant.Seed) item, pos); + } else if (item instanceof Honeypot) { + Dungeon.level.drop(((Honeypot) item).shatter(null, pos), + pos); + } else { + Dungeon.level.drop(item, pos); + } + } + Dungeon.droppedItems.remove(Dungeon.depth); + } + + Camera.main.target = hero; + fadeIn(); + } + + @Override + public void destroy() { + + freezeEmitters = false; + + scene = null; + Badges.saveGlobal(); + + super.destroy(); + } + + @Override + public synchronized void pause() { + try { + Dungeon.saveAll(); + Badges.saveGlobal(); + } catch (IOException e) { + // + } + } + + @Override + public synchronized void update() { + if (Dungeon.hero == null) { + return; + } + + super.update(); + + if (!freezeEmitters) + water.offset(0, -5 * Game.elapsed); + + Actor.process(); + + if (Dungeon.hero.ready && Dungeon.hero.paralysed == 0) { + log.newLine(); + } + + if (tagAttack != attack.active || tagLoot != loot.visible + || tagResume != resume.visible) { + + boolean atkAppearing = attack.active && !tagAttack; + boolean lootAppearing = loot.visible && !tagLoot; + boolean resAppearing = resume.visible && !tagResume; + + tagAttack = attack.active; + tagLoot = loot.visible; + tagResume = resume.visible; + + if (atkAppearing || lootAppearing || resAppearing) + layoutTags(); + } + + cellSelector.enable(Dungeon.hero.ready); + } + + private boolean tagAttack = false; + private boolean tagLoot = false; + private boolean tagResume = false; + + private void layoutTags() { + + float pos = tagAttack ? attack.top() : toolbar.top(); + + if (tagLoot) { + loot.setPos(uiCamera.width - loot.width(), pos - loot.height()); + pos = loot.top(); + } + + if (tagResume) { + resume.setPos(uiCamera.width - resume.width(), + pos - resume.height()); + } + } + + @Override + protected void onBackPressed() { + if (!cancel()) { + add(new WndGame()); + } + } + + @Override + protected void onMenuPressed() { + if (Dungeon.hero.ready) { + selectItem(null, WndBag.Mode.ALL, null); + } + } + + public void brightness(boolean value) { + water.rm = water.gm = water.bm = tiles.rm = tiles.gm = tiles.bm = value ? 1.5f + : 1.0f; + if (value) { + fog.am = +2f; + fog.aa = -1f; + } else { + fog.am = +1f; + fog.aa = 0f; + } + } + + private void addHeapSprite(Heap heap) { + ItemSprite sprite = heap.sprite = (ItemSprite) heaps + .recycle(ItemSprite.class); + sprite.revive(); + sprite.link(heap); + heaps.add(sprite); + } + + private void addDiscardedSprite(Heap heap) { + heap.sprite = (DiscardedItemSprite) heaps + .recycle(DiscardedItemSprite.class); + heap.sprite.revive(); + heap.sprite.link(heap); + heaps.add(heap.sprite); + } + + private void addPlantSprite(Plant plant) { + (plant.sprite = (PlantSprite) plants.recycle(PlantSprite.class)) + .reset(plant); + } + + private void addTrapSprite( Trap trap ) { + (trap.sprite = (TrapSprite)traps.recycle( TrapSprite.class )).reset( trap ); + trap.sprite.visible = trap.visible; + } + + private void addBlobSprite(final Blob gas) { + if (gas.emitter == null) { + gases.add(new BlobEmitter(gas)); + } + } + + private void addMobSprite(Mob mob) { + CharSprite sprite = mob.sprite(); + sprite.visible = Dungeon.visible[mob.pos]; + mobs.add(sprite); + sprite.link(mob); + } + + private void prompt(String text) { + + if (prompt != null) { + prompt.killAndErase(); + prompt = null; + } + + if (text != null) { + prompt = new Toast(text) { + @Override + protected void onClose() { + cancel(); + } + }; + prompt.camera = uiCamera; + prompt.setPos((uiCamera.width - prompt.width()) / 2, + uiCamera.height - 60); + add(prompt); + } + } + + private void showBanner(Banner banner) { + banner.camera = uiCamera; + banner.x = align(uiCamera, (uiCamera.width - banner.width) / 2); + banner.y = align(uiCamera, (uiCamera.height - banner.height) / 3); + //add(banner); + addToFront( banner ); + } + + // ------------------------------------------------------- + + public static void add(Plant plant) { + if (scene != null) { + scene.addPlantSprite(plant); + } + } + + public static void add( Trap trap ) { + if (scene != null) { + scene.addTrapSprite( trap ); + } + } + + public static void add(Blob gas) { + Actor.add(gas); + if (scene != null) { + scene.addBlobSprite(gas); + } + } + + public static void add(Heap heap) { + if (scene != null) { + scene.addHeapSprite(heap); + } + } + + public static void discard(Heap heap) { + if (scene != null) { + scene.addDiscardedSprite(heap); + } + } + + public static void add(Mob mob) { + Dungeon.level.mobs.add(mob); + Actor.add(mob); + Actor.occupyCell(mob); + scene.addMobSprite(mob); + } + + public static void add(Mob mob, float delay) { + Dungeon.level.mobs.add(mob); + Actor.addDelayed(mob, delay); + Actor.occupyCell(mob); + scene.addMobSprite(mob); + } + + public static void add(EmoIcon icon) { + scene.emoicons.add(icon); + } + + public static void add( CharHealthIndicator indicator ){ + if (scene != null) scene.healthIndicators.add(indicator); + } + + public static void effect(Visual effect) { + scene.effects.add(effect); + } + + public static Ripple ripple(int pos) { + Ripple ripple = (Ripple) scene.ripples.recycle(Ripple.class); + ripple.reset(pos); + return ripple; + } + + public static SpellSprite spellSprite() { + return (SpellSprite) scene.spells.recycle(SpellSprite.class); + } + + public static Emitter emitter() { + if (scene != null) { + Emitter emitter = (Emitter) scene.emitters.recycle(Emitter.class); + emitter.revive(); + return emitter; + } else { + return null; + } + } + + public static FloatingText status() { + return scene != null ? (FloatingText) scene.statuses + .recycle(FloatingText.class) : null; + } + + public static void pickUp(Item item) { + scene.toolbar.pickup(item); + } + + public static void resetMap() { + if (scene != null) { + scene.tiles.map(Dungeon.level.map, Level.getWidth() ); + + } + } + + public static void updateMap() { + if (scene != null) { + scene.tiles.updated.set(0, 0, Level.getWidth(), Level.HEIGHT); + } + } + + public static void updateMap(int cell) { + if (scene != null) { + scene.tiles.updated.union(cell % Level.getWidth(), cell / Level.getWidth()); + } + } + + public static void discoverTile(int pos, int oldValue) { + if (scene != null) { + scene.tiles.discover(pos, oldValue); + } + } + + public static void show(Window wnd) { + //cancelCellSelector(); + //scene.add(wnd); + if (scene != null) { + cancelCellSelector(); + scene.addToFront(wnd); + } + } + + public static void afterObserve() { + if (scene != null) { + scene.fog.updateVisibility(Dungeon.visible, Dungeon.level.visited, + Dungeon.level.mapped); + + for (Mob mob : Dungeon.level.mobs) { + mob.sprite.visible = Dungeon.visible[mob.pos]; + } + } + } + + public static void flash(int color) { + scene.fadeIn(0xFF000000 | color, true); + } + + public static void gameOver() { + Banner gameOver = new Banner( + BannerSprites.get(BannerSprites.Type.GAME_OVER)); + gameOver.show(0x000000, 1f); + scene.showBanner(gameOver); + + Sample.INSTANCE.play(Assets.SND_DEATH); + } + + public static void bossSlain() { + if (Dungeon.hero.isAlive()) { + Banner bossSlain = new Banner( + BannerSprites.get(BannerSprites.Type.BOSS_SLAIN)); + bossSlain.show(0xFFFFFF, 0.3f, 5f); + scene.showBanner(bossSlain); + + Sample.INSTANCE.play(Assets.SND_BOSS); + } + } + + public static void levelCleared() { + if (Dungeon.hero.isAlive()) { + Banner levelCleared = new Banner( + BannerSprites.get(BannerSprites.Type.CLEARED)); + levelCleared.show(0xFFFFFF, 0.3f, 5f); + scene.showBanner(levelCleared); + + Sample.INSTANCE.play(Assets.SND_BADGE); + } + } + + public static void handleCell(int cell) { + cellSelector.select(cell); + } + + public static void selectCell(CellSelector.Listener listener) { + cellSelector.listener = listener; + scene.prompt(listener.prompt()); + } + + private static boolean cancelCellSelector() { + if (cellSelector.listener != null + && cellSelector.listener != defaultCellListener) { + cellSelector.cancel(); + return true; + } else { + return false; + } + } + + public static WndBag selectItem(WndBag.Listener listener, WndBag.Mode mode, + String title) { + cancelCellSelector(); + + WndBag wnd = + mode == Mode.SEED ? WndBag.getBag(SeedPouch.class, listener, mode, title) : + mode == Mode.SCROLL ? WndBag.getBag(ScrollHolder.class, listener, mode, title) : + mode == Mode.POTION ? WndBag.getBag(PotionBandolier.class, listener, mode, title) : + mode == Mode.WAND ? WndBag.getBag(WandHolster.class, listener, mode, title) : + WndBag.lastBag(listener, mode, title); + + //scene.add(wnd); + + if (scene != null) scene.addToFront( wnd ); + + return wnd; + } + + static boolean cancel() { + if (Dungeon.hero.curAction != null || Dungeon.hero.restoreHealth) { + + Dungeon.hero.curAction = null; + Dungeon.hero.restoreHealth = false; + return true; + + } else { + + return cancelCellSelector(); + + } + } + + public static void ready() { + selectCell(defaultCellListener); + QuickSlotButton.cancel(); + if (scene != null && scene.toolbar != null) scene.toolbar.examining = false; + } + + public static void examineCell( Integer cell ) { + if (cell == null) { + return; + } + + if (cell < 0 || cell > Level.LENGTH || (!Dungeon.level.visited[cell] && !Dungeon.level.mapped[cell])) { + GameScene.show( new WndMessage( Messages.get(GameScene.class, "dont_know") ) ) ; + return; + } + + if (cell == Dungeon.hero.pos) { + GameScene.show( new WndHero() ); + return; + } + + if (Dungeon.visible[cell]) { + Mob mob = (Mob) Actor.findChar(cell); + if (mob != null) { + GameScene.show(new WndInfoMob(mob)); + return; + } + } + + Heap heap = Dungeon.level.heaps.get(cell); + if (heap != null && heap.seen) { + if (heap.type == Heap.Type.FOR_SALE && heap.size() == 1 && heap.peek().price() > 0) { + GameScene.show(new WndTradeItem(heap, false)); + } else { + GameScene.show(new WndInfoItem(heap)); + } + return; + } + + Plant plant = Dungeon.level.plants.get( cell ); + if (plant != null) { + GameScene.show( new WndInfoPlant( plant ) ); + return; + } + + Trap trap = Dungeon.level.traps.get( cell ); + if (trap != null && trap.visible) { + GameScene.show( new WndInfoTrap( trap )); + return; + } + + GameScene.show( new WndInfoCell( cell ) ); + } + + private static final CellSelector.Listener defaultCellListener = new CellSelector.Listener() { + @Override + public void onSelect(Integer cell) { + if (Dungeon.hero.handle(cell)) { + Dungeon.hero.next(); + } + } + + @Override + public String prompt() { + return null; + } + }; +} diff --git a/java/com/hmdzl/spspd/scenes/InterlevelScene.java b/java/com/hmdzl/spspd/scenes/InterlevelScene.java new file mode 100644 index 00000000..87b04f42 --- /dev/null +++ b/java/com/hmdzl/spspd/scenes/InterlevelScene.java @@ -0,0 +1,580 @@ +/* + * 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 + */ +package com.hmdzl.spspd.scenes; + +import java.io.FileNotFoundException; +import java.io.IOException; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.Statistics; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.items.artifacts.DriedRose; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.ui.GameLog; +import com.hmdzl.spspd.windows.WndError; +import com.hmdzl.spspd.windows.WndStory; +import com.watabou.noosa.Camera; +import com.watabou.noosa.Game; +import com.watabou.noosa.audio.Music; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Random; +import com.watabou.noosa.RenderedText; +import com.hmdzl.spspd.messages.Messages; + +public class InterlevelScene extends PixelScene { + + private static final float TIME_TO_FADE = 0.3f; + + public static enum Mode { + DESCEND, ASCEND, CONTINUE, RESURRECT, RETURN, FALL, /*PORT1, PORT2, PORT3,*/ PORT4, + /*PORTSEWERS, PORTPRISON, PORTCAVES, */ PORTSHADOWEATER,PORTPOT, PORTCRAB, PORTTENGU, PORTCOIN, PORTBONE, RETURNSAVE, + JOURNAL, SOKOBANFAIL, PALANTIR, BOSSRUSH, PORTMAP, SAVE, SLEEP, CHALLENGEBOOK, RESET,CHAOS + }; + + public static Mode mode; + + public static int returnDepth; + public static int returnPos; + + public static int journalpage; + public static boolean first; + + public static int challengelist; + + public static boolean noStory = false; + + public static boolean fallIntoPit; + + private enum Phase { + FADE_IN, STATIC, FADE_OUT + }; + + private Phase phase; + private float timeLeft; + + private RenderedText message; + + private Thread thread; + private Exception error = null; + + @Override + public void create() { + super.create(); + + String text = Messages.get(Mode.class, mode.name()); + + message = PixelScene.renderText(text, 9); + message.x = (Camera.main.width - message.width()) / 2; + message.y = (Camera.main.height - message.height()) / 2; + align(message); + add(message); + + phase = Phase.FADE_IN; + timeLeft = TIME_TO_FADE; + + thread = new Thread() { + @Override + public void run() { + + try { + + Generator.reset(); + + switch (mode) { + case DESCEND: + descend(); + break; + case ASCEND: + ascend(); + break; + case CONTINUE: + restore(); + break; + case RESURRECT: + resurrect(); + break; + case RETURN: + returnTo(); + break; + case RETURNSAVE: + returnToSave(); + break; + case FALL: + fall(); + break; + //case PORT1: + //portal(1); + //break; + //case PORT2: + //portal(2); + //break; + //case PORT3: + //portal(3); + //break; + case PORT4: + portal(4); + break; + //case PORTSEWERS: + //portal(5); + //break; + //case PORTPRISON: + //portal(6); + //break; + //case PORTCAVES: + //portal(7); + //break; + case PORTSHADOWEATER: + portal(8); + break; + case PORTPOT: + portal(9); + break; + case PORTCRAB: + portal(10); + break; + case PORTTENGU: + portal(11); + break; + case PORTCOIN: + portal(12); + break; + case PORTBONE: + portal(13); + break; + case JOURNAL: + journalPortal(journalpage); + break; + case SOKOBANFAIL: + ascend(); + break; + case PALANTIR: + portal(14); + break; + case BOSSRUSH: + portal(15); + break; + case PORTMAP: + portal(16); + break; + case SAVE: + restore2(); + break; + case SLEEP: + restore3(); + break; + case CHALLENGEBOOK: + challengePortal(challengelist); + break; + case RESET: + reset(); + break; + case CHAOS: + portal(17); + break; + } + + if ((Dungeon.depth % 5) == 0) { + Sample.INSTANCE.load(Assets.SND_BOSS); + } + + } catch (Exception e) { + + error = e; + + } + + if (phase == Phase.STATIC && error == null) { + phase = Phase.FADE_OUT; + timeLeft = TIME_TO_FADE; + } + } + }; + thread.start(); + } + + @Override + public void update() { + super.update(); + + float p = timeLeft / TIME_TO_FADE; + + switch (phase) { + + case FADE_IN: + message.alpha(1 - p); + if ((timeLeft -= Game.elapsed) <= 0) { + if (!thread.isAlive() && error == null) { + phase = Phase.FADE_OUT; + timeLeft = TIME_TO_FADE; + } else { + phase = Phase.STATIC; + } + } + break; + + case FADE_OUT: + message.alpha(p); + + if (mode == Mode.CONTINUE + || (mode == Mode.DESCEND && Dungeon.depth == 1)) { + Music.INSTANCE.volume(p); + } + if ((timeLeft -= Game.elapsed) <= 0) { + Game.switchScene(GameScene.class); + } + break; + + case STATIC: + if (error != null) { + String errorMsg; + if (error instanceof FileNotFoundException) errorMsg = Messages.get(this, "file_not_found"); + else if (error instanceof IOException) errorMsg = Messages.get(this, "io_error"); + else throw new RuntimeException( + "fatal error occured while moving between floors", + error); + + add(new WndError(errorMsg) { + @Override + public void onBackPressed() { + super.onBackPressed(); + Game.switchScene(StartScene.class); + }; + }); + error = null; + } + break; + } + } + + private void descend() throws IOException { + + Actor.fixTime(); + if (Dungeon.hero == null) { + DriedRose.clearHeldGhostHero(); + Dungeon.init(); + if (noStory) { + Dungeon.chapters.add(WndStory.ID_SEWERS); + noStory = false; + } + GameLog.wipe(); + } else { + //DriedRose.holdGhostHero( Dungeon.level ); + DriedRose.clearHeldGhostHero(); + //Dungeon.saveLevel(); + Dungeon.saveAll(); + } + + Level level; + if ((Dungeon.depth>55) && (Dungeon.depth >= Statistics.realdeepestFloor) && ((Random.Int(100)<101) || Dungeon.depth==56) ){ + level = Dungeon.newMineBossLevel(); + }else if (Dungeon.townCheck(Dungeon.depth) && (Dungeon.depth >= Statistics.realdeepestFloor || Random.Int(10)<2)){ + level = Dungeon.newLevel(); + }else if (Dungeon.depth >= Statistics.deepestFloor && !Dungeon.townCheck(Dungeon.depth) ){ + level = Dungeon.newLevel(); + } else { + Dungeon.depth++; + level = Dungeon.loadLevel(Dungeon.hero.heroClass); + } + Dungeon.switchLevel(level, level.entrance); + } + + private void fall() throws IOException { + + Actor.fixTime(); + DriedRose.clearHeldGhostHero(); + //DriedRose.holdGhostHero( Dungeon.level ); + //Dungeon.saveLevel(); + Dungeon.saveAll(); + + Level level; + if (Dungeon.depth >= Statistics.deepestFloor) { + level = Dungeon.newLevel(); + } else { + Dungeon.depth++; + level = Dungeon.loadLevel(Dungeon.hero.heroClass); + } + Dungeon.switchLevel(level, + fallIntoPit ? level.pitCell() : level.randomRespawnCell()); + } + + private void ascend() throws IOException { + Actor.fixTime(); + //DriedRose.holdGhostHero( Dungeon.level ); + DriedRose.clearHeldGhostHero(); + Dungeon.saveAll(); + //Dungeon.saveLevel(); + if (Dungeon.depth == 41) { + Dungeon.depth=40; + Level level = Dungeon.loadLevel(Dungeon.hero.heroClass); + Dungeon.switchLevel(level, level.entrance); + } else if (Dungeon.depth > 26 && !Dungeon.townCheck(Dungeon.depth)) { + Dungeon.depth=1; + Level level = Dungeon.loadLevel(Dungeon.hero.heroClass); + Dungeon.switchLevel(level, level.entrance); + } else { + Dungeon.depth--; + Level level = Dungeon.loadLevel(Dungeon.hero.heroClass); + Dungeon.switchLevel(level, level.exit); + } + } + + private void returnTo() throws IOException { + Actor.fixTime(); + DriedRose.clearHeldGhostHero(); + //DriedRose.holdGhostHero( Dungeon.level ); + //Dungeon.hero.invisible=0; + Dungeon.saveAll(); + Dungeon.depth = returnDepth; + Level level = Dungeon.loadLevel(Dungeon.hero.heroClass); + Dungeon.switchLevel(level, + Level.resizingNeeded ? level.adjustPos(returnPos) : returnPos); + } + + private void returnToSave() throws IOException { + + Actor.fixTime(); + DriedRose.clearHeldGhostHero(); + // Dungeon.hero.invisible=0; + Dungeon.saveAll(); + if (Dungeon.bossLevel(Statistics.deepestFloor)){ + Dungeon.depth = Statistics.deepestFloor-1; + } else { + Dungeon.depth = Statistics.deepestFloor; + } + Level level = Dungeon.loadLevel(Dungeon.hero.heroClass); + Dungeon.switchLevel(level, level.entrance); + } + + private void restore() throws IOException { + + Actor.fixTime(); + GameLog.wipe(); + DriedRose.clearHeldGhostHero(); + Dungeon.loadGame(StartScene.curClass); + if (Dungeon.depth == -1) { + Dungeon.depth = Statistics.deepestFloor; + Dungeon.switchLevel(Dungeon.loadLevel(StartScene.curClass), -1); + } else { + Level level = Dungeon.loadLevel(StartScene.curClass); + Dungeon.switchLevel(level, + Level.resizingNeeded ? level.adjustPos(Dungeon.hero.pos) + : Dungeon.hero.pos); + } + } + + private void restore2() throws IOException { + + Actor.fixTime(); + DriedRose.clearHeldGhostHero(); + Dungeon.loadGame(StartScene.curClass); + if (Dungeon.depth == -1) { + Dungeon.depth = Statistics.deepestFloor; + Dungeon.switchLevel(Dungeon.loadLevel(StartScene.curClass), -1); + } else { + Level level = Dungeon.loadLevel(StartScene.curClass); + Dungeon.switchLevel( level, Dungeon.hero.pos ); + //Dungeon.switchLevel(level,Level.resizingNeeded ? level.adjustPos(Dungeon.hero.pos): Dungeon.hero.pos); + } + } + + private void restore3() throws IOException { + + Actor.fixTime(); + DriedRose.clearHeldGhostHero(); + Dungeon.loadGame(StartScene.curClass); + if (Dungeon.depth == -1) { + Dungeon.depth = Statistics.deepestFloor; + Dungeon.switchLevel(Dungeon.loadLevel(StartScene.curClass), -1); + } else { + Level level = Dungeon.loadLevel(StartScene.curClass); + Dungeon.switchLevel( level, Dungeon.hero.pos ); + //Dungeon.switchLevel(level,Level.resizingNeeded ? level.adjustPos(Dungeon.hero.pos): Dungeon.hero.pos); + } + } + + private void resurrect() throws IOException { + + Actor.fixTime(); + DriedRose.clearHeldGhostHero(); + //DriedRose.holdGhostHero( Dungeon.level ); + + if (Dungeon.level.locked) { + Dungeon.hero.resurrect(Dungeon.depth); + Dungeon.depth--; + Level level = Dungeon.newLevel(); + Dungeon.switchLevel(level, level.entrance); + } else { + Dungeon.hero.resurrect(-1); + Dungeon.resetLevel(); + } + } + + private void reset() throws IOException { + + Actor.fixTime(); + Dungeon.depth--; + if (Dungeon.depth > 50) + {Level level = Dungeon.newChaosLevel(); + Dungeon.switchLevel( level, level.entrance ); + } else {Level level = Dungeon.newLevel(); + Dungeon.switchLevel( level, level.entrance );} + + } + + private void portal(int branch) throws IOException { + + Actor.fixTime(); + DriedRose.clearHeldGhostHero(); + Dungeon.saveAll(); + + Level level; + switch(branch){ + case 1: + level=Dungeon.newCatacombLevel(); + break; + case 2: + level = Dungeon.newFortressLevel(); + break; + case 3: + level = Dungeon.newChasmLevel(); + break; + case 4: + level = Dungeon.newInfestLevel(); + break; + case 5: + level = Dungeon.newFieldLevel(); + break; + case 6: + level = Dungeon.newBattleLevel(); + break; + case 7: + level = Dungeon.newFishLevel(); + break; + case 8: + level = Dungeon.newShadowEaterLevel(); + break; + case 9: + level = Dungeon.newPotLevel(); + break; + case 10: + level = Dungeon.newCrabBossLevel(); + break; + case 11: + level = Dungeon.newTenguHideoutLevel(); + break; + case 12: + level = Dungeon.newThiefBossLevel(); + break; + case 13: + level = Dungeon.newSkeletonBossLevel(); + break; + case 14: + level = Dungeon.newZotBossLevel(); + break; + case 15: + level = Dungeon.newBossRushLevel(); + break; + case 16: + level = Dungeon.newFieldBossLevel(); + break; + case 17: + level = Dungeon.newChaosLevel(); + break; + default: + level = Dungeon.newLevel(); + } + Dungeon.switchLevel(level, level.entrance); + } + + private void journalPortal(int branch) throws IOException { + Actor.fixTime(); + DriedRose.clearHeldGhostHero(); + //DriedRose.holdGhostHero( Dungeon.level ); + Dungeon.saveAll(); + + Level level; + + /*if (branch==5 && !first){ + Dungeon.depth=55; + level = Dungeon.loadLevel(Dungeon.hero.heroClass); + + } else*/ if (branch==0 && !first){ + Dungeon.depth=50; + level = Dungeon.loadLevel(Dungeon.hero.heroClass); + + } else if (branch==7 && !first){ + Dungeon.depth=67; + level = Dungeon.loadLevel(Dungeon.hero.heroClass); + } else { + level=Dungeon.newJournalLevel(branch, first); + } + + Dungeon.switchLevel(level, level.entrance); + } + + private void challengePortal(int branch) throws IOException { + Actor.fixTime(); + DriedRose.clearHeldGhostHero(); + //DriedRose.holdGhostHero( Dungeon.level ); + Dungeon.saveAll(); + Level level; + if (branch==0 && !first){ + Dungeon.depth=26; + level = Dungeon.loadLevel(Dungeon.hero.heroClass); + + } else if (branch==1 && !first){ + Dungeon.depth=27; + level = Dungeon.loadLevel(Dungeon.hero.heroClass); + + } else if (branch==2 && !first){ + Dungeon.depth=28; + level = Dungeon.loadLevel(Dungeon.hero.heroClass); + + } else if (branch==3 && !first){ + Dungeon.depth=29; + level = Dungeon.loadLevel(Dungeon.hero.heroClass); + + } else if (branch==4 && !first){ + Dungeon.depth=30; + level = Dungeon.loadLevel(Dungeon.hero.heroClass); + + } else if (branch==5 && !first){ + Dungeon.depth=31; + level = Dungeon.loadLevel(Dungeon.hero.heroClass); + + } else if (branch==6 && !first){ + Dungeon.depth=32; + level = Dungeon.loadLevel(Dungeon.hero.heroClass); + + /*} else if (branch==7 && !first){ + Dungeon.depth=33; + level = Dungeon.loadLevel(Dungeon.hero.heroClass);*/ + }else{ + level=Dungeon.newChallengeLevel(branch, first); + } + + Dungeon.switchLevel(level, level.entrance); + } + + @Override + protected void onBackPressed() { + // Do nothing + } +} diff --git a/java/com/hmdzl/spspd/scenes/IntroScene.java b/java/com/hmdzl/spspd/scenes/IntroScene.java new file mode 100644 index 00000000..80945174 --- /dev/null +++ b/java/com/hmdzl/spspd/scenes/IntroScene.java @@ -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 + */ +package com.hmdzl.spspd.scenes; + +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.windows.WndStory; +import com.watabou.noosa.Game; + +public class IntroScene extends PixelScene { + + @Override + public void create() { + super.create(); + + add(new WndStory(Messages.get(this, "text")) { + @Override + public void hide() { + super.hide(); + Game.switchScene(InterlevelScene.class); + } + }); + + fadeIn(); + } +} diff --git a/java/com/hmdzl/spspd/scenes/LoadSaveScene.java b/java/com/hmdzl/spspd/scenes/LoadSaveScene.java new file mode 100644 index 00000000..0d3c0ae6 --- /dev/null +++ b/java/com/hmdzl/spspd/scenes/LoadSaveScene.java @@ -0,0 +1,333 @@ + +// NOTE - the idea behind Load/Save functionality was originated in Soft Pixel Dungeon + package com.hmdzl.spspd.scenes; + + import java.io.File; + import java.io.FileInputStream; + import java.io.FileNotFoundException; + import java.io.FileOutputStream; + import java.io.IOException; + import java.io.OutputStream; + import java.util.ArrayList; + + import com.hmdzl.spspd.Dungeon; + import com.hmdzl.spspd.GamesInProgress; + import com.hmdzl.spspd.messages.Messages; + import com.hmdzl.spspd.ui.Archs; + import com.hmdzl.spspd.ui.RedButton; + import com.hmdzl.spspd.ui.Window; + //import com.hmdzl.spspd.utils.Utils; + import com.hmdzl.spspd.windows.WndOptions; + import com.hmdzl.spspd.windows.WndStory; + import com.watabou.noosa.Camera; + import com.watabou.noosa.Game; + import com.watabou.noosa.RenderedText; + import com.watabou.utils.Bundle; + + import android.annotation.SuppressLint; + +@SuppressLint("DefaultLocale") + public class LoadSaveScene extends PixelScene { + + private static final float BUTTON1_WIDTH = 34; + private static final float BUTTON2_WIDTH = 55; + private static final float BUTTON_HEIGHT = 20; + private static final float BUTTON_PADDING = 3; + + private static final String TXT_TITLE = "Save/Load "; + + //private static final String SD_ROOT = Environment.getExternalStorageDirectory().toString(); + + private static final String TXT_LOAD = "Load"; + private static final String TXT_SAVE = "Save"; + private static final String TXT_SLOTNAME= "Game"; + + private static final String HERO = "hero"; + private static final String DEPTH = "depth"; + private static final String LEVEL = "lvl"; + + private static final String TXT_REALLY = "Load"; + private static final String TXT_WARNING = "Your current progress will be lost."; + private static final String TXT_YES = "Yes, load " + TXT_SLOTNAME; + private static final String TXT_NO = "No, return to main menu"; + + private static final String TXT_DPTH_LVL = "Depth: %d, level: %d"; + + + private static final int CLR_WHITE = 0xFFFFFF; + + + @Override + public void create() { + + super.create(); + + uiCamera.visible = false; + + int w = Camera.main.width; + int h = Camera.main.height; + + Archs archs = new Archs(); + archs.setSize( w, h ); + add( archs ); + + String showClassName = capitalizeWord(Dungeon.hero.heroClass.title2()); + + RenderedText title = PixelScene.renderText( TXT_TITLE + showClassName, 9 ); + title.hardlight( Window.TITLE_COLOR ); + title.x = align( (w - title.width()) / 2 ); + title.y = BUTTON_PADDING; + add( title ); + + String currentProgress = "dead"; + GamesInProgress.Info info = GamesInProgress.check(Dungeon.hero.heroClass); + if (info != null) { + currentProgress = Messages.format(TXT_DPTH_LVL, info.depth, info.level); + } + RenderedText subTitle = PixelScene.renderText( "Currently " + currentProgress, 6 ); + subTitle.hardlight( Window.TITLE_COLOR ); + subTitle.x = align( (w - title.width()) / 2 ); + subTitle.y = (BUTTON_HEIGHT / 2) + BUTTON_PADDING ; + add( subTitle ); + + int posY = (int) BUTTON_HEIGHT + ( (int) BUTTON_PADDING * 3); + int posX2 = w - (int) (BUTTON2_WIDTH + BUTTON_PADDING); + int posX = (int) (BUTTON1_WIDTH + (BUTTON_PADDING * 3)); + + String[] classList = { "warrior", "mage", "rogue", "huntress", "performer", "soldier", "follower" }; + String[] slotList = { "A", "B", "C", "D", "E" }; + + for (String classInfo : classList) { + if (Dungeon.hero.heroClass.title2().equals(classInfo)) { + + for (String saveSlot : slotList) { + // add the row caption.. + RenderedText buttonCapton1 = PixelScene.renderText( TXT_SLOTNAME + " " + saveSlot, 9 ); + buttonCapton1.hardlight( CLR_WHITE ); + buttonCapton1.x = BUTTON_PADDING; + buttonCapton1.y = posY + (BUTTON_HEIGHT/3); + add( buttonCapton1 ); + + // add the save button.. + if (Dungeon.hero.isAlive() && (Dungeon.canSave==true /*|| Dungeon.isChallenged(Challenges.BOSSRUSH)*/)) { + GameButton btnSave = new GameButton( this, true, TXT_SAVE, "", classInfo, saveSlot ); + add( btnSave ); + btnSave.visible = true; + btnSave.setRect(posX, posY, BUTTON1_WIDTH, BUTTON_HEIGHT); + } + // add the load button if there are saved files to load.. + String saveSlotFolder = Game.instance.getFilesDir().toString() + "/" + classInfo + saveSlot; + + File backupFolder = new File(saveSlotFolder); + if (backupFolder.exists()) { + FileInputStream input; + try { + input = new FileInputStream(saveSlotFolder +"/" + classInfo +".dat"); + Bundle bundle = Bundle.read( input ); + input.close(); + int savedDepth = bundle.getInt( DEPTH ); + Bundle savedHero = bundle.getBundle( HERO ); + int savedLevel = savedHero.getInt( LEVEL ); + String savedProgress = Messages.format( TXT_DPTH_LVL, savedDepth, savedLevel ); + GameButton btnLoad1A = new GameButton( this, false, TXT_LOAD , savedProgress, classInfo, saveSlot ); + + add( btnLoad1A ); + btnLoad1A.visible = true; + btnLoad1A.setRect(posX2, posY, (int) (BUTTON2_WIDTH), BUTTON_HEIGHT); + } catch (FileNotFoundException e) { + //e.printStackTrace(); + } catch (IOException e) { + //e.printStackTrace(); + } + } + // move down the line now... + posY += BUTTON_HEIGHT + BUTTON_PADDING; + } + } + } + + fadeIn(); + } + + @Override + protected void onBackPressed() { + Dungeon.canSave = false; + InterlevelScene.mode = InterlevelScene.Mode.CONTINUE; + Game.switchScene( InterlevelScene.class ); + } + + protected static void exportGames(String classInfo, String saveSlot) { + ArrayList files = new ArrayList(); + String saveSlotFolder = Game.instance.getFilesDir().toString() + "/" + classInfo + saveSlot; + makeFolder(saveSlotFolder); + + for(String fileName : Game.instance.fileList()){ + if(isGameLevelFile(classInfo, fileName)){ + files.add(fileName); + } + } + + // remove previous saved game files.. + File backupFolder = new File(saveSlotFolder); + + for(File backupFile : backupFolder.listFiles()){ + if(isGameLevelFile(classInfo, backupFile.getName())){ + backupFile.delete(); + } + } + + for (String fileName : files){ + try { + FileInputStream in = Game.instance.openFileInput(fileName); + OutputStream out = new FileOutputStream(saveSlotFolder + "/" + fileName); + + // Transfer bytes from in to out + byte[] buf = new byte[23768]; + int len; + while ((len = in.read(buf)) > 0) { + out.write(buf, 0, len); + } + in.close(); + out.close(); + } + catch(Exception e){ + e.printStackTrace(); + WndStory.showChapter("Failed to save file " + fileName); + //Log.d("FAILED EXPORT", f); + } + } + Dungeon.canSave = false; + InterlevelScene.mode = InterlevelScene.Mode.SAVE; + Game.switchScene( InterlevelScene.class ); + } + + private static boolean isGameLevelFile(String classInfo, String fileName) { + return fileName.endsWith(".dat") && (fileName.startsWith(classInfo)); + } + + private static void makeFolder(String saveSlotFolder) { + File dir = new File(saveSlotFolder); + if (!dir.exists()) { + dir.mkdir(); + } + } + + protected static void importGames(String classInfo, String saveSlot) { + ArrayList files = new ArrayList(); + String saveSlotFolder = Game.instance.getFilesDir().toString() + "/" + classInfo + saveSlot; + File backupFolder = new File(saveSlotFolder); + + for(File backupFile : backupFolder.listFiles()){ + if(isGameLevelFile(classInfo, backupFile.getName())){ + files.add(backupFile.getName()); + } + } + + // remove in progress game files.. + for(String fileName : Game.instance.fileList()){ + if(fileName.startsWith("game_") || isGameLevelFile(classInfo, fileName)){ + Game.instance.deleteFile(fileName); + } + } + + + for (String fileName : files){ + try { + FileInputStream in = new FileInputStream(saveSlotFolder + "/" + fileName); // + OutputStream out = Game.instance.openFileOutput(fileName, Game.MODE_PRIVATE ); + + // Transfer bytes from in to out + byte[] buf = new byte[23768]; + int len; + while ((len = in.read(buf)) > 0) { + out.write(buf, 0, len); + } + in.close(); + out.close(); + } + catch(Exception e){ + e.printStackTrace(); + WndStory.showChapter("Failed to load file " + fileName); + } + } + Dungeon.canSave = false; + InterlevelScene.mode = InterlevelScene.Mode.CONTINUE; + Game.switchScene( InterlevelScene.class ); + + for(File backupFile : backupFolder.listFiles()){ + if(isGameLevelFile(classInfo, backupFile.getName())){ + backupFile.delete(); + } + } + + } + + private static class GameButton extends RedButton { + + private static final int SECONDARY_COLOR = 0xCACFC2; + + private RenderedText secondary; + private Boolean isSave = true; + private String classInfo = ""; + private String saveSlot = ""; + private LoadSaveScene loadSaveScene; + + public GameButton(LoadSaveScene loadSaveScene, Boolean isSave, String primary, String secondary, String classInfo, String saveSlot ) { + super( primary ); + this.secondary( secondary ); + this.isSave = isSave; + this.classInfo = classInfo; + this.saveSlot = saveSlot; + this.loadSaveScene = loadSaveScene; + } + @Override + protected void onClick() { + if (isSave) { + exportGames(classInfo, saveSlot); + } else { + loadSaveScene.add( new WndOptions( TXT_REALLY + " " +saveSlot + " " + secondary.text() + "?", TXT_WARNING, TXT_YES + " " + saveSlot, TXT_NO ) { + @Override + protected void onSelect( int index ) { + if (index == 0) { + importGames(classInfo, saveSlot); + } + } + } ); + } + }; + + @Override + protected void createChildren() { + super.createChildren(); + + secondary = renderText( 6 ); + secondary.hardlight( SECONDARY_COLOR ); + add( secondary ); + } + + @Override + protected void layout() { + super.layout(); + + if (secondary.text().length() > 0) { + text.y = y + (height - text.height() - secondary.baseLine()) / 2; + + secondary.x = align( x + (width - secondary.width()) / 2 ); + secondary.y = align( text.y + text.height() ); + } else { + text.y = y + (height - text.baseLine()) / 2; + } + } + + public void secondary( String text ) { + secondary.text( text ); + } + + } + public static String capitalizeWord(String oneWord) + { + return Character.toUpperCase(oneWord.charAt(0)) + oneWord.substring(1); + } + + + } \ No newline at end of file diff --git a/java/com/hmdzl/spspd/scenes/PixelScene.java b/java/com/hmdzl/spspd/scenes/PixelScene.java new file mode 100644 index 00000000..a06cccb0 --- /dev/null +++ b/java/com/hmdzl/spspd/scenes/PixelScene.java @@ -0,0 +1,381 @@ +/* + * 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 + */ +package com.hmdzl.spspd.scenes; + +import javax.microedition.khronos.opengles.GL10; + +import android.opengl.GLES20; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.ShatteredPixelDungeon; +import com.hmdzl.spspd.effects.BadgeBanner; +import com.hmdzl.spspd.ui.RenderedTextMultiline; +import com.watabou.input.Touchscreen; +import com.watabou.noosa.BitmapText; +import com.watabou.noosa.BitmapText.Font; +import com.watabou.noosa.BitmapTextMultiline; +import com.watabou.noosa.Camera; +import com.watabou.noosa.ColorBlock; +import com.watabou.noosa.Game; +import com.watabou.noosa.RenderedText; +import com.watabou.noosa.Scene; +import com.watabou.noosa.Visual; +import com.watabou.utils.BitmapCache; +import com.watabou.noosa.ui.Component; + +public class PixelScene extends Scene { + + // Minimum virtual display size for portrait orientation + public static final float MIN_WIDTH_P = 128; + public static final float MIN_HEIGHT_P = 224; + + // Minimum virtual display size for landscape orientation + public static final float MIN_WIDTH_L = 224; + public static final float MIN_HEIGHT_L = 160; + + public static int defaultZoom = 0; + public static int maxDefaultZoom = 0; + public static int maxScreenZoom = 0; + public static int minZoom; + public static int maxZoom; + + public static Camera uiCamera; + + public static BitmapText.Font font1x; + public static BitmapText.Font font15x; + public static BitmapText.Font font2x; + public static BitmapText.Font font25x; + public static BitmapText.Font font3x; + + public static BitmapText.Font pixelFont; + + @Override + public void create() { + + super.create(); + + GameScene.scene = null; + + float minWidth, minHeight; + if (ShatteredPixelDungeon.landscape()) { + minWidth = MIN_WIDTH_L; + minHeight = MIN_HEIGHT_L; + } else { + minWidth = MIN_WIDTH_P; + minHeight = MIN_HEIGHT_P; + } + + maxDefaultZoom = (int)Math.min(Game.width/minWidth, Game.height/minHeight); + maxScreenZoom = (int)Math.min(Game.dispWidth/minWidth, Game.dispHeight/minHeight); + + defaultZoom = (int) Math.ceil(Game.density * 2.5); + defaultZoom--; + while ((Game.width / defaultZoom < minWidth || Game.height + / defaultZoom < minHeight) + && defaultZoom > 1) { + + defaultZoom--; + } + + if (ShatteredPixelDungeon.scaleUp()) { + while (Game.width / (defaultZoom + 1) >= minWidth + && Game.height / (defaultZoom + 1) >= minHeight) { + defaultZoom++; + } + } + minZoom = 1; + maxZoom = defaultZoom * 2; + + Camera.reset(new PixelCamera(defaultZoom)); + + float uiZoom = defaultZoom; + uiCamera = Camera.createFullscreen(uiZoom); + Camera.add(uiCamera); + + if (font1x == null) { + + // 3x5 (6) + font1x = Font.colorMarked(BitmapCache.get(Assets.FONTS1X), + 0x00000000, BitmapText.Font.LATIN_FULL); + font1x.baseLine = 6; + font1x.tracking = -1; + + // 5x8 (10) + font15x = Font.colorMarked(BitmapCache.get(Assets.FONTS15X), 12, + 0x00000000, BitmapText.Font.LATIN_FULL); + font15x.baseLine = 9; + font15x.tracking = -1; + + // 6x10 (12) + font2x = Font.colorMarked(BitmapCache.get(Assets.FONTS2X), 14, + 0x00000000, BitmapText.Font.LATIN_FULL); + font2x.baseLine = 11; + font2x.tracking = -1; + + // 7x12 (15) + font25x = Font.colorMarked(BitmapCache.get(Assets.FONTS25X), 17, + 0x00000000, BitmapText.Font.LATIN_FULL); + font25x.baseLine = 13; + font25x.tracking = -1; + + // 9x15 (18) + font3x = Font.colorMarked(BitmapCache.get(Assets.FONTS3X), 22, + 0x00000000, BitmapText.Font.LATIN_FULL); + font3x.baseLine = 17; + font3x.tracking = -2; + } + } + + @Override + public void destroy() { + super.destroy(); + Touchscreen.event.removeAll(); + } + + public static BitmapText.Font font; + public static float scale; + + public static void chooseFont(float size) { + chooseFont(size, defaultZoom); + } + + public static void chooseFont(float size, float zoom) { + + float pt = size * zoom; + + if (pt >= 19) { + + scale = pt / 19; + if (1.5 <= scale && scale < 2) { + font = font25x; + scale = (int) (pt / 14); + } else { + font = font3x; + scale = (int) scale; + } + + } else if (pt >= 14) { + + scale = pt / 14; + if (1.8 <= scale && scale < 2) { + font = font2x; + scale = (int) (pt / 12); + } else { + font = font25x; + scale = (int) scale; + } + + } else if (pt >= 12) { + + scale = pt / 12; + if (1.7 <= scale && scale < 2) { + font = font15x; + scale = (int) (pt / 10); + } else { + font = font2x; + scale = (int) scale; + } + + } else if (pt >= 10) { + + scale = pt / 10; + if (1.4 <= scale && scale < 2) { + font = font1x; + scale = (int) (pt / 7); + } else { + font = font15x; + scale = (int) scale; + } + + } else { + + font = pixelFont; + scale = 1f; + + //font = font1x; + //scale = Math.max(1, (int) (pt / 7)); + + } + + + scale /= zoom; + } + + public static BitmapText createText(float size) { + return createText(null, size); + } + + public static BitmapText createText(String text, float size) { + + chooseFont(size); + + BitmapText result = new BitmapText(text, font); + result.scale.set(scale); + + return result; + } + + public static BitmapTextMultiline createMultiline(float size) { + return createMultiline(null, size); + } + + public static BitmapTextMultiline createMultiline(String text, float size) { + + chooseFont(size); + + BitmapTextMultiline result = new BitmapTextMultiline(text, font); + result.scale.set(scale); + + return result; + } + + + public static RenderedText renderText(int size ) { + return renderText("", size); + } + + public static RenderedText renderText( String text, int size ) { + RenderedText result = new RenderedText( text, size*defaultZoom); + result.scale.set(1/(float)defaultZoom); + return result; + } + + public static RenderedTextMultiline renderMultiline( int size ){ + return renderMultiline("", size); + } + + public static RenderedTextMultiline renderMultiline( String text, int size ){ + RenderedTextMultiline result = new RenderedTextMultiline( text, size*defaultZoom); + result.zoom(1/(float)defaultZoom); + return result; + } + + public static float align( float pos ) { + return Math.round(pos * defaultZoom) / (float)defaultZoom; + } + + public static float align( Camera camera, float pos ) { + return Math.round(pos * camera.zoom) / camera.zoom; + } + + public static void align( Visual v ) { + v.x = align( v.x ); + v.y = align( v.y ); + } + + public static void align( Component c ){ + c.setPos(align(c.left()), align(c.top())); + } + + public static boolean noFade = false; + + protected void fadeIn() { + if (noFade) { + noFade = false; + } else { + fadeIn(0xFF000000, false); + } + } + + protected void fadeIn(int color, boolean light) { + add(new Fader(color, light)); + } + + public static void showBadge(Badges.Badge badge) { + BadgeBanner banner = BadgeBanner.show(badge.image); + banner.camera = uiCamera; + banner.x = align(banner.camera, + (banner.camera.width - banner.width) / 2); + banner.y = align(banner.camera, + (banner.camera.height - banner.height) / 3); + Game.scene().add(banner); + } + + protected static class Fader extends ColorBlock { + + private static float FADE_TIME = 1f; + + private boolean light; + + private float time; + + public Fader(int color, boolean light) { + super(uiCamera.width, uiCamera.height, color); + + this.light = light; + + camera = uiCamera; + + alpha(1f); + time = FADE_TIME; + } + + @Override + public void update() { + + super.update(); + + if ((time -= Game.elapsed) <= 0) { + alpha(0f); + parent.remove(this); + } else { + alpha(time / FADE_TIME); + } + } + + @Override + public void draw() { + if (light) { + GLES20.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE); + super.draw(); + GLES20.glBlendFunc(GL10.GL_SRC_ALPHA, + GL10.GL_ONE_MINUS_SRC_ALPHA); + } else { + try { + super.draw(); + } catch (Exception e) { + } + } + } + } + + private static class PixelCamera extends Camera { + + public PixelCamera(float zoom) { + super( + (int) (Game.width - Math.ceil(Game.width / zoom) * zoom) / 2, + (int) (Game.height - Math.ceil(Game.height / zoom) * zoom) / 2, + (int) Math.ceil(Game.width / zoom), (int) Math + .ceil(Game.height / zoom), zoom); + } + + @Override + protected void updateMatrix() { + float sx = align(this, scroll.x + shakeX); + float sy = align(this, scroll.y + shakeY); + + matrix[0] = +zoom * invW2; + matrix[5] = -zoom * invH2; + + matrix[12] = -1 + x * invW2 - sx * matrix[0]; + matrix[13] = +1 - y * invH2 - sy * matrix[5]; + + } + } +} diff --git a/java/com/hmdzl/spspd/scenes/PowerHandScene.java b/java/com/hmdzl/spspd/scenes/PowerHandScene.java new file mode 100644 index 00000000..d3126b35 --- /dev/null +++ b/java/com/hmdzl/spspd/scenes/PowerHandScene.java @@ -0,0 +1,121 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2015 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.scenes; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.ResultDescriptions; +import com.hmdzl.spspd.effects.Flare; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.RedButton; +import com.hmdzl.spspd.ui.RenderedTextMultiline; +import com.watabou.noosa.Camera; +import com.watabou.noosa.Game; +import com.watabou.noosa.Image; +import com.watabou.utils.Random; + +public class PowerHandScene extends PixelScene { + + private static final int WIDTH = 120; + private static final int BTN_HEIGHT = 18; + private static final float SMALL_GAP = 2; + private static final float LARGE_GAP = 8; + + private Image pudding_cup; + + @Override + public void create() { + super.create(); + + RenderedTextMultiline text = null; + + text = renderMultiline( Messages.get(this, "text"), 8 ); + text.maxWidth(WIDTH); + add( text ); + + + pudding_cup = new Image(Assets.PUDDING_CUP); + add(pudding_cup); + + + RedButton btnExit = new RedButton( Messages.get(this, "exit") ) { + @Override + protected void onClick() { + Dungeon.win(Messages.format(ResultDescriptions.WIN2)); + Dungeon.deleteGame( Dungeon.hero.heroClass, true ); + Game.switchScene( RankingsScene.class); + } + }; + btnExit.setSize( WIDTH, BTN_HEIGHT ); + add( btnExit ); + + RedButton btnStay = new RedButton(Messages.get(this, "stay")) { + @Override + protected void onClick() { + InterlevelScene.mode = InterlevelScene.Mode.CHAOS; + Game.switchScene(InterlevelScene.class); + } + }; + btnStay.setSize(WIDTH, BTN_HEIGHT); + add(btnStay); + + float height; + + height = pudding_cup.height + LARGE_GAP + text.height() + LARGE_GAP + btnExit.height() + SMALL_GAP; + + pudding_cup.x = (Camera.main.width - pudding_cup.width) / 2; + pudding_cup.y = (Camera.main.height - height) / 2; + align(pudding_cup); + + text.setPos((Camera.main.width - text.width()) / 2, pudding_cup.y + pudding_cup.height + LARGE_GAP); + align(text); + + btnExit.setPos( (Camera.main.width - btnExit.width()) / 2, text.top() + text.height() + LARGE_GAP ); + btnStay.setPos( btnExit.left(), btnExit.bottom() + SMALL_GAP ); + + new Flare( 8, 48 ).color( 0xFFDDBB, true ).show( pudding_cup, 0 ).angularSpeed = +30; + + fadeIn(); + } + + //@Override + //protected void onBackPressed() { + //InterlevelScene.mode = InterlevelScene.Mode.CONTINUE; + //Game.switchScene( InterlevelScene.class ); + //} + + private float timer = 0; + + @Override + public void update() { + super.update(); + + if ((timer -= Game.elapsed) < 0) { + timer = Random.Float( 0.5f, 5f ); + + Speck star = (Speck)recycle( Speck.class ); + star.reset( 0, pudding_cup.x + 10.5f, pudding_cup.y + 5.5f, Speck.DISCOVER ); + add( star ); + } + } + +} diff --git a/java/com/hmdzl/spspd/scenes/Pudding_CupScene.java b/java/com/hmdzl/spspd/scenes/Pudding_CupScene.java new file mode 100644 index 00000000..411569d0 --- /dev/null +++ b/java/com/hmdzl/spspd/scenes/Pudding_CupScene.java @@ -0,0 +1,100 @@ +/* + * 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 + */ +package com.hmdzl.spspd.scenes; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.effects.Flare; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.RedButton; +import com.hmdzl.spspd.ui.RenderedTextMultiline; +import com.watabou.noosa.Camera; +import com.watabou.noosa.Game; +import com.watabou.noosa.Image; + +public class Pudding_CupScene extends PixelScene { + + private static final String TXT_EXIT = "Wait,WHAT?!"; + private static final String TXT_STAY = "I can't leave now."; + + private static final int WIDTH = 120; + private static final int BTN_HEIGHT = 18; + private static final float SMALL_GAP = 2; + private static final float LARGE_GAP = 8; + + private static final String TXT = "Looks like someone taken the Amulet and left Pudding cup here."; + + private Image pudding_cup; + + @Override + public void create() { + super.create(); + + RenderedTextMultiline text = null; + text = renderMultiline( Messages.get(this, "text"), 8 ); + text.maxWidth(WIDTH); + add( text ); + + + pudding_cup = new Image(Assets.PUDDING_CUP); + add(pudding_cup); + + RedButton btnExit = new RedButton( Messages.get(this, "exit") ){ + @Override + protected void onClick() { + onBackPressed(); + } + }; + btnExit.setSize(WIDTH, BTN_HEIGHT); + add(btnExit); + + RedButton btnStay = new RedButton(Messages.get(this, "stay")) { + @Override + protected void onClick() { + onBackPressed(); + } + }; + btnStay.setSize(WIDTH, BTN_HEIGHT); + add(btnStay); + + float height; + height = pudding_cup.height + LARGE_GAP + text.height() + LARGE_GAP + btnExit.height() + SMALL_GAP + btnStay.height(); + + pudding_cup.x = (Camera.main.width - pudding_cup.width) / 2; + pudding_cup.y = (Camera.main.height - height) / 2; + align(pudding_cup); + + text.setPos((Camera.main.width - text.width()) / 2, pudding_cup.y + pudding_cup.height + LARGE_GAP); + align(text); + + btnExit.setPos( (Camera.main.width - btnExit.width()) / 2, text.top() + text.height() + LARGE_GAP ); + btnStay.setPos( btnExit.left(), btnExit.bottom() + SMALL_GAP ); + + new Flare(8, 48).color(0xFFDDBB, true).show(pudding_cup, 0).angularSpeed = +30; + + fadeIn(); + } + + @Override + protected void onBackPressed() { + InterlevelScene.mode = InterlevelScene.Mode.CONTINUE; + Game.switchScene(InterlevelScene.class); + } + + private float timer = 0; + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/scenes/RankingsScene.java b/java/com/hmdzl/spspd/scenes/RankingsScene.java new file mode 100644 index 00000000..45af8dfc --- /dev/null +++ b/java/com/hmdzl/spspd/scenes/RankingsScene.java @@ -0,0 +1,300 @@ +/* + * 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 + */ +package com.hmdzl.spspd.scenes; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Rankings; +import com.hmdzl.spspd.ResultDescriptions; +import com.hmdzl.spspd.ShatteredPixelDungeon; +import com.hmdzl.spspd.effects.Flare; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.ui.Archs; +import com.hmdzl.spspd.ui.ExitButton; +import com.hmdzl.spspd.ui.Icons; +import com.hmdzl.spspd.ui.RenderedTextMultiline; +import com.hmdzl.spspd.ui.Window; +import com.hmdzl.spspd.windows.WndError; +import com.hmdzl.spspd.windows.WndRanking; +import com.watabou.noosa.BitmapText; +import com.watabou.noosa.RenderedText; +import com.watabou.noosa.Camera; +import com.watabou.noosa.Image; +import com.watabou.noosa.audio.Music; +import com.watabou.noosa.ui.Button; +import com.watabou.utils.GameMath; +import com.hmdzl.spspd.messages.Messages; + +public class RankingsScene extends PixelScene { + + private static final float ROW_HEIGHT_MAX = 20; + private static final float ROW_HEIGHT_MIN = 12; + + private static final float MAX_ROW_WIDTH = 160; + + private static final float GAP = 4; + + private Archs archs; + + @Override + public void create() { + + super.create(); + + Music.INSTANCE.play(Assets.THEME, true); + Music.INSTANCE.volume(1f); + + uiCamera.visible = false; + + int w = Camera.main.width; + int h = Camera.main.height; + + archs = new Archs(); + archs.setSize(w, h); + add(archs); + + Rankings.INSTANCE.load(); + + RenderedText title = PixelScene.renderText(Messages.get(this, "title"), 9); + title.hardlight(Window.SHPX_COLOR); + title.x = align((w - title.width()) / 2); + title.y = align(GAP); + add(title); + + if (Rankings.INSTANCE.records.size() > 0) { + + // attempts to give each record as much space as possible, ideally + // as much space as portrait mode + float rowHeight = GameMath.gate(ROW_HEIGHT_MIN, + (uiCamera.height - 26) / Rankings.INSTANCE.records.size(), + ROW_HEIGHT_MAX); + + float left = (w - Math.min(MAX_ROW_WIDTH, w)) / 2 + GAP; + float top = align((h - rowHeight * Rankings.INSTANCE.records.size()) / 2); + + int pos = 0; + + for (Rankings.Record rec : Rankings.INSTANCE.records) { + Record row = new Record(pos, + pos == Rankings.INSTANCE.lastRecord, rec); + float offset = rowHeight <= 14 ? pos % 2 == 1 ? 5 : -5 : 0; + row.setRect(left + offset, top + pos * rowHeight, w - left * 2, + rowHeight); + add(row); + + pos++; + } + + if (Rankings.INSTANCE.totalNumber >= Rankings.TABLE_SIZE) { + RenderedText label = PixelScene.renderText(Messages.get(this, "total") + " ", 8); + label.hardlight(0xCCCCCC); + add(label); + + RenderedText won = PixelScene.renderText( + Integer.toString(Rankings.INSTANCE.wonNumber), 8); + won.hardlight(Window.SHPX_COLOR); + add(won); + + RenderedText total = PixelScene.renderText("/" + + Rankings.INSTANCE.totalNumber, 8); + total.hardlight(0xCCCCCC); + total.x = align((w - total.width()) / 2); + total.y = align(top + pos * rowHeight + GAP); + add(total); + + float tw = label.width() + won.width() + total.width(); + label.x = align((w - tw) / 2); + won.x = label.x + label.width(); + total.x = won.x + won.width(); + label.y = won.y = total.y = align(h - label.height() - GAP); + + align(label); + align(total); + align(won); + + } + + } else { + + RenderedText noRec = PixelScene.renderText(Messages.get(this, "no_games"), 8); + noRec.hardlight(0xCCCCCC); + noRec.x = align((w - noRec.width()) / 2); + noRec.y = align((h - noRec.height()) / 2); + add(noRec); + + } + + ExitButton btnExit = new ExitButton(); + btnExit.setPos(Camera.main.width - btnExit.width(), 0); + add(btnExit); + + fadeIn(); + } + + @Override + protected void onBackPressed() { + ShatteredPixelDungeon.switchNoFade(TitleScene.class); + } + + public static class Record extends Button { + + private static final float GAP = 4; + + private static final int[] TEXT_WIN = { 0xFFFF88, 0xB2B25F }; + private static final int[] TEXT_LOSE = { 0xDDDDDD, 0x888888 }; + private static final int FLARE_WIN = 0x888866; + private static final int FLARE_LOSE = 0x666666; + + private Rankings.Record rec; + + protected ItemSprite shield; + private Flare flare; + private BitmapText position; + private RenderedTextMultiline desc; + private Image steps; + private BitmapText depth; + private Image classIcon; + private BitmapText level; + + public Record(int pos, boolean latest, Rankings.Record rec) { + super(); + + this.rec = rec; + + if (latest) { + flare = new Flare(6, 24); + flare.angularSpeed = 90; + flare.color(rec.win ? FLARE_WIN : FLARE_LOSE); + addToBack(flare); + } + + if (pos != Rankings.TABLE_SIZE - 1) { + position.text(Integer.toString(pos + 1)); + } else + position.text(" "); + position.measure(); + + desc.text(Messages.titleCase(Messages.get(ResultDescriptions.class,rec.info))); + + + int odd = pos % 2; + + if (rec.win) { + shield.view(ItemSpriteSheet.AMULET, null); + position.hardlight(TEXT_WIN[odd]); + desc.hardlight(TEXT_WIN[odd]); + depth.hardlight(TEXT_WIN[odd]); + level.hardlight(TEXT_WIN[odd]); + } else { + position.hardlight(TEXT_LOSE[odd]); + desc.hardlight(TEXT_LOSE[odd]); + depth.hardlight(TEXT_LOSE[odd]); + level.hardlight(TEXT_LOSE[odd]); + + if (rec.depth != 0) { + depth.text(Integer.toString(rec.depth)); + depth.measure(); + steps.copy(Icons.DEPTH.get()); + + add(steps); + add(depth); + } + + } + + if (rec.herolevel != 0) { + level.text(Integer.toString(rec.herolevel)); + level.measure(); + add(level); + } + + classIcon.copy(Icons.get(rec.heroClass)); + } + + @Override + protected void createChildren() { + + super.createChildren(); + + shield = new ItemSprite(ItemSpriteSheet.TOMB, null); + add(shield); + + position = new BitmapText(PixelScene.font1x); + position.alpha(0.8f); + add(position); + + desc = renderMultiline(7); + add(desc); + + depth = new BitmapText(PixelScene.font1x); + depth.alpha(0.8f); + + steps = new Image(); + + classIcon = new Image(); + add(classIcon); + + level = new BitmapText(PixelScene.font1x); + level.alpha(0.8f); + } + + @Override + protected void layout() { + + super.layout(); + + shield.x = x; + shield.y = y + (height - shield.height) / 2; + + position.x = align(shield.x + (shield.width - position.width()) / 2); + position.y = align(shield.y + (shield.height - position.height()) + / 2 + 1); + + if (flare != null) { + flare.point( shield.center() ); + } + + classIcon.x = x + width - classIcon.width; + classIcon.y = shield.y; + + level.x = classIcon.x + (classIcon.width - level.width()) / 2f; + level.y = classIcon.y + (classIcon.height - level.height()) / 2f + 1; + align(level); + + steps.x = x + width - steps.width - classIcon.width; + steps.y = shield.y; + + depth.x = steps.x + (steps.width - depth.width()) / 2f; + depth.y = steps.y + (steps.height - depth.height()) / 2f + 1; + align(depth); + + desc.maxWidth((int)(steps.x - (shield.x + shield.width + GAP))); + desc.setPos(shield.x + shield.width + GAP, shield.y + (shield.height - desc.height()) / 2f + 1); + align(desc); + } + + @Override + protected void onClick() { + if (rec.gameFile.length() > 0) { + parent.add(new WndRanking(rec.gameFile)); + } else { + parent.add(new WndError(Messages.get(this, "no_info"))); + } + } + } +} diff --git a/java/com/hmdzl/spspd/scenes/StartScene.java b/java/com/hmdzl/spspd/scenes/StartScene.java new file mode 100644 index 00000000..dacbb007 --- /dev/null +++ b/java/com/hmdzl/spspd/scenes/StartScene.java @@ -0,0 +1,531 @@ +/* + * 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 + */ +package com.hmdzl.spspd.scenes; + +import java.util.HashMap; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.GamesInProgress; +import com.hmdzl.spspd.ShatteredPixelDungeon; +import com.hmdzl.spspd.Skins; +import com.hmdzl.spspd.actors.hero.HeroClass; +import com.hmdzl.spspd.effects.BannerSprites; +import com.hmdzl.spspd.effects.BannerSprites.Type; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.ui.Archs; +import com.hmdzl.spspd.ui.ExitButton; +import com.hmdzl.spspd.ui.Icons; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.RedButton; +import com.hmdzl.spspd.windows.WndChallenges; +import com.hmdzl.spspd.windows.WndClass; +import com.hmdzl.spspd.windows.WndOptions; +import com.watabou.noosa.Camera; +import com.watabou.noosa.Game; +import com.watabou.noosa.Image; +import com.watabou.noosa.RenderedText; +import com.watabou.noosa.audio.Sample; +import com.watabou.noosa.particles.Emitter; +import com.watabou.noosa.particles.BitmaskEmitter; +import com.watabou.noosa.ui.Button; +import com.watabou.utils.Callback; + +import static com.hmdzl.spspd.Dungeon.skins; + +public class StartScene extends PixelScene { + + private static final float BUTTON_HEIGHT = 24; + private static final float GAP = 2; + + private static final float WIDTH_P = 116; + private static final float HEIGHT_P = 220; + + private static final float WIDTH_L = 224; + private static final float HEIGHT_L = 124; + + private static HashMap shields = new HashMap(); + + private float buttonX; + private float buttonY; + + private GameButton btnLoad; + private GameButton btnNewGame; + + public static HeroClass curClass; + + @Override + public void create() { + + super.create(); + + Badges.loadGlobal(); + + uiCamera.visible = false; + + int w = Camera.main.width; + int h = Camera.main.height; + + float width, height; + if (ShatteredPixelDungeon.landscape()) { + width = WIDTH_L; + height = HEIGHT_L; + } else { + width = WIDTH_P; + height = HEIGHT_P; + } + + float left = (w - width) / 2; + float top = (h - height) / 2; + float bottom = h - top; + + Archs archs = new Archs(); + archs.setSize(w, h); + add(archs); + + Image title = BannerSprites.get(Type.SELECT_YOUR_HERO); + title.x = align((w - title.width()) / 2); + title.y = align(top); + align(title); + add(title); + + buttonX = left; + buttonY = bottom - BUTTON_HEIGHT; + + btnNewGame = new GameButton(Messages.get(this, "new")) { + @Override + protected void onClick() { + if (GamesInProgress.check(curClass) != null) { + StartScene.this.add(new WndOptions( + Messages.get(StartScene.class, "really"), + Messages.get(StartScene.class, "warning"), + Messages.get(StartScene.class, "yes"), + Messages.get(StartScene.class, "no")) { + @Override + protected void onSelect(int index) { + if (index == 0) { + //startNewGame(); + askSkin(); + } + } + }); + + } else { + //startNewGame(); + askSkin(); + } + } + }; + add(btnNewGame); + + btnLoad = new GameButton(Messages.get(this, "load")) { + @Override + protected void onClick() { + InterlevelScene.mode = InterlevelScene.Mode.CONTINUE; + Game.switchScene(InterlevelScene.class); + } + }; + add(btnLoad); + + float centralHeight = buttonY - title.y - title.height(); + + HeroClass[] classes = { + HeroClass.WARRIOR, HeroClass.MAGE, HeroClass.ROGUE, HeroClass.HUNTRESS, HeroClass.PERFORMER, HeroClass.SOLDIER, HeroClass.FOLLOWER + }; + for (HeroClass cl : classes) { + ClassShield shield = new ClassShield(cl); + shields.put(cl, shield); + add(shield); + } + if (ShatteredPixelDungeon.landscape()) { + float shieldW = width / 7; + float shieldH = Math.min(centralHeight, shieldW); + top = title.y + title.height + (centralHeight - shieldH) / 2; + for (int i = 0; i < classes.length; i++) { + ClassShield shield = shields.get(classes[i]); + shield.setRect(left + i * shieldW, top, shieldW, shieldH); + } + + ChallengeButton challenge = new ChallengeButton(); + challenge.setPos( + title.x - challenge.width() / 2, + title.y + shieldH / 2 - challenge.height() / 2); + add(challenge); + + } else { + float shieldW = width / 4; + float shieldH = Math.min(centralHeight / 3, shieldW * 1.2f); + top = title.y + title.height() + centralHeight / 2 - shieldH; + for (int i = 0; i < classes.length; i++) { + ClassShield shield = shields.get(classes[i]); + if (i < 4) { + shield.setRect(left + (i % 4) * shieldW, top - shieldH * 0.5f, shieldW, shieldH); + }else{ + shield.setRect(left + (i % 4) * shieldW, top + /*(i / 2) **/ shieldH, shieldW, shieldH); + } + align(shield); + } + + ChallengeButton challenge = new ChallengeButton(); + challenge.setPos( + w / 2 - challenge.width() / 2, + top + shieldH - challenge.height() / 2 + 70 ); + align(challenge); + add(challenge); + + } + + ExitButton btnExit = new ExitButton(); + btnExit.setPos(Camera.main.width - btnExit.width(), 0); + add(btnExit); + + curClass = null; + updateClass(HeroClass.values()[ShatteredPixelDungeon.lastClass()]); + + fadeIn(); + + Badges.loadingListener = new Callback() { + @Override + public void call() { + if (Game.scene() == StartScene.this) { + ShatteredPixelDungeon.switchNoFade(StartScene.class); + } + } + }; + } + + @Override + public void destroy() { + + Badges.saveGlobal(); + Badges.loadingListener = null; + + super.destroy(); + + } + + private void updateClass(HeroClass cl) { + + if (curClass == cl) { + add(new WndClass(cl)); + return; + } + + if (curClass != null) { + shields.get(curClass).highlight(false); + } + shields.get(curClass = cl).highlight(true); + + + + GamesInProgress.Info info = GamesInProgress.check( curClass ); + if (info != null) { + + btnLoad.visible = true; + btnLoad.secondary( Messages.format( Messages.get(this, "depth_level"), info.depth, info.level ), info.challenges ); + btnNewGame.visible = true; + btnNewGame.secondary( Messages.get(this, "erase"), false ); + + float w = (Camera.main.width - GAP) / 2 - buttonX; + + btnLoad.setRect( + buttonX, buttonY, w, BUTTON_HEIGHT ); + btnNewGame.setRect( + btnLoad.right() + GAP, buttonY, w, BUTTON_HEIGHT ); + + } else { + btnLoad.visible = false; + + btnNewGame.visible = true; + btnNewGame.secondary( null, false ); + btnNewGame.setRect( buttonX, buttonY, Camera.main.width - buttonX * 2, BUTTON_HEIGHT ); + } + + } + + private void askSkin() { + + StartScene.this.add( new WndSkin() ); + } + + private void startNewGame() { + + Dungeon.hero = null; + InterlevelScene.mode = InterlevelScene.Mode.DESCEND; + + if (ShatteredPixelDungeon.intro()) { + ShatteredPixelDungeon.intro(false); + Game.switchScene(IntroScene.class); + } else { + Game.switchScene(InterlevelScene.class); + } + } + + @Override + protected void onBackPressed() { + ShatteredPixelDungeon.switchNoFade(TitleScene.class); + } + + private static class GameButton extends RedButton { + + private static final int SECONDARY_COLOR_N = 0xCACFC2; + private static final int SECONDARY_COLOR_H = 0xFFFF88; + + private RenderedText secondary; + + public GameButton(String primary) { + super(primary); + + this.secondary.text(null); + } + + @Override + protected void createChildren() { + super.createChildren(); + + secondary = renderText(6); + add(secondary); + } + + @Override + protected void layout() { + super.layout(); + + if (secondary.text().length() > 0) { + text.y = align(y + + (height - text.height() - secondary.baseLine()) / 2); + + secondary.x = align(x + (width - secondary.width()) / 2); + secondary.y = align(text.y + text.height()); + } else { + text.y = align(y + (height - text.baseLine()) / 2); + } + align(text); + align(secondary); + } + + public void secondary(String text, boolean highlighted) { + secondary.text(text); + secondary.hardlight(highlighted ? SECONDARY_COLOR_H : SECONDARY_COLOR_N); + } + } + + private class ClassShield extends Button { + + private static final float MIN_BRIGHTNESS = 0.6f; + + private static final int BASIC_NORMAL = 0x444444; + private static final int BASIC_HIGHLIGHTED = 0xCACFC2; + + private static final int MASTERY_NORMAL = 0x666644; + private static final int MASTERY_HIGHLIGHTED = 0xFFFF88; + + private static final int WIDTH = 24; + private static final int HEIGHT = 32; + private static final float SCALE = 1f; + + private HeroClass cl; + + private Image avatar; + private RenderedText name; + private Emitter emitter; + + private float brightness; + + private int normal; + private int highlighted; + + public ClassShield(HeroClass cl) { + super(); + + this.cl = cl; + + avatar.frame(cl.ordinal() * WIDTH, 0, WIDTH, HEIGHT); + avatar.scale.set(SCALE); + + if (Badges.isUnlocked(cl.masteryBadge())) { + normal = MASTERY_NORMAL; + highlighted = MASTERY_HIGHLIGHTED; + } else { + normal = BASIC_NORMAL; + highlighted = BASIC_HIGHLIGHTED; + } + + name.text( cl.title().toUpperCase() ); + name.hardlight( normal ); + + brightness = MIN_BRIGHTNESS; + updateBrightness(); + } + + @Override + protected void createChildren() { + + super.createChildren(); + + avatar = new Image(Assets.AVATARS); + add(avatar); + + name = PixelScene.renderText(9); + add(name); + + emitter = new BitmaskEmitter(avatar); + add(emitter); + } + + @Override + protected void layout() { + + super.layout(); + + avatar.x = x + (width - avatar.width()) / 2; + avatar.y = y + (height - avatar.height() - name.height()) / 2; + align(avatar); + + + name.x = align(x + (width - name.width()) / 2); + name.y = avatar.y + avatar.height() + SCALE; + align(name); + //emitter.pos(avatar.x, avatar.y, avatar.width(), avatar.height()); + } + + @Override + protected void onTouchDown() { + + emitter.revive(); + emitter.start(Speck.factory(Speck.LIGHT), 0.05f, 7); + + Sample.INSTANCE.play(Assets.SND_CLICK, 1, 1, 1.2f); + updateClass(cl); + } + + @Override + public void update() { + super.update(); + + if (brightness < 1.0f && brightness > MIN_BRIGHTNESS) { + if ((brightness -= Game.elapsed) <= MIN_BRIGHTNESS) { + brightness = MIN_BRIGHTNESS; + } + updateBrightness(); + } + } + + public void highlight(boolean value) { + if (value) { + brightness = 1.0f; + name.hardlight(highlighted); + } else { + brightness = 0.999f; + name.hardlight(normal); + } + + updateBrightness(); + } + + private void updateBrightness() { + avatar.gm = avatar.bm = avatar.rm = avatar.am = brightness; + } + } + + private class ChallengeButton extends Button { + + private Image image; + + public ChallengeButton() { + super(); + + width = image.width; + height = image.height; + + image.am = Badges.isUnlocked(Badges.Badge.MONSTERS_SLAIN_1) ? 1.0f : 0.5f; + } + + @Override + protected void createChildren() { + + super.createChildren(); + + image = Icons.get(ShatteredPixelDungeon.challenges() > 0 ? Icons.CHALLENGE_ON : Icons.CHALLENGE_OFF); + add(image); + } + + @Override + protected void layout() { + + super.layout(); + + image.x = x; + image.y = y; + } + + @Override + protected void onClick() { + StartScene.this.add(new WndChallenges(ShatteredPixelDungeon.challenges(), true) { + public void onBackPressed() { + super.onBackPressed(); + image.copy(Icons.get(ShatteredPixelDungeon.challenges() > 0 ? + Icons.CHALLENGE_ON : Icons.CHALLENGE_OFF)); + } + }); + + } + + @Override + protected void onTouchDown() { + Sample.INSTANCE.play(Assets.SND_CLICK); + } + } + + private class WndSkin extends WndOptions { + + public WndSkin() { + super(Messages.get(Skins.class, "title"), Messages.get(Skins.class, "info"),Messages.get(Skins.class, "normal"), + Messages.get(Skins.class, "first"),Messages.get(Skins.class, "second"),Messages.get(Skins.class, "third") ); + } + + @Override + protected void onSelect( int index ) { + + skins = index; + final String skin = Skins.NAME_IDS[index]; + StartScene.this.add( + new WndOptions( Messages.get(Skins.class,skin), + Messages.get(Skins.class, skin+"_desc"), + Messages.get(Skins.class, "yes"), + Messages.get(Skins.class, "no") + ) { + @Override + protected void onSelect( int index ) { + if (index == 0) { + + startNewGame(); + + } else { + + StartScene.this.add( new WndSkin() ); + + } + } + } ); + } + + } + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/scenes/SurfaceScene.java b/java/com/hmdzl/spspd/scenes/SurfaceScene.java new file mode 100644 index 00000000..527be573 --- /dev/null +++ b/java/com/hmdzl/spspd/scenes/SurfaceScene.java @@ -0,0 +1,379 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2014 Oleg Dolya + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.scenes; + +import java.nio.FloatBuffer; +import java.util.Calendar; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.hero.HeroClass; +import com.hmdzl.spspd.sprites.RatSprite; +import com.hmdzl.spspd.ui.Archs; +import com.hmdzl.spspd.ui.RedButton; +import com.watabou.gltextures.Gradient; +import com.watabou.gltextures.SmartTexture; +import com.watabou.glwrap.Matrix; +import com.watabou.glwrap.Quad; +import com.watabou.input.Touchscreen.Touch; +import com.watabou.noosa.Camera; +import com.watabou.noosa.ColorBlock; +import com.watabou.noosa.Game; +import com.watabou.noosa.Group; +import com.watabou.noosa.Image; +import com.watabou.noosa.NoosaScript; +import com.watabou.noosa.TextureFilm; +import com.watabou.noosa.TouchArea; +import com.watabou.noosa.Visual; +import com.watabou.noosa.audio.Music; +import com.watabou.utils.Point; +import com.watabou.utils.Random; +import com.hmdzl.spspd.messages.Messages; + +public class SurfaceScene extends PixelScene { + + private static final int FRAME_WIDTH = 88; + private static final int FRAME_HEIGHT = 125; + + private static final int FRAME_MARGIN_TOP = 9; + private static final int FRAME_MARGIN_X = 4; + + private static final int BUTTON_HEIGHT = 20; + + private static final int SKY_WIDTH = 80; + private static final int SKY_HEIGHT = 112; + + private static final int NSTARS = 100; + private static final int NCLOUDS = 5; + + private Camera viewport; + + @Override + public void create() { + + super.create(); + + Music.INSTANCE.play(Assets.HAPPY, true); + Music.INSTANCE.volume(1f); + + uiCamera.visible = false; + + int w = Camera.main.width; + int h = Camera.main.height; + + Archs archs = new Archs(); + archs.reversed = true; + archs.setSize(w, h); + add(archs); + + float vx = align((w - SKY_WIDTH) / 2); + float vy = align((h - SKY_HEIGHT - BUTTON_HEIGHT) / 2); + + Point s = Camera.main.cameraToScreen(vx, vy); + viewport = new Camera(s.x, s.y, SKY_WIDTH, SKY_HEIGHT, defaultZoom); + Camera.add(viewport); + + Group window = new Group(); + window.camera = viewport; + add(window); + + boolean dayTime = Calendar.getInstance().get(Calendar.HOUR_OF_DAY) >= 7; + + Sky sky = new Sky(dayTime); + sky.scale.set(SKY_WIDTH, SKY_HEIGHT); + window.add(sky); + + if (!dayTime) { + for (int i = 0; i < NSTARS; i++) { + float size = Random.Float(); + ColorBlock star = new ColorBlock(size, size, 0xFFFFFFFF); + star.x = Random.Float(SKY_WIDTH) - size / 2; + star.y = Random.Float(SKY_HEIGHT) - size / 2; + star.am = size * (1 - star.y / SKY_HEIGHT); + window.add(star); + } + } + + float range = SKY_HEIGHT * 2 / 3; + for (int i = 0; i < NCLOUDS; i++) { + Cloud cloud = new Cloud((NCLOUDS - 1 - i) * (range / NCLOUDS) + + Random.Float(range / NCLOUDS), dayTime); + window.add(cloud); + } + + int nPatches = (int) (sky.width() / GrassPatch.WIDTH + 1); + + for (int i = 0; i < nPatches * 4; i++) { + GrassPatch patch = new GrassPatch((i - 0.75f) * GrassPatch.WIDTH + / 4, SKY_HEIGHT + 1, dayTime); + patch.brightness(dayTime ? 0.7f : 0.4f); + window.add(patch); + } + + Avatar a = new Avatar(Dungeon.hero.heroClass); + // Removing semitransparent contour + a.am = 2; + a.aa = -1; + a.x = PixelScene.align((SKY_WIDTH - a.width) / 2); + a.y = SKY_HEIGHT - a.height; + window.add(a); + + final Pet pet = new Pet(); + pet.rm = pet.gm = pet.bm = 1.2f; + pet.x = SKY_WIDTH / 2 + 2; + pet.y = SKY_HEIGHT - pet.height; + window.add(pet); + + window.add(new TouchArea(sky) { + @Override + protected void onClick(Touch touch) { + pet.jump(); + }; + }); + + for (int i = 0; i < nPatches; i++) { + GrassPatch patch = new GrassPatch((i - 0.5f) * GrassPatch.WIDTH, + SKY_HEIGHT, dayTime); + patch.brightness(dayTime ? 1.0f : 0.8f); + window.add(patch); + } + + Image frame = new Image(Assets.SURFACE); + + frame.frame(0, 0, FRAME_WIDTH, FRAME_HEIGHT); + frame.x = vx - FRAME_MARGIN_X; + frame.y = vy - FRAME_MARGIN_TOP; + add(frame); + + if (dayTime) { + a.brightness(1.2f); + pet.brightness(1.2f); + } else { + frame.hardlight(0xDDEEFF); + } + + RedButton gameOver = new RedButton(Messages.get(this, "exit")) { + @Override + protected void onClick() { + Game.switchScene(TitleScene.class); + } + }; + gameOver.setSize(SKY_WIDTH - FRAME_MARGIN_X * 2, BUTTON_HEIGHT); + gameOver.setPos(frame.x + FRAME_MARGIN_X * 2, frame.y + frame.height + + 4); + add(gameOver); + + Badges.validateHappyEnd(); + Badges.saveGlobal(); + + fadeIn(); + } + + @Override + public void destroy() { + Badges.saveGlobal(); + + Camera.remove(viewport); + super.destroy(); + } + + @Override + protected void onBackPressed() { + } + + private static class Sky extends Visual { + + private static final int[] day = { 0xFF4488FF, 0xFFCCEEFF }; + private static final int[] night = { 0xFF001155, 0xFF335980 }; + + private SmartTexture texture; + private FloatBuffer verticesBuffer; + + public Sky(boolean dayTime) { + super(0, 0, 1, 1); + + texture = new Gradient(dayTime ? day : night); + + float[] vertices = new float[16]; + verticesBuffer = Quad.create(); + + vertices[2] = 0.25f; + vertices[6] = 0.25f; + vertices[10] = 0.75f; + vertices[14] = 0.75f; + + vertices[3] = 0; + vertices[7] = 1; + vertices[11] = 1; + vertices[15] = 0; + + vertices[0] = 0; + vertices[1] = 0; + + vertices[4] = 1; + vertices[5] = 0; + + vertices[8] = 1; + vertices[9] = 1; + + vertices[12] = 0; + vertices[13] = 1; + + verticesBuffer.position(0); + verticesBuffer.put(vertices); + } + + @Override + public void draw() { + + super.draw(); + + NoosaScript script = NoosaScript.get(); + + texture.bind(); + + script.camera(camera()); + + script.uModel.valueM4(matrix); + script.lighting(rm, gm, bm, am, ra, ga, ba, aa); + + script.drawQuad(verticesBuffer); + } + } + + private static class Cloud extends Image { + + private static int lastIndex = -1; + + public Cloud(float y, boolean dayTime) { + super(Assets.SURFACE); + + int index; + do { + index = Random.Int(3); + } while (index == lastIndex); + + switch (index) { + case 0: + frame(88, 0, 49, 20); + break; + case 1: + frame(88, 20, 49, 22); + break; + case 2: + frame(88, 42, 50, 18); + break; + } + + lastIndex = index; + + this.y = y; + + scale.set(1 - y / SKY_HEIGHT); + x = Random.Float(SKY_WIDTH + width()) - width(); + speed.x = scale.x * (dayTime ? +8 : -8); + + if (dayTime) { + tint(0xCCEEFF, 1 - scale.y); + } else { + rm = gm = bm = +3.0f; + ra = ga = ba = -2.1f; + } + } + + @Override + public void update() { + super.update(); + if (speed.x > 0 && x > SKY_WIDTH) { + x = -width(); + } else if (speed.x < 0 && x < -width()) { + x = SKY_WIDTH; + } + } + } + + private static class Avatar extends Image { + + private static final int WIDTH = 24; + private static final int HEIGHT = 32; + + public Avatar(HeroClass cl) { + super(Assets.AVATARS); + frame(new TextureFilm(texture, WIDTH, HEIGHT).get(cl.ordinal())); + } + } + + private static class Pet extends RatSprite { + + public void jump() { + play(run); + } + + @Override + public void onComplete(Animation anim) { + if (anim == run) { + idle(); + } + } + } + + private static class GrassPatch extends Image { + + public static final int WIDTH = 16; + public static final int HEIGHT = 14; + + private float tx; + private float ty; + + private double a = Random.Float(5); + private double angle; + + private boolean forward; + + public GrassPatch(float tx, float ty, boolean forward) { + + super(Assets.SURFACE); + + frame(88 + Random.Int(4) * WIDTH, 60, WIDTH, HEIGHT); + + this.tx = tx; + this.ty = ty; + + this.forward = forward; + } + + @Override + public void update() { + super.update(); + a += Random.Float(Game.elapsed * 5); + angle = (2 + Math.cos(a)) * (forward ? +0.2 : -0.2); + + scale.y = (float) Math.cos(angle); + + x = tx + (float) Math.tan(angle) * width; + y = ty - scale.y * height; + } + + @Override + protected void updateMatrix() { + super.updateMatrix(); + Matrix.skewX(matrix, (float) (angle / Matrix.G2RAD)); + } + } +} diff --git a/java/com/hmdzl/spspd/scenes/TitleScene.java b/java/com/hmdzl/spspd/scenes/TitleScene.java new file mode 100644 index 00000000..86b61c3c --- /dev/null +++ b/java/com/hmdzl/spspd/scenes/TitleScene.java @@ -0,0 +1,235 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2016 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.scenes; + +import android.opengl.GLES20; +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.ShatteredPixelDungeon; +import com.hmdzl.spspd.effects.BannerSprites; +import com.hmdzl.spspd.effects.Fireball; +import com.hmdzl.spspd.messages.Messages; +//import com.hmdzl.spspd.scenes.PixelScene; +import com.hmdzl.spspd.ui.Archs; +import com.hmdzl.spspd.ui.ChangesButton; +import com.hmdzl.spspd.ui.ExitButton; +import com.hmdzl.spspd.ui.LanguageButton; +import com.hmdzl.spspd.ui.PrefsButton; +import com.watabou.noosa.BitmapText; +import com.watabou.noosa.Camera; +import com.watabou.noosa.Game; +import com.watabou.noosa.Image; +import com.watabou.noosa.RenderedText; +import com.watabou.noosa.audio.Music; +import com.watabou.noosa.audio.Sample; +import com.watabou.noosa.ui.Button; + +import javax.microedition.khronos.opengles.GL10; + +public class TitleScene extends PixelScene { + + @Override + public void create() { + + super.create(); + + Music.INSTANCE.play( Assets.THEME, true ); + Music.INSTANCE.volume( 1f ); + + uiCamera.visible = false; + + int w = Camera.main.width; + int h = Camera.main.height; + + Archs archs = new Archs(); + archs.setSize( w, h ); + add( archs ); + + Image title = BannerSprites.get( BannerSprites.Type.PIXEL_DUNGEON ); + add( title ); + + float topRegion = Math.max(95f, h*0.45f); + + title.x = (w - title.width()) / 2f; + if (ShatteredPixelDungeon.landscape()) + title.y = (topRegion - title.height()) / 2f; + else + title.y = 16 + (topRegion - title.height() - 16) / 2f; + + align(title); + + placeTorch(title.x + 18, title.y + 20); + placeTorch(title.x + title.width - 18, title.y + 20); + + Image signs = new Image( BannerSprites.get( BannerSprites.Type.PIXEL_DUNGEON_SIGNS ) ) { + private float time = 0; + @Override + public void update() { + super.update(); + am = (float)Math.sin( -(time += Game.elapsed) ); + } + @Override + public void draw() { + GLES20.glBlendFunc( GL10.GL_SRC_ALPHA, GL10.GL_ONE ); + super.draw(); + GLES20.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA); + } + }; + signs.x = title.x + (title.width() - signs.width())/2f; + signs.y = title.y; + add( signs ); + + DashboardItem btnBadges = new DashboardItem( Messages.get(this, "badges"), 3 ) { + @Override + protected void onClick() { + ShatteredPixelDungeon.switchNoFade( BadgesScene.class ); + } + }; + add(btnBadges); + + DashboardItem btnAbout = new DashboardItem( Messages.get(this, "about"), 1 ) { + @Override + protected void onClick() { + ShatteredPixelDungeon.switchNoFade( AboutScene.class ); + } + }; + add( btnAbout ); + + DashboardItem btnPlay = new DashboardItem( Messages.get(this, "play"), 0 ) { + @Override + protected void onClick() { + ShatteredPixelDungeon.switchNoFade( StartScene.class ); + } + }; + add( btnPlay ); + + DashboardItem btnRankings = new DashboardItem( Messages.get(this, "rankings"), 2 ) { + @Override + protected void onClick() { + ShatteredPixelDungeon.switchNoFade( RankingsScene.class ); + } + }; + add( btnRankings ); + + if (ShatteredPixelDungeon.landscape()) { + btnRankings .setPos( w / 2 - btnRankings.width(), topRegion ); + btnBadges .setPos( w / 2, topRegion ); + btnPlay .setPos( btnRankings.left() - btnPlay.width(), topRegion ); + btnAbout .setPos( btnBadges.right(), topRegion ); + } else { + btnPlay.setPos( w / 2 - btnPlay.width(), topRegion ); + btnRankings.setPos( w / 2, btnPlay.top() ); + btnBadges.setPos( w / 2 - btnBadges.width(), btnPlay.top() + DashboardItem.SIZE ); + btnAbout.setPos( w / 2, btnBadges.top() ); + } + + BitmapText source = new BitmapText("PD v 1.7.5", font1x); + source.measure(); + source.hardlight(0x444444); + source.x = w - source.width(); + source.y = h - source.height(); + add(source); + + BitmapText version = new BitmapText("v " + Game.version + "", font1x); + version.measure(); + version.hardlight(0xCCCCCC); + version.x = w - version.width(); + version.y = h - version.height() - source.height(); + add(version); + + Button changes = new ChangesButton(); + changes.setPos( 6, h - version.height() - changes.height()); + add( changes ); + + PrefsButton btnPrefs = new PrefsButton(); + btnPrefs.setPos(0, 0); + add(btnPrefs); + + LanguageButton btnLang = new LanguageButton(); + btnLang.setPos(16, 1); + add( btnLang ); + + ExitButton btnExit = new ExitButton(); + btnExit.setPos(w - btnExit.width(), 0); + add(btnExit); + + fadeIn(); + } + + private void placeTorch( float x, float y ) { + Fireball fb = new Fireball(); + fb.setPos( x, y ); + add( fb ); + } + + private static class DashboardItem extends Button { + + public static final float SIZE = 48; + + private static final int IMAGE_SIZE = 32; + + private Image image; + private RenderedText label; + + public DashboardItem( String text, int index ) { + super(); + + image.frame( image.texture.uvRect( index * IMAGE_SIZE, 0, (index + 1) * IMAGE_SIZE, IMAGE_SIZE ) ); + this.label.text( text ); + + setSize( SIZE, SIZE ); + } + + @Override + protected void createChildren() { + super.createChildren(); + + image = new Image( Assets.DASHBOARD ); + add( image ); + + label = renderText( 9 ); + add( label ); + } + + @Override + protected void layout() { + super.layout(); + + image.x = x + (width - image.width()) / 2; + image.y = y; + align(image); + + label.x = x + (width - label.width()) / 2; + label.y = image.y + image.height() +2; + align(label); + } + + @Override + protected void onTouchDown() { + image.brightness( 1.5f ); + Sample.INSTANCE.play( Assets.SND_CLICK, 1, 1, 0.8f ); + } + + @Override + protected void onTouchUp() { + image.resetColor(); + } + } +} diff --git a/java/com/hmdzl/spspd/scenes/WelcomeScene.java b/java/com/hmdzl/spspd/scenes/WelcomeScene.java new file mode 100644 index 00000000..abf9e84b --- /dev/null +++ b/java/com/hmdzl/spspd/scenes/WelcomeScene.java @@ -0,0 +1,96 @@ +package com.hmdzl.spspd.scenes; + +import com.hmdzl.spspd.Chrome; +import com.hmdzl.spspd.ShatteredPixelDungeon; +import com.hmdzl.spspd.ui.Archs; +import com.hmdzl.spspd.ui.RedButton; +import com.hmdzl.spspd.ui.ScrollPane; +import com.hmdzl.spspd.ui.Window; +import com.watabou.noosa.Camera; +import com.watabou.noosa.NinePatch; +import com.watabou.noosa.ui.Component; +import com.hmdzl.spspd.ui.RenderedTextMultiline; +import com.hmdzl.spspd.messages.Messages; +import com.watabou.noosa.RenderedText; +import com.hmdzl.spspd.ui.ExitButton; + +//TODO: update this class with relevant info as new versions come out. +public class WelcomeScene extends PixelScene { + + + @Override + public void create() { + super.create(); + + int w = Camera.main.width; + int h = Camera.main.height; + + RenderedText title = PixelScene.renderText( Messages.get(this, "title"), 9 ); + title.hardlight(Window.TITLE_COLOR); + title.x = (w - title.width()) / 2 ; + title.y = 4; + align(title); + add(title); + + ExitButton btnExit = new ExitButton(); + btnExit.setPos( Camera.main.width - btnExit.width(), 0 ); + add( btnExit ); + + RenderedTextMultiline text = renderMultiline(Messages.get(WelcomeScene.class,"new_things"), 6 ); + + + int pw = w - 6; + int ph = h - 40; + + + NinePatch panel = Chrome.get(Chrome.Type.WINDOW); + panel.size( pw, ph ); + panel.x = (w - pw) / 2; + //panel.y = title.y + title.height() + 2; + panel.y = (h - ph) / 2; + add( panel ); + + ScrollPane list = new ScrollPane( new Component() ); + add( list ); + + Component content = list.content(); + content.clear(); + + text.maxWidth((int) panel.innerWidth()); + + content.add(text); + + content.setSize( panel.innerWidth(), text.height() ); + + list.setRect( + panel.x + panel.marginLeft(), + panel.y + panel.marginTop(), + panel.innerWidth(), + panel.innerHeight()); + list.scrollTo(0, 0); + + Archs archs = new Archs(); + archs.setSize( Camera.main.width, Camera.main.height ); + addToBack( archs ); + + fadeIn(); + + RedButton okay = new RedButton(Messages.get(this, "continue")){ + @Override + protected void onClick() { + super.onClick(); + //updateVersion(previousVersion); + ShatteredPixelDungeon.switchScene(TitleScene.class); + } + }; + + okay.setRect(title.x, h-20, title.width(), 16); + okay.textColor(0xBBBB33); + add(okay); + } + + @Override + protected void onBackPressed() { + ShatteredPixelDungeon.switchNoFade(TitleScene.class); + } +} diff --git a/java/com/hmdzl/spspd/sprites/AFlySprite.java b/java/com/hmdzl/spspd/sprites/AFlySprite.java new file mode 100644 index 00000000..9ca2b55f --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/AFlySprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class AFlySprite extends MobSprite { + + public AFlySprite() { + super(); + + texture( Assets.A_FLY ); + + TextureFilm frames = new TextureFilm( texture, 16, 16 ); + + idle = new Animation( 15, true ); + idle.frames(frames, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3); + + run = new Animation( 20, true ); + run.frames( frames, 0 ); + + attack = new Animation( 12, false ); + attack.frames( frames, 0, 2, 3 ); + + die = new Animation( 20, false ); + die.frames( frames, 0 ); + + play( idle ); + } + + +} diff --git a/java/com/hmdzl/spspd/sprites/ARealManSprite.java b/java/com/hmdzl/spspd/sprites/ARealManSprite.java new file mode 100644 index 00000000..139c0f9e --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/ARealManSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class ARealManSprite extends MobSprite { + + public ARealManSprite() { + super(); + + texture( Assets.M_AMD_W ); + + TextureFilm frames = new TextureFilm( texture, 16, 16 ); + + idle = new Animation( 3, true ); + idle.frames(frames, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3); + + run = new Animation( 20, true ); + run.frames( frames, 0 ); + + attack = new Animation( 12, false ); + attack.frames( frames, 0, 2, 3 ); + + die = new Animation( 20, false ); + die.frames( frames, 0 ); + + play( idle ); + } + + +} diff --git a/java/com/hmdzl/spspd/sprites/AcidicSprite.java b/java/com/hmdzl/spspd/sprites/AcidicSprite.java new file mode 100644 index 00000000..24967b90 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/AcidicSprite.java @@ -0,0 +1,54 @@ +/* + * 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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class AcidicSprite extends ScorpioSprite { + + public AcidicSprite() { + super(); + + texture(Assets.SCORPIO); + + TextureFilm frames = new TextureFilm(texture, 18, 17); + + idle = new Animation(12, true); + idle.frames(frames, 14, 14, 14, 14, 14, 14, 14, 14, 15, 16, 15, 16, 15, + 16); + + run = new Animation(4, true); + run.frames(frames, 19, 20); + + attack = new Animation(15, false); + attack.frames(frames, 14, 17, 18); + + zap = attack.clone(); + + die = new Animation(12, false); + die.frames(frames, 14, 21, 22, 23, 24); + + play(idle); + } + + @Override + public int blood() { + return 0xFF66FF22; + } +} diff --git a/java/com/hmdzl/spspd/sprites/AdultDragonVioletSprite.java b/java/com/hmdzl/spspd/sprites/AdultDragonVioletSprite.java new file mode 100644 index 00000000..60d514bb --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/AdultDragonVioletSprite.java @@ -0,0 +1,72 @@ +/* + * 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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.actors.mobs.AdultDragonViolet; +import com.hmdzl.spspd.effects.MagicMissile; +import com.watabou.noosa.TextureFilm; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Callback; + +public class AdultDragonVioletSprite extends MobSprite { + + private static final float DURATION = 2f; + private Animation cast; + + public AdultDragonVioletSprite() { + super(); + + texture(Assets.DRAGON); + + TextureFilm frames = new TextureFilm(texture, 16, 16); + + idle = new Animation(10, true); + idle.frames(frames, 0, 1, 0, 1, 0, 1, 0); + + run = new Animation(10, false); + run.frames(frames, 0, 2, 1); + + attack = new Animation(10, false); + attack.frames(frames, 0, 2, 3, 4, 5); + + cast = attack.clone(); + + die = new Animation(10, false); + die.frames(frames, 0, 5, 6, 7, 8, 9, 9, 9); + + play(run.clone()); + } + + + + @Override + public void zap(int cell) { + + turnTo(ch.pos, cell); + play(zap); + + MagicMissile.poison(parent, ch.pos, cell, new Callback() { + @Override + public void call() { + ((AdultDragonViolet) ch).onZapComplete(); + } + }); + Sample.INSTANCE.play(Assets.SND_ZAP); + } +} diff --git a/java/com/hmdzl/spspd/sprites/AlbinoPiranhaSprite.java b/java/com/hmdzl/spspd/sprites/AlbinoPiranhaSprite.java new file mode 100644 index 00000000..ceaf094a --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/AlbinoPiranhaSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.scenes.GameScene; +import com.watabou.noosa.TextureFilm; + +public class AlbinoPiranhaSprite extends MobSprite { + + public AlbinoPiranhaSprite() { + super(); + + texture(Assets.ALBINOPIRANHA); + + TextureFilm frames = new TextureFilm(texture, 12, 16); + + idle = new Animation(8, true); + idle.frames(frames, 0, 1, 2, 1); + + run = new Animation(20, true); + run.frames(frames, 0, 1, 2, 1); + + attack = new Animation(20, false); + attack.frames(frames, 3, 4, 5, 6, 7, 8, 9, 10, 11); + + die = new Animation(4, false); + die.frames(frames, 12, 13, 14); + + play(idle); + } + + @Override + public void onComplete(Animation anim) { + super.onComplete(anim); + + if (anim == attack) { + GameScene.ripple(ch.pos); + } + } +} diff --git a/java/com/hmdzl/spspd/sprites/AlbinoSprite.java b/java/com/hmdzl/spspd/sprites/AlbinoSprite.java new file mode 100644 index 00000000..92a92ff3 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/AlbinoSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class AlbinoSprite extends MobSprite { + + public AlbinoSprite() { + super(); + + texture(Assets.RAT); + + TextureFilm frames = new TextureFilm(texture, 16, 15); + + idle = new Animation(2, true); + idle.frames(frames, 16, 16, 16, 17); + + run = new Animation(10, true); + run.frames(frames, 22, 23, 24, 25, 26); + + attack = new Animation(15, false); + attack.frames(frames, 18, 19, 20, 21); + + die = new Animation(10, false); + die.frames(frames, 27, 28, 29, 30); + + play(idle); + } +} diff --git a/java/com/hmdzl/spspd/sprites/ApostleSprite.java b/java/com/hmdzl/spspd/sprites/ApostleSprite.java new file mode 100644 index 00000000..f16bb84d --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/ApostleSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class ApostleSprite extends MobSprite { + + public ApostleSprite() { + super(); + + texture( Assets.APOSTLE ); + + TextureFilm frames = new TextureFilm( texture, 16, 16 ); + + idle = new Animation( 3, true ); + idle.frames(frames, 0, 0, 1, 1, 2, 2, 3, 3, 3, 3, 3, 3); + + run = new Animation( 3, true ); + run.frames( frames, 0, 0, 1, 1, 2, 2, 3, 3, 3, 3, 3, 3 ); + + attack = new Animation( 12, false ); + attack.frames( frames, 0, 2, 3 ); + + die = new Animation( 20, false ); + die.frames( frames, 0 ); + + play( idle ); + } + + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/sprites/AssassinSprite.java b/java/com/hmdzl/spspd/sprites/AssassinSprite.java new file mode 100644 index 00000000..3fbc09c5 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/AssassinSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Slow; +import com.hmdzl.spspd.items.weapon.missiles.Smoke; +import com.hmdzl.spspd.levels.Level; +import com.watabou.noosa.TextureFilm; +import com.watabou.utils.Callback; +import com.watabou.utils.Random; + +public class AssassinSprite extends MobSprite { + + private Animation cast; + + public AssassinSprite() { + super(); + + texture(Assets.ASSASSIN); + + TextureFilm frames = new TextureFilm(texture, 14, 16); + + idle = new Animation(2, true); + idle.frames(frames, 0, 0, 0, 1); + + run = new Animation(15, false); + run.frames(frames, 2, 3, 4, 5, 0); + + attack = new Animation(15, false); + attack.frames(frames, 6, 7, 7, 0); + + cast = attack.clone(); + + die = new Animation(8, false); + die.frames(frames, 8, 9, 10, 10); + + play(run.clone()); + } + + + @Override + public void attack(int cell) { + if (!Level.adjacent(cell, ch.pos)) { + Char enemy = Actor.findChar(cell); + ((MissileSprite) parent.recycle(MissileSprite.class)).reset(ch.pos, + cell, new Smoke(), new Callback() { + @Override + public void call() { + ch.onAttackComplete(); + } + }); + + + if(Random.Int(5)==0){ + Buff.affect(enemy, Slow.class, Slow.duration(enemy)); + } + + + + play(cast); + turnTo(ch.pos, cell); + + } else { + + super.attack(cell); + + } + } + + @Override + public void onComplete(Animation anim) { + if (anim == run) { + isMoving = false; + idle(); + } else { + super.onComplete(anim); + } + } +} diff --git a/java/com/hmdzl/spspd/sprites/BaBaSprite.java b/java/com/hmdzl/spspd/sprites/BaBaSprite.java new file mode 100644 index 00000000..553d9fee --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/BaBaSprite.java @@ -0,0 +1,47 @@ +/* + * Pixel Dungeon + * Copyright (C) 2452-2454 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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; +import com.watabou.utils.Random; + +public class BaBaSprite extends MobSprite { + + public BaBaSprite() { + super(); + + texture(Assets.SHEEP); + + TextureFilm frames = new TextureFilm(texture, 16, 15); + + idle = new Animation(8, true); + idle.frames(frames, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 6, 7, 4); + + run = idle.clone(); + + attack = new Animation(12, false); + attack.frames(frames, 2, 3, 0, 1); + + die = new Animation(20, false); + die.frames(frames, 4); + + play(idle); + curFrame = Random.Int(curAnim.frames.length); + } +} diff --git a/java/com/hmdzl/spspd/sprites/BanditKingSprite.java b/java/com/hmdzl/spspd/sprites/BanditKingSprite.java new file mode 100644 index 00000000..6c3a4012 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/BanditKingSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.actors.Char; +import com.watabou.noosa.TextureFilm; + +public class BanditKingSprite extends MobSprite { + + public BanditKingSprite() { + super(); + + texture(Assets.BANDITKING); + TextureFilm film = new TextureFilm(texture, 12, 13); + + idle = new Animation(1, true); + idle.frames(film, 0, 0, 0, 1, 0, 0, 0, 0, 1); + + run = new Animation(15, true); + run.frames(film, 0, 0, 2, 3, 3, 4); + + die = new Animation(10, false); + die.frames(film, 1, 1, 5, 5, 5); + + attack = new Animation(12, false); + attack.frames(film, 10, 11, 12, 0); + + idle(); + } + + @Override + public void link(Char ch) { + super.link(ch); + add(State.LEVITATING); + } + + @Override + public void die() { + super.die(); + remove(State.LEVITATING); + } +} diff --git a/java/com/hmdzl/spspd/sprites/BanditSprite.java b/java/com/hmdzl/spspd/sprites/BanditSprite.java new file mode 100644 index 00000000..c8f80114 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/BanditSprite.java @@ -0,0 +1,45 @@ +/* + * 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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class BanditSprite extends MobSprite { + + public BanditSprite() { + super(); + + texture(Assets.THIEF); + TextureFilm film = new TextureFilm(texture, 12, 13); + + idle = new Animation(1, true); + idle.frames(film, 21, 21, 21, 22, 21, 21, 21, 21, 22); + + run = new Animation(15, true); + run.frames(film, 21, 21, 23, 24, 24, 25); + + die = new Animation(10, false); + die.frames(film, 25, 27, 28, 29, 30); + + attack = new Animation(12, false); + attack.frames(film, 31, 32, 33); + + idle(); + } +} diff --git a/java/com/hmdzl/spspd/sprites/BatSprite.java b/java/com/hmdzl/spspd/sprites/BatSprite.java new file mode 100644 index 00000000..323c559c --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/BatSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class BatSprite extends MobSprite { + + public BatSprite() { + super(); + + texture(Assets.BAT); + + TextureFilm frames = new TextureFilm(texture, 15, 15); + + idle = new Animation(8, true); + idle.frames(frames, 0, 1); + + run = new Animation(12, true); + run.frames(frames, 0, 1); + + attack = new Animation(12, false); + attack.frames(frames, 2, 3, 0, 1); + + die = new Animation(12, false); + die.frames(frames, 4, 5, 6); + + play(idle); + } +} diff --git a/java/com/hmdzl/spspd/sprites/BatteryTombSprite.java b/java/com/hmdzl/spspd/sprites/BatteryTombSprite.java new file mode 100644 index 00000000..24c9b683 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/BatteryTombSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.Game; +import com.watabou.noosa.TextureFilm; + +public class BatteryTombSprite extends MobSprite { + + public BatteryTombSprite() { + super(); + + texture( Assets.BATTERYTOMB ); + + TextureFilm frames = new TextureFilm( texture, 16, 16 ); + + idle = new Animation( 15, true ); + idle.frames(frames, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3); + + run = new Animation( 20, true ); + run.frames( frames, 0,1,2,3 ); + + attack = new Animation( 12, false ); + attack.frames( frames, 0, 2, 3 ); + + die = new Animation( 20, false ); + die.frames( frames, 0 ); + + play( idle ); + } + @Override + public void update() { + super.update(); + + if (flashTime <= 0){ + float interval = (Game.timeTotal % 9 ) /3f; + tint(interval > 2 ? interval - 2 : Math.max(0, 1 - interval), + interval > 1 ? Math.max(0, 2-interval): interval, + interval > 2 ? Math.max(0, 3-interval): interval-1, 0.5f); + } + } + +} diff --git a/java/com/hmdzl/spspd/sprites/BeastYearSprite.java b/java/com/hmdzl/spspd/sprites/BeastYearSprite.java new file mode 100644 index 00000000..bae3d902 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/BeastYearSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class BeastYearSprite extends MobSprite { + + public BeastYearSprite() { + super(); + + texture( Assets.BEAST_YEAR ); + + TextureFilm frames = new TextureFilm( texture, 16, 16 ); + + idle = new Animation( 15, true ); + idle.frames(frames, 0,0,1,1,0,0); + + run = new Animation( 20, true ); + run.frames( frames, 0,0 ); + + attack = new Animation( 12, false ); + attack.frames( frames, 1,1,2, 2,2, 3,3 ); + + die = new Animation( 20, false ); + die.frames( frames, 2,2,1,1,0,0 ); + + play( idle ); + } + + +} diff --git a/java/com/hmdzl/spspd/sprites/BeeSprite.java b/java/com/hmdzl/spspd/sprites/BeeSprite.java new file mode 100644 index 00000000..67c32293 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/BeeSprite.java @@ -0,0 +1,51 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class BeeSprite extends MobSprite { + + public BeeSprite() { + super(); + + texture(Assets.BEE); + + TextureFilm frames = new TextureFilm(texture, 16, 16); + + idle = new Animation(12, true); + idle.frames(frames, 0, 1, 1, 0, 2, 2); + + run = new Animation(15, true); + run.frames(frames, 0, 1, 1, 0, 2, 2); + + attack = new Animation(20, false); + attack.frames(frames, 3, 4, 5, 6); + + die = new Animation(20, false); + die.frames(frames, 7, 8, 9, 10); + + play(idle); + } + + @Override + public int blood() { + return 0xffd500; + } +} diff --git a/java/com/hmdzl/spspd/sprites/BilboldevSprite.java b/java/com/hmdzl/spspd/sprites/BilboldevSprite.java new file mode 100644 index 00000000..3b515915 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/BilboldevSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class BilboldevSprite extends MobSprite { + + public BilboldevSprite() { + super(); + + texture( Assets.BILBOLDEV ); + + TextureFilm frames = new TextureFilm( texture, 16, 14 ); + + idle = new Animation( 15, true ); + idle.frames(frames, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 3); + + run = new Animation( 20, true ); + run.frames( frames, 0 ); + + attack = new Animation( 12, false ); + attack.frames( frames, 0, 2, 3 ); + + die = new Animation( 20, false ); + die.frames( frames, 0 ); + + play( idle ); + } + + +} diff --git a/java/com/hmdzl/spspd/sprites/BlacksmithSprite.java b/java/com/hmdzl/spspd/sprites/BlacksmithSprite.java new file mode 100644 index 00000000..b55a220d --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/BlacksmithSprite.java @@ -0,0 +1,82 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2014 Oleg Dolya + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.levels.Level; +import com.watabou.noosa.TextureFilm; +import com.watabou.noosa.audio.Sample; +import com.watabou.noosa.particles.Emitter; + +public class BlacksmithSprite extends MobSprite { + + private Emitter emitter; + + public BlacksmithSprite() { + super(); + + texture(Assets.TROLL); + + TextureFilm frames = new TextureFilm(texture, 13, 16); + + idle = new Animation(15, true); + idle.frames(frames, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 3); + + run = new Animation(20, true); + run.frames(frames, 0); + + die = new Animation(20, false); + die.frames(frames, 0); + + play(idle); + } + + @Override + public void link(Char ch) { + super.link(ch); + + emitter = new Emitter(); + emitter.autoKill = false; + emitter.pos(x + 7, y + 12); + parent.add(emitter); + } + + @Override + public void update() { + super.update(); + + if (emitter != null) { + emitter.visible = visible; + } + } + + @Override + public void onComplete(Animation anim) { + super.onComplete(anim); + + if (visible && emitter != null && anim == idle) { + emitter.burst(Speck.factory(Speck.FORGE), 3); + float volume = 0.2f / (Level.distance(ch.pos, Dungeon.hero.pos)); + Sample.INSTANCE.play(Assets.SND_EVOKE, volume, volume, 0.8f); + } + } + +} diff --git a/java/com/hmdzl/spspd/sprites/BlueDragonSprite.java b/java/com/hmdzl/spspd/sprites/BlueDragonSprite.java new file mode 100644 index 00000000..874446c7 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/BlueDragonSprite.java @@ -0,0 +1,74 @@ +/* + * 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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.actors.mobs.pets.BlueDragon; +import com.hmdzl.spspd.effects.MagicMissile; +import com.watabou.noosa.TextureFilm; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Callback; + +public class BlueDragonSprite extends MobSprite { + + //Frames 1-4 are idle, 5-8 are moving, 9-12 are attack and the last are for death RBVG + + public BlueDragonSprite() { + super(); + + texture(Assets.PETDRAGON); + + TextureFilm frames = new TextureFilm(texture, 16, 16); + + idle = new Animation(2, true); + idle.frames(frames, 16, 17, 18, 19); + + run = new Animation(8, true); + run.frames(frames, 20, 21, 22, 23); + + attack = new Animation(8, false); + attack.frames(frames, 24, 25, 26, 27); + + zap = attack.clone(); + + die = new Animation(8, false); + die.frames(frames, 28, 29, 30, 31); + + play(idle); + } + + @Override + public void zap(int cell) { + + turnTo(ch.pos, cell); + play(zap); + + MagicMissile.coldLight(parent, ch.pos, cell, new Callback() { + @Override + public void call() { + ((BlueDragon) ch).onZapComplete(); + } + }); + Sample.INSTANCE.play(Assets.SND_ZAP); + } + + @Override + public int blood() { + return 0xFFcdcdb7; + } +} diff --git a/java/com/hmdzl/spspd/sprites/BlueWraithSprite.java b/java/com/hmdzl/spspd/sprites/BlueWraithSprite.java new file mode 100644 index 00000000..533fc8db --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/BlueWraithSprite.java @@ -0,0 +1,51 @@ +/* + * 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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class BlueWraithSprite extends MobSprite { + + public BlueWraithSprite() { + super(); + + texture(Assets.BLUEWRAITH); + + TextureFilm frames = new TextureFilm(texture, 14, 15); + + idle = new Animation(5, true); + idle.frames(frames, 0, 1); + + run = new Animation(10, true); + run.frames(frames, 0, 1); + + attack = new Animation(10, false); + attack.frames(frames, 0, 2, 3); + + die = new Animation(8, false); + die.frames(frames, 0, 4, 5, 6, 7); + + play(idle); + } + + @Override + public int blood() { + return 0x88000000; + } +} diff --git a/java/com/hmdzl/spspd/sprites/BrokenRobotSprite.java b/java/com/hmdzl/spspd/sprites/BrokenRobotSprite.java new file mode 100644 index 00000000..eb984391 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/BrokenRobotSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.DungeonTilemap; +import com.hmdzl.spspd.effects.DeathRay; +import com.watabou.noosa.TextureFilm; + +public class BrokenRobotSprite extends MobSprite { + + private int attackPos; + + public BrokenRobotSprite() { + super(); + + texture(Assets.BROKENROBOT); + + TextureFilm frames = new TextureFilm(texture, 16, 18); + + idle = new Animation(2, true); + idle.frames(frames, 0, 1, 0, 1); + + run = new Animation(12, true); + run.frames(frames, 2, 3, 4, 5, 6, 7); + + attack = new Animation(8, false); + attack.frames(frames, 8, 9); + + die = new Animation(8, false); + die.frames(frames, 10, 11, 12, 13); + + play(idle); + } + + @Override + public void attack(int pos) { + attackPos = pos; + super.attack(pos); + } + + + @Override + public void onComplete(Animation anim) { + super.onComplete(anim); + + if (anim == attack) { + if (Dungeon.visible[ch.pos] || Dungeon.visible[attackPos]) { + parent.add(new DeathRay(center(), DungeonTilemap + .tileCenterToWorld(attackPos))); + } + } + } +} diff --git a/java/com/hmdzl/spspd/sprites/BrownBatSprite.java b/java/com/hmdzl/spspd/sprites/BrownBatSprite.java new file mode 100644 index 00000000..93dfc475 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/BrownBatSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class BrownBatSprite extends MobSprite { + + public BrownBatSprite() { + super(); + + texture(Assets.BAT); + + TextureFilm frames = new TextureFilm(texture, 15, 15); + + idle = new Animation(8, true); + idle.frames(frames, 16, 17); + + run = new Animation(12, true); + run.frames(frames, 16, 17); + + attack = new Animation(12, false); + attack.frames(frames, 18, 19, 16, 17); + + die = new Animation(12, false); + die.frames(frames, 20, 21, 22); + + play(idle); + } +} diff --git a/java/com/hmdzl/spspd/sprites/BruteSprite.java b/java/com/hmdzl/spspd/sprites/BruteSprite.java new file mode 100644 index 00000000..23d7ae12 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/BruteSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.items.weapon.missiles.EscapeKnive; +import com.hmdzl.spspd.levels.Level; +import com.watabou.noosa.TextureFilm; +import com.watabou.utils.Callback; + +public class BruteSprite extends MobSprite { + + private Animation cast; + + public BruteSprite() { + super(); + + texture(Assets.BRUTE); + + TextureFilm frames = new TextureFilm(texture, 12, 16); + + idle = new Animation(2, true); + idle.frames(frames, 0, 0, 0, 1, 0, 0, 1, 1); + + run = new Animation(12, true); + run.frames(frames, 4, 5, 6, 7); + + attack = new Animation(12, false); + attack.frames(frames, 2, 3, 0); + + cast = attack.clone(); + + die = new Animation(12, false); + die.frames(frames, 8, 9, 10); + + play(idle); + } + + @Override + public void attack(int cell) { + if (!Level.adjacent(cell, ch.pos)) { + + ((MissileSprite) parent.recycle(MissileSprite.class)).reset(ch.pos, + cell, new EscapeKnive(), new Callback() { + @Override + public void call() { + ch.onAttackComplete(); + } + }); + + play(cast); + turnTo(ch.pos, cell); + + } else { + + super.attack(cell); + + } + } +} diff --git a/java/com/hmdzl/spspd/sprites/BugDragonSprite.java b/java/com/hmdzl/spspd/sprites/BugDragonSprite.java new file mode 100644 index 00000000..9dcfd4d0 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/BugDragonSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.actors.mobs.pets.BugDragon; +import com.hmdzl.spspd.effects.MagicMissile; +import com.watabou.noosa.TextureFilm; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Callback; + +public class BugDragonSprite extends MobSprite { + + //Frames 1-4 are idle, 5-8 are moving, 9-12 are attack and the last are for death RBVG + + private int[] points = new int[2]; + + public BugDragonSprite() { + super(); + + texture(Assets.PETDRAGON); + + TextureFilm frames = new TextureFilm(texture, 16, 16); + + idle = new Animation(2, true); + idle.frames(frames, 112, 113, 114, 115); + + run = new Animation(8, true); + run.frames(frames, 116, 117, 118, 119); + + attack = new Animation(8, false); + attack.frames(frames, 120, 121, 122, 123); + + zap = attack.clone(); + + die = new Animation(8, false); + die.frames(frames, 124, 125, 126, 127); + + play(idle); + } + @Override + public void zap(int cell) { + + turnTo(ch.pos, cell); + play(zap); + + MagicMissile.force(parent, ch.pos, cell, new Callback() { + @Override + public void call() { + ((BugDragon) ch).onZapComplete(); + } + }); + Sample.INSTANCE.play(Assets.SND_ZAP); + } + + @Override + public int blood() { + return 0xFFcdcdb7; + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/sprites/BunnySprite.java b/java/com/hmdzl/spspd/sprites/BunnySprite.java new file mode 100644 index 00000000..33dba824 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/BunnySprite.java @@ -0,0 +1,57 @@ +/* + * 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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; + +import com.watabou.noosa.TextureFilm; + +public class BunnySprite extends MobSprite { + + //Frames 0,2 are idle, 0,1,2 are moving, 0,3,4,1 are attack and 5,6,7 are for death + + + public BunnySprite() { + super(); + + texture(Assets.BUNNY); + + TextureFilm frames = new TextureFilm(texture, 14, 16); + + idle = new Animation(2, true); + idle.frames(frames, 0, 1, 0, 0); + + run = new Animation(4, true); + run.frames(frames, 0, 0, 0, 2); + + attack = new Animation(8, false); + attack.frames(frames, 0, 2, 3, 4); + + zap = attack.clone(); + + die = new Animation(8, false); + die.frames(frames, 5, 6, 7, 8); + + play(idle); + } + + @Override + public int blood() { + return 0xFFcdcdb7; + } +} diff --git a/java/com/hmdzl/spspd/sprites/BurningFistSprite.java b/java/com/hmdzl/spspd/sprites/BurningFistSprite.java new file mode 100644 index 00000000..62ec82c2 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/BurningFistSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.effects.MagicMissile; +import com.watabou.noosa.TextureFilm; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Callback; + +public class BurningFistSprite extends MobSprite { + + public BurningFistSprite() { + super(); + + texture(Assets.BURNING); + + TextureFilm frames = new TextureFilm(texture, 24, 17); + + idle = new Animation(2, true); + idle.frames(frames, 0, 0, 1); + + run = new Animation(3, true); + run.frames(frames, 0, 1); + + attack = new Animation(8, false); + attack.frames(frames, 0, 5, 6); + + die = new Animation(10, false); + die.frames(frames, 0, 2, 3, 4); + + play(idle); + } + + private int posToShoot; + + @Override + public void attack(int cell) { + posToShoot = cell; + super.attack(cell); + } + + @Override + public void onComplete(Animation anim) { + if (anim == attack) { + + Sample.INSTANCE.play(Assets.SND_ZAP); + MagicMissile.shadow(parent, ch.pos, posToShoot, new Callback() { + @Override + public void call() { + ch.onAttackComplete(); + } + }); + + idle(); + + } else { + super.onComplete(anim); + } + } +} diff --git a/java/com/hmdzl/spspd/sprites/CellmobSprite.java b/java/com/hmdzl/spspd/sprites/CellmobSprite.java new file mode 100644 index 00000000..67e22884 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/CellmobSprite.java @@ -0,0 +1,53 @@ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.DungeonTilemap; +import com.hmdzl.spspd.effects.DeathRay; +import com.watabou.noosa.TextureFilm; + +public class CellmobSprite extends MobSprite { + + private int attackPos; + + public CellmobSprite() { + super(); + + texture(Assets.CELL_MOB); + + TextureFilm frames = new TextureFilm(texture, 16, 18); + + idle = new Animation(2, true); + idle.frames(frames, 1, 2, 3, 4); + + run = new Animation(12, true); + run.frames(frames, 2, 3, 4); + + attack = new Animation(8, false); + attack.frames(frames, 1, 5); + + die = new Animation(8, false); + die.frames(frames, 1, 0, 6); + + play(idle); + } + + @Override + public void attack(int pos) { + attackPos = pos; + super.attack(pos); + } + + + @Override + public void onComplete(Animation anim) { + super.onComplete(anim); + + if (anim == attack) { + if (Dungeon.visible[ch.pos] || Dungeon.visible[attackPos]) { + parent.add(new DeathRay(center(), DungeonTilemap + .tileCenterToWorld(attackPos))); + } + } + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/sprites/CharSprite.java b/java/com/hmdzl/spspd/sprites/CharSprite.java new file mode 100644 index 00000000..131d238d --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/CharSprite.java @@ -0,0 +1,601 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2015 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.DungeonTilemap; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.effects.DarkBlock; +import com.hmdzl.spspd.effects.EmoIcon; +import com.hmdzl.spspd.effects.FloatingText; +import com.hmdzl.spspd.effects.IceBlock; +import com.hmdzl.spspd.effects.ShieldHalo; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.effects.Splash; +import com.hmdzl.spspd.effects.TorchHalo; +import com.hmdzl.spspd.effects.particles.FlameParticle; +import com.hmdzl.spspd.effects.particles.LeafParticle; +import com.hmdzl.spspd.effects.particles.ShadowParticle; +import com.hmdzl.spspd.effects.particles.SnowParticle; +import com.hmdzl.spspd.items.potions.PotionOfInvisibility; +import com.hmdzl.spspd.ui.CharHealthIndicator; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.GameScene; +import com.watabou.noosa.Game; +import com.watabou.noosa.MovieClip; +import com.watabou.noosa.Visual; +import com.watabou.noosa.audio.Sample; +import com.watabou.noosa.particles.Emitter; +import com.watabou.noosa.tweeners.AlphaTweener; +import com.watabou.noosa.tweeners.PosTweener; +import com.watabou.noosa.tweeners.Tweener; +import com.watabou.utils.Callback; +import com.watabou.utils.PointF; +import com.watabou.utils.Random; + +public class CharSprite extends MovieClip implements Tweener.Listener, MovieClip.Listener { + + // Color constants for floating text + public static final int DEFAULT = 0xFFFFFF; + public static final int POSITIVE = 0x00FF00; + public static final int NEGATIVE = 0xFF0000; + public static final int WARNING = 0xFF8800; + public static final int NEUTRAL = 0xFFFF00; + + private static final float MOVE_INTERVAL = 0.1f; + private static final float FLASH_INTERVAL = 0.05f; + + public enum State { + BURNING, LEVITATING, INVISIBLE, PARALYSED, FROZEN, ILLUMINATED, CHILLED, DARKENED, MARKED, REGROW, HEALING, SHIELDED, + } + + protected Animation idle; + protected Animation run; + protected Animation attack; + protected Animation operate; + protected Animation zap; + protected Animation die; + + protected Callback animCallback; + + protected Tweener motion; + + protected Emitter burning; + protected Emitter chilled; + protected Emitter marked; + protected Emitter levitation; + protected Emitter regrow; + protected Emitter healing; + + protected IceBlock iceBlock; + protected DarkBlock darkBlock; + protected TorchHalo halo; + protected ShieldHalo shield; + protected AlphaTweener invisible; + + protected EmoIcon emo; + protected CharHealthIndicator health; + + private Tweener jumpTweener; + private Callback jumpCallback; + + //private float flashTime = 0; + protected float flashTime = 0; + + protected boolean sleeping = false; + + public Char ch; + + public volatile boolean isMoving = false; + + public CharSprite() { + super(); + listener = this; + } + + public void link( Char ch ) { + this.ch = ch; + ch.sprite = this; + + place( ch.pos ); + turnTo( ch.pos, Random.Int( Level.LENGTH ) ); + + if (ch != Dungeon.hero) { + if (health == null) { + health = new CharHealthIndicator(ch); + } else { + health.target(ch); + } + } + + ch.updateSpriteState(); + } + + public PointF worldToCamera( int cell ) { + + final int csize = DungeonTilemap.SIZE; + + return new PointF( + ((cell % Level.WIDTH) + 0.5f) * csize - width * 0.5f, + ((cell / Level.WIDTH) + 1.0f) * csize - height + ); + } + + public void place( int cell ) { + point( worldToCamera( cell ) ); + } + + public void showStatus( int color, String text, Object... args ) { + if (visible) { + if (args.length > 0) { + text = Messages.format( text, args ); + } + if (ch != null) { + PointF tile = DungeonTilemap.tileCenterToWorld(ch.pos); + FloatingText.show( tile.x, tile.y-(width*0.5f), ch.pos, text, color ); + } else { + FloatingText.show( x + width * 0.5f, y, text, color ); + } + } + } + + public void idle() { + play( idle ); + } + + public void move( int from, int to ) { + turnTo( from , to ); + + play( run ); + + motion = new PosTweener( this, worldToCamera( to ), MOVE_INTERVAL ); + motion.listener = this; + parent.add( motion ); + + isMoving = true; + + if (visible && Level.water[from] && !ch.flying) { + GameScene.ripple( from ); + } + + } + + public void interruptMotion() { + if (motion != null) { + onComplete( motion ); + } + } + + public void attack( int cell ) { + turnTo( ch.pos, cell ); + play( attack ); + } + + public void attack( int cell, Callback callback ) { + animCallback = callback; + turnTo( ch.pos, cell ); + play( attack ); + } + + public void operate( int cell ) { + turnTo( ch.pos, cell ); + play( operate ); + } + + public void zap( int cell ) { + turnTo( ch.pos, cell ); + play( zap ); + } + + public void zap( int cell, Callback callback ) { + animCallback = callback; + zap( cell ); + } + + public void turnTo( int from, int to ) { + int fx = from % Level.WIDTH; + int tx = to % Level.WIDTH; + if (tx > fx) { + flipHorizontal = false; + } else if (tx < fx) { + flipHorizontal = true; + } + } + + public void jump( int from, int to, Callback callback ) { + jumpCallback = callback; + + int distance = Level.distance( from, to ); + jumpTweener = new JumpTweener( this, worldToCamera( to ), distance * 4, distance * 0.1f ); + jumpTweener.listener = this; + parent.add( jumpTweener ); + + turnTo( from, to ); + } + + public void die() { + sleeping = false; + play( die ); + + if (emo != null) { + emo.killAndErase(); + } + if (health != null){ + health.killAndErase(); + } + } + + public Emitter emitter() { + Emitter emitter = GameScene.emitter(); + emitter.pos( this ); + return emitter; + } + + public Emitter centerEmitter() { + Emitter emitter = GameScene.emitter(); + emitter.pos( center() ); + return emitter; + } + + public Emitter bottomEmitter() { + Emitter emitter = GameScene.emitter(); + emitter.pos( x, y + height, width, 0 ); + return emitter; + } + + public void burst( final int color, int n ) { + if (visible) { + Splash.at( center(), color, n ); + } + } + + public void bloodBurstA( PointF from, int damage ) { + if (visible) { + PointF c = center(); + int n = (int)Math.min( 9 * Math.sqrt( (double)damage / ch.HT ), 9 ); + Splash.at( c, PointF.angle( from, c ), 3.1415926f / 2, blood(), n ); + } + } + + public int blood() { + return 0xFFBB0000; + } + + public void flash() { + ra = ba = ga = 1f; + flashTime = FLASH_INTERVAL; + } + + public void add( State state ) { + switch (state) { + case BURNING: + burning = emitter(); + burning.pour( FlameParticle.FACTORY, 0.06f ); + if (visible) { + Sample.INSTANCE.play( Assets.SND_BURNING ); + } + break; + case LEVITATING: + levitation = emitter(); + levitation.pour( Speck.factory( Speck.JET ), 0.02f ); + break; + case INVISIBLE: + PotionOfInvisibility.melt( ch ); + break; + case PARALYSED: + paused = true; + break; + case FROZEN: + iceBlock = IceBlock.freeze( this ); + paused = true; + break; + case ILLUMINATED: + GameScene.effect( halo = new TorchHalo( this ) ); + break; + case CHILLED: + chilled = emitter(); + chilled.pour(SnowParticle.FACTORY, 0.1f); + break; + case DARKENED: + darkBlock = DarkBlock.darken( this ); + break; + case MARKED: + marked = emitter(); + marked.pour(ShadowParticle.UP, 0.1f); + break; + + case REGROW: + regrow = emitter(); + regrow.pour( LeafParticle.LEVEL_SPECIFIC, 0.06f ); + break; + case HEALING: + healing = emitter(); + healing.pour(Speck.factory(Speck.HEALING), 0.5f); + break; + case SHIELDED: + GameScene.effect( shield = new ShieldHalo( this )); + break; + } + } + + public void remove( State state ) { + switch (state) { + case BURNING: + if (burning != null) { + burning.on = false; + burning = null; + } + break; + case LEVITATING: + if (levitation != null) { + levitation.on = false; + levitation = null; + } + break; + case INVISIBLE: + alpha( 1f ); + break; + case PARALYSED: + paused = false; + break; + case FROZEN: + if (iceBlock != null) { + iceBlock.melt(); + iceBlock = null; + } + paused = false; + break; + case ILLUMINATED: + if (halo != null) { + halo.putOut(); + } + break; + case CHILLED: + if (chilled != null){ + chilled.on = false; + chilled = null; + } + break; + case DARKENED: + if (darkBlock != null) { + darkBlock.lighten(); + darkBlock = null; + } + break; + case MARKED: + if (marked != null){ + marked.on = false; + marked = null; + } + break; + case REGROW: + if (regrow != null) { + regrow.on = false; + regrow = null; + } + break; + case HEALING: + if (healing != null){ + healing.on = false; + healing = null; + } + break; + case SHIELDED: + if (shield != null){ + shield.putOut(); + } + break; + } + } + + @Override + public void update() { + + super.update(); + + if (paused && listener != null) { + listener.onComplete( curAnim ); + } + + if (flashTime > 0 && (flashTime -= Game.elapsed) <= 0) { + resetColor(); + } + + if (burning != null) { + burning.visible = visible; + } + if (levitation != null) { + levitation.visible = visible; + } + if (iceBlock != null) { + iceBlock.visible = visible; + } + if (chilled != null) { + chilled.visible = visible; + } + if (marked != null) { + marked.visible = visible; + } + if (sleeping) { + showSleep(); + } else { + hideSleep(); + } + if (emo != null) { + emo.visible = visible; + } + if (regrow != null) { + regrow.visible = visible; + } + + } + + @Override + public void resetColor() { + super.resetColor(); + if (invisible != null){ + alpha(0.4f); + } + } + + public synchronized void showSleep() { + if (emo instanceof EmoIcon.Sleep) { + + } else { + if (emo != null) { + emo.killAndErase(); + } + emo = new EmoIcon.Sleep( this ); + } + idle(); + } + + public synchronized void hideSleep() { + if (emo instanceof EmoIcon.Sleep) { + emo.killAndErase(); + emo = null; + } + } + + public synchronized void showAlert() { + if (emo instanceof EmoIcon.Alert) { + + } else { + if (emo != null) { + emo.killAndErase(); + } + emo = new EmoIcon.Alert( this ); + emo.visible = visible; + } + } + + public synchronized void hideAlert() { + if (emo instanceof EmoIcon.Alert) { + emo.killAndErase(); + emo = null; + } + } + + public synchronized void showLost() { + if (emo instanceof EmoIcon.Lost) { + + } else { + if (emo != null) { + emo.killAndErase(); + } + emo = new EmoIcon.Lost( this ); + emo.visible = visible; + } + } + + public synchronized void hideLost() { + if (emo instanceof EmoIcon.Lost) { + emo.killAndErase(); + emo = null; + } + } + + @Override + public void kill() { + super.kill(); + + if (emo != null) { + emo.killAndErase(); + emo = null; + } + + if (health != null){ + health.killAndErase(); + } + + } + + @Override + public void onComplete( Tweener tweener ) { + if (tweener == jumpTweener) { + + if (visible && Level.water[ch.pos] && !ch.flying) { + GameScene.ripple( ch.pos ); + } + if (jumpCallback != null) { + jumpCallback.call(); + } + + } else if (tweener == motion) { + + isMoving = false; + + motion.killAndErase(); + motion = null; + ch.onMotionComplete(); + } + } + + @Override + public void onComplete( Animation anim ) { + + if (animCallback != null) { + animCallback.call(); + animCallback = null; + } else { + + if (anim == attack) { + + idle(); + ch.onAttackComplete(); + + } else if (anim == operate) { + + idle(); + ch.onOperateComplete(); + + } + + } + } + + private static class JumpTweener extends Tweener { + + public Visual visual; + + public PointF start; + public PointF end; + + public float height; + + public JumpTweener( Visual visual, PointF pos, float height, float time ) { + super( visual, time ); + + this.visual = visual; + start = visual.point(); + end = pos; + + this.height = height; + } + + @Override + protected void updateValues( float progress ) { + visual.point( PointF.inter( start, end, progress ).offset( 0, -height * 4 * progress * (1 - progress) ) ); + } + } +} diff --git a/java/com/hmdzl/spspd/sprites/CoconutSprite.java b/java/com/hmdzl/spspd/sprites/CoconutSprite.java new file mode 100644 index 00000000..b5b215ef --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/CoconutSprite.java @@ -0,0 +1,73 @@ +/* + * 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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.levels.Level; +import com.watabou.noosa.TextureFilm; +import com.hmdzl.spspd.items.weapon.missiles.NormalBomb; +import com.watabou.utils.Callback; + +public class CoconutSprite extends MobSprite { + private Animation cast; + + public CoconutSprite() { + super(); + + texture( Assets.COCONUT ); + + TextureFilm frames = new TextureFilm( texture, 16, 16 ); + + idle = new Animation( 3, true ); + idle.frames(frames, 0, 0, 1, 1, 2, 2, 3, 3, 3, 3, 3, 3); + + run = new Animation( 20, true ); + run.frames( frames, 0 ); + + attack = new Animation( 12, false ); + attack.frames( frames, 0, 2, 3 ); + + die = new Animation( 20, false ); + die.frames( frames, 3,4,5,6 ); + + play( idle ); + } + + @Override + public void attack(int cell) { + if (!Level.adjacent(cell, ch.pos)) { + + ((MissileSprite) parent.recycle(MissileSprite.class)).reset(ch.pos, + cell, new NormalBomb(), new Callback() { + @Override + public void call() { + ch.onAttackComplete(); + } + }); + + play(cast); + turnTo(ch.pos, cell); + + } else { + + super.attack(cell); + + } + } + +} diff --git a/java/com/hmdzl/spspd/sprites/ConsideredHamsterSprite.java b/java/com/hmdzl/spspd/sprites/ConsideredHamsterSprite.java new file mode 100644 index 00000000..ba481b09 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/ConsideredHamsterSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class ConsideredHamsterSprite extends MobSprite { + + public ConsideredHamsterSprite() { + super(); + + texture( Assets.CONSIDEREDHAMSTER ); + + TextureFilm frames = new TextureFilm( texture, 16, 14 ); + + idle = new Animation( 15, true ); + idle.frames(frames, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 3); + + run = new Animation( 20, true ); + run.frames( frames, 0 ); + + attack = new Animation( 12, false ); + attack.frames( frames, 0, 2, 3 ); + + die = new Animation( 20, false ); + die.frames( frames, 0 ); + + play( idle ); + } + + +} diff --git a/java/com/hmdzl/spspd/sprites/CrabKingSprite.java b/java/com/hmdzl/spspd/sprites/CrabKingSprite.java new file mode 100644 index 00000000..7c19b602 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/CrabKingSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.items.weapon.missiles.Wave; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.scenes.GameScene; +import com.watabou.noosa.TextureFilm; +import com.watabou.utils.Callback; + +public class CrabKingSprite extends MobSprite { + + private static final float DURATION = 2f; + private Animation cast; + + public CrabKingSprite() { + super(); + + texture(Assets.CRABKING); + + TextureFilm frames = new TextureFilm(texture, 16, 16); + + idle = new Animation(2, true); + idle.frames(frames, 0, 1, 2, 3, 10, 11, 12); + + run = new Animation(15, false); + run.frames(frames, 4, 5, 6, 10, 11, 12); + + attack = new Animation(15, false); + attack.frames(frames, 7, 8, 9); + + cast = attack.clone(); + + die = new Animation(8, false); + die.frames(frames, 8, 9, 10, 10, 10, 10, 10, 10); + + play(run.clone()); + } + + @Override + public void move(int from, int to) { + + place(to); + + play(run); + turnTo(from, to); + + isMoving = true; + + if (Level.water[to]) { + GameScene.ripple(to); + } + + ch.onMotionComplete(); + } + + @Override + public void attack(int cell) { + if (!Level.adjacent(cell, ch.pos)) { + //Char enemy = Actor.findChar(cell); + ((MissileSprite) parent.recycle(MissileSprite.class)).reset(ch.pos, + cell, new Wave(), new Callback() { + @Override + public void call() { + ch.onAttackComplete(); + } + }); + + + play(cast); + turnTo(ch.pos, cell); + + } else { + + super.attack(cell); + + } + } + + @Override + public void onComplete(Animation anim) { + if (anim == run) { + isMoving = false; + idle(); + } else { + super.onComplete(anim); + } + } +} diff --git a/java/com/hmdzl/spspd/sprites/CrabSprite.java b/java/com/hmdzl/spspd/sprites/CrabSprite.java new file mode 100644 index 00000000..ac14d69d --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/CrabSprite.java @@ -0,0 +1,51 @@ +/* + * 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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class CrabSprite extends MobSprite { + + public CrabSprite() { + super(); + + texture(Assets.CRAB); + + TextureFilm frames = new TextureFilm(texture, 16, 16); + + idle = new Animation(5, true); + idle.frames(frames, 0, 1, 0, 2); + + run = new Animation(15, true); + run.frames(frames, 3, 4, 5, 6); + + attack = new Animation(12, false); + attack.frames(frames, 7, 8, 9); + + die = new Animation(12, false); + die.frames(frames, 10, 11, 12, 13); + + play(idle); + } + + @Override + public int blood() { + return 0xFFFFEA80; + } +} diff --git a/java/com/hmdzl/spspd/sprites/DM300Sprite.java b/java/com/hmdzl/spspd/sprites/DM300Sprite.java new file mode 100644 index 00000000..2557b72a --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/DM300Sprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.effects.Speck; +import com.watabou.noosa.TextureFilm; + +public class DM300Sprite extends MobSprite { + + public DM300Sprite() { + super(); + + texture(Assets.DM300); + + TextureFilm frames = new TextureFilm(texture, 22, 20); + + idle = new Animation(10, true); + idle.frames(frames, 0, 1); + + run = new Animation(10, true); + run.frames(frames, 2, 3); + + attack = new Animation(15, false); + attack.frames(frames, 4, 5, 6); + + die = new Animation(20, false); + die.frames(frames, 0, 7, 0, 7, 0, 7, 0, 7, 0, 7, 0, 7, 8); + + play(idle); + } + + @Override + public void onComplete(Animation anim) { + + super.onComplete(anim); + + if (anim == die) { + emitter().burst(Speck.factory(Speck.WOOL), 15); + } + } + + @Override + public int blood() { + return 0xFFFFFF88; + } +} diff --git a/java/com/hmdzl/spspd/sprites/DachhackSprite.java b/java/com/hmdzl/spspd/sprites/DachhackSprite.java new file mode 100644 index 00000000..180ad6e8 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/DachhackSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class DachhackSprite extends MobSprite { + + public DachhackSprite() { + super(); + + texture( Assets.DACHHACK ); + + TextureFilm frames = new TextureFilm( texture, 16, 16 ); + + idle = new Animation( 3, true ); + idle.frames(frames, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3); + + run = new Animation( 20, true ); + run.frames( frames, 0 ); + + attack = new Animation( 12, false ); + attack.frames( frames, 0, 2, 3 ); + + die = new Animation( 20, false ); + die.frames( frames, 0 ); + + play( idle ); + } + + +} diff --git a/java/com/hmdzl/spspd/sprites/DemonGooSprite.java b/java/com/hmdzl/spspd/sprites/DemonGooSprite.java new file mode 100644 index 00000000..c12b9b23 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/DemonGooSprite.java @@ -0,0 +1,127 @@ +/* + * 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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; +import com.watabou.noosa.particles.Emitter; +import com.watabou.noosa.particles.Emitter.Factory; +import com.watabou.noosa.particles.PixelParticle; +import com.watabou.utils.PointF; +import com.watabou.utils.Random; + +public class DemonGooSprite extends MobSprite { + + private Animation pump; + private Animation pumpAttack; + + public DemonGooSprite() { + super(); + + texture(Assets.DEMONGOO); + + TextureFilm frames = new TextureFilm(texture, 20, 14); + + idle = new Animation(10, true); + idle.frames(frames, 2, 1, 0, 0, 1); + + run = new Animation(15, true); + run.frames(frames, 3, 2, 1, 2); + + pump = new Animation(20, true); + pump.frames(frames, 4, 3, 2, 1, 0); + + pumpAttack = new Animation(20, false); + pumpAttack.frames(frames, 4, 3, 2, 1, 0, 7); + + attack = new Animation(10, false); + attack.frames(frames, 8, 9, 10); + + die = new Animation(10, false); + die.frames(frames, 5, 6, 7); + + play(idle); + } + + public void pumpUp() { + play(pump); + } + + public void pumpAttack() { + play(pumpAttack); + } + + @Override + public void play(Animation anim, boolean force) { + super.play(anim, force); + } + + @Override + public int blood() { + return 0xFF000000; + } + + public static class GooParticle extends PixelParticle.Shrinking { + + public static final Emitter.Factory FACTORY = new Factory() { + @Override + public void emit(Emitter emitter, int index, float x, float y) { + ((GooParticle) emitter.recycle(GooParticle.class)).reset(x, y); + } + }; + + public GooParticle() { + super(); + + color(0x000000); + lifespan = 0.3f; + + acc.set(0, +50); + } + + public void reset(float x, float y) { + revive(); + + this.x = x; + this.y = y; + + left = lifespan; + + size = 4; + speed.polar(-Random.Float(PointF.PI), Random.Float(32, 48)); + } + + @Override + public void update() { + super.update(); + float p = left / lifespan; + am = p > 0.5f ? (1 - p) * 2f : 1; + } + } + + @Override + public void onComplete(Animation anim) { + super.onComplete(anim); + + if (anim == pumpAttack) { + + idle(); + ch.onAttackComplete(); + } + } +} diff --git a/java/com/hmdzl/spspd/sprites/DemonflowerSprite.java b/java/com/hmdzl/spspd/sprites/DemonflowerSprite.java new file mode 100644 index 00000000..69be28b5 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/DemonflowerSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class DemonflowerSprite extends MobSprite { + + public DemonflowerSprite() { + super(); + + texture(Assets.DEMONFLOWER); + + TextureFilm frames = new TextureFilm(texture, 16, 16); + + idle = new Animation(2, true); + idle.frames(frames, 0, 0, 0, 1, 0, 0, 0, 1); + + run = new Animation(12, true); + run.frames(frames, 4, 5); + + attack = new Animation(12, false); + attack.frames(frames, 2, 3, 0); + + die = new Animation(12, false); + die.frames(frames, 0, 6, 7); + + play(idle); + } + + } diff --git a/java/com/hmdzl/spspd/sprites/DewProtectorSprite.java b/java/com/hmdzl/spspd/sprites/DewProtectorSprite.java new file mode 100644 index 00000000..fc6ca75c --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/DewProtectorSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.actors.mobs.FlyingProtector; +import com.hmdzl.spspd.effects.Lightning; +import com.watabou.noosa.TextureFilm; + +public class DewProtectorSprite extends MobSprite { + + private int[] points = new int[2]; + + public DewProtectorSprite() { + super(); + + texture(Assets.DEWPROTECTOR); + + TextureFilm frames = new TextureFilm(texture, 12, 15); + + idle = new Animation(2, true); + idle.frames(frames, 0, 0, 0, 0, 0, 1, 1); + + run = new Animation(15, true); + run.frames(frames, 2, 3, 4, 5, 6, 7); + + attack = new Animation(12, false); + attack.frames(frames, 8, 9, 10); + + zap = attack.clone(); + + die = new Animation(5, false); + die.frames(frames, 11, 12, 13, 14, 15, 15); + + play(idle); + } + + @Override + public void zap(int pos) { + + parent.add( new Lightning( ch.pos, pos, (FlyingProtector) ch)); + + turnTo(ch.pos, pos); + play(zap); + } + + @Override + public int blood() { + return 0xFFcdcdb7; + } +} diff --git a/java/com/hmdzl/spspd/sprites/DiscardedItemSprite.java b/java/com/hmdzl/spspd/sprites/DiscardedItemSprite.java new file mode 100644 index 00000000..c170c446 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/DiscardedItemSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.watabou.noosa.Game; + +public class DiscardedItemSprite extends ItemSprite { + + public DiscardedItemSprite() { + + super(); + + originToCenter(); + angularSpeed = 720; + } + + @Override + public void drop() { + scale.set(1); + am = 1; + } + + @Override + public void update() { + + super.update(); + + scale.set(scale.x * 0.9f); + if ((am -= Game.elapsed) <= 0) { + remove(); + } + } +} diff --git a/java/com/hmdzl/spspd/sprites/DragonkingSprite.java b/java/com/hmdzl/spspd/sprites/DragonkingSprite.java new file mode 100644 index 00000000..541859db --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/DragonkingSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class DragonkingSprite extends MobSprite { + + public DragonkingSprite() { + super(); + + texture(Assets.DRAGONKING); + + TextureFilm frames = new TextureFilm(texture, 16, 16); + + idle = new Animation(1, true); + idle.frames(frames, 0, 0, 0, 1, 1, 1); + + run = new Animation(1, true); + run.frames(frames, 0, 0, 0, 1, 1, 1); + + attack = new Animation(10, false); + attack.frames(frames, 0, 3, 4, 5); + + die = new Animation(10, false); + die.frames(frames, 0, 6, 7, 8, 9); + + play(idle); + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/sprites/DreamPlayerSprite.java b/java/com/hmdzl/spspd/sprites/DreamPlayerSprite.java new file mode 100644 index 00000000..d9be9f90 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/DreamPlayerSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.Game; +import com.watabou.noosa.TextureFilm; + +public class DreamPlayerSprite extends MobSprite { + + public DreamPlayerSprite() { + super(); + + texture( Assets.DREAMPLAYER ); + + TextureFilm frames = new TextureFilm( texture, 16, 16 ); + + idle = new Animation( 15, true ); + idle.frames(frames, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3); + + run = new Animation( 20, true ); + run.frames( frames, 0,1,2,3 ); + + attack = new Animation( 12, false ); + attack.frames( frames, 0, 2, 3 ); + + die = new Animation( 20, false ); + die.frames( frames, 0 ); + + play( idle ); + } + @Override + public void update() { + super.update(); + + if (flashTime <= 0){ + float interval = (Game.timeTotal % 9 ) /3f; + tint(interval > 2 ? interval - 2 : Math.max(0, 1 - interval), + interval > 1 ? Math.max(0, 2-interval): interval, + interval > 2 ? Math.max(0, 3-interval): interval-1, 0.5f); + } + } + +} diff --git a/java/com/hmdzl/spspd/sprites/DustElementSprite.java b/java/com/hmdzl/spspd/sprites/DustElementSprite.java new file mode 100644 index 00000000..faeef2db --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/DustElementSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + + +public class DustElementSprite extends MobSprite { + + public DustElementSprite() { + super(); + + texture(Assets.ELEMENTAL); + + TextureFilm frames = new TextureFilm(texture, 12, 14); + + idle = new Animation(10, true); + idle.frames(frames, 42, 43, 44); + + run = new Animation(12, true); + run.frames(frames, 42, 43, 45); + + attack = new Animation(15, false); + attack.frames(frames, 46, 47, 48); + + zap = attack.clone(); + + die = new Animation(15, false); + die.frames(frames, 49, 50, 51, 52, 53, 54, 55, 54); + + play(idle); + } + + + @Override + public int blood() { + return 0x999999; + } +} diff --git a/java/com/hmdzl/spspd/sprites/DwarfKingTombSprite.java b/java/com/hmdzl/spspd/sprites/DwarfKingTombSprite.java new file mode 100644 index 00000000..2615f12d --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/DwarfKingTombSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class DwarfKingTombSprite extends MobSprite { + + + public DwarfKingTombSprite() { + super(); + + texture(Assets.DWARFKINGTOMB); + TextureFilm frames = new TextureFilm(texture, 16, 16); + + idle = new Animation(10, true); + idle.frames(frames, 0, 0, 0, 0, 0, 0, 0, 0, 0); + + run = idle.clone(); + die = idle.clone(); + attack = idle.clone(); + + idle(); + } + +} diff --git a/java/com/hmdzl/spspd/sprites/DwarfLichSprite.java b/java/com/hmdzl/spspd/sprites/DwarfLichSprite.java new file mode 100644 index 00000000..e2a6c14a --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/DwarfLichSprite.java @@ -0,0 +1,118 @@ +/* + * 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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.ResultDescriptions; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Paralysis; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.levels.Level; + +import com.hmdzl.spspd.messages.Messages; +import com.watabou.noosa.TextureFilm; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Random; + +public class DwarfLichSprite extends MobSprite { + + public DwarfLichSprite() { + super(); + + texture(Assets.DWARFLICH); + + TextureFilm frames = new TextureFilm(texture, 12, 16); + + idle = new Animation(12, true); + idle.frames(frames, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3); + + run = new Animation(15, true); + run.frames(frames, 4, 5, 6, 7, 8, 9); + + attack = new Animation(15, false); + attack.frames(frames, 14, 15, 16); + + die = new Animation(12, false); + die.frames(frames, 10, 11, 12, 13); + + play(idle); + } + + @Override + public int blood() { + return 0xFF44FF22; + } + + public void boneExplode(int cell) { + for (int n : Level.NEIGHBOURS9) { + int c = cell + n; + if (c >= 0 && c < Level.getLength()) { + if (Dungeon.visible[c] && Level.passable[c]) { + Sample.INSTANCE.play(Assets.SND_BONES); + CellEmitter.center(c).start(Speck.factory(Speck.RATTLE), 0.1f, 3); + } + + Char ch = Actor.findChar(c); + if (ch != null && ch==Dungeon.hero) { + // those not at the center of the blast take damage less + // consistently. + int minDamage = c == cell ? Dungeon.depth + 5 : 1; + int maxDamage = 10 + Dungeon.depth * 2; + + + int dmg = Random.NormalIntRange(minDamage, maxDamage) - Math.max(ch.drRoll(),0); + + + if (dmg > 0) { + ch.damage(dmg, this); + if(Random.Int(15)==1){Buff.prolong(ch, Paralysis.class, 1);} + } + + + if (ch == Dungeon.hero && !ch.isAlive()){ + Dungeon.fail(Messages.format(ResultDescriptions.MOB)); + } + } + } + } + + } + + @Override + public void attack(int cell) { + if (!Level.adjacent(cell, ch.pos)) { + + turnTo(ch.pos, cell); + boneExplode(cell); + play(attack); + + } else { + + super.attack(cell); + + } + } + + + + +} diff --git a/java/com/hmdzl/spspd/sprites/ElderAvatarSprite.java b/java/com/hmdzl/spspd/sprites/ElderAvatarSprite.java new file mode 100644 index 00000000..30b1d90d --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/ElderAvatarSprite.java @@ -0,0 +1,74 @@ +/* + * 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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.items.weapon.missiles.PoisonDart; +import com.hmdzl.spspd.levels.Level; +import com.watabou.noosa.TextureFilm; +import com.watabou.utils.Callback; + +public class ElderAvatarSprite extends MobSprite { + + private Animation cast; + public ElderAvatarSprite() { + super(); + + texture( Assets.ELDER_AVATAR ); + + TextureFilm frames = new TextureFilm( texture, 16, 16 ); + + idle = new Animation( 3, true ); + idle.frames(frames, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3); + + run = new Animation( 20, true ); + run.frames( frames, 0 ); + + attack = new Animation( 12, false ); + attack.frames( frames, 0, 2, 3 ); + + cast = attack.clone(); + + die = new Animation( 20, false ); + die.frames( frames, 0 ); + + play( idle ); + } + + @Override + public void attack(int cell) { + if (!Level.adjacent(cell, ch.pos)) { + + ((MissileSprite) parent.recycle(MissileSprite.class)).reset(ch.pos, + cell, new PoisonDart(), new Callback() { + @Override + public void call() { + ch.onAttackComplete(); + } + }); + + play(cast); + turnTo(ch.pos, cell); + + } else { + + super.attack(cell); + + } + } +} diff --git a/java/com/hmdzl/spspd/sprites/ElectricwelderSprite.java b/java/com/hmdzl/spspd/sprites/ElectricwelderSprite.java new file mode 100644 index 00000000..09250f1b --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/ElectricwelderSprite.java @@ -0,0 +1,78 @@ +/* + * 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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; +import com.watabou.noosa.particles.Emitter; + +public class ElectricwelderSprite extends MobSprite { + + private Emitter emitter; + + public ElectricwelderSprite() { + super(); + + texture(Assets.TROLL); + + TextureFilm frames = new TextureFilm(texture, 13, 16); + + idle = new Animation(15, true); + idle.frames(frames, 4, 4, 4, 4, 4, 4, 4, 5, 6, 6, 6, 7); + + run = new Animation(20, true); + run.frames(frames, 4); + + die = new Animation(20, false); + die.frames(frames, 4); + + play(idle); + } + + /*@Override + public void link(Char ch) { + super.link(ch); + + emitter = new Emitter(); + emitter.autoKill = false; + emitter.pos(x + 7, y + 12); + parent.add(emitter); + }*/ + + /*@Override + public void update() { + super.update(); + + if (emitter != null) { + emitter.visible = visible; + } + }*/ + +/* @Override + public void onComplete(Animation anim) { + super.onComplete(anim); + + if (visible && emitter != null && anim == idle) { + //emitter.burst(Speck.factory(Speck.FORGE), 3); + emitter.burst(Speck.factory(Speck.STEAM), 3); + //float volume = 0.2f / (Level.distance(ch.pos, Dungeon.hero.pos)); + //Sample.INSTANCE.play(Assets.SND_EVOKE, volume, volume, 0.8f); + } + }*/ + +} diff --git a/java/com/hmdzl/spspd/sprites/ErrorSprite.java b/java/com/hmdzl/spspd/sprites/ErrorSprite.java new file mode 100644 index 00000000..37702d2e --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/ErrorSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class ErrorSprite extends MobSprite { + + public ErrorSprite() { + super(); + + texture( Assets.ERROR ); + + TextureFilm frames = new TextureFilm( texture, 16, 16 ); + + idle = new Animation( 3, true ); + idle.frames(frames, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3); + + run = new Animation( 20, true ); + run.frames( frames, 0 ); + + attack = new Animation( 12, false ); + attack.frames( frames, 0, 2, 3 ); + + die = new Animation( 20, false ); + die.frames( frames, 0 ); + + play( idle ); + } + + +} diff --git a/java/com/hmdzl/spspd/sprites/EvanSprite.java b/java/com/hmdzl/spspd/sprites/EvanSprite.java new file mode 100644 index 00000000..e36e8d18 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/EvanSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class EvanSprite extends MobSprite { + + public EvanSprite() { + super(); + + texture( Assets.EVAN ); + + TextureFilm frames = new TextureFilm( texture, 16, 14 ); + + idle = new Animation( 15, true ); + idle.frames(frames, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 3); + + run = new Animation( 20, true ); + run.frames( frames, 0 ); + + attack = new Animation( 12, false ); + attack.frames( frames, 0, 2, 3 ); + + die = new Animation( 20, false ); + die.frames( frames, 0 ); + + play( idle ); + } + + +} diff --git a/java/com/hmdzl/spspd/sprites/ExMobileSprite.java b/java/com/hmdzl/spspd/sprites/ExMobileSprite.java new file mode 100644 index 00000000..272fea42 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/ExMobileSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.items.weapon.missiles.EscapeKnive; +import com.hmdzl.spspd.levels.Level; +import com.watabou.noosa.TextureFilm; +import com.watabou.utils.Callback; + +public class ExMobileSprite extends MobSprite { + + private Animation cast; + + public ExMobileSprite() { + super(); + + texture( Assets.MOBILE ); + + TextureFilm frames = new TextureFilm( texture, 16, 16 ); + + idle = new Animation( 3, true ); + idle.frames(frames, 4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7); + + run = new Animation( 20, true ); + run.frames( frames, 4 ); + + attack = new Animation( 12, false ); + attack.frames( frames, 4, 6, 7 ); + + cast = attack.clone(); + + die = new Animation( 20, false ); + die.frames( frames, 4 ); + + play( idle ); + } + @Override + public void attack(int cell) { + if (!Level.adjacent(cell, ch.pos)) { + + ((MissileSprite) parent.recycle(MissileSprite.class)).reset(ch.pos, + cell, new EscapeKnive(), new Callback() { + @Override + public void call() { + ch.onAttackComplete(); + } + }); + + play(cast); + turnTo(ch.pos, cell); + + } else { + + super.attack(cell); + + } + } + +} diff --git a/java/com/hmdzl/spspd/sprites/EyeSprite.java b/java/com/hmdzl/spspd/sprites/EyeSprite.java new file mode 100644 index 00000000..74f9ca5d --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/EyeSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.DungeonTilemap; +import com.hmdzl.spspd.effects.DeathRay; +import com.watabou.noosa.TextureFilm; + +public class EyeSprite extends MobSprite { + + private int attackPos; + + public EyeSprite() { + super(); + + texture(Assets.EYE); + + TextureFilm frames = new TextureFilm(texture, 16, 18); + + idle = new Animation(8, true); + idle.frames(frames, 0, 1, 2); + + run = new Animation(12, true); + run.frames(frames, 5, 6); + + attack = new Animation(8, false); + attack.frames(frames, 4, 3); + + die = new Animation(8, false); + die.frames(frames, 7, 8, 9); + + play(idle); + } + + @Override + public void attack(int pos) { + attackPos = pos; + super.attack(pos); + } + + @Override + public void onComplete(Animation anim) { + super.onComplete(anim); + + if (anim == attack) { + if (Dungeon.visible[ch.pos] || Dungeon.visible[attackPos]) { + parent.add(new DeathRay(center(), DungeonTilemap + .tileCenterToWorld(attackPos))); + } + } + } +} diff --git a/java/com/hmdzl/spspd/sprites/FairySprite.java b/java/com/hmdzl/spspd/sprites/FairySprite.java new file mode 100644 index 00000000..3876aae3 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/FairySprite.java @@ -0,0 +1,57 @@ +/* + * 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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; + +import com.watabou.noosa.TextureFilm; + +public class FairySprite extends MobSprite { + + //Frames 0,2 are idle, 0,1,2 are moving, 0,3,4,1 are attack and 5,6,7 are for death + + private int[] points = new int[2]; + + public FairySprite() { + super(); + + texture(Assets.FAIRY); + + TextureFilm frames = new TextureFilm(texture, 15, 15); + + idle = new Animation(2, true); + idle.frames(frames, 0, 2, 3, 0); + + run = new Animation(8, true); + run.frames(frames, 0, 1, 2, 0); + + attack = new Animation(8, false); + attack.frames(frames, 0, 3, 4, 1); + + die = new Animation(8, false); + die.frames(frames, 5, 6, 7, 7); + + play(idle); + } + + + @Override + public int blood() { + return 0xFFcdcdb7; + } +} diff --git a/java/com/hmdzl/spspd/sprites/FetidRatSprite.java b/java/com/hmdzl/spspd/sprites/FetidRatSprite.java new file mode 100644 index 00000000..7908555f --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/FetidRatSprite.java @@ -0,0 +1,80 @@ +/* + * 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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.effects.Speck; +import com.watabou.noosa.TextureFilm; +import com.watabou.noosa.particles.Emitter; + +public class FetidRatSprite extends MobSprite { + + private Emitter cloud; + + public FetidRatSprite() { + super(); + + texture(Assets.RAT); + + TextureFilm frames = new TextureFilm(texture, 16, 15); + + idle = new Animation(2, true); + idle.frames(frames, 32, 32, 32, 33); + + run = new Animation(10, true); + run.frames(frames, 38, 39, 40, 41, 42); + + attack = new Animation(15, false); + attack.frames(frames, 34, 35, 36, 37, 32); + + die = new Animation(10, false); + die.frames(frames, 43, 44, 45, 46); + + play(idle); + } + + @Override + public void link(Char ch) { + super.link(ch); + + if (cloud == null) { + cloud = emitter(); + cloud.pour(Speck.factory(Speck.STENCH), 0.7f); + } + } + + @Override + public void update() { + + super.update(); + + if (cloud != null) { + cloud.visible = visible; + } + } + + @Override + public void die() { + super.die(); + + if (cloud != null) { + cloud.on = false; + } + } +} diff --git a/java/com/hmdzl/spspd/sprites/FiendSprite.java b/java/com/hmdzl/spspd/sprites/FiendSprite.java new file mode 100644 index 00000000..dd56d531 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/FiendSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.actors.mobs.Fiend; +import com.hmdzl.spspd.effects.MagicMissile; +import com.watabou.noosa.TextureFilm; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Callback; + +public class FiendSprite extends MobSprite { + + public FiendSprite() { + super(); + + texture(Assets.SPECTRALRAT); + + TextureFilm frames = new TextureFilm( texture, 16, 16 ); + + idle = new Animation( 5, true ); + idle.frames(frames, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 4, 10, 11, 10, 4, 1, 1 ); + + run = new Animation( 5, true ); + run.frames( frames, 0, 1, 2, 3 ); + + attack = new Animation( 15, false ); + attack.frames( frames, 10, 11, 12, 13, 14, 15 ); + + zap = attack.clone(); + + die = new Animation( 10, false ); + die.frames( frames, 16, 17, 18, 19, 19, 19 ); + + play( idle ); + } + + @Override + public void zap(int cell) { + + turnTo(ch.pos, cell); + play(zap); + + MagicMissile.shadow(parent, ch.pos, cell, new Callback() { + @Override + public void call() { + ((Fiend) ch).onZapComplete(); + } + }); + Sample.INSTANCE.play(Assets.SND_ZAP); + } + + @Override + public void onComplete(Animation anim) { + if (anim == zap) { + idle(); + } + super.onComplete(anim); + } +} diff --git a/java/com/hmdzl/spspd/sprites/FireElementalSprite.java b/java/com/hmdzl/spspd/sprites/FireElementalSprite.java new file mode 100644 index 00000000..a42d8092 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/FireElementalSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.actors.Char; +import com.watabou.noosa.TextureFilm; + + +public class FireElementalSprite extends MobSprite { + + public FireElementalSprite() { + super(); + + texture(Assets.ELEMENTAL); + + TextureFilm frames = new TextureFilm(texture, 12, 14); + + idle = new Animation(10, true); + idle.frames(frames, 0, 1, 2); + + run = new Animation(12, true); + run.frames(frames, 0, 1, 3); + + attack = new Animation(15, false); + attack.frames(frames, 4, 5, 6); + + zap = attack.clone(); + + die = new Animation(15, false); + die.frames(frames, 7, 8, 9, 10, 11, 12, 13, 12); + + play(idle); + } + + @Override + public void link(Char ch) { + super.link(ch); + add(State.BURNING); + } + + @Override + public void die() { + super.die(); + remove(State.BURNING); + } + + @Override + public int blood() { + return 0xFFFF7D13; + } +} diff --git a/java/com/hmdzl/spspd/sprites/FireRabbitSprite.java b/java/com/hmdzl/spspd/sprites/FireRabbitSprite.java new file mode 100644 index 00000000..144ba949 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/FireRabbitSprite.java @@ -0,0 +1,78 @@ +/* + * 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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.effects.MagicMissile; +import com.watabou.noosa.TextureFilm; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Callback; + +public class FireRabbitSprite extends MobSprite { + + public FireRabbitSprite() { + super(); + + texture( Assets.FIRERABBIT ); + + TextureFilm frames = new TextureFilm( texture, 16, 16 ); + + idle = new Animation( 3, true ); + idle.frames(frames, 0, 0, 0, 1, 1, 1); + + run = new Animation( 20, true ); + run.frames( frames, 0,2,3,4,5,6,7 ); + + attack = new Animation( 20, false ); + attack.frames( frames, 0, 8, 9,9,9,10 ); + + zap = attack.clone(); + + die = new Animation( 20, false ); + die.frames( frames, 0,11,11,12,12,13 ); + + play( idle ); + } + + private int posToShoot; + + @Override + public void attack(int cell) { + posToShoot = cell; + super.attack(cell); + } + + @Override + public void onComplete(Animation anim) { + if (anim == attack) { + + Sample.INSTANCE.play(Assets.SND_ZAP); + MagicMissile.fire(parent, ch.pos, posToShoot, new Callback() { + @Override + public void call() { + ch.onAttackComplete(); + } + }); + + idle(); + + } else { + super.onComplete(anim); + } + } +} diff --git a/java/com/hmdzl/spspd/sprites/FishProtectorSprite.java b/java/com/hmdzl/spspd/sprites/FishProtectorSprite.java new file mode 100644 index 00000000..7300fb48 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/FishProtectorSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.actors.mobs.FishProtector; +import com.hmdzl.spspd.effects.Lightning; +import com.watabou.noosa.TextureFilm; + +public class FishProtectorSprite extends MobSprite { + + private int[] points = new int[2]; + + public FishProtectorSprite() { + super(); + + texture(Assets.DEWPROTECTOR); + + TextureFilm frames = new TextureFilm(texture, 12, 15); + + idle = new Animation(2, true); + idle.frames(frames, 0, 0, 0, 0, 0, 1, 1); + + run = new Animation(15, true); + run.frames(frames, 2, 3, 4, 5, 6, 7); + + attack = new Animation(12, false); + attack.frames(frames, 8, 9, 10); + + zap = attack.clone(); + + die = new Animation(5, false); + die.frames(frames, 11, 12, 13, 14, 15, 15); + + play(idle); + } + + @Override + public void zap(int pos) { + + parent.add( new Lightning( ch.pos, pos, (FishProtector) ch)); + + turnTo(ch.pos, pos); + play(zap); + } + + @Override + public int blood() { + return 0xFFcdcdb7; + } +} diff --git a/java/com/hmdzl/spspd/sprites/FlySprite.java b/java/com/hmdzl/spspd/sprites/FlySprite.java new file mode 100644 index 00000000..32df11a7 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/FlySprite.java @@ -0,0 +1,57 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2015 Evan Debenham + * + * Goblins Pixel Dungeon + * Copyright (C) 2016 Mario Braun + * + * 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 + */ +package com.hmdzl.spspd.sprites; + +import com.watabou.noosa.TextureFilm; +import com.hmdzl.spspd.Assets; + +public class FlySprite extends MobSprite { + + public FlySprite() { + super(); + + texture( Assets.SWARM ); + + TextureFilm frames = new TextureFilm( texture, 16, 16 ); + + idle = new Animation( 15, true ); + idle.frames( frames, 16, 17, 18, 19, 20, 21 ); + + run = new Animation( 15, true ); + run.frames( frames, 16, 17, 18, 19, 20, 21 ); + + attack = new Animation( 20, false ); + attack.frames( frames, 22, 23, 24, 25 ); + + die = new Animation( 15, false ); + die.frames( frames, 26, 27, 28, 29, 30 ); + + play( idle ); + } + + @Override + public int blood() { + return 0xFF8BA077; + } +} diff --git a/java/com/hmdzl/spspd/sprites/FlyingProtectorSprite.java b/java/com/hmdzl/spspd/sprites/FlyingProtectorSprite.java new file mode 100644 index 00000000..3e447d3d --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/FlyingProtectorSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.actors.mobs.FlyingProtector; +import com.hmdzl.spspd.effects.Lightning; +import com.watabou.noosa.TextureFilm; + +public class FlyingProtectorSprite extends MobSprite { + + private int[] points = new int[2]; + + public FlyingProtectorSprite() { + super(); + + texture(Assets.FLYINGPROTECTOR); + + TextureFilm frames = new TextureFilm(texture, 12, 15); + + idle = new Animation(2, true); + idle.frames(frames, 0, 0, 0, 0, 0, 1, 1); + + run = new Animation(15, true); + run.frames(frames, 2, 3, 4, 5, 6, 7); + + attack = new Animation(12, false); + attack.frames(frames, 8, 9, 10); + + zap = attack.clone(); + + die = new Animation(5, false); + die.frames(frames, 11, 12, 13, 14, 15, 15); + + play(idle); + } + + @Override + public void zap(int pos) { + + parent.add( new Lightning( ch.pos, pos,(FlyingProtector) ch)); + + turnTo(ch.pos, pos); + play(zap); + } + + @Override + public int blood() { + return 0xFFcdcdb7; + } +} diff --git a/java/com/hmdzl/spspd/sprites/ForestProtectorSprite.java b/java/com/hmdzl/spspd/sprites/ForestProtectorSprite.java new file mode 100644 index 00000000..bb3a43e9 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/ForestProtectorSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.actors.mobs.ForestProtector; +import com.hmdzl.spspd.effects.Lightning; +import com.watabou.noosa.TextureFilm; + +public class ForestProtectorSprite extends MobSprite { + + private int[] points = new int[2]; + + public ForestProtectorSprite() { + super(); + + texture(Assets.DEWPROTECTOR); + + TextureFilm frames = new TextureFilm(texture, 12, 15); + + idle = new Animation(2, true); + idle.frames(frames, 0, 0, 0, 0, 0, 1, 1); + + run = new Animation(15, true); + run.frames(frames, 2, 3, 4, 5, 6, 7); + + attack = new Animation(12, false); + attack.frames(frames, 8, 9, 10); + + zap = attack.clone(); + + die = new Animation(5, false); + die.frames(frames, 11, 12, 13, 14, 15, 15); + + play(idle); + } + + @Override + public void zap(int pos) { + + parent.add( new Lightning( ch.pos, pos, (ForestProtector) ch)); + + turnTo(ch.pos, pos); + play(zap); + } + + @Override + public int blood() { + return 0xFFcdcdb7; + } +} diff --git a/java/com/hmdzl/spspd/sprites/FruitCatSprite.java b/java/com/hmdzl/spspd/sprites/FruitCatSprite.java new file mode 100644 index 00000000..3b033589 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/FruitCatSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class FruitCatSprite extends MobSprite { + + public FruitCatSprite() { + super(); + + texture( Assets.FRUITCAT ); + + TextureFilm frames = new TextureFilm( texture, 16, 16 ); + + idle = new Animation( 3, true ); + idle.frames(frames, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3); + + run = new Animation( 20, true ); + run.frames( frames, 0 ); + + attack = new Animation( 12, false ); + attack.frames( frames, 0, 2, 3 ); + + die = new Animation( 20, false ); + die.frames( frames, 0 ); + + play( idle ); + } + + +} diff --git a/java/com/hmdzl/spspd/sprites/G2159687Sprite.java b/java/com/hmdzl/spspd/sprites/G2159687Sprite.java new file mode 100644 index 00000000..e26ef2e0 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/G2159687Sprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class G2159687Sprite extends MobSprite { + + public G2159687Sprite() { + super(); + + texture( Assets.G2159687 ); + + TextureFilm frames = new TextureFilm( texture, 16, 16 ); + + idle = new Animation( 15, true ); + idle.frames(frames, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 3); + + run = new Animation( 20, true ); + run.frames( frames, 0 ); + + attack = new Animation( 12, false ); + attack.frames( frames, 0, 2, 3 ); + + die = new Animation( 20, false ); + die.frames( frames, 0 ); + + play( idle ); + } + + +} diff --git a/java/com/hmdzl/spspd/sprites/GentleCrabSprite.java b/java/com/hmdzl/spspd/sprites/GentleCrabSprite.java new file mode 100644 index 00000000..a582aa7a --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/GentleCrabSprite.java @@ -0,0 +1,51 @@ +/* + * 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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class GentleCrabSprite extends MobSprite { + + public GentleCrabSprite() { + super(); + + texture(Assets.GENTLECRAB); + + TextureFilm frames = new TextureFilm(texture, 16, 16); + + idle = new Animation(5, true); + idle.frames(frames, 0, 1, 0, 2); + + run = new Animation(15, true); + run.frames(frames, 3, 4, 5, 6); + + attack = new Animation(12, false); + attack.frames(frames, 7, 8, 9); + + die = new Animation(12, false); + die.frames(frames, 10, 11, 12, 13); + + play(idle); + } + + @Override + public int blood() { + return 0xFFFFEA80; + } +} diff --git a/java/com/hmdzl/spspd/sprites/GhostSprite.java b/java/com/hmdzl/spspd/sprites/GhostSprite.java new file mode 100644 index 00000000..8e6c9d03 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/GhostSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import javax.microedition.khronos.opengles.GL10; + +import android.opengl.GLES20; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.effects.particles.ShaftParticle; +import com.watabou.noosa.TextureFilm; + +public class GhostSprite extends MobSprite { + + public GhostSprite() { + super(); + + texture(Assets.GHOST); + + TextureFilm frames = new TextureFilm(texture, 14, 15); + + idle = new Animation(5, true); + idle.frames(frames, 0, 1); + + run = new Animation(10, true); + run.frames(frames, 0, 1); + + attack = new Animation(10, false); + attack.frames(frames, 0, 2, 3); + + die = new Animation(8, false); + die.frames(frames, 0, 4, 5, 6, 7); + + play(idle); + } + + /*@Override + public void link(Char ch) { + super.link(ch); + if (ch instanceof DriedRose.GhostHero){ + final Char finalCH = ch; + hpBar = new HealthBar(){ + @Override + public synchronized void update() { + super.update(); + hpBar.setRect(finalCH.sprite.x, finalCH.sprite.y-3, finalCH.sprite.width, hpBar.height()); + hpBar.level( finalCH ); + visible = finalCH.sprite.visible; + } + }; + ((GameScene) ShatteredPixelDungeon.scene()).ghostHP.add(hpBar); + } + }*/ + + @Override + public void draw() { + GLES20.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE); + super.draw(); + GLES20.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA); + } + + @Override + public void die() { + super.die(); + emitter().start(ShaftParticle.FACTORY, 0.3f, 4); + emitter().start(Speck.factory(Speck.LIGHT), 0.2f, 3); + } + + @Override + public int blood() { + return 0xFFFFFF; + } +} diff --git a/java/com/hmdzl/spspd/sprites/GnollArcherSprite.java b/java/com/hmdzl/spspd/sprites/GnollArcherSprite.java new file mode 100644 index 00000000..88069dd0 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/GnollArcherSprite.java @@ -0,0 +1,61 @@ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.items.weapon.missiles.EscapeKnive; +import com.hmdzl.spspd.levels.Level; +import com.watabou.noosa.TextureFilm; +import com.watabou.utils.Callback; + +/** + * Created by Evan on 09/10/2014. + */ +public class GnollArcherSprite extends MobSprite { + + private Animation cast; + + public GnollArcherSprite() { + super(); + + texture(Assets.GNOLLARCHER); + + TextureFilm frames = new TextureFilm(texture, 12, 15); + + idle = new Animation(2, true); + idle.frames(frames, 0, 0, 0, 1, 0, 0, 1, 1); + + run = new Animation(12, true); + run.frames(frames, 4, 5, 6, 7); + + attack = new Animation(12, false); + attack.frames(frames, 2, 3, 0); + + cast = attack.clone(); + + die = new Animation(12, false); + die.frames(frames, 8, 9, 10); + + play(idle); + } + + @Override + public void attack(int cell) { + if (!Level.adjacent(cell, ch.pos)) { + + ((MissileSprite) parent.recycle(MissileSprite.class)).reset(ch.pos, + cell, new EscapeKnive(), new Callback() { + @Override + public void call() { + ch.onAttackComplete(); + } + }); + + play(cast); + turnTo(ch.pos, cell); + + } else { + + super.attack(cell); + + } + } +} diff --git a/java/com/hmdzl/spspd/sprites/GnollKeeperSprite.java b/java/com/hmdzl/spspd/sprites/GnollKeeperSprite.java new file mode 100644 index 00000000..5c5bceac --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/GnollKeeperSprite.java @@ -0,0 +1,74 @@ +/* + * 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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.items.weapon.missiles.EscapeKnive; +import com.hmdzl.spspd.levels.Level; +import com.watabou.noosa.TextureFilm; +import com.watabou.utils.Callback; + +public class GnollKeeperSprite extends MobSprite { + + private Animation cast; + + public GnollKeeperSprite() { + super(); + + texture(Assets.GNOLLKING); + + TextureFilm frames = new TextureFilm(texture, 12, 16); + + idle = new Animation(2, true); + idle.frames(frames, 21, 21, 21, 22, 21, 21, 22, 22); + + run = new Animation(12, true); + run.frames(frames, 25, 26, 27, 28); + + attack = new Animation(12, false); + attack.frames(frames, 23, 24); + + cast = attack.clone(); + + die = new Animation(12, false); + die.frames(frames, 29, 30, 31); + + play(idle); + } + @Override + public void attack(int cell) { + if (!Level.adjacent(cell, ch.pos)) { + + ((MissileSprite) parent.recycle(MissileSprite.class)).reset(ch.pos, + cell, new EscapeKnive(), new Callback() { + @Override + public void call() { + ch.onAttackComplete(); + } + }); + + play(cast); + turnTo(ch.pos, cell); + + } else { + + super.attack(cell); + + } + } +} diff --git a/java/com/hmdzl/spspd/sprites/GnollKingSprite.java b/java/com/hmdzl/spspd/sprites/GnollKingSprite.java new file mode 100644 index 00000000..d3d0b4a3 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/GnollKingSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.items.weapon.missiles.EscapeKnive; +import com.hmdzl.spspd.levels.Level; +import com.watabou.noosa.TextureFilm; +import com.watabou.utils.Callback; + +public class GnollKingSprite extends MobSprite { + + private Animation cast; + + public GnollKingSprite() { + super(); + + texture(Assets.GNOLLKING); + + TextureFilm frames = new TextureFilm(texture, 12, 16); + + idle = new Animation(2, true); + idle.frames(frames, 0, 0, 0, 1, 0, 0, 1, 1); + + run = new Animation(12, true); + run.frames(frames, 4, 5, 6, 7); + + attack = new Animation(12, false); + attack.frames(frames, 2, 3, 0); + + cast = attack.clone(); + + die = new Animation(12, false); + die.frames(frames, 8, 9, 10); + + play(idle); + } + + @Override + public void attack(int cell) { + if (!Level.adjacent(cell, ch.pos)) { + + ((MissileSprite) parent.recycle(MissileSprite.class)).reset(ch.pos, + cell, new EscapeKnive(), new Callback() { + @Override + public void call() { + ch.onAttackComplete(); + } + }); + + play(cast); + turnTo(ch.pos, cell); + + } else { + + super.attack(cell); + + } + } +} diff --git a/java/com/hmdzl/spspd/sprites/GnollSprite.java b/java/com/hmdzl/spspd/sprites/GnollSprite.java new file mode 100644 index 00000000..5c6e2519 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/GnollSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.items.weapon.missiles.EscapeKnive; +import com.hmdzl.spspd.levels.Level; +import com.watabou.noosa.TextureFilm; +import com.watabou.utils.Callback; + +public class GnollSprite extends MobSprite { + + private Animation cast; + + public GnollSprite() { + super(); + + texture(Assets.GNOLL); + + TextureFilm frames = new TextureFilm(texture, 12, 15); + + idle = new Animation(2, true); + idle.frames(frames, 0, 0, 0, 1, 0, 0, 1, 1); + + run = new Animation(12, true); + run.frames(frames, 4, 5, 6, 7); + + attack = new Animation(12, false); + attack.frames(frames, 2, 3, 0); + + cast = attack.clone(); + + die = new Animation(12, false); + die.frames(frames, 8, 9, 10); + + play(idle); + } + + @Override + public void attack(int cell) { + if (!Level.adjacent(cell, ch.pos)) { + + ((MissileSprite) parent.recycle(MissileSprite.class)).reset(ch.pos, + cell, new EscapeKnive(), new Callback() { + @Override + public void call() { + ch.onAttackComplete(); + } + }); + + play(cast); + turnTo(ch.pos, cell); + + } else { + + super.attack(cell); + + } + } +} diff --git a/java/com/hmdzl/spspd/sprites/GnollTricksterSprite.java b/java/com/hmdzl/spspd/sprites/GnollTricksterSprite.java new file mode 100644 index 00000000..27794aea --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/GnollTricksterSprite.java @@ -0,0 +1,62 @@ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.items.weapon.missiles.PoisonDart; +import com.hmdzl.spspd.levels.Level; +import com.watabou.noosa.MovieClip; +import com.watabou.noosa.TextureFilm; +import com.watabou.utils.Callback; + +/** + * Created by Evan on 09/10/2014. + */ +public class GnollTricksterSprite extends MobSprite { + + private Animation cast; + + public GnollTricksterSprite() { + super(); + + texture(Assets.GNOLL); + + TextureFilm frames = new TextureFilm(texture, 12, 15); + + idle = new MovieClip.Animation(2, true); + idle.frames(frames, 21, 21, 21, 22, 21, 21, 22, 22); + + run = new MovieClip.Animation(12, true); + run.frames(frames, 25, 26, 27, 28); + + attack = new MovieClip.Animation(12, false); + attack.frames(frames, 23, 24, 21); + + cast = attack.clone(); + + die = new MovieClip.Animation(12, false); + die.frames(frames, 29, 30, 31); + + play(idle); + } + + @Override + public void attack(int cell) { + if (!Level.adjacent(cell, ch.pos)) { + + ((MissileSprite) parent.recycle(MissileSprite.class)).reset(ch.pos, + cell, new PoisonDart(), new Callback() { + @Override + public void call() { + ch.onAttackComplete(); + } + }); + + play(cast); + turnTo(ch.pos, cell); + + } else { + + super.attack(cell); + + } + } +} diff --git a/java/com/hmdzl/spspd/sprites/GoblinPlayerSprite.java b/java/com/hmdzl/spspd/sprites/GoblinPlayerSprite.java new file mode 100644 index 00000000..8dc16b6c --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/GoblinPlayerSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class GoblinPlayerSprite extends MobSprite { + + public GoblinPlayerSprite() { + super(); + + texture( Assets.GOBLIN_PLAYER ); + + TextureFilm frames = new TextureFilm( texture, 16, 16 ); + + idle = new Animation( 3, true ); + idle.frames(frames, 0, 0, 1, 1, 2, 2, 3, 3, 3, 3, 3, 3); + + run = new Animation( 3, true ); + run.frames( frames, 0, 0, 1, 1, 2, 2, 3, 3, 3, 3, 3, 3 ); + + attack = new Animation( 12, false ); + attack.frames( frames, 0, 2, 3 ); + + die = new Animation( 20, false ); + die.frames( frames, 0 ); + + play( idle ); + } + + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/sprites/GoldDragonSprite.java b/java/com/hmdzl/spspd/sprites/GoldDragonSprite.java new file mode 100644 index 00000000..76dd78ad --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/GoldDragonSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.actors.mobs.pets.GoldDragon; +import com.hmdzl.spspd.effects.MagicMissile; +import com.watabou.noosa.TextureFilm; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Callback; + +public class GoldDragonSprite extends MobSprite { + + //Frames 1-4 are idle, 5-8 are moving, 9-12 are attack and the last are for death RBVG + + private int[] points = new int[2]; + + public GoldDragonSprite() { + super(); + + texture(Assets.PETDRAGON); + + TextureFilm frames = new TextureFilm(texture, 16, 16); + + idle = new Animation(2, true); + idle.frames(frames, 80, 81, 82, 83); + + run = new Animation(8, true); + run.frames(frames, 84, 85, 86, 87); + + attack = new Animation(8, false); + attack.frames(frames, 88, 89, 90, 91); + + zap = attack.clone(); + + die = new Animation(8, false); + die.frames(frames, 92, 93, 94, 95); + + play(idle); + } + @Override + public void zap(int cell) { + + turnTo(ch.pos, cell); + play(zap); + + MagicMissile.force(parent, ch.pos, cell, new Callback() { + @Override + public void call() { + ((GoldDragon) ch).onZapComplete(); + } + }); + Sample.INSTANCE.play(Assets.SND_ZAP); + } + + @Override + public int blood() { + return 0xFFcdcdb7; + } +} diff --git a/java/com/hmdzl/spspd/sprites/GoldOrcSprite.java b/java/com/hmdzl/spspd/sprites/GoldOrcSprite.java new file mode 100644 index 00000000..550df5e4 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/GoldOrcSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class GoldOrcSprite extends MobSprite { + + public GoldOrcSprite() { + super(); + + texture(Assets.GREYONI); + + TextureFilm frames = new TextureFilm(texture, 12, 16); + + idle = new Animation(12, true); + idle.frames(frames, 0, 0, 0, 0, 0, 0, 1, 1 ); + + run = new Animation(15, true); + run.frames(frames, 0, 2, 3, 4, 5 ); + + attack = new Animation(15, false); + attack.frames(frames, 0, 5, 6); + + die = new Animation(12, false); + die.frames(frames, 7, 8, 9, 10, 10, 11, 12, 13, 14, 15, 16, 17); + + play(idle); + } + +} diff --git a/java/com/hmdzl/spspd/sprites/GoldThiefSprite.java b/java/com/hmdzl/spspd/sprites/GoldThiefSprite.java new file mode 100644 index 00000000..b9dbe28e --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/GoldThiefSprite.java @@ -0,0 +1,45 @@ +/* + * 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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class GoldThiefSprite extends MobSprite { + + public GoldThiefSprite() { + super(); + + texture(Assets.GOLDTHIEF); + TextureFilm film = new TextureFilm(texture, 12, 13); + + idle = new Animation(1, true); + idle.frames(film, 0, 0, 0, 1, 0, 0, 0, 0, 1); + + run = new Animation(15, true); + run.frames(film, 0, 0, 2, 3, 3, 4); + + die = new Animation(10, false); + die.frames(film, 5, 6, 7, 8, 9); + + attack = new Animation(12, false); + attack.frames(film, 10, 11, 12, 0); + + idle(); + } +} diff --git a/java/com/hmdzl/spspd/sprites/GolemSprite.java b/java/com/hmdzl/spspd/sprites/GolemSprite.java new file mode 100644 index 00000000..9e7fbff5 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/GolemSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.effects.particles.ElmoParticle; +import com.watabou.noosa.TextureFilm; + +public class GolemSprite extends MobSprite { + + public GolemSprite() { + super(); + + texture(Assets.GOLEM); + + TextureFilm frames = new TextureFilm(texture, 16, 16); + + idle = new Animation(4, true); + idle.frames(frames, 0, 1); + + run = new Animation(12, true); + run.frames(frames, 2, 3, 4, 5); + + attack = new Animation(10, false); + attack.frames(frames, 6, 7, 8); + + die = new Animation(15, false); + die.frames(frames, 9, 10, 11, 12, 13); + + play(idle); + } + + @Override + public int blood() { + return 0xFF80706c; + } + + @Override + public void onComplete(Animation anim) { + if (anim == die) { + emitter().burst(ElmoParticle.FACTORY, 4); + } + super.onComplete(anim); + } +} diff --git a/java/com/hmdzl/spspd/sprites/GooSprite.java b/java/com/hmdzl/spspd/sprites/GooSprite.java new file mode 100644 index 00000000..8af1e9f2 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/GooSprite.java @@ -0,0 +1,127 @@ +/* + * 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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; +import com.watabou.noosa.particles.Emitter; +import com.watabou.noosa.particles.Emitter.Factory; +import com.watabou.noosa.particles.PixelParticle; +import com.watabou.utils.PointF; +import com.watabou.utils.Random; + +public class GooSprite extends MobSprite { + + private Animation pump; + private Animation pumpAttack; + + public GooSprite() { + super(); + + texture(Assets.GOO); + + TextureFilm frames = new TextureFilm(texture, 20, 14); + + idle = new Animation(10, true); + idle.frames(frames, 2, 1, 0, 0, 1); + + run = new Animation(15, true); + run.frames(frames, 3, 2, 1, 2); + + pump = new Animation(20, true); + pump.frames(frames, 4, 3, 2, 1, 0); + + pumpAttack = new Animation(20, false); + pumpAttack.frames(frames, 4, 3, 2, 1, 0, 7); + + attack = new Animation(10, false); + attack.frames(frames, 8, 9, 10); + + die = new Animation(10, false); + die.frames(frames, 5, 6, 7); + + play(idle); + } + + public void pumpUp() { + play(pump); + } + + public void pumpAttack() { + play(pumpAttack); + } + + @Override + public void play(Animation anim, boolean force) { + super.play(anim, force); + } + + @Override + public int blood() { + return 0xFF000000; + } + + public static class GooParticle extends PixelParticle.Shrinking { + + public static final Emitter.Factory FACTORY = new Factory() { + @Override + public void emit(Emitter emitter, int index, float x, float y) { + ((GooParticle) emitter.recycle(GooParticle.class)).reset(x, y); + } + }; + + public GooParticle() { + super(); + + color(0x000000); + lifespan = 0.3f; + + acc.set(0, +50); + } + + public void reset(float x, float y) { + revive(); + + this.x = x; + this.y = y; + + left = lifespan; + + size = 4; + speed.polar(-Random.Float(PointF.PI), Random.Float(32, 48)); + } + + @Override + public void update() { + super.update(); + float p = left / lifespan; + am = p > 0.5f ? (1 - p) * 2f : 1; + } + } + + @Override + public void onComplete(Animation anim) { + super.onComplete(anim); + + if (anim == pumpAttack) { + + idle(); + ch.onAttackComplete(); + } + } +} diff --git a/java/com/hmdzl/spspd/sprites/GraveProtectorSprite.java b/java/com/hmdzl/spspd/sprites/GraveProtectorSprite.java new file mode 100644 index 00000000..43b670b6 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/GraveProtectorSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.actors.mobs.GraveProtector; +import com.hmdzl.spspd.effects.Lightning; +import com.watabou.noosa.TextureFilm; + +public class GraveProtectorSprite extends MobSprite { + + private int[] points = new int[2]; + + public GraveProtectorSprite() { + super(); + + texture(Assets.DEWPROTECTOR); + + TextureFilm frames = new TextureFilm(texture, 12, 15); + + idle = new Animation(2, true); + idle.frames(frames, 0, 0, 0, 0, 0, 1, 1); + + run = new Animation(15, true); + run.frames(frames, 2, 3, 4, 5, 6, 7); + + attack = new Animation(12, false); + attack.frames(frames, 8, 9, 10); + + zap = attack.clone(); + + die = new Animation(5, false); + die.frames(frames, 11, 12, 13, 14, 15, 15); + + play(idle); + } + + @Override + public void zap(int pos) { + parent.add( new Lightning( ch.pos, pos,(GraveProtector) ch)); + + turnTo(ch.pos, pos); + play(zap); + } + + @Override + public int blood() { + return 0xFFcdcdb7; + } +} diff --git a/java/com/hmdzl/spspd/sprites/GreatCrabSprite.java b/java/com/hmdzl/spspd/sprites/GreatCrabSprite.java new file mode 100644 index 00000000..334f924e --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/GreatCrabSprite.java @@ -0,0 +1,38 @@ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.MovieClip; +import com.watabou.noosa.TextureFilm; + +/** + * Created by Evan on 09/10/2014. + */ +public class GreatCrabSprite extends MobSprite { + + public GreatCrabSprite() { + super(); + + texture(Assets.CRAB); + + TextureFilm frames = new TextureFilm(texture, 16, 16); + + idle = new MovieClip.Animation(5, true); + idle.frames(frames, 16, 17, 16, 18); + + run = new MovieClip.Animation(10, true); + run.frames(frames, 19, 20, 21, 22); + + attack = new MovieClip.Animation(12, false); + attack.frames(frames, 23, 24, 25); + + die = new MovieClip.Animation(12, false); + die.frames(frames, 26, 27, 28, 29); + + play(idle); + } + + @Override + public int blood() { + return 0xFFFFEA80; + } +} diff --git a/java/com/hmdzl/spspd/sprites/GreenDragonSprite.java b/java/com/hmdzl/spspd/sprites/GreenDragonSprite.java new file mode 100644 index 00000000..975823c3 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/GreenDragonSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.actors.mobs.pets.GreenDragon; +import com.hmdzl.spspd.effects.Lightning; +import com.watabou.noosa.TextureFilm; + +public class GreenDragonSprite extends MobSprite { + + //Frames 1-4 are idle, 5-8 are moving, 9-12 are attack and the last are for death RBVG + + private int[] points = new int[2]; + + public GreenDragonSprite() { + super(); + + texture(Assets.PETDRAGON); + + TextureFilm frames = new TextureFilm(texture, 16, 16); + + idle = new Animation(2, true); + idle.frames(frames, 48, 49, 50, 51); + + run = new Animation(8, true); + run.frames(frames, 52, 53, 54, 55); + + attack = new Animation(8, false); + attack.frames(frames, 56, 57, 58, 59); + + zap = attack.clone(); + + die = new Animation(8, false); + die.frames(frames, 60, 61, 62, 63); + + play(idle); + } + + @Override + public void zap(int pos) { + + parent.add( new Lightning( ch.pos, pos, (GreenDragon) ch)); + + turnTo(ch.pos, pos); + play(zap); + } + + @Override + public int blood() { + return 0xFFcdcdb7; + } +} diff --git a/java/com/hmdzl/spspd/sprites/GreyRatSprite.java b/java/com/hmdzl/spspd/sprites/GreyRatSprite.java new file mode 100644 index 00000000..a1a6cd63 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/GreyRatSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class GreyRatSprite extends MobSprite { + + public GreyRatSprite() { + super(); + + texture(Assets.RAT); + + TextureFilm frames = new TextureFilm(texture, 16, 15); + + idle = new Animation(2, true); + idle.frames(frames, 48, 48, 48, 49); + + run = new Animation(10, true); + run.frames(frames, 54, 55, 56, 57, 58); + + attack = new Animation(15, false); + attack.frames(frames, 50, 51, 52, 53); + + die = new Animation(10, false); + die.frames(frames, 59, 60, 61, 62); + + play(idle); + } +} diff --git a/java/com/hmdzl/spspd/sprites/GuardSprite.java b/java/com/hmdzl/spspd/sprites/GuardSprite.java new file mode 100644 index 00000000..44d6135f --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/GuardSprite.java @@ -0,0 +1,61 @@ +/* + * 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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.effects.Speck; +import com.watabou.noosa.TextureFilm; + +public class GuardSprite extends MobSprite { + + public GuardSprite() { + super(); + + texture(Assets.GUARD); + + TextureFilm frames = new TextureFilm( texture, 12, 16 ); + + idle = new Animation( 2, true ); + idle.frames( frames, 0, 0, 0, 1, 0, 0, 1, 1 ); + + run = new Animation( 15, true ); + run.frames( frames, 2, 3, 4, 5, 6, 7 ); + + attack = new Animation( 12, false ); + attack.frames( frames, 8, 9, 10 ); + + die = new Animation( 8, false ); + die.frames( frames, 11, 12, 13, 14 ); + + play( idle ); + } + + @Override + public void die() { + super.die(); + if (Dungeon.visible[ch.pos]) { + emitter().burst(Speck.factory(Speck.BONE), 6); + } + } + + @Override + public int blood() { + return 0xFFcccccc; + } +} diff --git a/java/com/hmdzl/spspd/sprites/HBBSprite.java b/java/com/hmdzl/spspd/sprites/HBBSprite.java new file mode 100644 index 00000000..5f255ec9 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/HBBSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class HBBSprite extends MobSprite { + + public HBBSprite() { + super(); + + texture( Assets.HBB ); + + TextureFilm frames = new TextureFilm( texture, 16, 16 ); + + idle = new Animation( 3, true ); + idle.frames(frames, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3); + + run = new Animation( 20, true ); + run.frames( frames, 0 ); + + attack = new Animation( 12, false ); + attack.frames( frames, 0, 2, 3 ); + + die = new Animation( 20, false ); + die.frames( frames, 0 ); + + play( idle ); + } + + +} diff --git a/java/com/hmdzl/spspd/sprites/HateSokobanSprite.java b/java/com/hmdzl/spspd/sprites/HateSokobanSprite.java new file mode 100644 index 00000000..875fd2a0 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/HateSokobanSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class HateSokobanSprite extends MobSprite { + + public HateSokobanSprite() { + super(); + + texture( Assets.HS ); + + TextureFilm frames = new TextureFilm( texture, 16, 16 ); + + idle = new Animation( 3, true ); + idle.frames(frames, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3); + + run = new Animation( 20, true ); + run.frames( frames, 0 ); + + attack = new Animation( 12, false ); + attack.frames( frames, 0, 2, 3 ); + + die = new Animation( 20, false ); + die.frames( frames, 0 ); + + play( idle ); + } + + +} diff --git a/java/com/hmdzl/spspd/sprites/HeXASprite.java b/java/com/hmdzl/spspd/sprites/HeXASprite.java new file mode 100644 index 00000000..ff1c16e2 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/HeXASprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class HeXASprite extends MobSprite { + + public HeXASprite() { + super(); + + texture( Assets.HEXA ); + + TextureFilm frames = new TextureFilm( texture, 16, 16 ); + + idle = new Animation( 15, true ); + idle.frames(frames, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3); + + run = new Animation( 20, true ); + run.frames( frames, 0 ); + + attack = new Animation( 12, false ); + attack.frames( frames, 0, 2, 3 ); + + die = new Animation( 20, false ); + die.frames( frames, 0 ); + + play( idle ); + } + + +} diff --git a/java/com/hmdzl/spspd/sprites/HermitCrabSprite.java b/java/com/hmdzl/spspd/sprites/HermitCrabSprite.java new file mode 100644 index 00000000..cbfcbbbb --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/HermitCrabSprite.java @@ -0,0 +1,61 @@ +/* + * 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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.actors.mobs.HermitCrab; +import com.hmdzl.spspd.effects.Lightning; +import com.watabou.noosa.TextureFilm; + +public class HermitCrabSprite extends MobSprite { + + private int[] points = new int[2]; + + public HermitCrabSprite() { + super(); + + texture(Assets.HERMITCRAB); + + TextureFilm frames = new TextureFilm(texture, 16, 16); + + idle = new Animation(2, true); + idle.frames(frames, 0, 0, 0, 1, 0, 0, 1, 1); + + run = new Animation(12, true); + run.frames(frames, 2, 3, 4, 5, 6); + + attack = new Animation(12, false); + attack.frames(frames, 6, 7, 8, 9); + + zap = attack.clone(); + + die = new Animation(12, false); + die.frames(frames, 10, 11 ,12 ,13); + + play(idle); + } + + @Override + public void zap(int pos) { + + parent.add( new Lightning( ch.pos, pos,(HermitCrab) ch)); + + turnTo(ch.pos, pos); + play(zap); + } +} diff --git a/java/com/hmdzl/spspd/sprites/HeroSprite.java b/java/com/hmdzl/spspd/sprites/HeroSprite.java new file mode 100644 index 00000000..3a3cabeb --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/HeroSprite.java @@ -0,0 +1,149 @@ +/* + * 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 + */ +package com.hmdzl.spspd.sprites; + +import android.graphics.RectF; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.hero.HeroClass; +import com.watabou.gltextures.SmartTexture; +import com.watabou.gltextures.TextureCache; +import com.watabou.noosa.Camera; +import com.watabou.noosa.Image; +import com.watabou.noosa.TextureFilm; +import com.watabou.utils.Callback; + +public class HeroSprite extends CharSprite { + + private static final int FRAME_WIDTH = 12; + private static final int FRAME_HEIGHT = 15; + + private static final int RUN_FRAMERATE = 20; + + private static TextureFilm skins; + + private Animation fly; + private Animation read; + + public HeroSprite() { + super(); + + link(Dungeon.hero); + + texture(Dungeon.hero.heroClass.spritesheet()); + updateArmor(); + + idle(); + } + + public void updateArmor() { + + TextureFilm film = new TextureFilm(skins(), ((Hero) ch).useskin(), + FRAME_WIDTH, FRAME_HEIGHT); + + idle = new Animation(1, true); + idle.frames(film, 0, 0, 0, 1, 0, 0, 1, 1); + + run = new Animation(RUN_FRAMERATE, true); + run.frames(film, 2, 3, 4, 5, 6, 7); + + die = new Animation(20, false); + die.frames(film, 8, 9, 10, 11, 12, 11); + + attack = new Animation(15, false); + attack.frames(film, 13, 14, 15, 0); + + zap = attack.clone(); + + operate = new Animation(8, false); + operate.frames(film, 16, 17, 16, 17); + + fly = new Animation(1, true); + fly.frames(film, 18); + + read = new Animation( 8, false ); + read.frames(film, 16, 17, 16, 17); + } + + @Override + public void place(int p) { + super.place(p); + Camera.main.target = this; + } + + @Override + public void move(int from, int to) { + super.move(from, to); + if (ch.flying) { + play(fly); + } + Camera.main.target = this; + } + + @Override + public void jump(int from, int to, Callback callback) { + super.jump(from, to, callback); + play(fly); + } + + public void read() { + animCallback = new Callback() { + @Override + public void call() { + idle(); + ch.onOperateComplete(); + } + }; + play( read ); + } + + + @Override + public void update() { + sleeping = ((Hero) ch).restoreHealth; + + super.update(); + } + + public boolean sprint(boolean on) { + run.delay = on ? 0.667f / RUN_FRAMERATE : 1f / RUN_FRAMERATE; + return on; + } + + public static TextureFilm skins() { + if (skins == null) { + SmartTexture texture = TextureCache.get(Assets.ROGUE); + skins = new TextureFilm(texture, texture.width, FRAME_HEIGHT); + } + + return skins; + } + + public static Image avatar(HeroClass cl, int skin) { + + RectF patch = skins().get(skin); + Image avatar = new Image(cl.spritesheet()); + RectF frame = avatar.texture.uvRect(1, 0, FRAME_WIDTH, FRAME_HEIGHT); + frame.offset(patch.left, patch.top); + avatar.frame(frame); + + return avatar; + } +} diff --git a/java/com/hmdzl/spspd/sprites/Hmdzl001Sprite.java b/java/com/hmdzl/spspd/sprites/Hmdzl001Sprite.java new file mode 100644 index 00000000..aec4ccf4 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/Hmdzl001Sprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class Hmdzl001Sprite extends MobSprite { + + public Hmdzl001Sprite() { + super(); + + texture( Assets.HMDZL ); + + TextureFilm frames = new TextureFilm( texture, 16, 16 ); + + idle = new Animation( 15, true ); + idle.frames(frames, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 3); + + run = new Animation( 20, true ); + run.frames( frames, 0 ); + + attack = new Animation( 12, false ); + attack.frames( frames, 0, 2, 3 ); + + die = new Animation( 20, false ); + die.frames( frames, 0 ); + + play( idle ); + } + + +} diff --git a/java/com/hmdzl/spspd/sprites/HoneyPooootSprite.java b/java/com/hmdzl/spspd/sprites/HoneyPooootSprite.java new file mode 100644 index 00000000..3278a55a --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/HoneyPooootSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class HoneyPooootSprite extends MobSprite { + + public HoneyPooootSprite() { + super(); + + texture( Assets.HONEY_POOOOT ); + + TextureFilm frames = new TextureFilm( texture, 16, 16 ); + + idle = new Animation( 3, true ); + idle.frames(frames, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1); + + run = new Animation( 3, true ); + run.frames( frames, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1 ); + + attack = new Animation( 12, false ); + attack.frames( frames, 0, 1, 1 ); + + die = new Animation( 20, false ); + die.frames( frames, 0 ); + + play( idle ); + } + + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/sprites/HybridSprite.java b/java/com/hmdzl/spspd/sprites/HybridSprite.java new file mode 100644 index 00000000..7c830e52 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/HybridSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.DungeonTilemap; +import com.hmdzl.spspd.effects.Beam; +import com.watabou.noosa.TextureFilm; + +public class HybridSprite extends MobSprite { + private int attackPos; + public HybridSprite() { + super(); + + texture( Assets.HYBRID ); + + TextureFilm frames = new TextureFilm( texture, 16, 16 ); + + idle = new Animation( 3, true ); + idle.frames(frames, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3); + + run = new Animation( 20, true ); + run.frames( frames, 0 ); + + attack = new Animation( 12, false ); + attack.frames( frames, 0, 2, 3 ); + + die = new Animation( 20, false ); + die.frames( frames, 0 ); + + play( idle ); + } + + @Override + public void attack(int pos) { + attackPos = pos; + super.attack(pos); + } + + + @Override + public void onComplete(Animation anim) { + super.onComplete(anim); + + if (anim == attack) { + if (Dungeon.visible[ch.pos] || Dungeon.visible[attackPos]) { + parent.add(new Beam.WaterRay(center(), DungeonTilemap + .tileCenterToWorld(attackPos))); + } + } + } +} diff --git a/java/com/hmdzl/spspd/sprites/Ice13Sprite.java b/java/com/hmdzl/spspd/sprites/Ice13Sprite.java new file mode 100644 index 00000000..17fe28b1 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/Ice13Sprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class Ice13Sprite extends MobSprite { + + public Ice13Sprite() { + super(); + + texture( Assets.ICE13 ); + + TextureFilm frames = new TextureFilm( texture, 16, 16 ); + + idle = new Animation( 15, true ); + idle.frames(frames, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3); + + run = new Animation( 20, true ); + run.frames( frames, 0 ); + + attack = new Animation( 12, false ); + attack.frames( frames, 0, 2, 3 ); + + die = new Animation( 20, false ); + die.frames( frames, 0 ); + + play( idle ); + } + + +} diff --git a/java/com/hmdzl/spspd/sprites/IceRabbitSprite.java b/java/com/hmdzl/spspd/sprites/IceRabbitSprite.java new file mode 100644 index 00000000..23bdba99 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/IceRabbitSprite.java @@ -0,0 +1,85 @@ +/* + * 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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.effects.MagicMissile; +import com.watabou.noosa.TextureFilm; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Callback; + +public class IceRabbitSprite extends MobSprite { + + public IceRabbitSprite() { + super(); + + texture( Assets.FIRERABBIT ); + + TextureFilm frames = new TextureFilm( texture, 16, 16 ); + + idle = new Animation( 3, true ); + idle.frames(frames, 14, 14, 14, 15, 15, 15); + + run = new Animation( 20, true ); + run.frames( frames, 14,16,17,18,19,20,21 ); + + attack = new Animation( 20, false ); + attack.frames( frames, 14, 22, 23,23,23,24 ); + + zap = attack.clone(); + + die = new Animation( 20, false ); + die.frames( frames, 14,25,25,26,26,27 ); + + play( idle ); + } + + private int posToShoot; + + @Override + public void link(Char ch) { + super.link(ch); + add(State.CHILLED); + } + + @Override + public void attack(int cell) { + posToShoot = cell; + super.attack(cell); + } + + @Override + public void onComplete(Animation anim) { + if (anim == attack) { + + Sample.INSTANCE.play(Assets.SND_ZAP); + MagicMissile.fire(parent, ch.pos, posToShoot, new Callback() { + @Override + public void call() { + ch.onAttackComplete(); + } + }); + + idle(); + + } else { + super.onComplete(anim); + } + } +} diff --git a/java/com/hmdzl/spspd/sprites/ImpSprite.java b/java/com/hmdzl/spspd/sprites/ImpSprite.java new file mode 100644 index 00000000..d744c916 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/ImpSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.mobs.npcs.Imp; +import com.hmdzl.spspd.effects.Speck; +import com.watabou.noosa.TextureFilm; + +public class ImpSprite extends MobSprite { + + public ImpSprite() { + super(); + + texture(Assets.IMP); + + TextureFilm frames = new TextureFilm(texture, 12, 14); + + idle = new Animation(10, true); + idle.frames(frames, 0, 1, 2, 3, 0, 1, 2, 3, 0, 0, 0, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 3, 0, 0, 0, 4, 4, 4, + 4, 4, 4, 4, 4, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4); + + run = new Animation(20, true); + run.frames(frames, 0); + + die = new Animation(10, false); + die.frames(frames, 0, 3, 2, 1, 0, 3, 2, 1, 0); + + play(idle); + } + + @Override + public void link(Char ch) { + super.link(ch); + + if (ch instanceof Imp) { + alpha(0.4f); + } + } + + @Override + public void onComplete(Animation anim) { + if (anim == die) { + + emitter().burst(Speck.factory(Speck.WOOL), 15); + killAndErase(); + + } else { + super.onComplete(anim); + } + } +} diff --git a/java/com/hmdzl/spspd/sprites/InfectingFistSprite.java b/java/com/hmdzl/spspd/sprites/InfectingFistSprite.java new file mode 100644 index 00000000..4f4bb152 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/InfectingFistSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.Camera; +import com.watabou.noosa.TextureFilm; + +public class InfectingFistSprite extends MobSprite { + + private static final float FALL_SPEED = 64; + + public InfectingFistSprite() { + super(); + + texture(Assets.INFECTING); + + TextureFilm frames = new TextureFilm(texture, 24, 17); + + idle = new Animation(2, true); + idle.frames(frames, 0, 0, 1); + + run = new Animation(3, true); + run.frames(frames, 0, 1); + + attack = new Animation(2, false); + attack.frames(frames, 0); + + die = new Animation(10, false); + die.frames(frames, 0, 2, 3, 4); + + play(idle); + } + + @Override + public void attack(int cell) { + super.attack(cell); + + speed.set(0, -FALL_SPEED); + acc.set(0, FALL_SPEED * 4); + } + + @Override + public void onComplete(Animation anim) { + super.onComplete(anim); + if (anim == attack) { + speed.set(0); + acc.set(0); + place(ch.pos); + + Camera.main.shake(4, 0.2f); + } + } +} diff --git a/java/com/hmdzl/spspd/sprites/ItemSprite.java b/java/com/hmdzl/spspd/sprites/ItemSprite.java new file mode 100644 index 00000000..b0eff89a --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/ItemSprite.java @@ -0,0 +1,233 @@ +/* + * 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 + */ +package com.hmdzl.spspd.sprites; + +import android.graphics.Bitmap; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.DungeonTilemap; +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.Gold; +import com.hmdzl.spspd.items.Heap; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.Terrain; +import com.hmdzl.spspd.scenes.GameScene; +import com.watabou.gltextures.TextureCache; +import com.watabou.noosa.Game; +import com.watabou.noosa.MovieClip; +import com.watabou.noosa.TextureFilm; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.PointF; +import com.watabou.utils.Random; + +public class ItemSprite extends MovieClip { + + public static final int SIZE = 16; + + private static final float DROP_INTERVAL = 0.4f; + + protected static TextureFilm film; + + public Heap heap; + + private Glowing glowing; + private float phase; + private boolean glowUp; + + private float dropInterval; + + public ItemSprite() { + this(ItemSpriteSheet.SOMETHING, null); + } + + public ItemSprite(Item item) { + this(item.image(), item.glowing()); + } + + public ItemSprite(int image, Glowing glowing) { + super(Assets.ITEMS); + + if (film == null) { + film = new TextureFilm(texture, SIZE, SIZE); + } + + view(image, glowing); + } + + public void originToCenter() { + origin.set(SIZE / 2); + } + + public void link() { + link(heap); + } + + public void link(Heap heap) { + this.heap = heap; + view(heap.image(), heap.glowing()); + place(heap.pos); + } + + @Override + public void revive() { + super.revive(); + + speed.set(0); + acc.set(0); + dropInterval = 0; + + heap = null; + } + + public PointF worldToCamera(int cell) { + final int csize = DungeonTilemap.SIZE; + + return new PointF(cell % Level.getWidth() * csize + (csize - SIZE) * 0.5f, + cell / Level.getWidth() * csize + (csize - SIZE) * 0.5f); + } + + public void place(int p) { + point(worldToCamera(p)); + } + + public void drop() { + + if (heap.isEmpty()) { + return; + } + + dropInterval = DROP_INTERVAL; + + speed.set(0, -100); + acc.set(0, -speed.y / DROP_INTERVAL * 2); + + if (visible && heap != null && heap.peek() instanceof Gold) { + CellEmitter.center(heap.pos).burst(Speck.factory(Speck.COIN), 5); + Sample.INSTANCE.play(Assets.SND_GOLD, 1, 1, + Random.Float(0.9f, 1.1f)); + } + } + + public void drop(int from) { + + if (heap.pos == from) { + drop(); + } else { + + float px = x; + float py = y; + drop(); + + place(from); + + speed.offset((px - x) / DROP_INTERVAL, (py - y) / DROP_INTERVAL); + } + } + + public ItemSprite view(int image, Glowing glowing) { + frame(film.get(image)); + if ((this.glowing = glowing) == null) { + resetColor(); + } + return this; + } + + @Override + public void update() { + super.update(); + + visible = (heap == null || heap.seen); + + if (dropInterval > 0 && (dropInterval -= Game.elapsed) <= 0) { + + speed.set(0); + acc.set(0); + place(heap.pos); + + if (visible) { + boolean water = Level.water[heap.pos]; + + if (water) { + GameScene.ripple(heap.pos); + } else { + int cell = Dungeon.level.map[heap.pos]; + water = (cell == Terrain.WELL || cell == Terrain.ALCHEMY); + } + + if (!(heap.peek() instanceof Gold)) { + Sample.INSTANCE.play(water ? Assets.SND_WATER + : Assets.SND_STEP, 0.8f, 0.8f, 1.2f); + } + } + } + + if (visible && glowing != null) { + if (glowUp && (phase += Game.elapsed) > glowing.period) { + + glowUp = false; + phase = glowing.period; + + } else if (!glowUp && (phase -= Game.elapsed) < 0) { + + glowUp = true; + phase = 0; + + } + + float value = phase / glowing.period * 0.6f; + + rm = gm = bm = 1 - value; + ra = glowing.red * value; + ga = glowing.green * value; + ba = glowing.blue * value; + } + } + + public static int pick(int index, int x, int y) { + Bitmap bmp = TextureCache.get(Assets.ITEMS).bitmap; + int rows = bmp.getWidth() / SIZE; + int row = index / rows; + int col = index % rows; + return bmp.getPixel(col * SIZE + x, row * SIZE + y); + } + + public static class Glowing { + + public static final Glowing WHITE = new Glowing(0xFFFFFF, 0.6f); + + public float red; + public float green; + public float blue; + public float period; + + public Glowing(int color) { + this(color, 1f); + } + + public Glowing(int color, float period) { + red = (color >> 16) / 255f; + green = ((color >> 8) & 0xFF) / 255f; + blue = (color & 0xFF) / 255f; + + this.period = period; + } + } +} diff --git a/java/com/hmdzl/spspd/sprites/ItemSpriteSheet.java b/java/com/hmdzl/spspd/sprites/ItemSpriteSheet.java new file mode 100644 index 00000000..03d44a9b --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/ItemSpriteSheet.java @@ -0,0 +1,585 @@ +/* + * 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 + */ +package com.hmdzl.spspd.sprites; + +public class ItemSpriteSheet { + + // Row definers + private static final int ROW1 = 0 * 16; + private static final int ROW2 = 1 * 16; + private static final int ROW3 = 2 * 16; + private static final int ROW4 = 3 * 16; + private static final int ROW5 = 4 * 16; + private static final int ROW6 = 5 * 16; + private static final int ROW7 = 6 * 16; + private static final int ROW8 = 7 * 16; + private static final int ROW9 = 8 * 16; + private static final int ROW10 = 9 * 16; + private static final int ROW11 = 10 * 16; + private static final int ROW12 = 11 * 16; + private static final int ROW13 = 12 * 16; + private static final int ROW14 = 13 * 16; + private static final int ROW15 = 14 * 16; + private static final int ROW16 = 15 * 16; + private static final int ROW17 = 16 * 16; + private static final int ROW18 = 17 * 16; + private static final int ROW19 = 18 * 16; + private static final int ROW20 = 19 * 16; + private static final int ROW21 = 20 * 16; + private static final int ROW22 = 21 * 16; + private static final int ROW23 = 22 * 16; + private static final int ROW24 = 23 * 16; + private static final int ROW25 = 24 * 16; + private static final int ROW26 = 25 * 16; + private static final int ROW27 = 26 * 16; + private static final int ROW28 = 27 * 16; + + // Row One: Items which can't be obtained + // null warning occupies space 0, should only show up if there's a bug. + public static final int NULLWARN = ROW1 + 0; + public static final int DEWDROP = ROW1 + 1; + public static final int PETAL = ROW1 + 2; + public static final int SANDBAG = ROW1 + 3; + public static final int REDDEWDROP = ROW8 + 8; + public static final int YELLOWDEWDROP = ROW8 + 14; + public static final int VIOLETDEWDROP = ROW14 + 13; + public static final int COIN = ROW14 + 14; + public static final int ARTIFACT = ROW14 + 15; + + // Heaps (containers) + public static final int BONES = ROW1 + 4; + public static final int REMAINS = ROW1 + 5; + public static final int TOMB = ROW1 + 6; + public static final int GRAVE = ROW1 + 7; + public static final int CHEST = ROW1 + 8; + public static final int LOCKED_CHEST = ROW1 + 9; + public static final int CRYSTAL_CHEST = ROW1 + 10; + // Placeholders + public static final int WEAPON_HOLDER = ROW1 + 11; + public static final int ARMOR_HOLDER = ROW1 + 12; + public static final int RING_HOLDER = ROW1 + 13; + public static final int SOMETHING = ROW1 + 14; + + // Row Two: Miscellaneous single use items + public static final int GOLD = ROW2 + 0; + public static final int TORCH = ROW2 + 1; + public static final int STYLUS = ROW2 + 2; + public static final int ANKH = ROW2 + 3; + // Keys + public static final int IRON_KEY = ROW2 + 4; + public static final int GOLDEN_KEY = ROW2 + 5; + public static final int SKELETON_KEY = ROW2 + 6; + // Boss Rewards + public static final int BEACON = ROW2 + 7; + public static final int MASTERY = ROW2 + 8; + public static final int KIT = ROW2 + 9; + public static final int AMULET = ROW2 + 10; + public static final int WEIGHT = ROW2 + 11; + public static final int BOMB = ROW2 + 12; + public static final int DBL_BOMB = ROW2 + 13; + public static final int HONEYPOT = ROW2 + 14; + public static final int SHATTPOT = ROW2 + 15; + public static final int SHELL = ROW5 + 10; + public static final int BONE = ROW5 + 11; + + + // Row Three: Melee weapons + public static final int KNUCKLEDUSTER = ROW3 + 0; + public static final int DAGGER = ROW3 + 1; + public static final int SHORT_SWORD = ROW3 + 2; + public static final int HANDAXE = ROW3 + 3; + public static final int SPEAR = ROW3 + 4; + public static final int SCIMITAR = ROW3 + 5; + public static final int WHIP = ROW3 + 6; + public static final int BATTLE_AXE = ROW3 + 7; + public static final int ASSASSINSBLADE = ROW3 + 8; + public static final int WAR_HAMMER = ROW3 + 9; + public static final int GLAIVE = ROW3 + 10; + public static final int ADAMANT_WEAPON = ROW3 + 11; + public static final int HANDCANNON = ROW3 + 12; + public static final int MAGEBOOK = ROW3 + 13; + public static final int SPKEY = ROW3 + 14; + + // Row Four: Missile weapons and sporks + public static final int KNIVE = ROW4 + 0; + public static final int BOOMERANG = ROW4 + 1; + public static final int INCENDIARY_DART = ROW4 + 2; + public static final int SHURIKEN = ROW4 + 3; + public static final int POSION_DART = ROW4 + 4; + public static final int BOLA = ROW4 + 5; + public static final int TOMAHAWK = ROW4 + 6; + public static final int SPORK = ROW4 + 7; + public static final int RUNICBLADE = ROW4 + 8; + public static final int WAVE = ROW4 + 9; + public static final int AMMO = ROW4 + 12; + public static final int SOUL_COLLECT = ROW4 + 13; + public static final int PALANTIR = ROW20 + 8; + public static final int SKULLWEP = ROW4 + 14; + public static final int STONE = ROW4 + 15; + + + // Row Five: Armors + public static final int ARMOR_CLOTH = ROW5 + 0; + public static final int ARMOR_LEATHER = ROW5 + 1; + public static final int ARMOR_MAIL = ROW5 + 2; + public static final int ARMOR_SCALE = ROW5 + 3; + public static final int ARMOR_PLATE = ROW5 + 4; + public static final int ARMOR_WARRIOR = ROW5 + 5; + public static final int ARMOR_MAGE = ROW5 + 6; + public static final int ARMOR_ROGUE = ROW5 + 7; + public static final int ARMOR_HUNTRESS = ROW5 + 8; + public static final int ARMOR_ADAMANT = ROW5 + 9; + public static final int ARMOR_DISC = ROW17 + 8; + + // Row Six: Wands + public static final int WAND_MAGIC_MISSILE = ROW6 + 0; + public static final int WAND_ACID = ROW6 + 1; + public static final int WAND_METEORITE = ROW6 + 2; + public static final int WAND_FLOW = ROW6 + 3; + public static final int WAND_CHARM = ROW6 + 4; + public static final int WAND_DISINTEGRATION = ROW6 + 5; + public static final int WAND_FIREBOLT = ROW6 + 6; + public static final int WAND_BLOOD = ROW6 + 7; + public static final int WAND_FREEZE = ROW6 + 8; + public static final int WAND_LIGHTNING = ROW6 + 9; + public static final int WAND_POISON = ROW6 + 10; + public static final int WAND_REGROWTH = ROW6 + 11; + public static final int WAND_FLOCK = ROW6 + 12; + public static final int WAND_ADAMANT = ROW6 + 13; + public static final int WAND_TCLOUD = ROW4 + 11; + + // Row Seven: Rings + public static final int RING_GARNET = ROW7 + 0; + public static final int RING_RUBY = ROW7 + 1; + public static final int RING_TOPAZ = ROW7 + 2; + public static final int RING_EMERALD = ROW7 + 3; + public static final int RING_ONYX = ROW7 + 4; + public static final int RING_OPAL = ROW7 + 5; + public static final int RING_TOURMALINE = ROW7 + 6; + public static final int RING_SAPPHIRE = ROW7 + 7; + public static final int RING_AMETHYST = ROW7 + 8; + public static final int RING_QUARTZ = ROW7 + 9; + public static final int RING_AGATE = ROW7 + 10; + public static final int RING_DIAMOND = ROW7 + 11; + public static final int RING_ADAMANT = ROW7 + 12; + + // Row Eight: Artifacts with Static Images + public static final int ARTIFACT_CLOAK = ROW8 + 0; + public static final int ARTIFACT_ARMBAND = ROW8 + 1; + public static final int ARTIFACT_CAPE = ROW8 + 2; + public static final int ARTIFACT_TALISMAN = ROW8 + 3; + public static final int ARTIFACT_HOURGLASS = ROW8 + 4; + public static final int ARTIFACT_TOOLKIT = ROW8 + 5; + public static final int ARTIFACT_SPELLBOOK = ROW8 + 6; + + public static final int COURAGETRIAL = ROW8 + 9; + public static final int POWERTRIAL = ROW8 + 10; + public static final int WISDOMTRIAL = ROW8 + 11; + public static final int DWARFHAMMER = ROW8 + 12; + public static final int ANCIENTKEY = ROW8 + 13; + public static final int OTILUKES_JOURNAL = ROW16 + 3; + public static final int RING_DISINTEGRATION = ROW7 + 13; + public static final int RING_FROST = ROW7 + 15; + + // Row Nine: Artifacts with Dynamic Images + public static final int ARTIFACT_HORN1 = ROW9 + 0; + public static final int ARTIFACT_HORN2 = ROW9 + 1; + public static final int ARTIFACT_HORN3 = ROW9 + 2; + public static final int ARTIFACT_HORN4 = ROW9 + 3; + public static final int ARTIFACT_CHALICE1 = ROW9 + 4; + public static final int ARTIFACT_CHALICE2 = ROW9 + 5; + public static final int ARTIFACT_CHALICE3 = ROW9 + 6; + public static final int ARTIFACT_SANDALS = ROW9 + 7; + public static final int ARTIFACT_SHOES = ROW9 + 8; + public static final int ARTIFACT_BOOTS = ROW9 + 9; + public static final int ARTIFACT_GREAVES = ROW9 + 10; + public static final int ARTIFACT_ROSE1 = ROW9 + 11; + public static final int ARTIFACT_ROSE2 = ROW9 + 12; + public static final int ARTIFACT_ROSE3 = ROW9 + 13; + public static final int ARTIFACT_CHAINS = ROW17 + 15; + public static final int LUCKY_BADGE = ROW5 + 14; + + // Row Ten: Scrolls + public static final int SCROLL_KAUNAN = ROW10 + 0; + public static final int SCROLL_SOWILO = ROW10 + 1; + public static final int SCROLL_LAGUZ = ROW10 + 2; + public static final int SCROLL_YNGVI = ROW10 + 3; + public static final int SCROLL_GYFU = ROW10 + 4; + public static final int SCROLL_RAIDO = ROW10 + 5; + public static final int SCROLL_ISAZ = ROW10 + 6; + public static final int SCROLL_MANNAZ = ROW10 + 7; + public static final int SCROLL_NAUDIZ = ROW10 + 8; + public static final int SCROLL_BERKANAN = ROW10 + 9; + public static final int SCROLL_NCOSRANE = ROW10 + 10; + public static final int SCROLL_TIWAZ = ROW10 + 11; + public static final int SCROLL_NENDIL = ROW10 + 12; + public static final int SCROLL_LIBRA = ROW10 + 14; + public static final int JOURNAL_PAGE = ROW10 + 13; + + // Row Eleven: Potions + public static final int POTION_CRIMSON = ROW11 + 0; + public static final int POTION_AMBER = ROW11 + 1; + public static final int POTION_GOLDEN = ROW11 + 2; + public static final int POTION_JADE = ROW11 + 3; + public static final int POTION_TURQUOISE = ROW11 + 4; + public static final int POTION_AZURE = ROW11 + 5; + public static final int POTION_INDIGO = ROW11 + 6; + public static final int POTION_MAGENTA = ROW11 + 7; + public static final int POTION_BISTRE = ROW11 + 8; + public static final int POTION_CHARCOAL = ROW11 + 9; + public static final int POTION_SILVER = ROW11 + 10; + public static final int POTION_IVORY = ROW11 + 11; + public static final int POTION_AQUA = ROW11 + 12; + public static final int POTION_HONEY = ROW11 + 13; + public static final int POTION_VIOLET = ROW11 + 14; + + // Row Twelve: Seeds + public static final int SEED_ROTBERRY = ROW12 + 0; + public static final int SEED_FIREBLOOM = ROW12 + 1; + public static final int SEED_BLINDWEED = ROW12 + 2; + public static final int SEED_SUNGRASS = ROW12 + 3; + public static final int SEED_ICECAP = ROW12 + 4; + public static final int SEED_STORMVINE = ROW12 + 5; + public static final int SEED_SORROWMOSS = ROW12 + 6; + public static final int SEED_DREAMFOIL = ROW12 + 7; + public static final int SEED_EARTHROOT = ROW12 + 8; + public static final int SEED_FADELEAF = ROW12 + 9; + public static final int SEED_BLANDFRUIT = ROW12 + 10; + public static final int SEED_DUNGEONNUT = ROW12 + 11; + public static final int SEED_TOASTEDDUNGEONNUT = ROW12 + 12; + public static final int SEED_GOLDENDUNGEONNUT = ROW12 + 13; + public static final int SEED_BLACKBERRY = ROW12 + 14; + public static final int SEED_RICE = ROW12 + 15; + public static final int SEED_CLOUDBERRY = ROW13 + 11; + public static final int SEED_BLUEBERRY = ROW13 + 12; + public static final int SEED_MOONBERRY = ROW13 + 14; + public static final int SEED_FULLMOONBERRY = ROW13 + 15; + public static final int SEED_STARFLOWER = ROW9 + 15; + public static final int SEED_PHASEPITCHER = ROW14 + 5; + public static final int SEED_FLYTRAP = ROW5 + 12; + public static final int SEED_DEWCATCHER = ROW5+13; + public static final int SEED_SEEDPOD = ROW5 + 15; + + // Row Thirteen: Food + public static final int MEAT = ROW13 + 0; + public static final int STEAK = ROW13 + 1; + public static final int OVERPRICED = ROW13 + 2; + public static final int CARPACCIO = ROW13 + 3; + public static final int BLANDFRUIT = ROW13 + 4; + public static final int RATION = ROW13 + 5; + public static final int PASTY = ROW13 + 6; + public static final int MYSTERYMEAT = ROW13 + 7; + + // Row Fourteen: Quest Items + public static final int SKULL = ROW14 + 0; + public static final int DUST = ROW14 + 1; + public static final int PICKAXE = ROW14 + 2; + public static final int ORE = ROW14 + 3; + public static final int TOKEN = ROW14 + 4; + public static final int ATRIFORCE = ROW13 + 9; + public static final int TRIFORCE = ROW17 + 4; + public static final int MUSHROOM = ROW9 + 14; + public static final int MUSHROOM_DEATHCAP = ROW14 + 9; + public static final int MUSHROOM_LANTERN = ROW14 + 6; + public static final int MUSHROOM_LICHEN = ROW14 + 8; + public static final int MUSHROOM_EARTHSTAR = ROW14 + 7; + public static final int MUSHROOM_BLUEMILK = ROW14 + 12; + public static final int MUSHROOM_GOLDENJELLY = ROW14 + 11; + public static final int MUSHROOM_PIXIEPARASOL= ROW14 + 10; + + // Row Fifteen: Containers/Bags + public static final int VIAL = ROW15 + 0; + public static final int POUCH = ROW15 + 1; + public static final int HOLDER = ROW15 + 2; + public static final int BANDOLIER = ROW15 + 3; + public static final int HOLSTER = ROW15 + 4; + public static final int SHOPCART = ROW15 + 5; + public static final int ACTIVEMRD = ROW15 + 6; + public static final int ACTIVEMRD2 = ROW15 + 7; + public static final int ORBOFZOT = ROW15 + 10; + public static final int KEYRING = ROW4 + 10; + + //Bombs + public static final int DARK_BOMB = ROW13 + 8; + public static final int FISH_BOMB = ROW13 + 10; + public static final int LIGHT_BOMB = ROW13 + 13; + public static final int FIRE_BOMB = ROW15 + 11; + public static final int STORM_BOMB = ROW15 + 12; + public static final int EARTH_BOMB = ROW15 + 13; + public static final int ICE_BOMB = ROW15 + 14; + public static final int HUGE_BOMB = ROW15 + 15; + public static final int MINI_BOMB = ROW15 + 8; + public static final int BUILD_BOMB = ROW15 + 9; + + // Row Sixteen: Random OP Stuff + public static final int UPGRADEGOO_YELLOW = ROW16 + 0; + public static final int UPGRADEGOO_RED = ROW16 + 1; + public static final int UPGRADEGOO_VIOLET = ROW16 + 2; + public static final int EGG = ROW16 + 4; + public static final int TRIDENT = ROW16 + 5; + public static final int ARESSWORD = ROW16 + 6; + public static final int JUPITERSWRAITH = ROW16 + 7; + public static final int CROMAXE = ROW16 + 8; + public static final int LOKISFLAIL = ROW16 + 9; + public static final int NORNGREEN = ROW16 + 11; + public static final int NORNBLUE = ROW16 + 12; + public static final int NORNORANGE = ROW16 + 13; + public static final int NORNPURPLE = ROW16 + 14; + public static final int NORNYELLOW = ROW16 + 15; + + // Row Seventeen: Random Lame Stuff + public static final int TOWEL = ROW17 + 0; + public static final int OTILUKES_SPECS = ROW17 + 1; + public static final int PUDDING_CUP = ROW17 + 2; + public static final int POCKET_BALL = ROW17 + 3; + + public static final int BOSSRUSH = ROW8 + 7; + public static final int JUMP = ROW17 + 5; + public static final int SHIELD = ROW17 + 6; + public static final int DKNIVE = ROW17 + 7; + public static final int NUNCHAKUS = ROW17 + 9; + + public static final int TEKKOKAGI = ROW17 + 10; + public static final int WRAITHBREATH = ROW4 + 9; + public static final int GSWORD = ROW17 + 11; + public static final int HALBERD = ROW17 + 12; + public static final int MAP = ROW6 + 14; + public static final int PLAYERICON = ROW17 + 13; + public static final int SHOESKIT = ROW17 + 14; + public static final int TREE = ROW6 + 15; + + public static final int SEWERSKEY = ROW18 + 0; + public static final int PRISONKEY = ROW18 + 1; + public static final int CAVEKEY = ROW18 + 2; + public static final int CITYKEY = ROW18 + 3; + public static final int POTKEY = ROW18 + 4; + public static final int TENGUKEY = ROW18 + 5; + + public static final int RANDOWNEGG = ROW19 + 0; + public static final int SCORPIONEGG = ROW19 + 1; + public static final int SPIDEREGG = ROW19 + 2; + public static final int FIREEGG = ROW19 + 3; + public static final int RED_DRAGONEGG = ROW19 + 4; + public static final int BLUE_DRAGONEGG = ROW19 + 5; + public static final int VIOLET_DRAGONEGG = ROW19 + 6; + public static final int GREEN_DRAGONEGG = ROW19 + 7; + public static final int SHADOWEGG = ROW19 + 8; + public static final int BEEEGG = ROW19 + 9; + public static final int RABBITEGG = ROW19 + 10; + public static final int VELOCIROOSTEREGG = ROW19 + 11; + public static final int LIGHT_DRAGONEGG = ROW19 + 13; + public static final int GOLD_DRAGONEGG = ROW19 + 14; + + public static final int FAIRYCARD = ROW19 + 12; + + public static final int HUGESHURIKEN = ROW8 + 15; + public static final int TPTRAP = ROW3 + 15; + + public static final int POTION = ROW18 + 12; + + public static final int FIGHTGLOVES = ROW18 + 6; + public static final int LANCE = ROW20 + 11; + public static final int RAPIER = ROW20 + 12; + public static final int CLUB = ROW20 + 13; + public static final int GNOLL_ARMOR = ROW20 + 14; + public static final int FIRECRACKER = ROW20 + 15; + + + public static final int PETFOOD = ROW18 + 15; + public static final int PUMPKIN = ROW19 + 15; + + public static final int EASTER_EGG = ROW16 + 10; + public static final int PUMPKIN_PIE = ROW20 + 0 ; + public static final int CANDY_CANE = ROW20 + 1 ; + public static final int TURKEY_MEAT = ROW20 + 2; + public static final int SPRING_ASSORTED = ROW20 + 3; + + public static final int MOAI = ROW20 + 6; + public static final int POCKETBALL_EMPTY = ROW20 + 7; + public static final int SPAMMO = ROW20 + 9; + + public static final int ERROR_WEAPON = ROW18 + 7; + public static final int ERROR_ARMOR = ROW18 + 8; + public static final int ERROR_WAND = ROW18 + 9; + public static final int ERROR_FOOD = ROW18 + 11; + public static final int ERROR_AMMO = ROW20 + 5; + + public static final int ERROR_BOOK = ROW18 + 13; + + public static final int H_O_SCARECROW = ROW18 + 14; + + public static final int ELEVATOR = ROW20 + 10; + + public static final int HOOK_HAM = ROW21 + 1; + public static final int KNOWNLADGE_FOOD = ROW21 + 2; + + public static final int SKILL_ATK = ROW21 + 8; + public static final int SKILL_DEF = ROW21 + 9; + public static final int SKILL_MIG = ROW21 + 10; + public static final int WARRIORSHIELD = ROW21 + 11; + + public static final int TRIANGOLO = ROW21 + 0; + public static final int FLUTE = ROW21 + 3; + public static final int WARDURM = ROW21 + 4; + public static final int TRUMPET = ROW21 + 5; + public static final int HARP = ROW21 + 6; + public static final int SHOVEL = ROW21 + 7; + public static final int GLASSTOTEM = ROW21 + 12 ; + public static final int ARMOR_PERFORMER = ROW21 + 13; + + public static final int HAMBURGER = ROW22 + 0; + public static final int HONEYWATER = ROW22 + 1; + public static final int CHICKENNUGGET = ROW22 + 2; + public static final int HONEYMEAT = ROW22 + 3; + public static final int MEATSOUP = ROW22 + 4; + public static final int HOTDOG = ROW22 + 5; + public static final int KEBAB = ROW22 + 6 ; + public static final int SANDWICH = ROW22 + 7; + public static final int ALIEN_BAG = ROW22 + 8; + public static final int ICECREAM = ROW22 + 9; + public static final int VEGETABLESOUP = ROW22 + 10; + public static final int RICE = ROW22 + 11; + public static final int FRUITSALAD = ROW22 + 12; + public static final int FOAMED = ROW22 + 13; + public static final int EAT_GRASS = ROW22 + 14; + public static final int PERFECT_FOOD = ROW22 + 15; + + public static final int CHALLENGE_BOOK = ROW21 + 14; + public static final int GOEI = ROW21 + 15; + + public static final int VEST_ARMOR = ROW23 + 0; + public static final int RUBBER_ARMOR = ROW23 + 1; + public static final int CD_ARMOR = ROW23 + 2; + public static final int STY_ARMOR = ROW23 + 3; + public static final int PRO_ARMOR = ROW23 + 4; + public static final int PHANTOM_ARMOR = ROW23 + 5; + + public static final int WOODEN_ARMOR = ROW23 + 6; + public static final int CERAMICS_ARMOR = ROW23 + 7; + public static final int STONE_ARMOR = ROW23 + 8; + public static final int MUL_ARMOR = ROW23 + 9; + public static final int BULLET_ARMOR = ROW23 + 10; + public static final int MECH_ARMOR = ROW23 + 11; + + public static final int ARMOR_SOLDIER = ROW23 + 13; + public static final int ARMOR_FOLLOWER = ROW27 + 8; + + public static final int HERB_MEAT = ROW23 + 12; + + public static final int GUN_A = ROW24 + 0; + public static final int GUN_B = ROW24 + 1; + public static final int GUN_C = ROW24 + 2; + public static final int GUN_D = ROW24 + 3; + public static final int GUN_E = ROW24 + 4; + public static final int GUN_S = ROW24 + 5; + public static final int TOYGUN = ROW24 + 6; + public static final int SLING = ROW24 + 7; + public static final int MOBS = ROW24 + 8; + public static final int BRICK = ROW24 + 9; + public static final int PILL_ATK = ROW24 + 10; + public static final int PILL_DEF = ROW24 + 11; + public static final int PILL_STR = ROW24 + 12; + public static final int PILL_MIG = ROW24 + 13; + public static final int PILL_MUC = ROW24 + 14; + public static final int PILL_SOT = ROW24 + 15; + + public static final int W_BRICK = ROW20 + 4; + + public static final int FOURCLOVER = ROW23 + 14; + public static final int POTION_OF_MAGE = ROW23 + 15; + + public static final int LOLLIPOP = ROW25 + 0; + public static final int JELLY_SWORD = ROW25 + 1; + public static final int POWER_HAND = ROW25 + 2; + public static final int S_J_R_B_M = ROW25 + 3; + public static final int FRENCHFRIES = ROW25 + 4; + public static final int CHOCOLATE = ROW25 + 5; + public static final int FOODFANS = ROW25 + 6; + + public static final int ATTACKSHIELD = ROW25 + 8; + + public static final int BSHOVEL = ROW25 + 7; + + public static final int CANNON_OF_MAGE = ROW25 + 9; + + public static final int MANY_KNIVE = ROW25 + 10; + + public static final int MK_BOX = ROW25 + 11; + + public static final int WOODEN_H = ROW25 + 12; + + public static final int S_AND_S = ROW25 + 13; + + public static final int AFLY_FOOD = ROW25 + 14; + + public static final int FLAG = ROW25 + 15; + + public static final int COPY_BALL = ROW26 + 1; + public static final int EMPTY_BOMB = ROW26 + 2; + public static final int SHATTERED_AMMO = ROW26 + 3; + public static final int BOW = ROW26 + 4; + + public static final int STAR_FLOWER = ROW26 + 5; + public static final int UP_EATER = ROW26 + 6; + public static final int TRAN_BALL = ROW26 + 7; + public static final int DREAM_L = ROW26 + 8; + public static final int HEAL_L = ROW26 + 9; + public static final int MECH_POCKET = ROW26 + 10; + + public static final int DEMO_SCROLL = ROW26 + 11; + public static final int UNDEAD_BOOK = ROW26 + 12; + public static final int GNOLL_MARK = ROW26 + 13; + + public static final int HELMET = ROW26 + 14; + public static final int WOODEN_STAFF = ROW26 + 15; + + + public static final int HEAL_BAG = ROW27 + 0; + + public static final int MACE = ROW27 + 4; + public static final int HOLY_WATER = ROW27 + 2; + public static final int PRAYER_WHEEL = ROW27 + 5; + public static final int STONE_CROSS = ROW27 + 1; + + public static final int FAITH_SIGN = ROW27 + 6; + public static final int ARTIFACT_BEACON = ROW27 + 7; + + public static final int DIAMOND_PICKAXE = ROW27 + 3; + + public static final int MONEY_PACK = ROW27 + 10; + + public static final int DOOR_BLOCK = ROW27 + 11; + public static final int WALL_BLOCK = ROW27 + 12; + public static final int STONE_BLOCK = ROW27 + 13; + public static final int WOODEN_BLOCK = ROW27 + 14; + public static final int BOOK_BLOCK = ROW27 + 15; + + public static final int HORSE_TOTEM = ROW28 + 0; + public static final int RANGE_BAG = ROW28 + 1; + public static final int DANCE_LION = ROW28 + 2; + + public static final int LIVE_ARMOR = ROW28 + 3; + public static final int SHADOW_EATER = ROW28 + 4; + + public static final int GOBLIN_SHIELD = ROW28 + 5; + public static final int CURSE_BLOOD = ROW28 + 6; + public static final int TENGU_SWORD = ROW28 + 7; + public static final int SP_KNUCKLE = ROW28 + 8; + + +} diff --git a/java/com/hmdzl/spspd/sprites/JinkeloidSprite.java b/java/com/hmdzl/spspd/sprites/JinkeloidSprite.java new file mode 100644 index 00000000..0d0832f3 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/JinkeloidSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class JinkeloidSprite extends MobSprite { + + public JinkeloidSprite() { + super(); + + texture( Assets.JINKELOID ); + + TextureFilm frames = new TextureFilm( texture, 16, 16 ); + + idle = new Animation( 15, true ); + idle.frames(frames, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3); + + run = new Animation( 20, true ); + run.frames( frames, 0 ); + + attack = new Animation( 12, false ); + attack.frames( frames, 0, 2, 3 ); + + die = new Animation( 20, false ); + die.frames( frames, 0 ); + + play( idle ); + } + + +} diff --git a/java/com/hmdzl/spspd/sprites/Juh9870Sprite.java b/java/com/hmdzl/spspd/sprites/Juh9870Sprite.java new file mode 100644 index 00000000..f844b7b1 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/Juh9870Sprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class Juh9870Sprite extends MobSprite { + + public Juh9870Sprite() { + super(); + + texture( Assets.JUH9870 ); + + TextureFilm frames = new TextureFilm( texture, 16, 16 ); + + idle = new Animation( 3, true ); + idle.frames(frames, 0, 0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 3); + + run = new Animation( 20, true ); + run.frames( frames, 0 ); + + attack = new Animation( 12, false ); + attack.frames( frames, 0, 2, 3 ); + + die = new Animation( 20, false ); + die.frames( frames, 0 ); + + play( idle ); + } + + +} diff --git a/java/com/hmdzl/spspd/sprites/KeKeSprite.java b/java/com/hmdzl/spspd/sprites/KeKeSprite.java new file mode 100644 index 00000000..0a029571 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/KeKeSprite.java @@ -0,0 +1,59 @@ +/* + * Pixel Dungeon + * Copyright (C) 5415-5415 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 5 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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.effects.Lightning; +import com.hmdzl.spspd.items.wands.WandOfTCloud; +import com.watabou.noosa.TextureFilm; + +public class KeKeSprite extends MobSprite { + + public KeKeSprite() { + super(); + + texture(Assets.T_CLOUD); + + TextureFilm frames = new TextureFilm( texture, 16, 16 ); + + idle = new Animation( 5, true ); + idle.frames(frames, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7); + + run = new Animation( 54, true ); + run.frames( frames, 4 ); + + attack = new Animation( 15, false ); + attack.frames( frames, 4, 5, 5 ); + + die = new Animation( 24, false ); + die.frames( frames, 4 ); + + zap = attack.clone(); + + play(idle); + } + + @Override + public void zap(int pos) { + + parent.add( new Lightning( ch.pos, pos, (WandOfTCloud.STCloud) ch)); + + turnTo(ch.pos, pos); + play(zap); + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/sprites/KingSprite.java b/java/com/hmdzl/spspd/sprites/KingSprite.java new file mode 100644 index 00000000..b6658727 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/KingSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class KingSprite extends MobSprite { + + public KingSprite() { + super(); + + texture(Assets.KING); + + TextureFilm frames = new TextureFilm(texture, 16, 16); + + idle = new Animation( 5, true ); + idle.frames(frames, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 1, 1, 1); + + run = new Animation( 15, true ); + run.frames( frames, 3, 4, 5, 6, 7, 8 ); + + attack = new Animation( 15, false ); + attack.frames( frames, 9, 10, 11, 12, 13, 14, 15 ); + + die = new Animation( 10, false ); + die.frames( frames, 21, 22, 23, 24 ); + + play(idle); + } +} diff --git a/java/com/hmdzl/spspd/sprites/Kostis12345Sprite.java b/java/com/hmdzl/spspd/sprites/Kostis12345Sprite.java new file mode 100644 index 00000000..bf3a83ad --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/Kostis12345Sprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class Kostis12345Sprite extends MobSprite { + + public Kostis12345Sprite() { + super(); + + texture( Assets.KOSTIS ); + + TextureFilm frames = new TextureFilm( texture, 16, 16 ); + + idle = new Animation( 3, true ); + idle.frames(frames, 0, 0, 1, 1, 2, 2, 3, 3, 3, 3, 3, 3); + + run = new Animation( 3, true ); + run.frames( frames, 0, 0, 1, 1, 2, 2, 3, 3, 3, 3, 3, 3 ); + + attack = new Animation( 12, false ); + attack.frames( frames, 0, 2, 3 ); + + die = new Animation( 20, false ); + die.frames( frames, 0 ); + + play( idle ); + } + + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/sprites/LaJiSprite.java b/java/com/hmdzl/spspd/sprites/LaJiSprite.java new file mode 100644 index 00000000..317a9a8a --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/LaJiSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class LaJiSprite extends MobSprite { + + public LaJiSprite() { + super(); + + texture( Assets.LAJI ); + + TextureFilm frames = new TextureFilm( texture, 16, 16 ); + + idle = new Animation( 3, true ); + idle.frames(frames, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3); + + run = new Animation( 20, true ); + run.frames( frames, 0 ); + + attack = new Animation( 12, false ); + attack.frames( frames, 0, 2, 3 ); + + die = new Animation( 20, false ); + die.frames( frames, 0 ); + + play( idle ); + } + + +} diff --git a/java/com/hmdzl/spspd/sprites/LarvaSprite.java b/java/com/hmdzl/spspd/sprites/LarvaSprite.java new file mode 100644 index 00000000..ccaac5ef --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/LarvaSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.effects.Splash; +import com.watabou.noosa.TextureFilm; + +public class LarvaSprite extends MobSprite { + + public LarvaSprite() { + super(); + + texture(Assets.LARVA); + + TextureFilm frames = new TextureFilm(texture, 12, 8); + + idle = new Animation(5, true); + idle.frames(frames, 4, 4, 4, 4, 4, 5, 5); + + run = new Animation(12, true); + run.frames(frames, 0, 1, 2, 3); + + attack = new Animation(15, false); + attack.frames(frames, 6, 5, 7); + + die = new Animation(10, false); + die.frames(frames, 8); + + play(idle); + } + + @Override + public int blood() { + return 0xbbcc66; + } + + @Override + public void die() { + Splash.at(center(), blood(), 10); + super.die(); + } +} diff --git a/java/com/hmdzl/spspd/sprites/LerySprite.java b/java/com/hmdzl/spspd/sprites/LerySprite.java new file mode 100644 index 00000000..8921d639 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/LerySprite.java @@ -0,0 +1,85 @@ +/* + * 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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.mobs.pets.LeryFire; +import com.hmdzl.spspd.effects.MagicMissile; +import com.watabou.noosa.TextureFilm; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Callback; + +public class LerySprite extends MobSprite { + + public LerySprite() { + super(); + + texture( Assets.ELEMENTAL ); + + TextureFilm frames = new TextureFilm( texture, 12, 14 ); + + idle = new Animation( 10, true ); + idle.frames( frames, 21, 22, 23 ); + + run = new Animation( 12, true ); + run.frames( frames, 21, 22, 24 ); + + attack = new Animation( 15, false ); + attack.frames( frames, 25, 26, 27 ); + + zap = attack.clone(); + + die = new Animation( 15, false ); + die.frames( frames, 28, 29, 30, 31, 32, 33, 34, 33 ); + + play( idle ); + } + + @Override + public void link( Char ch ) { + super.link( ch ); + add( CharSprite.State.BURNING ); + } + @Override + public void die() { + super.die(); + remove( CharSprite.State.BURNING ); + } + + @Override + public void zap(int cell) { + + turnTo(ch.pos, cell); + play(zap); + + MagicMissile.fire(parent, ch.pos, cell, new Callback() { + @Override + public void call() { + ((LeryFire) ch).onZapComplete(); + } + }); + Sample.INSTANCE.play(Assets.SND_ZAP); + } + @Override + public int blood() { + return 0xFFFF7D13; + } + + +} diff --git a/java/com/hmdzl/spspd/sprites/LichDancerSprite.java b/java/com/hmdzl/spspd/sprites/LichDancerSprite.java new file mode 100644 index 00000000..b06615c7 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/LichDancerSprite.java @@ -0,0 +1,41 @@ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.Game; +import com.watabou.noosa.TextureFilm; + +public class LichDancerSprite extends MobSprite { + + public LichDancerSprite() { + super(); + + texture(Assets.LICH_DANCER); + + TextureFilm frames = new TextureFilm(texture, 16, 16); + + idle = new Animation(10, true); + idle.frames(frames, 0, 0, 0, 0, 1, 2, 0, 1); + + run = new Animation(15, true); + run.frames(frames, 2, 3, 4, 5); + + attack = new Animation(12, false); + attack.frames(frames, 6, 7, 8, 9); + + die = new Animation(12, false); + die.frames(frames, 10, 11, 12, 13); + + play(idle); + } + + @Override + public void update() { + super.update(); + if (flashTime <= 0 ){ + float interval = (Game.timeTotal % 9 ) /3f; + tint(interval > 2 ? interval - 2 : Math.max(0, 1 - interval), + interval > 1 ? Math.max(0, 2-interval): interval, + interval > 2 ? Math.max(0, 3-interval): interval-1, 0.5f); + } + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/sprites/LightDragonSprite.java b/java/com/hmdzl/spspd/sprites/LightDragonSprite.java new file mode 100644 index 00000000..40b36928 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/LightDragonSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.DungeonTilemap; +import com.hmdzl.spspd.effects.Beam; +import com.watabou.noosa.TextureFilm; + +public class LightDragonSprite extends MobSprite { + private int attackPos; + //Frames 1-4 are idle, 5-8 are moving, 9-12 are attack and the last are for death RBVG + + private int[] points = new int[2]; + + public LightDragonSprite() { + super(); + + texture(Assets.PETDRAGON); + + TextureFilm frames = new TextureFilm(texture, 16, 16); + + idle = new Animation(2, true); + idle.frames(frames, 96, 97, 98, 99); + + run = new Animation(8, true); + run.frames(frames, 100, 101, 102, 103); + + attack = new Animation(8, false); + attack.frames(frames, 104, 105, 106, 107); + + zap = attack.clone(); + + die = new Animation(8, false); + die.frames(frames, 108, 109, 110, 111); + + play(idle); + } + + @Override + public void attack(int pos) { + attackPos = pos; + super.attack(pos); + } + + + @Override + public void onComplete(Animation anim) { + super.onComplete(anim); + + if (anim == attack) { + if (Dungeon.visible[ch.pos] || Dungeon.visible[attackPos]) { + parent.add(new Beam.LightRay(center(), DungeonTilemap + .tileCenterToWorld(attackPos))); + } + } + } + + @Override + public int blood() { + return 0xFFcdcdb7; + } +} diff --git a/java/com/hmdzl/spspd/sprites/LiveMossSprite.java b/java/com/hmdzl/spspd/sprites/LiveMossSprite.java new file mode 100644 index 00000000..30876ff9 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/LiveMossSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class LiveMossSprite extends MobSprite { + + public LiveMossSprite() { + super(); + + texture( Assets.LIVEMOSS ); + + TextureFilm frames = new TextureFilm(texture, 16, 15); + + idle = new Animation( 2, true ); + idle.frames( frames, 0,0,0,1); + + run = new Animation( 10, true ); + run.frames( frames, 0,1,1,1,0,0); + + attack = new Animation( 15, false ); + attack.frames( frames, 1, 2, 2, 1, 1 ); + + die = new Animation( 10, false ); + die.frames( frames, 2, 2, 3, 3 ); + + play( idle ); + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/sprites/LocastanSprite.java b/java/com/hmdzl/spspd/sprites/LocastanSprite.java new file mode 100644 index 00000000..a2519bd3 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/LocastanSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class LocastanSprite extends MobSprite { + + public LocastanSprite() { + super(); + + texture( Assets.LOCASTAN ); + + TextureFilm frames = new TextureFilm( texture, 16, 16 ); + + idle = new Animation( 3, true ); + idle.frames(frames, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3); + + run = new Animation( 20, true ); + run.frames( frames, 0 ); + + attack = new Animation( 12, false ); + attack.frames( frames, 0, 2, 3 ); + + die = new Animation( 20, false ); + die.frames( frames, 0 ); + + play( idle ); + } + + +} diff --git a/java/com/hmdzl/spspd/sprites/LynSprite.java b/java/com/hmdzl/spspd/sprites/LynSprite.java new file mode 100644 index 00000000..ff63194c --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/LynSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class LynSprite extends MobSprite { + + public LynSprite() { + super(); + + texture( Assets.LYN ); + + TextureFilm frames = new TextureFilm( texture, 16, 16 ); + + idle = new Animation( 3, true ); + idle.frames(frames, 0, 0, 1, 1, 2, 2, 3, 3, 3, 3, 3, 3); + + run = new Animation( 20, true ); + run.frames( frames, 0 ); + + attack = new Animation( 12, false ); + attack.frames( frames, 0, 2, 3 ); + + die = new Animation( 20, false ); + die.frames( frames, 0 ); + + play( idle ); + } + + +} diff --git a/java/com/hmdzl/spspd/sprites/LynnSprite.java b/java/com/hmdzl/spspd/sprites/LynnSprite.java new file mode 100644 index 00000000..67a0cc7a --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/LynnSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class LynnSprite extends MobSprite { + + public LynnSprite() { + super(); + + texture( Assets.LYNN ); + + TextureFilm frames = new TextureFilm( texture, 16, 16 ); + + idle = new Animation( 3, true ); + idle.frames(frames, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3); + + run = new Animation( 20, true ); + run.frames( frames, 0 ); + + attack = new Animation( 12, false ); + attack.frames( frames, 0, 2, 3 ); + + die = new Animation( 20, false ); + die.frames( frames, 0 ); + + play( idle ); + } + + +} diff --git a/java/com/hmdzl/spspd/sprites/MagicEyeSprite.java b/java/com/hmdzl/spspd/sprites/MagicEyeSprite.java new file mode 100644 index 00000000..e74c6f22 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/MagicEyeSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.DungeonTilemap; +import com.hmdzl.spspd.effects.DeathRay; +import com.watabou.noosa.TextureFilm; + +public class MagicEyeSprite extends MobSprite { + + private int attackPos; + + public MagicEyeSprite() { + super(); + + texture(Assets.MAGICEYE); + + TextureFilm frames = new TextureFilm(texture, 16, 18); + + idle = new Animation(8, true); + idle.frames(frames, 0, 1, 2); + + run = new Animation(12, true); + run.frames(frames, 5, 6); + + attack = new Animation(8, false); + attack.frames(frames, 4, 3); + + die = new Animation(8, false); + die.frames(frames, 7, 8, 9); + + play(idle); + } + + @Override + public void attack(int pos) { + attackPos = pos; + super.attack(pos); + } + + @Override + public void onComplete(Animation anim) { + super.onComplete(anim); + + if (anim == attack) { + if (Dungeon.visible[ch.pos] || Dungeon.visible[attackPos]) { + parent.add(new DeathRay(center(), DungeonTilemap + .tileCenterToWorld(attackPos))); + } + } + } +} diff --git a/java/com/hmdzl/spspd/sprites/ManySkeletonSprite.java b/java/com/hmdzl/spspd/sprites/ManySkeletonSprite.java new file mode 100644 index 00000000..ef111c88 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/ManySkeletonSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class ManySkeletonSprite extends MobSprite { + + public ManySkeletonSprite() { + super(); + + texture( Assets.MANY_SKELETON ); + + TextureFilm frames = new TextureFilm( texture, 16, 16 ); + + idle = new Animation( 15, true ); + idle.frames(frames, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3); + + run = new Animation( 20, true ); + run.frames( frames, 0 ); + + attack = new Animation( 12, false ); + attack.frames( frames, 0, 2, 3 ); + + die = new Animation( 20, false ); + die.frames( frames, 0 ); + + play( idle ); + } + + +} diff --git a/java/com/hmdzl/spspd/sprites/MemoryOfSandSprite.java b/java/com/hmdzl/spspd/sprites/MemoryOfSandSprite.java new file mode 100644 index 00000000..0bce298e --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/MemoryOfSandSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class MemoryOfSandSprite extends MobSprite { + + public MemoryOfSandSprite() { + super(); + + texture( Assets.MOS ); + + TextureFilm frames = new TextureFilm( texture, 16, 16 ); + + idle = new Animation( 3, true ); + idle.frames(frames, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3); + + run = new Animation( 20, true ); + run.frames( frames, 0 ); + + attack = new Animation( 12, false ); + attack.frames( frames, 0, 2, 3 ); + + die = new Animation( 20, false ); + die.frames( frames, 0 ); + + play( idle ); + } + + +} diff --git a/java/com/hmdzl/spspd/sprites/MillilitreSprite.java b/java/com/hmdzl/spspd/sprites/MillilitreSprite.java new file mode 100644 index 00000000..664f7d61 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/MillilitreSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class MillilitreSprite extends MobSprite { + + public MillilitreSprite() { + super(); + + texture( Assets.MILLILITRE ); + + TextureFilm frames = new TextureFilm( texture, 16, 16 ); + + idle = new Animation( 3, true ); + idle.frames(frames, 0, 0, 1, 1, 2, 2, 3, 3, 3, 3, 3, 3); + + run = new Animation( 3, true ); + run.frames( frames, 0, 0, 1, 1, 2, 2, 3, 3, 3, 3, 3, 3 ); + + attack = new Animation( 12, false ); + attack.frames( frames, 0, 2, 3 ); + + die = new Animation( 20, false ); + die.frames( frames, 0 ); + + play( idle ); + } + + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/sprites/MimicSprite.java b/java/com/hmdzl/spspd/sprites/MimicSprite.java new file mode 100644 index 00000000..476d7e3e --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/MimicSprite.java @@ -0,0 +1,51 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class MimicSprite extends MobSprite { + + public MimicSprite() { + super(); + + texture(Assets.MIMIC); + + TextureFilm frames = new TextureFilm(texture, 16, 16); + + idle = new Animation(5, true); + idle.frames(frames, 0, 0, 0, 1, 1); + + run = new Animation(10, true); + run.frames(frames, 0, 1, 2, 3, 3, 2, 1); + + attack = new Animation(10, false); + attack.frames(frames, 0, 4, 5, 6); + + die = new Animation(5, false); + die.frames(frames, 7, 8, 9); + + play(idle); + } + + @Override + public int blood() { + return 0xFFcb9700; + } +} diff --git a/java/com/hmdzl/spspd/sprites/MirrorSprite.java b/java/com/hmdzl/spspd/sprites/MirrorSprite.java new file mode 100644 index 00000000..68d242c4 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/MirrorSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.mobs.npcs.MirrorImage; +import com.watabou.noosa.TextureFilm; + +public class MirrorSprite extends MobSprite { + + private static final int FRAME_WIDTH = 12; + private static final int FRAME_HEIGHT = 15; + + public MirrorSprite() { + super(); + + texture(Dungeon.hero.heroClass.spritesheet()); + updateArmor(0); + idle(); + } + + @Override + public void link(Char ch) { + super.link(ch); + updateArmor(((MirrorImage) ch).skin); + } + + public void updateArmor(int tier) { + TextureFilm film = new TextureFilm(HeroSprite.skins(), tier, + FRAME_WIDTH, FRAME_HEIGHT); + + idle = new Animation(1, true); + idle.frames(film, 0, 0, 0, 1, 0, 0, 1, 1); + + run = new Animation(20, true); + run.frames(film, 2, 3, 4, 5, 6, 7); + + die = new Animation(20, false); + die.frames(film, 0); + + attack = new Animation(15, false); + attack.frames(film, 13, 14, 15, 0); + + idle(); + } +} diff --git a/java/com/hmdzl/spspd/sprites/MissileSprite.java b/java/com/hmdzl/spspd/sprites/MissileSprite.java new file mode 100644 index 00000000..3557e458 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/MissileSprite.java @@ -0,0 +1,91 @@ +/* + * 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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.DungeonTilemap; +import com.hmdzl.spspd.items.Item; +import com.watabou.noosa.tweeners.PosTweener; +import com.watabou.noosa.tweeners.Tweener; +import com.watabou.utils.Callback; +import com.watabou.utils.PointF; + +public class MissileSprite extends ItemSprite implements Tweener.Listener { + + private static final float SPEED = 240f; + + private Callback callback; + + public MissileSprite() { + super(); + originToCenter(); + } + + public void reset(int from, int to, Item item, Callback listener) { + if (item == null) { + reset(from, to, 0, null, listener); + } else { + reset(from, to, item.image(), item.glowing(), listener); + } + } + + public void reset(int from, int to, int image, Glowing glowing, + Callback listener) { + revive(); + + view(image, glowing); + + this.callback = listener; + + point(DungeonTilemap.tileToWorld(from)); + PointF dest = DungeonTilemap.tileToWorld(to); + + PointF d = PointF.diff(dest, point()); + speed.set(d).normalize().scale(SPEED); + + if (image == ItemSpriteSheet.KNIVE + || image == ItemSpriteSheet.INCENDIARY_DART + || image == ItemSpriteSheet.POSION_DART) { + + angularSpeed = 0; + angle = 135 - (float) (Math.atan2(d.x, d.y) / 3.1415926 * 180); + + } else if (image == ItemSpriteSheet.WAVE + || image == ItemSpriteSheet.SKULLWEP) { + + angularSpeed = 0; + angle = 90 - (float) (Math.atan2(d.x, d.y) / 3.1415926 * 180); + + } else { + + angularSpeed = image == 15 || image == 106 ? 1440 : 720; + + } + + PosTweener tweener = new PosTweener(this, dest, d.length() / SPEED); + tweener.listener = this; + parent.add(tweener); + } + + @Override + public void onComplete(Tweener tweener) { + kill(); + if (callback != null) { + callback.call(); + } + } +} diff --git a/java/com/hmdzl/spspd/sprites/MobSprite.java b/java/com/hmdzl/spspd/sprites/MobSprite.java new file mode 100644 index 00000000..c83a7fd9 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/MobSprite.java @@ -0,0 +1,73 @@ +/* + * 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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.DungeonTilemap; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.watabou.noosa.tweeners.AlphaTweener; +import com.watabou.noosa.tweeners.ScaleTweener; +import com.watabou.utils.PointF; +import com.watabou.utils.Random; + +public class MobSprite extends CharSprite { + + private static final float FADE_TIME = 3f; + private static final float FALL_TIME = 1f; + + @Override + public void update() { + sleeping = ch != null && ((Mob) ch).state == ((Mob) ch).SLEEPING; + super.update(); + } + + @Override + public void onComplete(Animation anim) { + + super.onComplete(anim); + + if (anim == die) { + parent.add(new AlphaTweener(this, 0, FADE_TIME) { + @Override + protected void onComplete() { + MobSprite.this.killAndErase(); + parent.erase(this); + }; + }); + } + } + + public void fall() { + + origin.set(width / 2, height - DungeonTilemap.SIZE / 2); + angularSpeed = Random.Int(2) == 0 ? -720 : 720; + + parent.add(new ScaleTweener(this, new PointF(0, 0), FALL_TIME) { + @Override + protected void onComplete() { + MobSprite.this.killAndErase(); + parent.erase(this); + }; + + @Override + protected void updateValues(float progress) { + super.updateValues(progress); + am = 1 - progress; + } + }); + } +} diff --git a/java/com/hmdzl/spspd/sprites/MobileSprite.java b/java/com/hmdzl/spspd/sprites/MobileSprite.java new file mode 100644 index 00000000..60d37546 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/MobileSprite.java @@ -0,0 +1,73 @@ +/* + * 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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.items.weapon.missiles.EscapeKnive; +import com.hmdzl.spspd.levels.Level; +import com.watabou.noosa.TextureFilm; +import com.watabou.utils.Callback; + +public class MobileSprite extends MobSprite { + private Animation cast; + public MobileSprite() { + super(); + + texture( Assets.MOBILE ); + + TextureFilm frames = new TextureFilm( texture, 16, 16 ); + + idle = new Animation( 3, true ); + idle.frames(frames, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3); + + run = new Animation( 20, true ); + run.frames( frames, 0 ); + + attack = new Animation( 12, false ); + attack.frames( frames, 0, 2, 3 ); + + cast = attack.clone(); + + die = new Animation( 20, false ); + die.frames( frames, 0 ); + + play( idle ); + } + @Override + public void attack(int cell) { + if (!Level.adjacent(cell, ch.pos)) { + + ((MissileSprite) parent.recycle(MissileSprite.class)).reset(ch.pos, + cell, new EscapeKnive(), new Callback() { + @Override + public void call() { + ch.onAttackComplete(); + } + }); + + play(cast); + turnTo(ch.pos, cell); + + } else { + + super.attack(cell); + + } + } + +} diff --git a/java/com/hmdzl/spspd/sprites/MonkSprite.java b/java/com/hmdzl/spspd/sprites/MonkSprite.java new file mode 100644 index 00000000..4667649f --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/MonkSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; +import com.watabou.utils.Random; + +public class MonkSprite extends MobSprite { + + private Animation kick; + + public MonkSprite() { + super(); + + texture(Assets.MONK); + + TextureFilm frames = new TextureFilm(texture, 15, 14); + + idle = new Animation(6, true); + idle.frames(frames, 1, 0, 1, 2); + + run = new Animation(15, true); + run.frames(frames, 11, 12, 13, 14, 15, 16); + + attack = new Animation(12, false); + attack.frames(frames, 3, 4, 3, 4); + + kick = new Animation(10, false); + kick.frames(frames, 5, 6, 5); + + die = new Animation(15, false); + die.frames(frames, 1, 7, 8, 8, 9, 10); + + play(idle); + } + + @Override + public void attack(int cell) { + super.attack(cell); + if (Random.Float() < 0.5f) { + play(kick); + } + } + + @Override + public void onComplete(Animation anim) { + super.onComplete(anim == kick ? attack : anim); + } +} diff --git a/java/com/hmdzl/spspd/sprites/MonkeySprite.java b/java/com/hmdzl/spspd/sprites/MonkeySprite.java new file mode 100644 index 00000000..4c78d75c --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/MonkeySprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class MonkeySprite extends MobSprite { + + //Frames 1-4 are idle, 5-8 are moving, 9-12 are attack and the last are for death RBVG + + public MonkeySprite() { + super(); + + texture(Assets.KLIKS); + + TextureFilm frames = new TextureFilm(texture, 16, 16); + + idle = new Animation(2, true); + idle.frames(frames, 17, 18, 19, 20); + + run = new Animation(8, true); + run.frames(frames, 21, 22, 23, 24); + + attack = new Animation(8, false); + attack.frames(frames, 25, 26, 27, 28); + + zap = attack.clone(); + + die = new Animation(8, false); + die.frames(frames, 29, 30, 30, 30); + + play(idle); + } + + + @Override + public int blood() { + return 0xFFcdcdb7; + } +} diff --git a/java/com/hmdzl/spspd/sprites/MonsterBoxSprite.java b/java/com/hmdzl/spspd/sprites/MonsterBoxSprite.java new file mode 100644 index 00000000..d72100ab --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/MonsterBoxSprite.java @@ -0,0 +1,51 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class MonsterBoxSprite extends MobSprite { + + public MonsterBoxSprite() { + super(); + + texture(Assets.MONSTERBOX); + + TextureFilm frames = new TextureFilm(texture, 16, 16); + + idle = new Animation(5, true); + idle.frames(frames, 0, 0, 0, 1, 1); + + run = new Animation(10, true); + run.frames(frames, 0, 1, 2, 3, 3, 2, 1); + + attack = new Animation(10, false); + attack.frames(frames, 0, 4, 5, 6); + + die = new Animation(5, false); + die.frames(frames, 7, 8, 9); + + play(idle); + } + + @Override + public int blood() { + return 0xFFcb9700; + } +} diff --git a/java/com/hmdzl/spspd/sprites/MossySkeletonSprite.java b/java/com/hmdzl/spspd/sprites/MossySkeletonSprite.java new file mode 100644 index 00000000..632230e5 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/MossySkeletonSprite.java @@ -0,0 +1,61 @@ +/* + * 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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.effects.Speck; +import com.watabou.noosa.TextureFilm; + +public class MossySkeletonSprite extends MobSprite { + + public MossySkeletonSprite() { + super(); + + texture(Assets.MOSSYSKELETON); + + TextureFilm frames = new TextureFilm(texture, 12, 15); + + idle = new Animation(12, true); + idle.frames(frames, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3); + + run = new Animation(15, true); + run.frames(frames, 4, 5, 6, 7, 8, 9); + + attack = new Animation(15, false); + attack.frames(frames, 14, 15, 16); + + die = new Animation(12, false); + die.frames(frames, 10, 11, 12, 13); + + play(idle); + } + + @Override + public void die() { + super.die(); + if (Dungeon.visible[ch.pos]) { + emitter().burst(Speck.factory(Speck.BONE), 6); + } + } + + @Override + public int blood() { + return 0xFFcccccc; + } +} diff --git a/java/com/hmdzl/spspd/sprites/MrDestructo2dot0Sprite.java b/java/com/hmdzl/spspd/sprites/MrDestructo2dot0Sprite.java new file mode 100644 index 00000000..5c6c02a6 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/MrDestructo2dot0Sprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.DungeonTilemap; +import com.hmdzl.spspd.effects.DeathRay; +import com.watabou.noosa.TextureFilm; + +public class MrDestructo2dot0Sprite extends MobSprite { + + private int attackPos; + + public MrDestructo2dot0Sprite() { + super(); + + texture(Assets.MRDESTRUCTO2); + + TextureFilm frames = new TextureFilm(texture, 16, 18); + + idle = new Animation(2, true); + idle.frames(frames, 1, 2, 3, 4); + + run = new Animation(12, true); + run.frames(frames, 2, 3, 4); + + attack = new Animation(8, false); + attack.frames(frames, 1, 5); + + die = new Animation(8, false); + die.frames(frames, 1, 0, 6); + + play(idle); + } + + @Override + public void attack(int pos) { + attackPos = pos; + super.attack(pos); + } + + + @Override + public void onComplete(Animation anim) { + super.onComplete(anim); + + if (anim == attack) { + if (Dungeon.visible[ch.pos] || Dungeon.visible[attackPos]) { + parent.add(new DeathRay(center(), DungeonTilemap + .tileCenterToWorld(attackPos))); + } + } + } +} diff --git a/java/com/hmdzl/spspd/sprites/MrDestructoSprite.java b/java/com/hmdzl/spspd/sprites/MrDestructoSprite.java new file mode 100644 index 00000000..e8721bff --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/MrDestructoSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.DungeonTilemap; +import com.hmdzl.spspd.effects.DeathRay; +import com.watabou.noosa.TextureFilm; + +public class MrDestructoSprite extends MobSprite { + + private int attackPos; + + public MrDestructoSprite() { + super(); + + texture(Assets.MRDESTRUCTO); + + TextureFilm frames = new TextureFilm(texture, 16, 18); + + idle = new Animation(2, true); + idle.frames(frames, 1, 2, 3, 4); + + run = new Animation(12, true); + run.frames(frames, 2, 3, 4); + + attack = new Animation(8, false); + attack.frames(frames, 1, 5); + + die = new Animation(8, false); + die.frames(frames, 1, 0, 6); + + play(idle); + } + + @Override + public void attack(int pos) { + attackPos = pos; + super.attack(pos); + } + + + @Override + public void onComplete(Animation anim) { + super.onComplete(anim); + + if (anim == attack) { + if (Dungeon.visible[ch.pos] || Dungeon.visible[attackPos]) { + parent.add(new DeathRay(center(), DungeonTilemap + .tileCenterToWorld(attackPos))); + } + } + } +} diff --git a/java/com/hmdzl/spspd/sprites/MusketeerSprite.java b/java/com/hmdzl/spspd/sprites/MusketeerSprite.java new file mode 100644 index 00000000..3741bd99 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/MusketeerSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.items.weapon.missiles.ShatteredAmmo; +import com.hmdzl.spspd.levels.Level; +import com.watabou.noosa.TextureFilm; +import com.watabou.utils.Callback; + +public class MusketeerSprite extends MobSprite { + + private Animation cast; + + public MusketeerSprite() { + super(); + + texture(Assets.MUSKETEER); + + TextureFilm frames = new TextureFilm(texture, 15, 14); + + idle = new Animation(6, true); + idle.frames(frames, 1, 0, 1, 2); + + run = new Animation(15, true); + run.frames(frames, 9, 10, 11, 12, 13, 14); + + attack = new Animation(12, false); + attack.frames(frames, 3, 4, 3); + + cast = attack.clone(); + + die = new Animation(15, false); + die.frames(frames, 1, 5, 6, 7, 8); + + play(idle); + } + + @Override + public void attack(int cell) { + if (!Level.adjacent(cell, ch.pos)) { + + ((MissileSprite) parent.recycle(MissileSprite.class)).reset(ch.pos, + cell, new ShatteredAmmo(), new Callback() { + @Override + public void call() { + ch.onAttackComplete(); + } + }); + + play(cast); + turnTo(ch.pos, cell); + + } else { + + super.attack(cell); + + } + } + +} diff --git a/java/com/hmdzl/spspd/sprites/NYRDSSprite.java b/java/com/hmdzl/spspd/sprites/NYRDSSprite.java new file mode 100644 index 00000000..6bd88319 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/NYRDSSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class NYRDSSprite extends MobSprite { + + public NYRDSSprite() { + super(); + + texture( Assets.NYRDS ); + + TextureFilm frames = new TextureFilm( texture, 16, 14 ); + + idle = new Animation( 15, true ); + idle.frames(frames, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 3); + + run = new Animation( 20, true ); + run.frames( frames, 0 ); + + attack = new Animation( 12, false ); + attack.frames( frames, 0, 2, 3 ); + + die = new Animation( 20, false ); + die.frames( frames, 0 ); + + play( idle ); + } + + +} diff --git a/java/com/hmdzl/spspd/sprites/NewPlayerSprite.java b/java/com/hmdzl/spspd/sprites/NewPlayerSprite.java new file mode 100644 index 00000000..c28047fd --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/NewPlayerSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class NewPlayerSprite extends MobSprite { + + public NewPlayerSprite() { + super(); + + texture( Assets.NEW_PLAYER ); + + TextureFilm frames = new TextureFilm( texture, 16, 16 ); + + idle = new Animation( 3, true ); + idle.frames(frames, 0, 0, 1, 1, 2, 2, 3, 3, 3, 3, 3, 3); + + run = new Animation( 3, true ); + run.frames( frames, 0, 0, 1, 1, 2, 2, 3, 3, 3, 3, 3, 3 ); + + attack = new Animation( 12, false ); + attack.frames( frames, 0, 2, 3 ); + + die = new Animation( 20, false ); + die.frames( frames, 0 ); + + play( idle ); + } + + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/sprites/NoodlemireSprite.java b/java/com/hmdzl/spspd/sprites/NoodlemireSprite.java new file mode 100644 index 00000000..518ce378 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/NoodlemireSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class NoodlemireSprite extends MobSprite { + + public NoodlemireSprite() { + super(); + + texture( Assets.NOODLEMIRE ); + + TextureFilm frames = new TextureFilm( texture, 16, 16 ); + + idle = new Animation( 3, true ); + idle.frames(frames, 0, 0, 1, 1, 2, 2, 3, 3, 3, 3, 3, 3); + + run = new Animation( 3, true ); + run.frames( frames, 0, 0, 1, 1, 2, 2, 3, 3, 3, 3, 3, 3 ); + + attack = new Animation( 12, false ); + attack.frames( frames, 0, 2, 3 ); + + die = new Animation( 20, false ); + die.frames( frames, 0 ); + + play( idle ); + } + + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/sprites/ObeliskSprite.java b/java/com/hmdzl/spspd/sprites/ObeliskSprite.java new file mode 100644 index 00000000..2698614a --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/ObeliskSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class ObeliskSprite extends MobSprite { + + public ObeliskSprite() { + super(); + + texture( Assets.OBELISK ); + + TextureFilm frames = new TextureFilm( texture, 16, 16 ); + + idle = new Animation( 3, true ); + idle.frames(frames, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3); + + run = new Animation( 20, true ); + run.frames( frames, 0 ); + + attack = new Animation( 12, false ); + attack.frames( frames, 0, 2, 3 ); + + die = new Animation( 20, false ); + die.frames( frames, 0 ); + + play( idle ); + } + + +} diff --git a/java/com/hmdzl/spspd/sprites/OldNewStwistSprite.java b/java/com/hmdzl/spspd/sprites/OldNewStwistSprite.java new file mode 100644 index 00000000..16ecb3cc --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/OldNewStwistSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.watabou.noosa.TextureFilm; + +public class OldNewStwistSprite extends MobSprite { + + public boolean gnollmission; + + public OldNewStwistSprite() { + super(); + + + gnollmission = (Dungeon.gnollmission == false); + + + final int c = gnollmission ? 8 : 0; + + texture(Assets.OLDNEWSTWIST); + + TextureFilm frames = new TextureFilm(texture, 12, 15); + + idle = new Animation(2, true); + idle.frames(frames, c + 0, c + 0, c + 0, c + 1); + + run = new Animation(10, true); + run.frames(frames, c + 2, c + 3, c + 4, c + 5, c + 6); + + attack = new Animation(15, false); + attack.frames(frames, c + 0); + + die = new Animation(10, false); + die.frames(frames, c + 0); + + play(idle); + } +} diff --git a/java/com/hmdzl/spspd/sprites/Omicronrg9Sprite.java b/java/com/hmdzl/spspd/sprites/Omicronrg9Sprite.java new file mode 100644 index 00000000..f11e0417 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/Omicronrg9Sprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class Omicronrg9Sprite extends MobSprite { + + public Omicronrg9Sprite() { + super(); + + texture( Assets.OMICRONRG9 ); + + TextureFilm frames = new TextureFilm( texture, 16, 16 ); + + idle = new Animation( 15, true ); + idle.frames(frames, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3); + + run = new Animation( 20, true ); + run.frames( frames, 0 ); + + attack = new Animation( 12, false ); + attack.frames( frames, 0, 2, 3 ); + + die = new Animation( 20, false ); + die.frames( frames, 0 ); + + play( idle ); + } + + +} diff --git a/java/com/hmdzl/spspd/sprites/OrbOfZotSprite.java b/java/com/hmdzl/spspd/sprites/OrbOfZotSprite.java new file mode 100644 index 00000000..366c8f22 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/OrbOfZotSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.DungeonTilemap; +import com.hmdzl.spspd.effects.DeathRay; +import com.watabou.noosa.TextureFilm; + +public class OrbOfZotSprite extends MobSprite { + + private int attackPos; + + public OrbOfZotSprite() { + super(); + + texture(Assets.ORBOFZOT); + + TextureFilm frames = new TextureFilm(texture, 16, 18); + + idle = new Animation(2, true); + idle.frames(frames, 1, 2, 3, 4); + + run = new Animation(12, true); + run.frames(frames, 2, 3, 4); + + attack = new Animation(8, false); + attack.frames(frames, 1, 5); + + die = new Animation(8, false); + die.frames(frames, 1, 0, 6); + + play(idle); + } + + @Override + public void attack(int pos) { + attackPos = pos; + super.attack(pos); + } + + + @Override + public void onComplete(Animation anim) { + super.onComplete(anim); + + if (anim == attack) { + if (Dungeon.visible[ch.pos] || Dungeon.visible[attackPos]) { + parent.add(new DeathRay(center(), DungeonTilemap + .tileCenterToWorld(attackPos))); + } + } + } +} diff --git a/java/com/hmdzl/spspd/sprites/OrcSprite.java b/java/com/hmdzl/spspd/sprites/OrcSprite.java new file mode 100644 index 00000000..79e3870a --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/OrcSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class OrcSprite extends MobSprite { + + public OrcSprite() { + super(); + + texture(Assets.ONI); + + TextureFilm frames = new TextureFilm(texture, 12, 16); + + idle = new Animation(12, true); + idle.frames(frames, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1); + + run = new Animation(15, true); + run.frames(frames, 0, 2, 3, 4); + + attack = new Animation(15, false); + attack.frames(frames, 5, 6, 6); + + die = new Animation(12, false); + die.frames(frames, 7, 8, 9, 10); + + play(idle); + } + +} diff --git a/java/com/hmdzl/spspd/sprites/OtiluckStoneSprite.java b/java/com/hmdzl/spspd/sprites/OtiluckStoneSprite.java new file mode 100644 index 00000000..29fa2089 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/OtiluckStoneSprite.java @@ -0,0 +1,61 @@ +/* + * 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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.actors.mobs.LitTower; +import com.hmdzl.spspd.effects.Lightning; +import com.watabou.noosa.TextureFilm; + +public class OtiluckStoneSprite extends MobSprite { + + private int[] points = new int[2]; + + public OtiluckStoneSprite() { + super(); + + texture(Assets.OTILUKESTONE); + TextureFilm frames = new TextureFilm(texture, 16, 16); + + idle = new Animation(2, true); + idle.frames(frames, 0, 0, 0, 3, 0, 0, 3, 3); + + run = new Animation(15, true); + run.frames(frames, 0, 1, 2, 0); + + attack = new Animation(12, false); + attack.frames(frames, 0, 1, 4, 4, 4); + + zap = attack.clone(); + + die = new Animation(15, false); + die.frames(frames, 0, 5, 6, 7, 8, 7); + + play(idle); + } + + @Override + public void zap(int pos) { + + parent.add( new Lightning( ch.pos, pos,(LitTower) ch)); + + turnTo(ch.pos, pos); + play(zap); + } + +} diff --git a/java/com/hmdzl/spspd/sprites/OtilukeNPCSprite.java b/java/com/hmdzl/spspd/sprites/OtilukeNPCSprite.java new file mode 100644 index 00000000..373750d0 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/OtilukeNPCSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class OtilukeNPCSprite extends MobSprite { + + public OtilukeNPCSprite() { + super(); + + texture(Assets.OTILUKE); + + TextureFilm frames = new TextureFilm(texture, 16, 16); + + idle = new Animation(10, true); + idle.frames(frames, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, + 3, 3, 3, 3, 3, 2, 1); + + run = new Animation(20, true); + run.frames(frames, 0); + + die = new Animation(20, false); + die.frames(frames, 0); + + play(idle); + } + + +} diff --git a/java/com/hmdzl/spspd/sprites/OtilukeSprite.java b/java/com/hmdzl/spspd/sprites/OtilukeSprite.java new file mode 100644 index 00000000..153b8247 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/OtilukeSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.actors.mobs.Otiluke; +import com.hmdzl.spspd.effects.MagicMissile; +import com.watabou.noosa.TextureFilm; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Callback; + +public class OtilukeSprite extends MobSprite { + + public OtilukeSprite() { + super(); + + texture(Assets.OTILUKE); + + TextureFilm frames = new TextureFilm(texture, 16, 16); + + idle = new Animation(2, true); + idle.frames(frames, 0, 0, 0, 3, 0, 0, 3, 3); + + run = new Animation(15, true); + run.frames(frames, 0, 1, 2, 0); + + attack = new Animation(12, false); + attack.frames(frames, 0, 1, 4, 4, 4); + + zap = attack.clone(); + + die = new Animation(15, false); + die.frames(frames, 0, 5, 6, 7, 8, 7); + + play(idle); + } + + @Override + public void zap(int cell) { + + turnTo(ch.pos, cell); + play(zap); + + MagicMissile.shadow(parent, ch.pos, cell, new Callback() { + @Override + public void call() { + ((Otiluke) ch).onZapComplete(); + } + }); + Sample.INSTANCE.play(Assets.SND_ZAP); + } + + @Override + public void onComplete(Animation anim) { + if (anim == zap) { + idle(); + } + super.onComplete(anim); + } +} diff --git a/java/com/hmdzl/spspd/sprites/PainterSprite.java b/java/com/hmdzl/spspd/sprites/PainterSprite.java new file mode 100644 index 00000000..0a972b06 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/PainterSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class PainterSprite extends MobSprite { + + public PainterSprite() { + super(); + + texture( Assets.PAINTER ); + + TextureFilm frames = new TextureFilm( texture, 16, 16 ); + + idle = new Animation( 15, true ); + idle.frames(frames, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3); + + run = new Animation( 20, true ); + run.frames( frames, 0 ); + + attack = new Animation( 12, false ); + attack.frames( frames, 0, 2, 3 ); + + die = new Animation( 20, false ); + die.frames( frames, 0 ); + + play( idle ); + } + + +} diff --git a/java/com/hmdzl/spspd/sprites/PatrolUAVSprite.java b/java/com/hmdzl/spspd/sprites/PatrolUAVSprite.java new file mode 100644 index 00000000..3ff12135 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/PatrolUAVSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class PatrolUAVSprite extends MobSprite { + + public PatrolUAVSprite() { + super(); + + texture(Assets.PATROLUAV); + + TextureFilm frames = new TextureFilm(texture, 16, 16); + + idle = new Animation(4, true); + idle.frames(frames, 0, 1, 2, 3, 4); + + run = new Animation(12, true); + run.frames(frames, 0,5,6,7); + + attack = new Animation(12, false); + attack.frames(frames, 0,8,9,8); + + die = new Animation(12, false); + die.frames(frames, 0, 10, 11,11); + + play(idle); + } + + } diff --git a/java/com/hmdzl/spspd/sprites/PinningFistSprite.java b/java/com/hmdzl/spspd/sprites/PinningFistSprite.java new file mode 100644 index 00000000..acaafc1c --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/PinningFistSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.effects.MagicMissile; +import com.watabou.noosa.TextureFilm; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Callback; + +public class PinningFistSprite extends MobSprite { + + public PinningFistSprite() { + super(); + + texture(Assets.PINNING); + + TextureFilm frames = new TextureFilm(texture, 24, 17); + + idle = new Animation(2, true); + idle.frames(frames, 0, 0, 1); + + run = new Animation(3, true); + run.frames(frames, 0, 1); + + attack = new Animation(8, false); + attack.frames(frames, 0, 5, 6); + + die = new Animation(10, false); + die.frames(frames, 0, 2, 3, 4); + + play(idle); + } + + private int posToShoot; + + @Override + public void attack(int cell) { + posToShoot = cell; + super.attack(cell); + } + + @Override + public void onComplete(Animation anim) { + if (anim == attack) { + + Sample.INSTANCE.play(Assets.SND_ZAP); + MagicMissile.force(parent, ch.pos, posToShoot, new Callback() { + @Override + public void call() { + ch.onAttackComplete(); + } + }); + + idle(); + + } else { + super.onComplete(anim); + } + } +} diff --git a/java/com/hmdzl/spspd/sprites/PiranhaSprite.java b/java/com/hmdzl/spspd/sprites/PiranhaSprite.java new file mode 100644 index 00000000..fbe71e95 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/PiranhaSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.scenes.GameScene; +import com.watabou.noosa.TextureFilm; + +public class PiranhaSprite extends MobSprite { + + public PiranhaSprite() { + super(); + + texture(Assets.PIRANHA); + + TextureFilm frames = new TextureFilm(texture, 12, 16); + + idle = new Animation(8, true); + idle.frames(frames, 0, 1, 2, 1); + + run = new Animation(20, true); + run.frames(frames, 0, 1, 2, 1); + + attack = new Animation(20, false); + attack.frames(frames, 3, 4, 5, 6, 7, 8, 9, 10, 11); + + die = new Animation(4, false); + die.frames(frames, 12, 13, 14); + + play(idle); + } + + @Override + public void onComplete(Animation anim) { + super.onComplete(anim); + + if (anim == attack) { + GameScene.ripple(ch.pos); + } + } +} diff --git a/java/com/hmdzl/spspd/sprites/PlagueDoctorSprite.java b/java/com/hmdzl/spspd/sprites/PlagueDoctorSprite.java new file mode 100644 index 00000000..3e2e547f --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/PlagueDoctorSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class PlagueDoctorSprite extends MobSprite { + + public PlagueDoctorSprite() { + super(); + + texture( Assets.PLAGUEDOCTOR ); + + TextureFilm frames = new TextureFilm(texture, 16, 16); + + idle = new Animation( 2, true ); + idle.frames( frames, 0,0,1,1); + + run = new Animation( 10, true ); + run.frames( frames, 1,2,2,3,2,1); + + attack = new Animation( 15, false ); + attack.frames( frames, 4, 5, 6, 7, 8 ); + + die = new Animation( 10, false ); + die.frames( frames, 8, 8, 9, 10 ); + + play( idle ); + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/sprites/PlantKingSprite.java b/java/com/hmdzl/spspd/sprites/PlantKingSprite.java new file mode 100644 index 00000000..da2ff3bb --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/PlantKingSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class PlantKingSprite extends MobSprite { + + public PlantKingSprite() { + super(); + + texture( Assets.PLANT_KING ); + + TextureFilm frames = new TextureFilm( texture, 16, 16 ); + + idle = new Animation( 15, true ); + idle.frames(frames, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3); + + run = new Animation( 20, true ); + run.frames( frames, 0 ); + + attack = new Animation( 12, false ); + attack.frames( frames, 0, 2, 3 ); + + die = new Animation( 20, false ); + die.frames( frames, 0 ); + + play( idle ); + } + + +} diff --git a/java/com/hmdzl/spspd/sprites/PlantSprite.java b/java/com/hmdzl/spspd/sprites/PlantSprite.java new file mode 100644 index 00000000..4639d3d9 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/PlantSprite.java @@ -0,0 +1,109 @@ +/* + * 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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.DungeonTilemap; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.plants.Plant; +import com.watabou.noosa.Game; +import com.watabou.noosa.Image; +import com.watabou.noosa.TextureFilm; + +public class PlantSprite extends Image { + + private static final float DELAY = 0.2f; + + private enum State { + GROWING, NORMAL, WITHERING + } + + private State state = State.NORMAL; + private float time; + + private static TextureFilm frames; + + private int pos = -1; + + public PlantSprite() { + super(Assets.PLANTS); + + if (frames == null) { + frames = new TextureFilm(texture, 16, 16); + } + + origin.set(8, 12); + } + + public PlantSprite(int image) { + this(); + reset(image); + } + + public void reset(Plant plant) { + + revive(); + + reset(plant.image); + alpha(1f); + + pos = plant.pos; + x = (pos % Level.getWidth()) * DungeonTilemap.SIZE; + y = (pos / Level.getWidth()) * DungeonTilemap.SIZE; + + state = State.GROWING; + time = DELAY; + } + + public void reset(int image) { + frame(frames.get(image)); + } + + @Override + public void update() { + super.update(); + + visible = pos == -1 || Dungeon.visible[pos]; + + switch (state) { + case GROWING: + if ((time -= Game.elapsed) <= 0) { + state = State.NORMAL; + scale.set(1); + } else { + scale.set(1 - time / DELAY); + } + break; + case WITHERING: + if ((time -= Game.elapsed) <= 0) { + super.kill(); + } else { + alpha(time / DELAY); + } + break; + default: + } + } + + @Override + public void kill() { + state = State.WITHERING; + time = DELAY; + } +} diff --git a/java/com/hmdzl/spspd/sprites/PoisonGooSprite.java b/java/com/hmdzl/spspd/sprites/PoisonGooSprite.java new file mode 100644 index 00000000..2c647be4 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/PoisonGooSprite.java @@ -0,0 +1,127 @@ +/* + * 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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; +import com.watabou.noosa.particles.Emitter; +import com.watabou.noosa.particles.Emitter.Factory; +import com.watabou.noosa.particles.PixelParticle; +import com.watabou.utils.PointF; +import com.watabou.utils.Random; + +public class PoisonGooSprite extends MobSprite { + + private Animation pump; + private Animation pumpAttack; + + public PoisonGooSprite() { + super(); + + texture(Assets.POISONGOO); + + TextureFilm frames = new TextureFilm(texture, 20, 14); + + idle = new Animation(10, true); + idle.frames(frames, 2, 1, 0, 0, 1); + + run = new Animation(15, true); + run.frames(frames, 3, 2, 1, 2); + + pump = new Animation(20, true); + pump.frames(frames, 4, 3, 2, 1, 0); + + pumpAttack = new Animation(20, false); + pumpAttack.frames(frames, 4, 3, 2, 1, 0, 7); + + attack = new Animation(10, false); + attack.frames(frames, 8, 9, 10); + + die = new Animation(10, false); + die.frames(frames, 5, 6, 7); + + play(idle); + } + + public void pumpUp() { + play(pump); + } + + public void pumpAttack() { + play(pumpAttack); + } + + @Override + public void play(Animation anim, boolean force) { + super.play(anim, force); + } + + @Override + public int blood() { + return 0xFF000000; + } + + public static class GooParticle extends PixelParticle.Shrinking { + + public static final Emitter.Factory FACTORY = new Factory() { + @Override + public void emit(Emitter emitter, int index, float x, float y) { + ((GooParticle) emitter.recycle(GooParticle.class)).reset(x, y); + } + }; + + public GooParticle() { + super(); + + color(0x000000); + lifespan = 0.3f; + + acc.set(0, +50); + } + + public void reset(float x, float y) { + revive(); + + this.x = x; + this.y = y; + + left = lifespan; + + size = 4; + speed.polar(-Random.Float(PointF.PI), Random.Float(32, 48)); + } + + @Override + public void update() { + super.update(); + float p = left / lifespan; + am = p > 0.5f ? (1 - p) * 2f : 1; + } + } + + @Override + public void onComplete(Animation anim) { + super.onComplete(anim); + + if (anim == pumpAttack) { + + idle(); + ch.onAttackComplete(); + } + } +} diff --git a/java/com/hmdzl/spspd/sprites/PrisonWanderSprite.java b/java/com/hmdzl/spspd/sprites/PrisonWanderSprite.java new file mode 100644 index 00000000..08b6d716 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/PrisonWanderSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class PrisonWanderSprite extends MobSprite { + + public PrisonWanderSprite() { + super(); + + texture(Assets.PRISONWANDER); + + TextureFilm frames = new TextureFilm( texture, 12, 16 ); + + idle = new Animation( 2, true ); + idle.frames( frames, 0, 0, 0, 1, 0, 0, 1, 1 ); + + run = new Animation( 15, true ); + run.frames( frames, 2, 3, 4, 5, 6, 7 ); + + attack = new Animation( 12, false ); + attack.frames( frames, 8, 9, 10 ); + + die = new Animation( 8, false ); + die.frames( frames, 11, 12, 13, 14 ); + + play( idle ); + } + +} diff --git a/java/com/hmdzl/spspd/sprites/RENSprite.java b/java/com/hmdzl/spspd/sprites/RENSprite.java new file mode 100644 index 00000000..83a83561 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/RENSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class RENSprite extends MobSprite { + + public RENSprite() { + super(); + + texture( Assets.REN ); + + TextureFilm frames = new TextureFilm( texture, 16, 16 ); + + idle = new Animation( 15, true ); + idle.frames(frames, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3); + + run = new Animation( 20, true ); + run.frames( frames, 0 ); + + attack = new Animation( 12, false ); + attack.frames( frames, 0, 2, 3 ); + + die = new Animation( 20, false ); + die.frames( frames, 0 ); + + play( idle ); + } + + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/sprites/RainSprite.java b/java/com/hmdzl/spspd/sprites/RainSprite.java new file mode 100644 index 00000000..d4a1d7c2 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/RainSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class RainSprite extends MobSprite { + + public RainSprite() { + super(); + + texture( Assets.RAIN ); + + TextureFilm frames = new TextureFilm( texture, 16, 16 ); + + idle = new Animation( 3, true ); + idle.frames(frames, 0, 0, 1, 1, 2, 2, 3, 3, 3, 3, 3, 3); + + run = new Animation( 3, true ); + run.frames( frames, 0, 0, 1, 1, 2, 2, 3, 3, 3, 3, 3, 3 ); + + attack = new Animation( 12, false ); + attack.frames( frames, 0, 2, 3 ); + + die = new Animation( 20, false ); + die.frames( frames, 0 ); + + play( idle ); + } + + +} diff --git a/java/com/hmdzl/spspd/sprites/RatBossSprite.java b/java/com/hmdzl/spspd/sprites/RatBossSprite.java new file mode 100644 index 00000000..3247e9ad --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/RatBossSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class RatBossSprite extends MobSprite { + + public RatBossSprite() { + super(); + + texture(Assets.RAT); + + TextureFilm frames = new TextureFilm(texture, 16, 15); + + idle = new Animation(2, true); + idle.frames(frames, 80, 80, 80, 81); + + run = new Animation(10, true); + run.frames(frames, 86, 87, 88, 89, 90); + + attack = new Animation(15, false); + attack.frames(frames, 82, 83,84, 85, 80); + + die = new Animation(10, false); + die.frames(frames, 91, 92, 93, 94); + + play(idle); + } +} diff --git a/java/com/hmdzl/spspd/sprites/RatKingSprite.java b/java/com/hmdzl/spspd/sprites/RatKingSprite.java new file mode 100644 index 00000000..df45c7d3 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/RatKingSprite.java @@ -0,0 +1,57 @@ +/* + * 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 + */ +package com.hmdzl.spspd.sprites; + +import java.util.Calendar; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class RatKingSprite extends MobSprite { + + public boolean festive; + + public RatKingSprite() { + super(); + + final Calendar calendar = Calendar.getInstance(); + // once a year the rat king feels a bit festive! + festive = (calendar.get(Calendar.MONTH) == 11 && calendar + .get(Calendar.WEEK_OF_MONTH) > 2); + + final int c = festive ? 8 : 0; + + texture(Assets.RATKING); + + TextureFilm frames = new TextureFilm(texture, 16, 17); + + idle = new Animation(2, true); + idle.frames(frames, c + 0, c + 0, c + 0, c + 1); + + run = new Animation(10, true); + run.frames(frames, c + 2, c + 3, c + 4, c + 5, c + 6); + + attack = new Animation(15, false); + attack.frames(frames, c + 0); + + die = new Animation(10, false); + die.frames(frames, c + 0); + + play(idle); + } +} diff --git a/java/com/hmdzl/spspd/sprites/RatSprite.java b/java/com/hmdzl/spspd/sprites/RatSprite.java new file mode 100644 index 00000000..dca8f011 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/RatSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class RatSprite extends MobSprite { + + public RatSprite() { + super(); + + texture(Assets.RAT); + + TextureFilm frames = new TextureFilm(texture, 16, 15); + + idle = new Animation(2, true); + idle.frames(frames, 0, 0, 0, 1); + + run = new Animation(10, true); + run.frames(frames, 6, 7, 8, 9, 10); + + attack = new Animation(15, false); + attack.frames(frames, 2, 3, 4, 5, 0); + + die = new Animation(10, false); + die.frames(frames, 11, 12, 13, 14); + + play(idle); + } +} diff --git a/java/com/hmdzl/spspd/sprites/RavenwolfSprite.java b/java/com/hmdzl/spspd/sprites/RavenwolfSprite.java new file mode 100644 index 00000000..7d7b8ac4 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/RavenwolfSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class RavenwolfSprite extends MobSprite { + + public RavenwolfSprite() { + super(); + + texture( Assets.RAVEBWOLF ); + + TextureFilm frames = new TextureFilm( texture, 16, 16 ); + + idle = new Animation( 3, true ); + idle.frames(frames, 0, 0, 1, 1, 2, 2, 3, 3, 3, 3, 3, 3); + + run = new Animation( 3, true ); + run.frames( frames, 0, 0, 1, 1, 2, 2, 3, 3, 3, 3, 3, 3 ); + + attack = new Animation( 12, false ); + attack.frames( frames, 0, 2, 3 ); + + die = new Animation( 20, false ); + die.frames( frames, 0 ); + + play( idle ); + } + + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/sprites/RedDragonSprite.java b/java/com/hmdzl/spspd/sprites/RedDragonSprite.java new file mode 100644 index 00000000..562e954a --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/RedDragonSprite.java @@ -0,0 +1,74 @@ +/* + * 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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.actors.mobs.pets.RedDragon; +import com.hmdzl.spspd.effects.MagicMissile; +import com.watabou.noosa.TextureFilm; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Callback; + +public class RedDragonSprite extends MobSprite { + + //Frames 1-4 are idle, 5-8 are moving, 9-12 are attack and the last are for death + + public RedDragonSprite() { + super(); + + texture(Assets.PETDRAGON); + + TextureFilm frames = new TextureFilm(texture, 16, 16); + + idle = new Animation(2, true); + idle.frames(frames, 0, 1, 2, 3); + + run = new Animation(8, true); + run.frames(frames, 4, 5, 6, 7); + + attack = new Animation(8, false); + attack.frames(frames, 8, 9, 10, 11); + + zap = attack.clone(); + + die = new Animation(8, false); + die.frames(frames, 12, 13, 14, 15); + + play(idle); + } + + @Override + public void zap(int cell) { + + turnTo(ch.pos, cell); + play(zap); + + MagicMissile.fire(parent, ch.pos, cell, new Callback() { + @Override + public void call() { + ((RedDragon) ch).onZapComplete(); + } + }); + Sample.INSTANCE.play(Assets.SND_ZAP); + } + + @Override + public int blood() { + return 0xFFcdcdb7; + } +} diff --git a/java/com/hmdzl/spspd/sprites/RedWraithSprite.java b/java/com/hmdzl/spspd/sprites/RedWraithSprite.java new file mode 100644 index 00000000..9bd5935c --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/RedWraithSprite.java @@ -0,0 +1,81 @@ +/* + * 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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.items.weapon.missiles.Wave; +import com.hmdzl.spspd.levels.Level; +import com.watabou.noosa.TextureFilm; +import com.watabou.utils.Callback; + +public class RedWraithSprite extends MobSprite { + + private Animation cast; + + public RedWraithSprite() { + super(); + + texture(Assets.REDWRAITH); + + TextureFilm frames = new TextureFilm(texture, 14, 15); + + idle = new Animation(5, true); + idle.frames(frames, 0, 1); + + run = new Animation(10, true); + run.frames(frames, 0, 1); + + attack = new Animation(10, false); + attack.frames(frames, 0, 2, 3); + + cast = attack.clone(); + + die = new Animation(8, false); + die.frames(frames, 0, 4, 5, 6, 7); + + play(idle); + } + + @Override + public int blood() { + return 0x88000000; + } + + @Override + public void attack(int cell) { + if (!Level.adjacent(cell, ch.pos)) { + //Char enemy = Actor.findChar(cell); + ((MissileSprite) parent.recycle(MissileSprite.class)).reset(ch.pos, + cell, new Wave(), new Callback() { + @Override + public void call() { + ch.onAttackComplete(); + } + }); + + + play(cast); + turnTo(ch.pos, cell); + + } else { + + super.attack(cell); + + } + } +} diff --git a/java/com/hmdzl/spspd/sprites/RottingFistSprite.java b/java/com/hmdzl/spspd/sprites/RottingFistSprite.java new file mode 100644 index 00000000..16338117 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/RottingFistSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.Camera; +import com.watabou.noosa.TextureFilm; + +public class RottingFistSprite extends MobSprite { + + private static final float FALL_SPEED = 64; + + public RottingFistSprite() { + super(); + + texture(Assets.ROTTING); + + TextureFilm frames = new TextureFilm(texture, 24, 17); + + idle = new Animation(2, true); + idle.frames(frames, 0, 0, 1); + + run = new Animation(3, true); + run.frames(frames, 0, 1); + + attack = new Animation(2, false); + attack.frames(frames, 0); + + die = new Animation(10, false); + die.frames(frames, 0, 2, 3, 4); + + play(idle); + } + + @Override + public void attack(int cell) { + super.attack(cell); + + speed.set(0, -FALL_SPEED); + acc.set(0, FALL_SPEED * 4); + } + + @Override + public void onComplete(Animation anim) { + super.onComplete(anim); + if (anim == attack) { + speed.set(0); + acc.set(0); + place(ch.pos); + + Camera.main.shake(4, 0.2f); + } + } +} diff --git a/java/com/hmdzl/spspd/sprites/RustybladeSprite.java b/java/com/hmdzl/spspd/sprites/RustybladeSprite.java new file mode 100644 index 00000000..bd5def93 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/RustybladeSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class RustybladeSprite extends MobSprite { + + public RustybladeSprite() { + super(); + + texture( Assets.RUSTYBLADE ); + + TextureFilm frames = new TextureFilm( texture, 16, 16 ); + + idle = new Animation( 15, true ); + idle.frames(frames, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3); + + run = new Animation( 20, true ); + run.frames( frames, 0 ); + + attack = new Animation( 12, false ); + attack.frames( frames, 0, 2, 3 ); + + die = new Animation( 20, false ); + die.frames( frames, 0 ); + + play( idle ); + } + + +} diff --git a/java/com/hmdzl/spspd/sprites/SFBSprite.java b/java/com/hmdzl/spspd/sprites/SFBSprite.java new file mode 100644 index 00000000..57d93772 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/SFBSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class SFBSprite extends MobSprite { + + public SFBSprite() { + super(); + + texture( Assets.SFB ); + + TextureFilm frames = new TextureFilm( texture, 16, 16 ); + + idle = new Animation( 3, true ); + idle.frames(frames, 0, 0, 1, 1, 2, 2, 3, 3, 3, 3, 3, 3); + + run = new Animation( 20, true ); + run.frames( frames, 0 ); + + attack = new Animation( 12, false ); + attack.frames( frames, 0, 2, 3 ); + + die = new Animation( 20, false ); + die.frames( frames, 0 ); + + play( idle ); + } + + +} diff --git a/java/com/hmdzl/spspd/sprites/SP931Sprite.java b/java/com/hmdzl/spspd/sprites/SP931Sprite.java new file mode 100644 index 00000000..d99faad4 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/SP931Sprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class SP931Sprite extends MobSprite { + + public SP931Sprite() { + super(); + + texture( Assets.SP931 ); + + TextureFilm frames = new TextureFilm( texture, 16, 16 ); + + idle = new Animation( 3, true ); + idle.frames(frames, 0, 0, 1, 1, 2, 2, 3, 3, 3, 3, 3, 3); + + run = new Animation( 3, true ); + run.frames( frames, 0, 0, 1, 1, 2, 2, 3, 3, 3, 3, 3, 3 ); + + attack = new Animation( 12, false ); + attack.frames( frames, 0, 2, 3 ); + + die = new Animation( 20, false ); + die.frames( frames, 0 ); + + play( idle ); + } + + +} diff --git a/java/com/hmdzl/spspd/sprites/SadSaltanSprite.java b/java/com/hmdzl/spspd/sprites/SadSaltanSprite.java new file mode 100644 index 00000000..578a220e --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/SadSaltanSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class SadSaltanSprite extends CharSprite { + + + public SadSaltanSprite(){ + super(); + + texture(Assets.SADSALTAN); + + TextureFilm film = new TextureFilm(texture, 12, 15); + + idle = new Animation(1, true); + idle.frames(film, 0, 0, 0, 1, 0, 0, 1, 1); + + run = new Animation(20, true); + run.frames(film, 2, 3, 4, 5, 6, 7); + + die = new Animation(20, false); + die.frames(film, 8, 9, 10, 11, 12, 11); + + attack = new Animation(15, false); + attack.frames(film, 13, 14, 15, 0); + + play(idle); + + } +} diff --git a/java/com/hmdzl/spspd/sprites/SaidbySunSprite.java b/java/com/hmdzl/spspd/sprites/SaidbySunSprite.java new file mode 100644 index 00000000..63538a12 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/SaidbySunSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class SaidbySunSprite extends MobSprite { + + public SaidbySunSprite() { + super(); + + texture( Assets.SAID_BY_SUN); + + TextureFilm frames = new TextureFilm( texture, 16, 16 ); + + idle = new Animation( 3, true ); + idle.frames(frames, 0, 0, 1, 1, 2, 2, 3, 3, 3, 3, 3, 3); + + run = new Animation( 3, true ); + run.frames( frames, 0, 0, 1, 1, 2, 2, 3, 3, 3, 3, 3, 3 ); + + attack = new Animation( 12, false ); + attack.frames( frames, 0, 2, 3 ); + + die = new Animation( 20, false ); + die.frames( frames, 0 ); + + play( idle ); + } + + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/sprites/SandmobSprite.java b/java/com/hmdzl/spspd/sprites/SandmobSprite.java new file mode 100644 index 00000000..d0cc5493 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/SandmobSprite.java @@ -0,0 +1,88 @@ +/* + * Unleashed Pixel Dungeon + * Copyright (C) 2015 David Mitchell + * + * 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 + */ +package com.hmdzl.spspd.sprites; + +import com.watabou.noosa.TextureFilm; +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.scenes.GameScene; + +public class SandmobSprite extends MobSprite { + + // private int cellToAttack; + + public SandmobSprite() { + super(); + + texture( Assets.SANDMOB ); + + TextureFilm frames = new TextureFilm( texture, 16, 17 ); + + idle = new Animation( 8, true ); + idle.frames( frames, 0, 1, 2, 1 ); + + run = new Animation( 8, true ); + run.frames( frames, 0, 1, 2, 1 ); + + attack = new Animation( 14, false ); + attack.frames( frames, 3, 4, 5, 6, 5, 4, 3 ); + + die = new Animation( 6, false ); + die.frames( frames, 7, 8, 9 ); + + play( idle ); + } + + /* + @Override + public void attack( int cell ) { + if (!Level.adjacent(cell, ch.pos)) { + + cellToAttack = cell; + turnTo( ch.pos , cell ); + play( zap ); + + } else { + + super.attack( cell ); + + } + } + */ + + @Override + public void onComplete( Animation anim ) { + super.onComplete( anim ); + + /* + if (anim == zap) { + idle(); + + ((MissileSprite)parent.recycle( MissileSprite.class )). + reset(ch.pos, cellToAttack, new Dart(), new Callback() { + @Override + public void call() { + ch.onAttackComplete(); + } + }); + } else + */ + if (anim == attack) { + GameScene.ripple( ch.pos ); + } + } +} diff --git a/java/com/hmdzl/spspd/sprites/ScarecrowSprite.java b/java/com/hmdzl/spspd/sprites/ScarecrowSprite.java new file mode 100644 index 00000000..c3b70ad5 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/ScarecrowSprite.java @@ -0,0 +1,77 @@ +/* + * 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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.items.weapon.missiles.PoisonDart; +import com.hmdzl.spspd.levels.Level; +import com.watabou.noosa.TextureFilm; +import com.watabou.utils.Callback; + +public class ScarecrowSprite extends MobSprite { + +private Animation cast; + + public ScarecrowSprite() { + super(); + + texture( Assets.SCARECROW ); + + TextureFilm frames = new TextureFilm( texture, 16, 16 ); + + idle = new Animation( 3, true ); + idle.frames(frames, 0, 0, 1, 1, 2, 2, 3, 3, 3, 3, 3, 3); + + run = new Animation( 3, true ); + run.frames( frames, 0, 0, 1, 1, 2, 2, 3, 3, 3, 3, 3, 3 ); + + attack = new Animation( 12, false ); + attack.frames( frames, 0, 2, 3 ); + + cast = attack.clone(); + + die = new Animation( 20, false ); + die.frames( frames, 0 ); + + play( idle ); + } + + + @Override + public void attack(int cell) { + if (!Level.adjacent(cell, ch.pos)) { + + ((MissileSprite) parent.recycle(MissileSprite.class)).reset(ch.pos, + cell, new PoisonDart(), new Callback() { + @Override + public void call() { + ch.onAttackComplete(); + } + }); + + play(cast); + turnTo(ch.pos, cell); + + } else { + + super.attack(cell); + + } + } + +} diff --git a/java/com/hmdzl/spspd/sprites/ScorpioSprite.java b/java/com/hmdzl/spspd/sprites/ScorpioSprite.java new file mode 100644 index 00000000..3b17dec1 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/ScorpioSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.items.weapon.missiles.EscapeKnive; +import com.hmdzl.spspd.levels.Level; +import com.watabou.noosa.TextureFilm; +import com.watabou.utils.Callback; + +public class ScorpioSprite extends MobSprite { + + private int cellToAttack; + + public ScorpioSprite() { + super(); + + texture(Assets.SCORPIO); + + TextureFilm frames = new TextureFilm(texture, 18, 17); + + idle = new Animation(12, true); + idle.frames(frames, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 1, 2, 1, 2); + + run = new Animation(8, true); + run.frames(frames, 5, 5, 6, 6); + + attack = new Animation(15, false); + attack.frames(frames, 0, 3, 4); + + zap = attack.clone(); + + die = new Animation(12, false); + die.frames(frames, 0, 7, 8, 9, 10); + + play(idle); + } + + @Override + public int blood() { + return 0xFF44FF22; + } + + @Override + public void attack(int cell) { + if (!Level.adjacent(cell, ch.pos)) { + + cellToAttack = cell; + turnTo(ch.pos, cell); + play(zap); + + } else { + + super.attack(cell); + + } + } + + @Override + public void onComplete(Animation anim) { + if (anim == zap) { + idle(); + + ((MissileSprite) parent.recycle(MissileSprite.class)).reset(ch.pos, + cellToAttack, new EscapeKnive(), new Callback() { + @Override + public void call() { + ch.onAttackComplete(); + } + }); + } else { + super.onComplete(anim); + } + } +} diff --git a/java/com/hmdzl/spspd/sprites/ScorpionSprite.java b/java/com/hmdzl/spspd/sprites/ScorpionSprite.java new file mode 100644 index 00000000..71d5a3f3 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/ScorpionSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class ScorpionSprite extends MobSprite { + + + public ScorpionSprite() { + super(); + + texture(Assets.SCORPIO); + + TextureFilm frames = new TextureFilm(texture, 18, 17); + + idle = new Animation(12, true); + idle.frames(frames, 28, 28, 28, 28, 28, 28, 28, 28, 29, 30, 29, 30, 29, 30); + + run = new Animation(8, true); + run.frames(frames, 33, 33, 34, 34); + + attack = new Animation(15, false); + attack.frames(frames, 28, 31, 32); + + die = new Animation(12, false); + die.frames(frames, 28, 35, 36, 37, 38); + + play(idle); + } + + @Override + public int blood() { + return 0xFF44FF22; + } + +} diff --git a/java/com/hmdzl/spspd/sprites/SeekingBombSprite.java b/java/com/hmdzl/spspd/sprites/SeekingBombSprite.java new file mode 100644 index 00000000..5cbbe955 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/SeekingBombSprite.java @@ -0,0 +1,51 @@ +/* + * 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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class SeekingBombSprite extends MobSprite { + + public SeekingBombSprite() { + super(); + + texture(Assets.SEEKINGBOMB); + + TextureFilm frames = new TextureFilm(texture, 16, 16); + + idle = new Animation(5, true); + idle.frames(frames, 0, 0, 0, 0); + + run = new Animation(15, true); + run.frames(frames, 1, 2, 3, 4); + + attack = new Animation(12, false); + attack.frames(frames, 1, 2, 3); + + die = new Animation(12, false); + die.frames(frames, 4, 4, 4, 4); + + play(idle); + } + + @Override + public int blood() { + return 0xFFFFEA80; + } +} diff --git a/java/com/hmdzl/spspd/sprites/SeekingClusterBombSprite.java b/java/com/hmdzl/spspd/sprites/SeekingClusterBombSprite.java new file mode 100644 index 00000000..3e25c639 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/SeekingClusterBombSprite.java @@ -0,0 +1,51 @@ +/* + * 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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class SeekingClusterBombSprite extends MobSprite { + + public SeekingClusterBombSprite() { + super(); + + texture(Assets.SEEKINGBOMB); + + TextureFilm frames = new TextureFilm(texture, 16, 16); + + idle = new Animation(5, true); + idle.frames(frames, 16, 16, 16, 16); + + run = new Animation(15, true); + run.frames(frames, 17, 18, 19, 20); + + attack = new Animation(12, false); + attack.frames(frames, 17, 18, 19); + + die = new Animation(12, false); + die.frames(frames, 20, 20, 20, 20); + + play(idle); + } + + @Override + public int blood() { + return 0xFFFFEA80; + } +} diff --git a/java/com/hmdzl/spspd/sprites/SeniorSprite.java b/java/com/hmdzl/spspd/sprites/SeniorSprite.java new file mode 100644 index 00000000..8dfd1629 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/SeniorSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; +import com.watabou.utils.Random; + +public class SeniorSprite extends MobSprite { + + private Animation kick; + + public SeniorSprite() { + super(); + + texture(Assets.MONK); + + TextureFilm frames = new TextureFilm(texture, 15, 14); + + idle = new Animation(6, true); + idle.frames(frames, 18, 17, 18, 19); + + run = new Animation(15, true); + run.frames(frames, 28, 29, 30, 31, 32, 33); + + attack = new Animation(12, false); + attack.frames(frames, 20, 21, 20, 21); + + kick = new Animation(10, false); + kick.frames(frames, 22, 23, 22); + + die = new Animation(15, false); + die.frames(frames, 18, 24, 25, 25, 26, 27); + + play(idle); + } + + @Override + public void attack(int cell) { + super.attack(cell); + if (Random.Float() < 0.3f) { + play(kick); + } + } + + @Override + public void onComplete(Animation anim) { + super.onComplete(anim == kick ? attack : anim); + } +} diff --git a/java/com/hmdzl/spspd/sprites/SentinelSprite.java b/java/com/hmdzl/spspd/sprites/SentinelSprite.java new file mode 100644 index 00000000..4b43bd15 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/SentinelSprite.java @@ -0,0 +1,51 @@ +/* + * 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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class SentinelSprite extends MobSprite { + + public SentinelSprite() { + super(); + + texture(Assets.SENTINEL); + + TextureFilm frames = new TextureFilm(texture, 12, 15); + + idle = new Animation(2, true); + idle.frames(frames, 0, 0, 0, 0, 0, 1, 1); + + run = new Animation(15, true); + run.frames(frames, 2, 3, 4, 5, 6, 7); + + attack = new Animation(12, false); + attack.frames(frames, 8, 9, 10); + + die = new Animation(5, false); + die.frames(frames, 11, 12, 13, 14, 15, 15); + + play(idle); + } + + @Override + public int blood() { + return 0xFFcdcdb7; + } +} diff --git a/java/com/hmdzl/spspd/sprites/SewerHeartSprite.java b/java/com/hmdzl/spspd/sprites/SewerHeartSprite.java new file mode 100644 index 00000000..35c5c3dc --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/SewerHeartSprite.java @@ -0,0 +1,140 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2015 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.DungeonTilemap; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.mobs.SewerHeart; +import com.hmdzl.spspd.effects.Beam; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.effects.particles.EnergyParticle; +import com.watabou.noosa.MovieClip; +import com.watabou.noosa.TextureFilm; +import com.watabou.noosa.particles.Emitter; + +public class SewerHeartSprite extends MobSprite { + + private int zapPos; + + private Emitter cloud; + private Animation charging; + private Emitter chargeParticles; + + public SewerHeartSprite(){ + super(); + + texture( Assets.SEWER_HEART ); + + TextureFilm frames = new TextureFilm( texture, 16, 16 ); + + idle = new MovieClip.Animation( 1, true ); + idle.frames( frames, 0); + + run = new MovieClip.Animation( 1, true ); + run.frames( frames, 0 ); + + attack = new MovieClip.Animation( 10, false ); + attack.frames( frames, 0,1 ); + zap = attack.clone(); + + chargeParticles = centerEmitter(); + chargeParticles.autoKill = false; + chargeParticles.pour( EnergyParticle.FACTORY, 0.05f); + chargeParticles.on = false; + + die = new MovieClip.Animation( 8, false ); + die.frames( frames, 1, 2, 3, 4, 5, 6, 7, 7, 7 ); + + play( idle ); + } + + @Override + public void link( Char ch ) { + super.link( ch ); + if (((SewerHeart)ch).beamCharged) play(charging); + if (cloud == null) { + cloud = emitter(); + cloud.pour( Speck.factory(Speck.TOXIC), 0.7f ); + } + } + + @Override + public void turnTo(int from, int to) { + //do nothing + } + + @Override + public void update() { + + super.update(); + chargeParticles.pos(center()); + chargeParticles.visible = visible; + if (cloud != null) { + cloud.visible = visible; + } + } + + @Override + public void die() { + super.die(); + + if (cloud != null) { + cloud.on = false; + } + } + + public void charge( int pos ){ + turnTo(ch.pos, pos); + play(charging); + } + + @Override + public void play(Animation anim) { + chargeParticles.on = anim == charging; + super.play(anim); + } + + @Override + public void zap( int pos ) { + zapPos = pos; + super.zap( pos ); + } + + @Override + public void onComplete( Animation anim ) { + super.onComplete( anim ); + + if (anim == zap) { + idle(); + if (Actor.findChar(zapPos) != null){ + parent.add(new Beam.LightRay(center(), Actor.findChar(zapPos).sprite.center())); + } else { + parent.add(new Beam.LightRay(center(), DungeonTilemap.raisedTileCenterToWorld(zapPos))); + } + ((SewerHeart)ch).deathGaze(); + ch.next(); + } else if (anim == die){ + chargeParticles.killAndErase(); + } + } +} diff --git a/java/com/hmdzl/spspd/sprites/SewerLasherSprite.java b/java/com/hmdzl/spspd/sprites/SewerLasherSprite.java new file mode 100644 index 00000000..86710270 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/SewerLasherSprite.java @@ -0,0 +1,49 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2015 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class SewerLasherSprite extends MobSprite { + + public SewerLasherSprite() { + super(); + + texture( Assets.SEWER_LASHER ); + + TextureFilm frames = new TextureFilm( texture, 12, 16 ); + + idle = new Animation( 0, true ); + idle.frames( frames, 0); + + run = new Animation( 0, true ); + run.frames( frames, 0); + + attack = new Animation( 24, false ); + attack.frames( frames, 0, 1, 2, 2, 1 ); + + die = new Animation( 12, false ); + die.frames( frames, 3, 4, 5, 6 ); + + play( idle ); + } +} diff --git a/java/com/hmdzl/spspd/sprites/ShadowDragonSprite.java b/java/com/hmdzl/spspd/sprites/ShadowDragonSprite.java new file mode 100644 index 00000000..5392c6a3 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/ShadowDragonSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.actors.mobs.pets.ShadowDragon; +import com.hmdzl.spspd.effects.MagicMissile; +import com.watabou.noosa.TextureFilm; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Callback; + +public class ShadowDragonSprite extends MobSprite { + + //Frames 1-4 are idle, 5-8 are moving, 9-12 are attack and the last are for death RBVG + + private int[] points = new int[2]; + + public ShadowDragonSprite() { + super(); + + texture(Assets.PETDRAGON); + + TextureFilm frames = new TextureFilm(texture, 16, 16); + + idle = new Animation(2, true); + idle.frames(frames, 64, 65, 66, 67); + + run = new Animation(8, true); + run.frames(frames, 68, 69, 70, 71); + + attack = new Animation(8, false); + attack.frames(frames, 72, 73, 74, 75); + + zap = attack.clone(); + + die = new Animation(8, false); + die.frames(frames, 76, 77, 78, 79); + + play(idle); + } + + @Override + public void zap(int cell) { + + turnTo(ch.pos, cell); + play(zap); + + MagicMissile.shadow(parent, ch.pos, cell, new Callback() { + @Override + public void call() { + ((ShadowDragon) ch).onZapComplete(); + } + }); + Sample.INSTANCE.play(Assets.SND_ZAP); + } + + @Override + public int blood() { + return 0xFFcdcdb7; + } +} diff --git a/java/com/hmdzl/spspd/sprites/ShadowRatSprite.java b/java/com/hmdzl/spspd/sprites/ShadowRatSprite.java new file mode 100644 index 00000000..c2f53125 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/ShadowRatSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class ShadowRatSprite extends MobSprite { + + public ShadowRatSprite() { + super(); + + texture(Assets.RAT); + + TextureFilm frames = new TextureFilm(texture, 16, 15); + + idle = new Animation(2, true); + idle.frames(frames, 64, 64, 64, 65); + + run = new Animation(10, true); + run.frames(frames, 70, 71, 72, 73, 74); + + attack = new Animation(15, false); + attack.frames(frames, 66, 67, 68, 64); + + die = new Animation(10, false); + die.frames(frames, 75, 76, 77, 78); + + play(idle); + } +} diff --git a/java/com/hmdzl/spspd/sprites/ShadowYogSprite.java b/java/com/hmdzl/spspd/sprites/ShadowYogSprite.java new file mode 100644 index 00000000..91dccbb7 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/ShadowYogSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.effects.Splash; +import com.watabou.noosa.TextureFilm; + +public class ShadowYogSprite extends MobSprite { + + + public ShadowYogSprite() { + super(); + + texture(Assets.SHADOWYOG); + + TextureFilm frames = new TextureFilm(texture, 20, 19); + + idle = new Animation(10, true); + idle.frames(frames, 0, 1, 2, 2, 1, 0, 3, 4, 4, 3, 0, 5, 6, 6, 5); + + run = new Animation(12, true); + run.frames(frames, 0); + + attack = new Animation(12, false); + attack.frames(frames, 0); + + zap = attack.clone(); + + die = new Animation(10, false); + die.frames(frames, 0, 7, 8, 9); + + play(idle); + } + + + @Override + public void die() { + super.die(); + + Splash.at(center(), blood(), 12); + } +} diff --git a/java/com/hmdzl/spspd/sprites/ShamanSprite.java b/java/com/hmdzl/spspd/sprites/ShamanSprite.java new file mode 100644 index 00000000..860fe4b9 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/ShamanSprite.java @@ -0,0 +1,61 @@ +/* + * 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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.actors.mobs.GnollShaman; +import com.hmdzl.spspd.effects.Lightning; +import com.watabou.noosa.TextureFilm; + +public class ShamanSprite extends MobSprite { + + private int[] points = new int[2]; + + public ShamanSprite() { + super(); + + texture(Assets.SHAMAN); + + TextureFilm frames = new TextureFilm(texture, 12, 15); + + idle = new Animation(2, true); + idle.frames(frames, 0, 0, 0, 1, 0, 0, 1, 1); + + run = new Animation(12, true); + run.frames(frames, 4, 5, 6, 7); + + attack = new Animation(12, false); + attack.frames(frames, 2, 3, 0); + + zap = attack.clone(); + + die = new Animation(12, false); + die.frames(frames, 8, 9, 10); + + play(idle); + } + + @Override + public void zap(int pos) { + + parent.add( new Lightning( ch.pos, pos, (GnollShaman) ch)); + + turnTo(ch.pos, pos); + play(zap); + } +} diff --git a/java/com/hmdzl/spspd/sprites/SheepSprite.java b/java/com/hmdzl/spspd/sprites/SheepSprite.java new file mode 100644 index 00000000..1c04d05c --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/SheepSprite.java @@ -0,0 +1,45 @@ +/* + * 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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; +import com.watabou.utils.Random; + +public class SheepSprite extends MobSprite { + + public SheepSprite() { + super(); + + texture(Assets.SHEEP); + + TextureFilm frames = new TextureFilm(texture, 16, 15); + + idle = new Animation(8, true); + idle.frames(frames, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 0); + + run = idle.clone(); + attack = idle.clone(); + + die = new Animation(20, false); + die.frames(frames, 0); + + play(idle); + curFrame = Random.Int(curAnim.frames.length); + } +} diff --git a/java/com/hmdzl/spspd/sprites/ShellSprite.java b/java/com/hmdzl/spspd/sprites/ShellSprite.java new file mode 100644 index 00000000..a84eac30 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/ShellSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.actors.mobs.Shell; +import com.hmdzl.spspd.effects.Lightning; +import com.watabou.noosa.TextureFilm; + +public class ShellSprite extends MobSprite { + + private int[] points = new int[2]; + + public ShellSprite() { + super(); + + texture(Assets.SHELL); + TextureFilm frames = new TextureFilm(texture, 16, 16); + + idle = new Animation(10, true); + idle.frames(frames, 0, 0, 0, 0, 0, 0, 0, 0, 0); + + run = idle.clone(); + die = idle.clone(); + attack = idle.clone(); + + zap = attack.clone(); + + idle(); + } + + @Override + public void zap(int pos) { + + parent.add( new Lightning( ch.pos, pos,(Shell) ch)); + + turnTo(ch.pos, pos); + play(zap); + } + +} diff --git a/java/com/hmdzl/spspd/sprites/ShieldedSprite.java b/java/com/hmdzl/spspd/sprites/ShieldedSprite.java new file mode 100644 index 00000000..2f50f3f1 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/ShieldedSprite.java @@ -0,0 +1,74 @@ +/* + * 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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.items.weapon.missiles.EscapeKnive; +import com.hmdzl.spspd.levels.Level; +import com.watabou.noosa.TextureFilm; +import com.watabou.utils.Callback; + +public class ShieldedSprite extends MobSprite { + + private Animation cast; + + public ShieldedSprite() { + super(); + + texture(Assets.BRUTE); + + TextureFilm frames = new TextureFilm(texture, 12, 16); + + idle = new Animation(2, true); + idle.frames(frames, 21, 21, 21, 22, 21, 21, 22, 22); + + run = new Animation(12, true); + run.frames(frames, 25, 26, 27, 28); + + attack = new Animation(12, false); + attack.frames(frames, 23, 24); + + cast = attack.clone(); + + die = new Animation(12, false); + die.frames(frames, 29, 30, 31); + + play(idle); + } + @Override + public void attack(int cell) { + if (!Level.adjacent(cell, ch.pos)) { + + ((MissileSprite) parent.recycle(MissileSprite.class)).reset(ch.pos, + cell, new EscapeKnive(), new Callback() { + @Override + public void call() { + ch.onAttackComplete(); + } + }); + + play(cast); + turnTo(ch.pos, cell); + + } else { + + super.attack(cell); + + } + } +} diff --git a/java/com/hmdzl/spspd/sprites/ShopkeeperSprite.java b/java/com/hmdzl/spspd/sprites/ShopkeeperSprite.java new file mode 100644 index 00000000..db2a663e --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/ShopkeeperSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; +import com.watabou.noosa.particles.PixelParticle; + +public class ShopkeeperSprite extends MobSprite { + + private PixelParticle coin; + + public ShopkeeperSprite() { + super(); + + texture(Assets.KEEPER); + TextureFilm film = new TextureFilm(texture, 14, 14); + + idle = new Animation(10, true); + idle.frames(film, 1, 1, 1, 1, 1, 0, 0, 0, 0); + + run = idle.clone(); + die = idle.clone(); + attack = idle.clone(); + + idle(); + } + + @Override + public void onComplete(Animation anim) { + super.onComplete(anim); + + if (visible && anim == idle) { + if (coin == null) { + coin = new PixelParticle(); + parent.add(coin); + } + coin.reset(x + (flipHorizontal ? 0 : 13), y + 7, 0xFFFF00, 1, 0.5f); + coin.speed.y = -40; + coin.acc.y = +160; + } + } +} diff --git a/java/com/hmdzl/spspd/sprites/ShowerSprite.java b/java/com/hmdzl/spspd/sprites/ShowerSprite.java new file mode 100644 index 00000000..bedbc74d --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/ShowerSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class ShowerSprite extends MobSprite { + + public ShowerSprite() { + super(); + + texture( Assets.SHOWER ); + + TextureFilm frames = new TextureFilm( texture, 16, 16 ); + + idle = new Animation( 3, true ); + idle.frames(frames, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1); + + run = new Animation( 3, true ); + run.frames( frames, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1 ); + + attack = new Animation( 12, false ); + attack.frames( frames, 0, 1, 1 ); + + die = new Animation( 20, false ); + die.frames( frames, 0 ); + + play( idle ); + } + + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/sprites/SkeletonHand1Sprite.java b/java/com/hmdzl/spspd/sprites/SkeletonHand1Sprite.java new file mode 100644 index 00000000..66b3e8cd --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/SkeletonHand1Sprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.actors.Char; +import com.watabou.noosa.TextureFilm; + +public class SkeletonHand1Sprite extends MobSprite { + + public SkeletonHand1Sprite() { + super(); + + texture(Assets.SKELETONHAND1); + + TextureFilm frames = new TextureFilm(texture, 16, 16); + + idle = new Animation(2, true); + idle.frames(frames, 0, 1); + + run = new Animation(4, true); + run.frames(frames, 0, 1); + + attack = new Animation(5, false); + attack.frames(frames, 2, 3, 4, 5); + + die = new Animation(5, false); + die.frames(frames, 6, 7, 8, 9); + + play(idle); + } + + @Override + public void link(Char ch) { + super.link(ch); + add(State.BURNING); + } + + @Override + public void die() { + super.die(); + remove(State.BURNING); + } + +} diff --git a/java/com/hmdzl/spspd/sprites/SkeletonHand2Sprite.java b/java/com/hmdzl/spspd/sprites/SkeletonHand2Sprite.java new file mode 100644 index 00000000..72799a32 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/SkeletonHand2Sprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class SkeletonHand2Sprite extends MobSprite { + + public SkeletonHand2Sprite() { + super(); + + texture(Assets.SKELETONHAND1); + + TextureFilm frames = new TextureFilm(texture, 16, 16); + + idle = new Animation(2, true); + idle.frames(frames, 0, 1); + + run = new Animation(4, true); + run.frames(frames, 0, 1); + + attack = new Animation(5, false); + attack.frames(frames, 2, 3, 4, 5); + + die = new Animation(5, false); + die.frames(frames, 6, 7, 8, 9); + + play(idle); + } + +} diff --git a/java/com/hmdzl/spspd/sprites/SkeletonKingSprite.java b/java/com/hmdzl/spspd/sprites/SkeletonKingSprite.java new file mode 100644 index 00000000..e4ed397c --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/SkeletonKingSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class SkeletonKingSprite extends MobSprite { + + public SkeletonKingSprite() { + super(); + + texture(Assets.SKELETONKING); + + TextureFilm frames = new TextureFilm(texture, 16, 16); + + idle = new Animation(5, true); + idle.frames(frames, 0, 1, 2); + + run = new Animation(6, true); + run.frames(frames, 3, 4); + + attack = new Animation(5, false); + attack.frames(frames, 5, 6, 7); + + die = new Animation(5, false); + die.frames(frames, 8, 9, 10, 11, 12, 13); + + play(idle); + } + +} diff --git a/java/com/hmdzl/spspd/sprites/SkeletonSprite.java b/java/com/hmdzl/spspd/sprites/SkeletonSprite.java new file mode 100644 index 00000000..8e68f5c9 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/SkeletonSprite.java @@ -0,0 +1,61 @@ +/* + * 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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.effects.Speck; +import com.watabou.noosa.TextureFilm; + +public class SkeletonSprite extends MobSprite { + + public SkeletonSprite() { + super(); + + texture(Assets.SKELETON); + + TextureFilm frames = new TextureFilm(texture, 12, 15); + + idle = new Animation(12, true); + idle.frames(frames, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3); + + run = new Animation(15, true); + run.frames(frames, 4, 5, 6, 7, 8, 9); + + attack = new Animation(15, false); + attack.frames(frames, 14, 15, 16); + + die = new Animation(12, false); + die.frames(frames, 10, 11, 12, 13); + + play(idle); + } + + @Override + public void die() { + super.die(); + if (Dungeon.visible[ch.pos]) { + emitter().burst(Speck.factory(Speck.BONE), 6); + } + } + + @Override + public int blood() { + return 0xFFcccccc; + } +} diff --git a/java/com/hmdzl/spspd/sprites/SnakeSprite.java b/java/com/hmdzl/spspd/sprites/SnakeSprite.java new file mode 100644 index 00000000..b72bc39e --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/SnakeSprite.java @@ -0,0 +1,46 @@ +/* + * Unleashed Pixel Dungeon + * Copyright (C) 2015 David Mitchell + * + * 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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class SnakeSprite extends MobSprite { + + public SnakeSprite() { + super(); + + texture( Assets.SNAKE ); + + TextureFilm frames = new TextureFilm( texture, 16, 16 ); + + idle = new Animation( 2, true ); + idle.frames( frames, 0, 0, 0, 1 ); + + run = new Animation( 10, true ); + run.frames( frames, 5, 4, 3, 4, 5 ); + + attack = new Animation( 14, false ); + attack.frames( frames, 0, 2, 0 ); + + die = new Animation( 10, false ); + die.frames( frames, 2, 6, 7 ); + + play( idle ); + } +} diff --git a/java/com/hmdzl/spspd/sprites/SokobanBlackSheepSprite.java b/java/com/hmdzl/spspd/sprites/SokobanBlackSheepSprite.java new file mode 100644 index 00000000..d580d578 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/SokobanBlackSheepSprite.java @@ -0,0 +1,45 @@ +/* + * 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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; +import com.watabou.utils.Random; + +public class SokobanBlackSheepSprite extends MobSprite { + + public SokobanBlackSheepSprite() { + super(); + + texture(Assets.SOKOBANSHEEP); + + TextureFilm frames = new TextureFilm(texture, 16, 15); + + idle = new Animation(8, true); + idle.frames(frames, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 14, 15, 12); + + run = idle.clone(); + attack = idle.clone(); + + die = new Animation(20, false); + die.frames(frames, 8); + + play(idle); + curFrame = Random.Int(curAnim.frames.length); + } +} diff --git a/java/com/hmdzl/spspd/sprites/SokobanCornerSheepSprite.java b/java/com/hmdzl/spspd/sprites/SokobanCornerSheepSprite.java new file mode 100644 index 00000000..b6fb6ddf --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/SokobanCornerSheepSprite.java @@ -0,0 +1,45 @@ +/* + * 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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; +import com.watabou.utils.Random; + +public class SokobanCornerSheepSprite extends MobSprite { + + public SokobanCornerSheepSprite() { + super(); + + texture(Assets.SOKOBANSHEEP); + + TextureFilm frames = new TextureFilm(texture, 16, 15); + + idle = new Animation(8, true); + idle.frames(frames, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 6, 7, 4); + + run = idle.clone(); + attack = idle.clone(); + + die = new Animation(20, false); + die.frames(frames, 4); + + play(idle); + curFrame = Random.Int(curAnim.frames.length); + } +} diff --git a/java/com/hmdzl/spspd/sprites/SokobanSheepSprite.java b/java/com/hmdzl/spspd/sprites/SokobanSheepSprite.java new file mode 100644 index 00000000..1902bf26 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/SokobanSheepSprite.java @@ -0,0 +1,45 @@ +/* + * 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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; +import com.watabou.utils.Random; + +public class SokobanSheepSprite extends MobSprite { + + public SokobanSheepSprite() { + super(); + + texture(Assets.SOKOBANSHEEP); + + TextureFilm frames = new TextureFilm(texture, 16, 15); + + idle = new Animation(8, true); + idle.frames(frames, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 0); + + run = idle.clone(); + attack = idle.clone(); + + die = new Animation(20, false); + die.frames(frames, 0); + + play(idle); + curFrame = Random.Int(curAnim.frames.length); + } +} diff --git a/java/com/hmdzl/spspd/sprites/SokobanSheepSwitchSprite.java b/java/com/hmdzl/spspd/sprites/SokobanSheepSwitchSprite.java new file mode 100644 index 00000000..7ad4bea8 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/SokobanSheepSwitchSprite.java @@ -0,0 +1,45 @@ +/* + * 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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; +import com.watabou.utils.Random; + +public class SokobanSheepSwitchSprite extends MobSprite { + + public SokobanSheepSwitchSprite() { + super(); + + texture(Assets.SOKOBANSHEEP); + + TextureFilm frames = new TextureFilm(texture, 16, 15); + + idle = new Animation(8, true); + idle.frames(frames, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 10, 11, 8); + + run = idle.clone(); + attack = idle.clone(); + + die = new Animation(20, false); + die.frames(frames, 8); + + play(idle); + curFrame = Random.Int(curAnim.frames.length); + } +} diff --git a/java/com/hmdzl/spspd/sprites/SpiderBotSprite.java b/java/com/hmdzl/spspd/sprites/SpiderBotSprite.java new file mode 100644 index 00000000..f577a8a4 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/SpiderBotSprite.java @@ -0,0 +1,50 @@ +/* + * Unleashed Pixel Dungeon + * Copyright (C) 2015 David Mitchell + * + * 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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class SpiderBotSprite extends MobSprite { + public SpiderBotSprite() { + super(); + + texture(Assets.SPIDERBOT); + + TextureFilm frames = new TextureFilm( texture, 16, 16 ); + + idle = new Animation( 10, true ); + idle.frames( frames, 0, 0, 0, 0, 0, 1, 0, 1 ); + + run = new Animation( 15, true ); + run.frames( frames, 0, 2, 0, 3 ); + + attack = new Animation( 12, false ); + attack.frames( frames, 0, 4, 5, 0 ); + + die = new Animation( 12, false ); + die.frames( frames, 6, 7, 8, 9 ); + + play( idle ); + } + + @Override + public int blood() { + return 0xFFFFFF88; + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/sprites/SpiderEggSprite.java b/java/com/hmdzl/spspd/sprites/SpiderEggSprite.java new file mode 100644 index 00000000..429054e6 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/SpiderEggSprite.java @@ -0,0 +1,34 @@ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class SpiderEggSprite extends MobSprite { + + public SpiderEggSprite() { + super(); + + texture(Assets.SPIDEREGG); + + TextureFilm frames = new TextureFilm(texture, 16, 16); + + idle = new Animation(10, true); + idle.frames(frames, 0, 0, 0, 0, 0, 1, 0, 1); + + run = new Animation(15, true); + run.frames(frames, 0, 1, 0, 1); + + attack = new Animation(12, false); + attack.frames(frames, 0, 1, 0, 0); + + die = new Animation(12, false); + die.frames(frames, 1, 2, 3, 4); + + play(idle); + } + + @Override + public int blood() { + return 0xFFBFE5B8; + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/sprites/SpiderGoldSprite.java b/java/com/hmdzl/spspd/sprites/SpiderGoldSprite.java new file mode 100644 index 00000000..5466ffab --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/SpiderGoldSprite.java @@ -0,0 +1,34 @@ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class SpiderGoldSprite extends MobSprite { + + public SpiderGoldSprite() { + super(); + + texture(Assets.SPIDERMIND); + + TextureFilm frames = new TextureFilm(texture, 16, 16); + + idle = new Animation(10, true); + idle.frames(frames, 16, 16, 16, 16, 16, 17, 16, 17); + + run = new Animation(15, true); + run.frames(frames, 16, 18, 19, 20); + + attack = new Animation(12, false); + attack.frames(frames, 20, 21, 22, 23); + + die = new Animation(12, false); + die.frames(frames, 24, 25, 25, 25); + + play(idle); + } + + @Override + public int blood() { + return 0xFFBFE5B8; + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/sprites/SpiderJumpSprite.java b/java/com/hmdzl/spspd/sprites/SpiderJumpSprite.java new file mode 100644 index 00000000..0df475cc --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/SpiderJumpSprite.java @@ -0,0 +1,34 @@ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class SpiderJumpSprite extends MobSprite { + + public SpiderJumpSprite() { + super(); + + texture(Assets.SPIDERWORKER); + + TextureFilm frames = new TextureFilm(texture, 16, 16); + + idle = new Animation(10, true); + idle.frames(frames, 16, 16, 16, 16, 17, 18, 16, 17); + + run = new Animation(15, true); + run.frames(frames, 18, 19, 20, 21); + + attack = new Animation(12, false); + attack.frames(frames, 22, 23, 24, 25); + + die = new Animation(12, false); + die.frames(frames, 26, 27, 27, 27); + + play(idle); + } + + @Override + public int blood() { + return 0xFFBFE5B8; + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/sprites/SpiderMindSprite.java b/java/com/hmdzl/spspd/sprites/SpiderMindSprite.java new file mode 100644 index 00000000..55870700 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/SpiderMindSprite.java @@ -0,0 +1,34 @@ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class SpiderMindSprite extends MobSprite { + + public SpiderMindSprite() { + super(); + + texture(Assets.SPIDERMIND); + + TextureFilm frames = new TextureFilm(texture, 16, 16); + + idle = new Animation(10, true); + idle.frames(frames, 0, 0, 0, 0, 0, 1, 0, 1); + + run = new Animation(15, true); + run.frames(frames, 0, 2, 3, 4); + + attack = new Animation(12, false); + attack.frames(frames, 4, 5, 6, 7); + + die = new Animation(12, false); + die.frames(frames, 8, 9, 10, 11); + + play(idle); + } + + @Override + public int blood() { + return 0xFFBFE5B8; + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/sprites/SpiderNormalSprite.java b/java/com/hmdzl/spspd/sprites/SpiderNormalSprite.java new file mode 100644 index 00000000..653fe2d2 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/SpiderNormalSprite.java @@ -0,0 +1,34 @@ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class SpiderNormalSprite extends MobSprite { + + public SpiderNormalSprite() { + super(); + + texture(Assets.SPIDERWORKER); + + TextureFilm frames = new TextureFilm(texture, 16, 16); + + idle = new Animation(10, true); + idle.frames(frames, 0, 0, 0, 0, 1, 2, 0, 1); + + run = new Animation(15, true); + run.frames(frames, 2, 3, 4, 5); + + attack = new Animation(12, false); + attack.frames(frames, 6, 7, 8, 9); + + die = new Animation(12, false); + die.frames(frames, 10, 11, 12, 13); + + play(idle); + } + + @Override + public int blood() { + return 0xFFBFE5B8; + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/sprites/SpiderQueenSprite.java b/java/com/hmdzl/spspd/sprites/SpiderQueenSprite.java new file mode 100644 index 00000000..5f7c788b --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/SpiderQueenSprite.java @@ -0,0 +1,34 @@ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class SpiderQueenSprite extends MobSprite { + + public SpiderQueenSprite() { + super(); + + texture(Assets.SPIDERQUEEN); + + TextureFilm frames = new TextureFilm(texture, 16, 16); + + idle = new Animation(10, true); + idle.frames(frames, 0, 0, 1, 2, 1, 0, 0, 1); + + run = new Animation(15, true); + run.frames(frames, 2, 2, 3, 4); + + attack = new Animation(12, false); + attack.frames(frames, 4, 5, 6, 7); + + die = new Animation(12, false); + die.frames(frames, 8, 9, 10, 11); + + play(idle); + } + + @Override + public int blood() { + return 0xFFBFE5B8; + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/sprites/SpiderSprite.java b/java/com/hmdzl/spspd/sprites/SpiderSprite.java new file mode 100644 index 00000000..04e6513a --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/SpiderSprite.java @@ -0,0 +1,51 @@ +/* + * 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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class SpiderSprite extends MobSprite { + + public SpiderSprite() { + super(); + + texture(Assets.SPINNER); + + TextureFilm frames = new TextureFilm(texture, 16, 16); + + idle = new Animation(10, true); + idle.frames(frames, 16, 16, 16, 16, 16, 17, 16, 17); + + run = new Animation(15, true); + run.frames(frames, 16, 18, 16, 19); + + attack = new Animation(12, false); + attack.frames(frames, 16, 20, 21, 16); + + die = new Animation(12, false); + die.frames(frames, 22, 23, 24, 25); + + play(idle); + } + + @Override + public int blood() { + return 0xFFBFE5B8; + } +} diff --git a/java/com/hmdzl/spspd/sprites/SpinnerSprite.java b/java/com/hmdzl/spspd/sprites/SpinnerSprite.java new file mode 100644 index 00000000..e7df4e30 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/SpinnerSprite.java @@ -0,0 +1,51 @@ +/* + * 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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class SpinnerSprite extends MobSprite { + + public SpinnerSprite() { + super(); + + texture(Assets.SPINNER); + + TextureFilm frames = new TextureFilm(texture, 16, 16); + + idle = new Animation(10, true); + idle.frames(frames, 0, 0, 0, 0, 0, 1, 0, 1); + + run = new Animation(15, true); + run.frames(frames, 0, 2, 0, 3); + + attack = new Animation(12, false); + attack.frames(frames, 0, 4, 5, 0); + + die = new Animation(12, false); + die.frames(frames, 6, 7, 8, 9); + + play(idle); + } + + @Override + public int blood() { + return 0xFFBFE5B8; + } +} diff --git a/java/com/hmdzl/spspd/sprites/StatueSprite.java b/java/com/hmdzl/spspd/sprites/StatueSprite.java new file mode 100644 index 00000000..677646cc --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/StatueSprite.java @@ -0,0 +1,51 @@ +/* + * 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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class StatueSprite extends MobSprite { + + public StatueSprite() { + super(); + + texture(Assets.STATUE); + + TextureFilm frames = new TextureFilm(texture, 12, 15); + + idle = new Animation(2, true); + idle.frames(frames, 0, 0, 0, 0, 0, 1, 1); + + run = new Animation(15, true); + run.frames(frames, 2, 3, 4, 5, 6, 7); + + attack = new Animation(12, false); + attack.frames(frames, 8, 9, 10); + + die = new Animation(5, false); + die.frames(frames, 11, 12, 13, 14, 15, 15); + + play(idle); + } + + @Override + public int blood() { + return 0xFFcdcdb7; + } +} diff --git a/java/com/hmdzl/spspd/sprites/SteelBeeSprite.java b/java/com/hmdzl/spspd/sprites/SteelBeeSprite.java new file mode 100644 index 00000000..7336dcc2 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/SteelBeeSprite.java @@ -0,0 +1,52 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class SteelBeeSprite extends MobSprite { + + public SteelBeeSprite() { + super(); + + texture(Assets.BEE); + + TextureFilm frames = new TextureFilm(texture, 16, 16); + + idle = new Animation(12, true); + idle.frames(frames, 16, 17, 17, 16, 18, 18); + + run = new Animation(15, true); + run.frames(frames, 16, 17, 17, 16, 18, 18); + + attack = new Animation(20, false); + attack.frames(frames, 19, 20, 21, 22); + + die = new Animation(20, false); + die.frames(frames, 23, 24, 25, 26); + + + play(idle); + } + + @Override + public int blood() { + return 0xffd500; + } +} diff --git a/java/com/hmdzl/spspd/sprites/StoneSprite.java b/java/com/hmdzl/spspd/sprites/StoneSprite.java new file mode 100644 index 00000000..a42f588c --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/StoneSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class StoneSprite extends MobSprite { + + //Frames 1-4 are idle, 5-8 are moving, 9-12 are attack and the last are for death + + public StoneSprite() { + super(); + + texture(Assets.KLIKS); + + TextureFilm frames = new TextureFilm(texture, 16, 16); + + idle = new Animation(2, true); + idle.frames(frames, 0, 1, 2, 3); + + run = new Animation(4, true); + run.frames(frames, 4, 5, 6, 7); + + attack = new Animation(8, false); + attack.frames(frames, 8, 9, 10, 11); + + zap = attack.clone(); + + die = new Animation(6, false); + die.frames(frames, 12, 13, 14, 15); + + play(idle); + } + + + @Override + public int blood() { + return 0xFFcdcdb7; + } +} diff --git a/java/com/hmdzl/spspd/sprites/StormAndRainSprite.java b/java/com/hmdzl/spspd/sprites/StormAndRainSprite.java new file mode 100644 index 00000000..f83da061 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/StormAndRainSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class StormAndRainSprite extends MobSprite { + + public StormAndRainSprite() { + super(); + + texture( Assets.SAR ); + + TextureFilm frames = new TextureFilm( texture, 16, 16 ); + + idle = new Animation( 3, true ); + idle.frames(frames, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3); + + run = new Animation( 20, true ); + run.frames( frames, 0 ); + + attack = new Animation( 12, false ); + attack.frames( frames, 0, 2, 3 ); + + die = new Animation( 20, false ); + die.frames( frames, 0 ); + + play( idle ); + } + + +} diff --git a/java/com/hmdzl/spspd/sprites/SuccubusSprite.java b/java/com/hmdzl/spspd/sprites/SuccubusSprite.java new file mode 100644 index 00000000..d1f7a5a6 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/SuccubusSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.effects.particles.ShadowParticle; +import com.watabou.noosa.TextureFilm; + +public class SuccubusSprite extends MobSprite { + + public SuccubusSprite() { + super(); + + texture(Assets.SUCCUBUS); + + TextureFilm frames = new TextureFilm(texture, 12, 15); + + idle = new Animation(8, true); + idle.frames(frames, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, + 2, 2, 1); + + run = new Animation(15, true); + run.frames(frames, 3, 4, 5, 6, 7, 8); + + attack = new Animation(12, false); + attack.frames(frames, 9, 10, 11); + + die = new Animation(10, false); + die.frames(frames, 12); + + play(idle); + } + + @Override + public void die() { + super.die(); + emitter().burst(Speck.factory(Speck.HEART), 6); + emitter().burst(ShadowParticle.UP, 8); + } +} diff --git a/java/com/hmdzl/spspd/sprites/SuffererSprite.java b/java/com/hmdzl/spspd/sprites/SuffererSprite.java new file mode 100644 index 00000000..9d2e6af3 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/SuffererSprite.java @@ -0,0 +1,55 @@ +/* + * Unleashed Pixel Dungeon + * Copyright (C) 2015 David Mitchell + * + * 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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.effects.particles.ElmoParticle; +import com.watabou.noosa.TextureFilm; + +public class SuffererSprite extends MobSprite { + + public SuffererSprite() { + super(); + + texture( Assets.SUFFERER ); + + TextureFilm frames = new TextureFilm( texture, 12, 14 ); + + idle = new Animation( 8, true ); + idle.frames( frames, 0, 0, 0, 1, 0, 0, 1, 1 ); + + run = new Animation( 12, true ); + run.frames( frames, 2, 3, 4, 5, 6, 7 ); + + attack = new Animation( 12, false ); + attack.frames( frames, 8, 9, 10 ); + + die = new Animation( 12, false ); + die.frames( frames, 11, 12, 13, 14 ); + + play( idle ); + } + + @Override + public void onComplete( Animation anim ) { + if (anim == die) { + emitter().burst( ElmoParticle.FACTORY, 4 ); + } + super.onComplete( anim ); + } +} diff --git a/java/com/hmdzl/spspd/sprites/SugarplumFairySprite.java b/java/com/hmdzl/spspd/sprites/SugarplumFairySprite.java new file mode 100644 index 00000000..c7422bcb --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/SugarplumFairySprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; + +import com.watabou.noosa.TextureFilm; + +public class SugarplumFairySprite extends MobSprite { + + //Frames 0,2 are idle, 0,1,2 are moving, 0,3,4,1 are attack and 5,6,7 are for death + + private int[] points = new int[2]; + + public SugarplumFairySprite() { + super(); + + texture(Assets.FAIRY); + + TextureFilm frames = new TextureFilm(texture, 15, 15); + + idle = new Animation(2, true); + idle.frames(frames, 16, 18, 19, 16); + + run = new Animation(8, true); + run.frames(frames, 16, 17, 18, 16); + + attack = new Animation(8, false); + attack.frames(frames, 16, 19, 20, 17); + + die = new Animation(8, false); + die.frames(frames, 21, 22, 23, 23); + + play(idle); + } + + @Override + public int blood() { + return 0xFFcdcdb7; + } +} diff --git a/java/com/hmdzl/spspd/sprites/SwarmSprite.java b/java/com/hmdzl/spspd/sprites/SwarmSprite.java new file mode 100644 index 00000000..6d014727 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/SwarmSprite.java @@ -0,0 +1,51 @@ +/* + * 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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class SwarmSprite extends MobSprite { + + public SwarmSprite() { + super(); + + texture(Assets.SWARM); + + TextureFilm frames = new TextureFilm(texture, 16, 16); + + idle = new Animation(15, true); + idle.frames(frames, 0, 1, 2, 3, 4, 5); + + run = new Animation(15, true); + run.frames(frames, 0, 1, 2, 3, 4, 5); + + attack = new Animation(20, false); + attack.frames(frames, 6, 7, 8, 9); + + die = new Animation(15, false); + die.frames(frames, 10, 11, 12, 13, 14); + + play(idle); + } + + @Override + public int blood() { + return 0xFF8BA077; + } +} diff --git a/java/com/hmdzl/spspd/sprites/TCloudSprite.java b/java/com/hmdzl/spspd/sprites/TCloudSprite.java new file mode 100644 index 00000000..86f1310f --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/TCloudSprite.java @@ -0,0 +1,61 @@ +/* + * 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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.effects.Lightning; +import com.hmdzl.spspd.items.wands.WandOfTCloud; +import com.watabou.noosa.TextureFilm; + +public class TCloudSprite extends MobSprite { + + private int[] points = new int[2]; + + public TCloudSprite() { + super(); + + texture(Assets.T_CLOUD); + + TextureFilm frames = new TextureFilm( texture, 16, 16 ); + + idle = new Animation( 3, true ); + idle.frames(frames, 0, 0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 3); + + run = new Animation( 20, true ); + run.frames( frames, 0 ); + + attack = new Animation( 12, false ); + attack.frames( frames, 0, 2, 3 ); + + die = new Animation( 20, false ); + die.frames( frames, 0 ); + + zap = attack.clone(); + + play(idle); + } + + @Override + public void zap(int pos) { + + parent.add( new Lightning( ch.pos, pos, (WandOfTCloud.TCloud) ch)); + + turnTo(ch.pos, pos); + play(zap); + } +} diff --git a/java/com/hmdzl/spspd/sprites/TankSprite.java b/java/com/hmdzl/spspd/sprites/TankSprite.java new file mode 100644 index 00000000..660791f2 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/TankSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class TankSprite extends MobSprite { + + public TankSprite() { + super(); + + texture(Assets.TANK); + + TextureFilm frames = new TextureFilm(texture, 16, 14); + + idle = new Animation(2, true); + idle.frames(frames, 0, 0, 0, 1); + + run = new Animation(10, true); + run.frames(frames, 6, 7, 8, 9, 10); + + attack = new Animation(15, false); + attack.frames(frames, 2, 3, 4, 5, 0); + + die = new Animation(10, false); + die.frames(frames, 11, 12, 13, 14); + + play(idle); + } + + } diff --git a/java/com/hmdzl/spspd/sprites/Tempest102Sprite.java b/java/com/hmdzl/spspd/sprites/Tempest102Sprite.java new file mode 100644 index 00000000..989256e0 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/Tempest102Sprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class Tempest102Sprite extends MobSprite { + + public Tempest102Sprite() { + super(); + + texture( Assets.TEMPEST102 ); + + TextureFilm frames = new TextureFilm( texture, 16, 16 ); + + idle = new Animation( 3, true ); + idle.frames(frames, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3); + + run = new Animation( 20, true ); + run.frames( frames, 0 ); + + attack = new Animation( 12, false ); + attack.frames( frames, 0, 2, 3 ); + + die = new Animation( 20, false ); + die.frames( frames, 0 ); + + play( idle ); + } + + +} diff --git a/java/com/hmdzl/spspd/sprites/TenguSprite.java b/java/com/hmdzl/spspd/sprites/TenguSprite.java new file mode 100644 index 00000000..a0dc2823 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/TenguSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.items.weapon.missiles.HugeShuriken; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.scenes.GameScene; +import com.watabou.noosa.TextureFilm; +import com.watabou.utils.Callback; + +public class TenguSprite extends MobSprite { + + private static final float DURATION = 2f; + private Animation cast; + + public TenguSprite() { + super(); + + texture(Assets.TENGU); + + TextureFilm frames = new TextureFilm(texture, 14, 16); + + idle = new Animation(2, true); + idle.frames(frames, 0, 0, 0, 1); + + run = new Animation(15, false); + run.frames(frames, 2, 3, 4, 5, 0); + + attack = new Animation(15, false); + attack.frames(frames, 6, 7, 7, 0); + + cast = attack.clone(); + + die = new Animation(8, false); + die.frames(frames, 8, 9, 10, 10, 10, 10, 10, 10); + + play(run.clone()); + } + + @Override + public void move(int from, int to) { + + place(to); + + play(run); + turnTo(from, to); + + isMoving = true; + + if (Level.water[to]) { + GameScene.ripple(to); + } + + ch.onMotionComplete(); + } + + @Override + public void attack(int cell) { + if (!Level.adjacent(cell, ch.pos)) { + Char enemy = Actor.findChar(cell); + ((MissileSprite) parent.recycle(MissileSprite.class)).reset(ch.pos, + cell, new HugeShuriken(), new Callback() { + @Override + public void call() { + ch.onAttackComplete(); + } + }); + play(cast); + turnTo(ch.pos, cell); + + } else { + + super.attack(cell); + + } + } + + @Override + public void onComplete(Animation anim) { + if (anim == run) { + isMoving = false; + idle(); + } else { + super.onComplete(anim); + } + } +} diff --git a/java/com/hmdzl/spspd/sprites/ThankListSprite.java b/java/com/hmdzl/spspd/sprites/ThankListSprite.java new file mode 100644 index 00000000..a033811d --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/ThankListSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class ThankListSprite extends MobSprite { + + public ThankListSprite() { + super(); + + texture( Assets.THANK_LIST ); + + TextureFilm frames = new TextureFilm( texture, 16, 16 ); + + idle = new Animation( 3, true ); + idle.frames(frames, 0, 0, 1, 1, 2, 2, 3, 3, 3, 3, 3, 3); + + run = new Animation( 3, true ); + run.frames( frames, 0, 0, 1, 1, 2, 2, 3, 3, 3, 3, 3, 3 ); + + attack = new Animation( 12, false ); + attack.frames( frames, 0, 2, 3 ); + + die = new Animation( 20, false ); + die.frames( frames, 0 ); + + play( idle ); + } + + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/sprites/ThiefImpSprite.java b/java/com/hmdzl/spspd/sprites/ThiefImpSprite.java new file mode 100644 index 00000000..5bd53237 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/ThiefImpSprite.java @@ -0,0 +1,35 @@ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class ThiefImpSprite extends MobSprite { + + public ThiefImpSprite() { + super(); + + texture( Assets.THIEFIMP ); + + TextureFilm frames = new TextureFilm( texture, 16, 16 ); + + idle = new Animation( 5, true ); + idle.frames(frames, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 4, 5, 6, 7); + + run = new Animation( 10, true ); + run.frames( frames, 0, 1, 2, 3 ); + + attack = new Animation( 15, false ); + attack.frames( frames, 8, 9, 10, 11, 12 ); + +// cast = new Animation( 15, false ); +// cast.frames( frames, 8, 9, 10, 11, 12 ); + + zap = new Animation( 10, false ); + zap.frames( frames, 13, 14, 15, 0 ); + + die = new Animation( 10, false ); + die.frames( frames, 16, 17, 18, 19, 20, 21 ); + + play( idle ); + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/sprites/ThiefKingSprite.java b/java/com/hmdzl/spspd/sprites/ThiefKingSprite.java new file mode 100644 index 00000000..e6997b73 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/ThiefKingSprite.java @@ -0,0 +1,137 @@ +/* + * 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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Poison; +import com.hmdzl.spspd.actors.buffs.Slow; +import com.hmdzl.spspd.items.weapon.missiles.EscapeKnive; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.scenes.GameScene; +import com.watabou.noosa.TextureFilm; +import com.watabou.utils.Callback; +import com.watabou.utils.Random; + +public class ThiefKingSprite extends MobSprite { + + private static final float DURATION = 2f; + private Animation cast; + + + + public ThiefKingSprite() { + super(); + + texture(Assets.THIEFKING); + + TextureFilm frames = new TextureFilm(texture, 16, 16); + + idle = new Animation(2, true); + idle.frames(frames, 0, 0, 0, 0); + + run = new Animation(15, false); + run.frames(frames, 1, 2, 3, 4, 5); + + attack = new Animation(15, false); + attack.frames(frames, 6, 7, 8); + + cast = new Animation(15, false); + cast.frames(frames, 9, 10); + + die = new Animation(8, false); + die.frames(frames, 11, 12, 13, 14); + + play(run.clone()); + } + + @Override + public void link(Char ch) { + super.link(ch); + add(State.LEVITATING); + } + + @Override + public void die() { + super.die(); + remove(State.LEVITATING); + } + + @Override + public void move(int from, int to) { + + place(to); + + play(run); + turnTo(from, to); + + isMoving = true; + + if (Level.water[to]) { + GameScene.ripple(to); + } + + + + ch.onMotionComplete(); + } + + + @Override + public void attack(int cell) { + if (!Level.adjacent(cell, ch.pos)) { + Char enemy = Actor.findChar(cell); + ((MissileSprite) parent.recycle(MissileSprite.class)).reset(ch.pos, + cell, new EscapeKnive(), new Callback() { + @Override + public void call() { + ch.onAttackComplete(); + } + }); + + + if(Random.Int(10)==0){ + Buff.affect(enemy, Slow.class, Slow.duration(enemy) / 2); + } + + if(Random.Int(10)==0){ + Buff.affect(enemy, Poison.class).set(Random.Int(7, 9) * Poison.durationFactor(enemy)); + } + + play(cast); + turnTo(ch.pos, cell); + + } else { + + super.attack(cell); + + } + } + + @Override + public void onComplete(Animation anim) { + if (anim == run) { + isMoving = false; + idle(); + } else { + super.onComplete(anim); + } + } +} diff --git a/java/com/hmdzl/spspd/sprites/ThiefSprite.java b/java/com/hmdzl/spspd/sprites/ThiefSprite.java new file mode 100644 index 00000000..b261560c --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/ThiefSprite.java @@ -0,0 +1,45 @@ +/* + * 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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class ThiefSprite extends MobSprite { + + public ThiefSprite() { + super(); + + texture(Assets.THIEF); + TextureFilm film = new TextureFilm(texture, 12, 13); + + idle = new Animation(1, true); + idle.frames(film, 0, 0, 0, 1, 0, 0, 0, 0, 1); + + run = new Animation(15, true); + run.frames(film, 0, 0, 2, 3, 3, 4); + + die = new Animation(10, false); + die.frames(film, 5, 6, 7, 8, 9); + + attack = new Animation(12, false); + attack.frames(film, 10, 11, 12, 0); + + idle(); + } +} diff --git a/java/com/hmdzl/spspd/sprites/TinkererSprite.java b/java/com/hmdzl/spspd/sprites/TinkererSprite.java new file mode 100644 index 00000000..e905348d --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/TinkererSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import javax.microedition.khronos.opengles.GL10; + +import android.opengl.GLES20; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.effects.Halo; +import com.hmdzl.spspd.effects.particles.ElmoParticle; +import com.watabou.noosa.Game; +import com.watabou.noosa.TextureFilm; +import com.watabou.utils.PointF; + +public class TinkererSprite extends MobSprite { + + private Shield shield; + + public TinkererSprite() { + super(); + + texture(Assets.TINKERER1); + + TextureFilm frames = new TextureFilm(texture, 12, 14); + + idle = new Animation(10, true); + idle.frames(frames, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, + 3, 3, 3, 3, 3, 2, 1); + + run = new Animation(20, true); + run.frames(frames, 0); + + die = new Animation(20, false); + die.frames(frames, 0); + + play(idle); + } + + @Override + public void link(Char ch) { + super.link(ch); + + if (shield == null) { + parent.add(shield = new Shield()); + } + } + + @Override + public void die() { + super.die(); + + if (shield != null) { + shield.putOut(); + } + emitter().start(ElmoParticle.FACTORY, 0.03f, 60); + } + + public class Shield extends Halo { + + private float phase; + + public Shield() { + + super(14, 0xBBAACC, 1f); + + am = -1; + aa = +1; + + phase = 1; + } + + @Override + public void update() { + super.update(); + + if (phase < 1) { + if ((phase -= Game.elapsed) <= 0) { + killAndErase(); + } else { + scale.set((2 - phase) * radius / RADIUS); + am = phase * (-1); + aa = phase * (+1); + } + } + + if (visible = TinkererSprite.this.visible) { + PointF p = TinkererSprite.this.center(); + point(p.x, p.y); + } + } + + @Override + public void draw() { + GLES20.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE); + super.draw(); + GLES20.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA); + } + + public void putOut() { + phase = 0.999f; + } + } + +} diff --git a/java/com/hmdzl/spspd/sprites/TowerSprite.java b/java/com/hmdzl/spspd/sprites/TowerSprite.java new file mode 100644 index 00000000..c4982d46 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/TowerSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class TowerSprite extends MobSprite { + + + public TowerSprite() { + super(); + + texture(Assets.TOWER); + TextureFilm frames = new TextureFilm(texture, 16, 16); + + idle = new Animation(10, true); + idle.frames(frames, 0, 0, 0, 0, 0, 0, 0, 0, 0); + + run = idle.clone(); + die = idle.clone(); + attack = idle.clone(); + + idle(); + } + +} diff --git a/java/com/hmdzl/spspd/sprites/TrapSprite.java b/java/com/hmdzl/spspd/sprites/TrapSprite.java new file mode 100644 index 00000000..9d5d05d8 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/TrapSprite.java @@ -0,0 +1,89 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2015 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.DungeonTilemap; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.traps.Trap; +import com.watabou.noosa.Image; +import com.watabou.noosa.TextureFilm; + +public class TrapSprite extends Image { + + private static TextureFilm frames; + + private int pos = -1; + + //trap colors + public static final int RED = 0; + public static final int ORANGE = 1; + public static final int YELLOW = 2; + public static final int GREEN = 3; + public static final int TEAL = 4; + public static final int VIOLET = 5; + public static final int WHITE = 6; + public static final int GREY = 7; + public static final int BLACK = 8; + + //trap shapes + public static final int DOTS = 0; + public static final int WAVES = 1; + public static final int GRILL = 2; + public static final int STARS = 3; + public static final int DIAMOND = 4; + public static final int CROSSHAIR = 5; + public static final int LARGE_DOT = 6; + + + public TrapSprite() { + super( Assets.TRAPS ); + + if (frames == null) { + frames = new TextureFilm( texture, 16, 16 ); + } + + origin.set( 8, 12 ); + } + + public TrapSprite( int image ) { + this(); + reset( image ); + } + + public void reset( Trap trap ) { + + revive(); + + reset( (trap.active ? trap.color : BLACK) + (trap.shape * 16) ); + alpha( 1f ); + + pos = trap.pos; + x = (pos % Level.WIDTH) * DungeonTilemap.SIZE; + y = (pos / Level.WIDTH) * DungeonTilemap.SIZE; + + } + + public void reset( int image ) { + frame( frames.get( image ) ); + } + +} diff --git a/java/com/hmdzl/spspd/sprites/TrollWarriorSprite.java b/java/com/hmdzl/spspd/sprites/TrollWarriorSprite.java new file mode 100644 index 00000000..cf80d269 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/TrollWarriorSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class TrollWarriorSprite extends MobSprite { + + public TrollWarriorSprite() { + super(); + + texture(Assets.TROLLWARRIOR); + + TextureFilm frames = new TextureFilm(texture, 16, 16); + + idle = new Animation(2, true); + idle.frames(frames, 0, 0, 0, 1); + + run = new Animation(12, true); + run.frames(frames,0, 2,3,4,5,6,7); + + attack = new Animation(12, false); + attack.frames(frames, 0,8,9,10,11); + + die = new Animation(12, false); + die.frames(frames, 0, 11, 12); + + play(idle); + } + + } diff --git a/java/com/hmdzl/spspd/sprites/TypedScrollSprite.java b/java/com/hmdzl/spspd/sprites/TypedScrollSprite.java new file mode 100644 index 00000000..d90c0353 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/TypedScrollSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class TypedScrollSprite extends MobSprite { + + public TypedScrollSprite() { + super(); + + texture( Assets.TYPEDSCROLL ); + + TextureFilm frames = new TextureFilm( texture, 15, 14 ); + + idle = new Animation( 15, true ); + idle.frames(frames, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 3); + + run = new Animation( 20, true ); + run.frames( frames, 0 ); + + attack = new Animation( 12, false ); + attack.frames( frames, 0, 2, 3 ); + + die = new Animation( 20, false ); + die.frames( frames, 0 ); + + play( idle ); + } + + +} diff --git a/java/com/hmdzl/spspd/sprites/UDM300Sprite.java b/java/com/hmdzl/spspd/sprites/UDM300Sprite.java new file mode 100644 index 00000000..b98befb1 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/UDM300Sprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.effects.Speck; +import com.watabou.noosa.TextureFilm; + +public class UDM300Sprite extends MobSprite { + + public UDM300Sprite() { + super(); + + texture(Assets.DM300); + + TextureFilm frames = new TextureFilm(texture, 22, 20); + + idle = new Animation(10, true); + idle.frames(frames, 9, 10); + + run = new Animation(10, true); + run.frames(frames, 11, 12); + + attack = new Animation(15, false); + attack.frames(frames, 13, 14, 15); + + die = new Animation(20, false); + die.frames(frames, 9, 16, 9, 16, 9, 16, 9, 16, 9, 16, 9, 16, 17); + + play(idle); + } + + @Override + public void onComplete(Animation anim) { + + super.onComplete(anim); + + if (anim == die) { + emitter().burst(Speck.factory(Speck.WOOL), 15); + } + } + + @Override + public int blood() { + return 0xFFFFFF88; + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/sprites/UGooSprite.java b/java/com/hmdzl/spspd/sprites/UGooSprite.java new file mode 100644 index 00000000..8102108a --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/UGooSprite.java @@ -0,0 +1,150 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Yet Another Pixel Dungeon + * Copyright (C) 2015-2016 Considered Hamster + * + * 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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class UGooSprite extends MobSprite { + + + public UGooSprite() { + super(); + + texture( Assets.UGOO ); + + TextureFilm frames = new TextureFilm( texture, 20, 16 ); + + idle = new Animation( 10, true ); + idle.frames( frames, 0, 1, 1, 2, 1, 1 ); + + run = new Animation( 10, true ); + run.frames( frames, 0, 1, 2, 1 ); + + attack = new Animation( 10, false ); + attack.frames( frames, 3, 4, 5 ); + + die = new Animation( 10, false ); + die.frames( frames, 6, 7, 8, 9 ); + + play( idle ); + } + + @Override + public int blood() { + return 0xFF000000; + } + + public static class IceSpawnSprite extends MobSprite { + + public IceSpawnSprite() { + super(); + texture( Assets.UGOO ); + + TextureFilm frames = new TextureFilm( texture, 20, 16 ); + + idle = new Animation( 10, true ); + idle.frames( frames, 10, 11, 11, 12, 11, 11 ); + + run = new Animation( 10, true ); + run.frames( frames, 10, 11, 12, 11 ); + + attack = new Animation( 10, false ); + attack.frames( frames, 13, 14, 15 ); + + die = new Animation( 10, false ); + die.frames( frames, 16, 17, 18, 19 ); + + play( idle ); + } + } + + public static class EarthSpawnSprite extends MobSprite { + + public EarthSpawnSprite() { + super(); + texture( Assets.UGOO ); + + TextureFilm frames = new TextureFilm( texture, 20, 16 ); + + idle = new Animation( 10, true ); + idle.frames( frames, 20, 21, 21, 22, 21, 21 ); + + run = new Animation( 10, true ); + run.frames( frames, 20, 21, 22, 21 ); + + attack = new Animation( 10, false ); + attack.frames( frames, 23, 24, 25 ); + + die = new Animation( 10, false ); + die.frames( frames, 26, 27, 28, 29 ); + + play( idle ); + } + } + + public static class FireSpawnSprite extends MobSprite { + + public FireSpawnSprite() { + super(); + texture( Assets.UGOO ); + + TextureFilm frames = new TextureFilm( texture, 20, 16 ); + + idle = new Animation( 10, true ); + idle.frames( frames, 30, 31, 31, 32, 31, 31 ); + + run = new Animation( 10, true ); + run.frames( frames, 30, 31, 32, 31 ); + + attack = new Animation( 10, false ); + attack.frames( frames, 33, 34, 35 ); + + die = new Animation( 10, false ); + die.frames( frames, 36, 37, 38, 39 ); + + play( idle ); + } + } + + public static class ShockSpawnSprite extends MobSprite { + public ShockSpawnSprite() { + super(); + texture( Assets.UGOO ); + + TextureFilm frames = new TextureFilm( texture, 20, 16 ); + + idle = new Animation( 10, true ); + idle.frames( frames, 40, 41, 41, 42, 41, 41 ); + + run = new Animation( 10, true ); + run.frames( frames, 40, 41, 42, 41 ); + + attack = new Animation( 10, false ); + attack.frames( frames, 43, 44, 45 ); + + die = new Animation( 10, false ); + die.frames( frames, 46, 47, 48, 49 ); + + play( idle ); + } + } +} diff --git a/java/com/hmdzl/spspd/sprites/UTenguSprite.java b/java/com/hmdzl/spspd/sprites/UTenguSprite.java new file mode 100644 index 00000000..a6246357 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/UTenguSprite.java @@ -0,0 +1,124 @@ +/* + * 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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Burning; +import com.hmdzl.spspd.actors.buffs.Paralysis; +import com.hmdzl.spspd.actors.buffs.Slow; +import com.hmdzl.spspd.effects.particles.FlameParticle; +import com.hmdzl.spspd.items.weapon.missiles.HugeShuriken; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.scenes.GameScene; +import com.watabou.noosa.TextureFilm; +import com.watabou.utils.Callback; +import com.watabou.utils.Random; + +public class UTenguSprite extends MobSprite { + + private static final float DURATION = 2f; + private Animation cast; + + public UTenguSprite() { + super(); + + texture(Assets.TENGU); + + TextureFilm frames = new TextureFilm(texture, 14, 16); + + idle = new Animation(2, true); + idle.frames(frames, 11, 11, 11, 12); + + run = new Animation(15, false); + run.frames(frames, 13, 14, 15, 16, 11); + + attack = new Animation(15, false); + attack.frames(frames, 17, 18, 18, 11); + + cast = attack.clone(); + + die = new Animation(8, false); + die.frames(frames, 19, 20, 21, 21, 21, 21, 21, 21); + + play(run.clone()); + } + + @Override + public void move(int from, int to) { + + place(to); + + play(run); + turnTo(from, to); + + isMoving = true; + + if (Level.water[to]) { + GameScene.ripple(to); + } + + ch.onMotionComplete(); + } + + @Override + public void attack(int cell) { + if (!Level.adjacent(cell, ch.pos)) { + Char enemy = Actor.findChar(cell); + ((MissileSprite) parent.recycle(MissileSprite.class)).reset(ch.pos, + cell, new HugeShuriken(), new Callback() { + @Override + public void call() { + ch.onAttackComplete(); + } + }); + + if(Random.Int(15)==0){ + Buff.affect(enemy, Burning.class).reignite(enemy); + enemy.sprite.emitter().burst(FlameParticle.FACTORY, 5); + } + if(Random.Int(20)==0){ + Buff.affect(enemy, Slow.class, Slow.duration(enemy) / 2); + } + + if(Random.Int(30)==0){ + Buff.prolong(enemy, Paralysis.class, DURATION); + } + + play(cast); + turnTo(ch.pos, cell); + + } else { + + super.attack(cell); + + } + } + + @Override + public void onComplete(Animation anim) { + if (anim == run) { + isMoving = false; + idle(); + } else { + super.onComplete(anim); + } + } +} diff --git a/java/com/hmdzl/spspd/sprites/UdawosSprite.java b/java/com/hmdzl/spspd/sprites/UdawosSprite.java new file mode 100644 index 00000000..2a7611c0 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/UdawosSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class UdawosSprite extends MobSprite { + + + public UdawosSprite() { + super(); + + texture( Assets.UDAWOS ); + + TextureFilm frames = new TextureFilm( texture, 14, 16 ); + + idle = new Animation( 15, true ); + idle.frames(frames, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 3); + + run = new Animation( 20, true ); + run.frames( frames, 0 ); + + attack = new Animation( 12, false ); + attack.frames( frames, 0, 2, 3 ); + + die = new Animation( 20, false ); + die.frames( frames, 0 ); + + play( idle ); + } + +} diff --git a/java/com/hmdzl/spspd/sprites/UncleSSprite.java b/java/com/hmdzl/spspd/sprites/UncleSSprite.java new file mode 100644 index 00000000..9be69560 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/UncleSSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class UncleSSprite extends MobSprite { + + public UncleSSprite() { + super(); + + texture( Assets.UNCLE_S ); + + TextureFilm frames = new TextureFilm( texture, 16, 16 ); + + idle = new Animation( 3, true ); + idle.frames(frames, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3); + + run = new Animation( 20, true ); + run.frames( frames, 0 ); + + attack = new Animation( 12, false ); + attack.frames( frames, 0, 2, 3 ); + + die = new Animation( 20, false ); + die.frames( frames, 0 ); + + play( idle ); + } + + +} diff --git a/java/com/hmdzl/spspd/sprites/UndeadSprite.java b/java/com/hmdzl/spspd/sprites/UndeadSprite.java new file mode 100644 index 00000000..00be6630 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/UndeadSprite.java @@ -0,0 +1,61 @@ +/* + * 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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.effects.Speck; +import com.watabou.noosa.TextureFilm; + +public class UndeadSprite extends MobSprite { + + public UndeadSprite() { + super(); + + texture(Assets.UNDEAD); + + TextureFilm frames = new TextureFilm(texture, 12, 16); + + idle = new Animation(12, true); + idle.frames(frames, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3); + + run = new Animation(15, true); + run.frames(frames, 4, 5, 6, 7, 8, 9); + + attack = new Animation(15, false); + attack.frames(frames, 14, 15, 16); + + die = new Animation(12, false); + die.frames(frames, 10, 11, 12, 13); + + play(idle); + } + + @Override + public void die() { + super.die(); + if (Dungeon.visible[ch.pos]) { + emitter().burst(Speck.factory(Speck.BONE), 3); + } + } + + @Override + public int blood() { + return 0xFFcccccc; + } +} diff --git a/java/com/hmdzl/spspd/sprites/VaultProtectorSprite.java b/java/com/hmdzl/spspd/sprites/VaultProtectorSprite.java new file mode 100644 index 00000000..8bb66b0a --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/VaultProtectorSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.actors.mobs.VaultProtector; +import com.hmdzl.spspd.effects.Lightning; +import com.watabou.noosa.TextureFilm; + +public class VaultProtectorSprite extends MobSprite { + + private int[] points = new int[2]; + + public VaultProtectorSprite() { + super(); + + texture(Assets.DEWPROTECTOR); + + TextureFilm frames = new TextureFilm(texture, 12, 15); + + idle = new Animation(2, true); + idle.frames(frames, 0, 0, 0, 0, 0, 1, 1); + + run = new Animation(15, true); + run.frames(frames, 2, 3, 4, 5, 6, 7); + + attack = new Animation(12, false); + attack.frames(frames, 8, 9, 10); + + zap = attack.clone(); + + die = new Animation(5, false); + die.frames(frames, 11, 12, 13, 14, 15, 15); + + play(idle); + } + + @Override + public void zap(int pos) { + + parent.add( new Lightning( ch.pos, pos,(VaultProtector) ch)); + + turnTo(ch.pos, pos); + play(zap); + } + + @Override + public int blood() { + return 0xFFcdcdb7; + } +} diff --git a/java/com/hmdzl/spspd/sprites/VelociroosterSprite.java b/java/com/hmdzl/spspd/sprites/VelociroosterSprite.java new file mode 100644 index 00000000..084b2d10 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/VelociroosterSprite.java @@ -0,0 +1,51 @@ +/* + * 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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class VelociroosterSprite extends MobSprite { + + public VelociroosterSprite() { + super(); + + texture( Assets.VELOCIROOSTER ); + + TextureFilm frames = new TextureFilm( texture, 16, 16 ); + + idle = new Animation( 2, true ); + idle.frames( frames, 0, 0, 1 ); + + run = new Animation( 10, true ); + run.frames( frames, 3, 4, 5, 4 ); + + attack = new Animation( 14, false ); + attack.frames( frames, 1, 2, 1 ); + + die = new Animation( 10, false ); + die.frames( frames, 1, 6, 7 ); + + play( idle ); + } + + @Override + public int blood() { + return 0xFFFFEA80; + } +} diff --git a/java/com/hmdzl/spspd/sprites/VillagerSprite.java b/java/com/hmdzl/spspd/sprites/VillagerSprite.java new file mode 100644 index 00000000..6f6a225e --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/VillagerSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class VillagerSprite extends MobSprite { + + public VillagerSprite() { + super(); + + texture(Assets.TINKERER1); + + TextureFilm frames = new TextureFilm(texture, 12, 14); + + idle = new Animation(10, true); + idle.frames(frames, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, + 3, 3, 3, 3, 3, 2, 1); + + run = new Animation(20, true); + run.frames(frames, 0); + + die = new Animation(20, false); + die.frames(frames, 0); + + play(idle); + } + + + +} diff --git a/java/com/hmdzl/spspd/sprites/VioletDragonSprite.java b/java/com/hmdzl/spspd/sprites/VioletDragonSprite.java new file mode 100644 index 00000000..23189236 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/VioletDragonSprite.java @@ -0,0 +1,74 @@ +/* + * 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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.actors.mobs.pets.VioletDragon; +import com.hmdzl.spspd.effects.MagicMissile; +import com.watabou.noosa.TextureFilm; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Callback; + +public class VioletDragonSprite extends MobSprite { + + //Frames 1-4 are idle, 5-8 are moving, 9-12 are attack and the last are for death + + public VioletDragonSprite() { + super(); + + texture(Assets.PETDRAGON); + + TextureFilm frames = new TextureFilm(texture, 16, 16); + + idle = new Animation(2, true); + idle.frames(frames, 32, 33, 34, 35); + + run = new Animation(8, true); + run.frames(frames, 36, 37, 38, 39); + + attack = new Animation(8, false); + attack.frames(frames, 40, 41, 42, 43); + + zap = attack.clone(); + + die = new Animation(8, false); + die.frames(frames, 44, 45, 46, 47); + + play(idle); + } + + @Override + public void zap(int cell) { + + turnTo(ch.pos, cell); + play(zap); + + MagicMissile.poison(parent, ch.pos, cell, new Callback() { + @Override + public void call() { + ((VioletDragon) ch).onZapComplete(); + } + }); + Sample.INSTANCE.play(Assets.SND_ZAP); + } + + @Override + public int blood() { + return 0xFFcdcdb7; + } +} diff --git a/java/com/hmdzl/spspd/sprites/WandmakerSprite.java b/java/com/hmdzl/spspd/sprites/WandmakerSprite.java new file mode 100644 index 00000000..8e57fc22 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/WandmakerSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import javax.microedition.khronos.opengles.GL10; + +import android.opengl.GLES20; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.effects.Halo; +import com.hmdzl.spspd.effects.particles.ElmoParticle; +import com.watabou.noosa.Game; +import com.watabou.noosa.TextureFilm; +import com.watabou.utils.PointF; + +public class WandmakerSprite extends MobSprite { + + private Shield shield; + + public WandmakerSprite() { + super(); + + texture(Assets.MAKER); + + TextureFilm frames = new TextureFilm(texture, 12, 14); + + idle = new Animation(10, true); + idle.frames(frames, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, + 3, 3, 3, 3, 3, 2, 1); + + run = new Animation(20, true); + run.frames(frames, 0); + + die = new Animation(20, false); + die.frames(frames, 0); + + play(idle); + } + + @Override + public void link(Char ch) { + super.link(ch); + + if (shield == null) { + parent.add(shield = new Shield()); + } + } + + @Override + public void die() { + super.die(); + + if (shield != null) { + shield.putOut(); + } + emitter().start(ElmoParticle.FACTORY, 0.03f, 60); + } + + public class Shield extends Halo { + + private float phase; + + public Shield() { + + super(14, 0xBBAACC, 1f); + + am = -1; + aa = +1; + + phase = 1; + } + + @Override + public void update() { + super.update(); + + if (phase < 1) { + if ((phase -= Game.elapsed) <= 0) { + killAndErase(); + } else { + scale.set((2 - phase) * radius / RADIUS); + am = phase * (-1); + aa = phase * (+1); + } + } + + if (visible = WandmakerSprite.this.visible) { + PointF p = WandmakerSprite.this.center(); + point(p.x, p.y); + } + } + + @Override + public void draw() { + GLES20.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE); + super.draw(); + GLES20.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA); + } + + public void putOut() { + phase = 0.999f; + } + } + +} diff --git a/java/com/hmdzl/spspd/sprites/WarlockSprite.java b/java/com/hmdzl/spspd/sprites/WarlockSprite.java new file mode 100644 index 00000000..2fe4cd47 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/WarlockSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.actors.mobs.Warlock; +import com.hmdzl.spspd.effects.MagicMissile; +import com.watabou.noosa.TextureFilm; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Callback; + +public class WarlockSprite extends MobSprite { + + public WarlockSprite() { + super(); + + texture(Assets.WARLOCK); + + TextureFilm frames = new TextureFilm(texture, 12, 15); + + idle = new Animation(2, true); + idle.frames(frames, 0, 0, 0, 1, 0, 0, 1, 1); + + run = new Animation(15, true); + run.frames(frames, 0, 2, 3, 4); + + attack = new Animation(12, false); + attack.frames(frames, 0, 5, 6); + + zap = attack.clone(); + + die = new Animation(15, false); + die.frames(frames, 0, 7, 8, 8, 9, 10); + + play(idle); + } + + @Override + public void zap(int cell) { + + turnTo(ch.pos, cell); + play(zap); + + MagicMissile.shadow(parent, ch.pos, cell, new Callback() { + @Override + public void call() { + ((Warlock) ch).onZapComplete(); + } + }); + Sample.INSTANCE.play(Assets.SND_ZAP); + } + + @Override + public void onComplete(Animation anim) { + if (anim == zap) { + idle(); + } + super.onComplete(anim); + } +} diff --git a/java/com/hmdzl/spspd/sprites/WatabouSprite.java b/java/com/hmdzl/spspd/sprites/WatabouSprite.java new file mode 100644 index 00000000..2e62ea1f --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/WatabouSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class WatabouSprite extends MobSprite { + + public WatabouSprite() { + super(); + + texture( Assets.WATABOU ); + + TextureFilm frames = new TextureFilm( texture, 16, 14 ); + + idle = new Animation( 15, true ); + idle.frames(frames, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2); + + run = new Animation( 20, true ); + run.frames( frames, 0 ); + + attack = new Animation( 12, false ); + attack.frames( frames, 0, 2, 3 ); + + die = new Animation( 20, false ); + die.frames( frames, 0 ); + + play( idle ); + } + + +} diff --git a/java/com/hmdzl/spspd/sprites/WhiteGhostSprite.java b/java/com/hmdzl/spspd/sprites/WhiteGhostSprite.java new file mode 100644 index 00000000..bd1bbaaa --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/WhiteGhostSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class WhiteGhostSprite extends MobSprite { + + public WhiteGhostSprite() { + super(); + + texture( Assets.M_AMD_W ); + + TextureFilm frames = new TextureFilm( texture, 16, 16 ); + + idle = new Animation( 3, true ); + idle.frames(frames, 4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7); + + run = new Animation( 20, true ); + run.frames( frames, 4 ); + + attack = new Animation( 12, false ); + attack.frames( frames, 4, 6, 7 ); + + die = new Animation( 20, false ); + die.frames( frames, 4 ); + + play( idle ); + } + + +} diff --git a/java/com/hmdzl/spspd/sprites/WraithSprite.java b/java/com/hmdzl/spspd/sprites/WraithSprite.java new file mode 100644 index 00000000..d8809487 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/WraithSprite.java @@ -0,0 +1,81 @@ +/* + * 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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.items.weapon.missiles.Wave; +import com.hmdzl.spspd.levels.Level; +import com.watabou.noosa.TextureFilm; +import com.watabou.utils.Callback; + +public class WraithSprite extends MobSprite { + + private Animation cast; + + public WraithSprite() { + super(); + + texture(Assets.WRAITH); + + TextureFilm frames = new TextureFilm(texture, 14, 15); + + idle = new Animation(5, true); + idle.frames(frames, 0, 1); + + run = new Animation(10, true); + run.frames(frames, 0, 1); + + attack = new Animation(10, false); + attack.frames(frames, 0, 2, 3); + + cast = attack.clone(); + + die = new Animation(8, false); + die.frames(frames, 0, 4, 5, 6, 7); + + play(idle); + } + + @Override + public int blood() { + return 0x88000000; + } + + @Override + public void attack(int cell) { + if (!Level.adjacent(cell, ch.pos)) { + //Char enemy = Actor.findChar(cell); + ((MissileSprite) parent.recycle(MissileSprite.class)).reset(ch.pos, + cell, new Wave(), new Callback() { + @Override + public void call() { + ch.onAttackComplete(); + } + }); + + + play(cast); + turnTo(ch.pos, cell); + + } else { + + super.attack(cell); + + } + } +} diff --git a/java/com/hmdzl/spspd/sprites/Xavier251998Sprite.java b/java/com/hmdzl/spspd/sprites/Xavier251998Sprite.java new file mode 100644 index 00000000..515a7264 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/Xavier251998Sprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class Xavier251998Sprite extends MobSprite { + + public Xavier251998Sprite() { + super(); + + texture( Assets.XAVIER ); + + TextureFilm film = new TextureFilm(texture, 12, 15); + + idle = new Animation(1, true); + idle.frames(film, 0, 1); + + run = new Animation(20, true); + run.frames(film, 0,1,2,3); + + die = new Animation(20, false); + die.frames(film,0,1,2,3); + + attack = new Animation(15, false); + attack.frames(film, 0,1,2,3); + + play(idle); + } + + +} diff --git a/java/com/hmdzl/spspd/sprites/XixiZeroSprite.java b/java/com/hmdzl/spspd/sprites/XixiZeroSprite.java new file mode 100644 index 00000000..28e9fb27 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/XixiZeroSprite.java @@ -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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class XixiZeroSprite extends MobSprite { + + public XixiZeroSprite() { + super(); + + texture( Assets.XIXIZERO ); + + TextureFilm frames = new TextureFilm( texture, 16, 16 ); + + idle = new Animation( 15, true ); + idle.frames(frames, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3); + + run = new Animation( 20, true ); + run.frames( frames, 0 ); + + attack = new Animation( 12, false ); + attack.frames( frames, 0, 2, 3 ); + + die = new Animation( 20, false ); + die.frames( frames, 0 ); + + play( idle ); + } + + +} diff --git a/java/com/hmdzl/spspd/sprites/YogSprite.java b/java/com/hmdzl/spspd/sprites/YogSprite.java new file mode 100644 index 00000000..9067ab5a --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/YogSprite.java @@ -0,0 +1,54 @@ +/* + * 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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.effects.Splash; +import com.watabou.noosa.TextureFilm; + +public class YogSprite extends MobSprite { + + public YogSprite() { + super(); + + texture(Assets.YOG); + + TextureFilm frames = new TextureFilm(texture, 20, 19); + + idle = new Animation(10, true); + idle.frames(frames, 0, 1, 2, 2, 1, 0, 3, 4, 4, 3, 0, 5, 6, 6, 5); + + run = new Animation(12, true); + run.frames(frames, 0); + + attack = new Animation(12, false); + attack.frames(frames, 0); + + die = new Animation(10, false); + die.frames(frames, 0, 7, 8, 9); + + play(idle); + } + + @Override + public void die() { + super.die(); + + Splash.at(center(), blood(), 12); + } +} diff --git a/java/com/hmdzl/spspd/sprites/ZombieSprite.java b/java/com/hmdzl/spspd/sprites/ZombieSprite.java new file mode 100644 index 00000000..8ba76881 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/ZombieSprite.java @@ -0,0 +1,51 @@ +/* + * Unleashed Pixel Dungeon + * Copyright (C) 2015 David Mitchell + * + * 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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class ZombieSprite extends MobSprite { + + public ZombieSprite() { + super(); + + texture( Assets.ZOMBIE ); + + TextureFilm frames = new TextureFilm( texture, 12, 16 ); + + idle = new Animation( 5, true ); + idle.frames( frames, 0, 1 ); + + run = new Animation( 10, true ); + run.frames( frames, 2, 3, 4, 5, 6 ); + + attack = new Animation( 10, false ); + attack.frames( frames, 7, 8, 9, 8 ); + + die = new Animation( 8, false ); + die.frames( frames, 1, 10, 11, 12 ); + + play( idle ); + } + + @Override + public int blood() { + return 0x99FF99; + } +} diff --git a/java/com/hmdzl/spspd/sprites/ZotPhaseSprite.java b/java/com/hmdzl/spspd/sprites/ZotPhaseSprite.java new file mode 100644 index 00000000..1c63b0ad --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/ZotPhaseSprite.java @@ -0,0 +1,51 @@ +/* + * 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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.TextureFilm; + +public class ZotPhaseSprite extends MobSprite { + + private int[] points = new int[2]; + + public ZotPhaseSprite() { + super(); + + texture(Assets.ZOTPHASE); + + TextureFilm frames = new TextureFilm(texture, 18, 18); + + idle = new Animation(2, true); + idle.frames(frames, 0, 0, 0, 1, 0); + + run = new Animation(8, false); + run.frames(frames, 0, 1, 2); + + attack = new Animation(8, false); + attack.frames(frames, 0, 2, 2); + + zap = new Animation(8, false); + zap.frames(frames, 2, 3, 4); + + die = new Animation(8, false); + die.frames(frames, 0, 5, 6, 7, 8, 9, 8); + + play(idle); + } +} diff --git a/java/com/hmdzl/spspd/sprites/ZotSprite.java b/java/com/hmdzl/spspd/sprites/ZotSprite.java new file mode 100644 index 00000000..8008b890 --- /dev/null +++ b/java/com/hmdzl/spspd/sprites/ZotSprite.java @@ -0,0 +1,158 @@ +/* + * 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 + */ +package com.hmdzl.spspd.sprites; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.Char; + +import com.hmdzl.spspd.effects.CellEmitter; +import com.hmdzl.spspd.effects.particles.BlastParticle; +import com.hmdzl.spspd.items.weapon.missiles.Skull; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.Terrain; +import com.hmdzl.spspd.scenes.GameScene; + +import com.watabou.noosa.TextureFilm; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Callback; +import com.watabou.utils.Random; + +public class ZotSprite extends MobSprite { + + private Animation cast; + + public ZotSprite() { + super(); + + texture(Assets.ZOT); + + TextureFilm frames = new TextureFilm(texture, 18, 18); + + idle = new Animation(2, true); + idle.frames(frames, 0, 0, 0, 1, 0); + + run = new Animation(8, false); + run.frames(frames, 0, 1, 2); + + attack = new Animation(8, false); + attack.frames(frames, 0, 2, 2); + + cast = new Animation(8, false); + cast.frames(frames, 2, 3, 4); + + die = new Animation(8, false); + die.frames(frames, 0, 5, 6, 7, 8, 9, 8); + + play(run.clone()); + } + + @Override + public void move(int from, int to) { + + place(to); + + play(run); + turnTo(from, to); + + isMoving = true; + + if (Level.water[to]) { + GameScene.ripple(to); + } + + ch.onMotionComplete(); + } + + @Override + public void attack(int cell) { + if (!Level.adjacent(cell, ch.pos)) { + //Char enemy = Actor.findChar(cell); + ((MissileSprite) parent.recycle(MissileSprite.class)).reset(ch.pos, + cell, new Skull(), new Callback() { + @Override + public void call() { + ch.onAttackComplete(); + } + }); + + + play(cast); + turnTo(ch.pos, cell); + explode(cell); + + } else { + + super.attack(cell); + + } + } + + public void explode(int cell) { + + Sample.INSTANCE.play(Assets.SND_BLAST, 2); + + if (Dungeon.visible[cell]) { + CellEmitter.center(cell).burst(BlastParticle.FACTORY, 30); + } + + boolean terrainAffected = false; + for (int n : Level.NEIGHBOURS9) { + int c = cell + n; + if (c >= 0 && c < Level.getLength()) { + + if (Level.flamable[c]) { + Level.set(c, Terrain.EMBERS); + GameScene.updateMap(c); + terrainAffected = true; + } + + Char ch = Actor.findChar(c); + if (ch != null && ch==Dungeon.hero) { + // those not at the center of the blast take damage less + // consistently. + int minDamage = c == cell ? Dungeon.depth + 5 : 1; + int maxDamage = 10 + Dungeon.depth; + + int dmg = Random.NormalIntRange(minDamage, maxDamage) + - Math.max(ch.drRoll(),0); + if (dmg > 0) { + ch.damage(dmg, this); + } + } + } + } + + if (terrainAffected) { + Dungeon.observe(); + } + + } + + + @Override + public void onComplete(Animation anim) { + if (anim == run) { + isMoving = false; + idle(); + } else { + super.onComplete(anim); + } + } +} diff --git a/java/com/hmdzl/spspd/ui/ActionIndicator.java b/java/com/hmdzl/spspd/ui/ActionIndicator.java new file mode 100644 index 00000000..3a283bb3 --- /dev/null +++ b/java/com/hmdzl/spspd/ui/ActionIndicator.java @@ -0,0 +1,119 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2016 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.ui; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.scenes.PixelScene; +import com.watabou.noosa.Image; + +public class ActionIndicator extends Tag { + + Image icon; + + public static Action action; + public static ActionIndicator instance; + + public ActionIndicator() { + super( 0xFFFF4C ); + + instance = this; + + setSize( 24, 24 ); + visible = false; + } + + @Override + public void destroy() { + super.destroy(); + instance = null; + action = null; + } + + @Override + protected void layout() { + super.layout(); + + if (icon != null){ + icon.x = x + (width - icon.width()) / 2; + icon.y = y + (height - icon.height()) / 2; + PixelScene.align(icon); + if (!members.contains(icon)) + add(icon); + } + } + + @Override + public void update() { + super.update(); + + if (!Dungeon.hero.ready){ + if (icon != null) icon.alpha(0.5f); + } else { + if (icon != null) icon.alpha(1f); + } + + if (!visible && action != null){ + visible = true; + updateIcon(); + flash(); + } else { + visible = action != null; + } + } + + @Override + protected void onClick() { + if (action != null && Dungeon.hero.ready) + action.doAction(); + } + + public static void setAction(Action action){ + ActionIndicator.action = action; + updateIcon(); + } + + public static void clearAction(Action action){ + if (ActionIndicator.action == action) + ActionIndicator.action = null; + } + + public static void updateIcon(){ + if (instance != null){ + if (instance.icon != null){ + instance.icon.killAndErase(); + instance.icon = null; + } + if (action != null){ + instance.icon = action.getIcon(); + instance.layout(); + } + } + } + + public interface Action{ + + public Image getIcon(); + + public void doAction(); + + } + +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/ui/Archs.java b/java/com/hmdzl/spspd/ui/Archs.java new file mode 100644 index 00000000..e6f505c5 --- /dev/null +++ b/java/com/hmdzl/spspd/ui/Archs.java @@ -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 + */ +package com.hmdzl.spspd.ui; + +import com.hmdzl.spspd.Assets; +import com.watabou.noosa.Game; +import com.watabou.noosa.SkinnedBlock; +import com.watabou.noosa.ui.Component; + +public class Archs extends Component { + + private static final float SCROLL_SPEED = 20f; + + private SkinnedBlock arcsBg; + private SkinnedBlock arcsFg; + + private static float offsB = 0; + private static float offsF = 0; + + public boolean reversed = false; + + @Override + protected void createChildren() { + arcsBg = new SkinnedBlock(1, 1, Assets.ARCS_BG); + arcsBg.offsetTo(0, offsB); + add(arcsBg); + + arcsFg = new SkinnedBlock(1, 1, Assets.ARCS_FG); + arcsFg.offsetTo(0, offsF); + add(arcsFg); + } + + @Override + protected void layout() { + arcsBg.size(width, height); + arcsBg.offset(arcsBg.texture.width / 4 - (width % arcsBg.texture.width) + / 2, 0); + + arcsFg.size(width, height); + arcsFg.offset(arcsFg.texture.width / 4 - (width % arcsFg.texture.width) + / 2, 0); + } + + @Override + public void update() { + + super.update(); + + float shift = Game.elapsed * SCROLL_SPEED; + if (reversed) { + shift = -shift; + } + + arcsBg.offset(0, shift); + arcsFg.offset(0, shift * 2); + + offsB = arcsBg.offsetY(); + offsF = arcsFg.offsetY(); + } +} diff --git a/java/com/hmdzl/spspd/ui/AttackIndicator.java b/java/com/hmdzl/spspd/ui/AttackIndicator.java new file mode 100644 index 00000000..b6058b2e --- /dev/null +++ b/java/com/hmdzl/spspd/ui/AttackIndicator.java @@ -0,0 +1,181 @@ +/* + * 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 + */ +package com.hmdzl.spspd.ui; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.scenes.PixelScene; +import com.hmdzl.spspd.sprites.CharSprite; +import com.watabou.noosa.Game; +import com.watabou.utils.Random; + +public class AttackIndicator extends Tag { + + private static final float ENABLED = 1.0f; + private static final float DISABLED = 0.3f; + + private static float delay = 0.75f; + + private static AttackIndicator instance; + + private CharSprite sprite = null; + + private static Mob lastTarget = null; + private ArrayList candidates = new ArrayList(); + + public AttackIndicator() { + super(DangerIndicator.COLOR); + + instance = this; + + setSize(24, 24); + visible(false); + enable(false); + } + + @Override + protected void createChildren() { + super.createChildren(); + } + + @Override + protected void layout() { + super.layout(); + + if (sprite != null) { + sprite.x = x + (width - sprite.width()) / 2; + sprite.y = y + (height - sprite.height()) / 2; + PixelScene.align(sprite); + } + } + + @Override + public void update() { + super.update(); + + if (!bg.visible) { + enable(false); + if (delay > 0f) + delay -= Game.elapsed; + if (delay <= 0f) + active = false; + } else { + delay = 0.75f; + active = true; + + if (Dungeon.hero.isAlive()) { + + enable(Dungeon.hero.ready); + + } else { + visible(false); + enable(false); + } + } + } + + private void checkEnemies() { + + candidates.clear(); + int v = Dungeon.hero.visibleEnemies(); + for (int i = 0; i < v; i++) { + Mob mob = Dungeon.hero.visibleEnemy(i); + if (Dungeon.hero.canAttack(mob)) { + candidates.add(mob); + } + } + + if (!candidates.contains(lastTarget)) { + if (candidates.isEmpty()) { + lastTarget = null; + } else { + active = true; + lastTarget = Random.element(candidates); + updateImage(); + flash(); + } + } else { + if (!bg.visible) { + active = true; + flash(); + } + } + + visible(lastTarget != null); + enable(bg.visible); + } + + private void updateImage() { + + if (sprite != null) { + sprite.killAndErase(); + sprite = null; + } + + try { + sprite = lastTarget.spriteClass.newInstance(); + active = true; + sprite.idle(); + sprite.paused = true; + add(sprite); + + sprite.x = x + (width - sprite.width()) / 2 + 1; + sprite.y = y + (height - sprite.height()) / 2; + PixelScene.align(sprite); + + } catch (Exception e) { + } + } + + private boolean enabled = true; + + private void enable(boolean value) { + enabled = value; + if (sprite != null) { + sprite.alpha(value ? ENABLED : DISABLED); + } + } + + private void visible(boolean value) { + bg.visible = value; + if (sprite != null) { + sprite.visible = value; + } + } + + @Override + protected void onClick() { + if (enabled) { + Dungeon.hero.handle(lastTarget.pos); + } + } + + public static void target(Char target) { + lastTarget = (Mob) target; + instance.updateImage(); + + HealthIndicator.instance.target(target); + } + + public static void updateState() { + instance.checkEnemies(); + } +} diff --git a/java/com/hmdzl/spspd/ui/BadgesList.java b/java/com/hmdzl/spspd/ui/BadgesList.java new file mode 100644 index 00000000..9693d5ed --- /dev/null +++ b/java/com/hmdzl/spspd/ui/BadgesList.java @@ -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 + */ +package com.hmdzl.spspd.ui; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.effects.BadgeBanner; +import com.hmdzl.spspd.scenes.PixelScene; +import com.hmdzl.spspd.windows.WndBadge; +import com.watabou.noosa.Game; +import com.watabou.noosa.Image; +import com.watabou.noosa.audio.Sample; +import com.watabou.noosa.ui.Component; +import com.watabou.noosa.RenderedText; + +public class BadgesList extends ScrollPane { + + private ArrayList items = new ArrayList(); + + public BadgesList(boolean global) { + super(new Component()); + + for (Badges.Badge badge : Badges.filtered(global)) { + + if (badge.image == -1) { + continue; + } + + ListItem item = new ListItem(badge); + content.add(item); + items.add(item); + } + } + + @Override + protected void layout() { + super.layout(); + + float pos = 0; + + int size = items.size(); + for (int i = 0; i < size; i++) { + items.get(i).setRect(0, pos, width, ListItem.HEIGHT); + pos += ListItem.HEIGHT; + } + + content.setSize(width, pos); + } + + @Override + public void onClick(float x, float y) { + int size = items.size(); + for (int i = 0; i < size; i++) { + if (items.get(i).onClick(x, y)) { + break; + } + } + } + + private class ListItem extends Component { + + private static final float HEIGHT = 20; + + private Badges.Badge badge; + + private Image icon; + private RenderedText label; + + public ListItem(Badges.Badge badge) { + super(); + + this.badge = badge; + icon.copy(BadgeBanner.image(badge.image)); + label.text(badge.desc() ); + } + + @Override + protected void createChildren() { + icon = new Image(); + add(icon); + + label = PixelScene.renderText(6); + add(label); + } + + @Override + protected void layout() { + icon.x = x; + icon.y = PixelScene.align(y + (height - icon.height) / 2); + + label.x = icon.x + icon.width + 2; + label.y = PixelScene.align(y + (height - label.baseLine()) / 2); + } + + public boolean onClick(float x, float y) { + if (inside(x, y)) { + Sample.INSTANCE.play(Assets.SND_CLICK, 0.7f, 0.7f, 1.2f); + Game.scene().add(new WndBadge(badge)); + return true; + } else { + return false; + } + } + } +} diff --git a/java/com/hmdzl/spspd/ui/Banner.java b/java/com/hmdzl/spspd/ui/Banner.java new file mode 100644 index 00000000..5c3393d1 --- /dev/null +++ b/java/com/hmdzl/spspd/ui/Banner.java @@ -0,0 +1,102 @@ +/* + * 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 + */ +package com.hmdzl.spspd.ui; + +import com.watabou.noosa.Game; +import com.watabou.noosa.Image; + +public class Banner extends Image { + + private enum State { + FADE_IN, STATIC, FADE_OUT + }; + + private State state; + + private float time; + + private int color; + private float fadeTime; + private float showTime; + + public Banner(Image sample) { + super(); + copy(sample); + alpha(0); + } + + public Banner(Object tx) { + super(tx); + alpha(0); + } + + public void show(int color, float fadeTime, float showTime) { + + this.color = color; + this.fadeTime = fadeTime; + this.showTime = showTime; + + state = State.FADE_IN; + + time = fadeTime; + } + + public void show(int color, float fadeTime) { + show(color, fadeTime, Float.MAX_VALUE); + } + + @Override + public void update() { + super.update(); + + time -= Game.elapsed; + if (time >= 0) { + + float p = time / fadeTime; + + switch (state) { + case FADE_IN: + tint(color, p); + alpha(1 - p); + break; + case STATIC: + break; + case FADE_OUT: + alpha(p); + break; + } + + } else { + + switch (state) { + case FADE_IN: + time = showTime; + state = State.STATIC; + break; + case STATIC: + time = fadeTime; + state = State.FADE_OUT; + break; + case FADE_OUT: + killAndErase(); + break; + } + + } + } +} diff --git a/java/com/hmdzl/spspd/ui/BuffIndicator.java b/java/com/hmdzl/spspd/ui/BuffIndicator.java new file mode 100644 index 00000000..3a6db04f --- /dev/null +++ b/java/com/hmdzl/spspd/ui/BuffIndicator.java @@ -0,0 +1,306 @@ +/* + * 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 + */ +package com.hmdzl.spspd.ui; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.windows.WndInfoBuff; +import com.watabou.gltextures.SmartTexture; +import com.watabou.gltextures.TextureCache; +import com.watabou.noosa.Image; +import com.watabou.noosa.TextureFilm; +import com.watabou.noosa.tweeners.AlphaTweener; +import com.watabou.noosa.ui.Button; +import com.watabou.noosa.ui.Component; +import com.watabou.utils.SparseArray; + +public class BuffIndicator extends Component { + + public static final int NONE = -1; + + public static final int MIND_VISION = 0; + public static final int LEVITATION = 1; + public static final int FIRE = 2; + public static final int POISON = 3; + public static final int PARALYSIS = 4; + public static final int HUNGER = 5; + public static final int STARVATION = 6; + public static final int SLOW = 7; + public static final int OOZE = 8; + public static final int AMOK = 9; + public static final int TERROR = 10; + public static final int ROOTS = 11; + public static final int INVISIBLE = 12; + public static final int SHADOWS = 13; + public static final int WEAKNESS = 14; + public static final int FROST = 15; + public static final int BLINDNESS = 16; + public static final int COMBO = 17; + public static final int FURY = 18; + public static final int HEALING = 19; + public static final int ARMOR = 20; + public static final int HEART = 21; + public static final int LIGHT = 22; + public static final int CRIPPLE = 23; + public static final int BARKSKIN = 24; + public static final int IMMUNITY = 25; + public static final int BLEEDING = 26; + public static final int MARK = 27; + public static final int DEFERRED = 28; + public static final int DROWSY = 29; + public static final int MAGIC_SLEEP = 30; + public static final int THORNS = 31; + public static final int FORESIGHT = 32; + public static final int VERTIGO = 33; + public static final int RECHARGING = 34; + public static final int LOCKED_FLOOR= 35; + public static final int CORRUPT = 36; + public static final int BLESS = 37; + public static final int HASTE = 38; + public static final int REGEN = 39; + public static final int COUNTDOWN = 40; + public static final int MOON_FURY = 41; + public static final int DEWCHARGE = 42; + public static final int DISPEL = 43; + public static final int PFIRE = 44; + public static final int PTOXIC = 45; + public static final int PEARTH = 46; + public static final int PBLOOD = 47; + public static final int SHIELDBLOCK = 48; + public static final int OVERFED = 49; + public static final int TAR = 50; + public static final int WET = 51; + public static final int HOT = 52; + public static final int COLD = 53; + public static final int DRY = 54; + public static final int SILENT = 55; + public static final int DISARM = 56; + public static final int GLASS_SHIELD = 57; + public static final int ARMOR_BREAK = 58; + public static final int TAUNT = 59; + public static final int GROW_SEED = 60; + public static final int ATTACK_UP = 61; + public static final int SHOCKED = 62; + public static final int RHYTHM = 63; + public static final int RHYTHM2 = 64; + public static final int ARCANE = 65; + public static final int NO_FUSHIGI = 66; + public static final int GOLDTOUCH = 67; + public static final int NEEDLING = 68; + public static final int FEED = 69; + public static final int NOTICE = 70; + public static final int BLOODANGRY = 71; + public static final int WARGROOVE = 72; + public static final int MECHARMOR = 73; + public static final int VOICE_UP = 74; + public static final int HIGH_ATTACK = 75; + public static final int SMASH = 76; + public static final int UNKNOW_BOX = 77; + public static final int MIRROR_SHIELD = 78; + + public static final int HUMAN_FAITH = 79; + public static final int DEMON_FAITH = 80; + public static final int LIFE_FAITH = 81; + public static final int MECH_FAITH = 82; + public static final int BALANCE_FAITH = 83; + + public static final int STONE_ICE = 84; + public static final int BUFF_REMOVE = 85; + public static final int BUFF_CURSE = 86; + + public static final int SIZE = 7; + + /*private static BuffIndicator heroInstance; + + private SmartTexture texture; + private TextureFilm film; + + private SparseArray icons = new SparseArray(); + + private Char ch; + + public BuffIndicator(Char ch) { + super(); + + this.ch = ch; + if (ch == Dungeon.hero) { + heroInstance = this; + } + } + + @Override + public void destroy() { + super.destroy(); + + if (this == heroInstance) { + heroInstance = null; + } + } + + @Override + protected void createChildren() { + texture = TextureCache.get(Assets.BUFFS_SMALL); + film = new TextureFilm(texture, SIZE, SIZE); + } + + @Override + protected void layout() { + clear(); + + SparseArray newIcons = new SparseArray(); + + for (Buff buff : ch.buffs()) { + int icon = buff.icon(); + if (icon != NONE) { + Image img = new Image(texture); + img.frame(film.get(icon)); + img.x = x + members.size() * (SIZE + 2); + img.y = y; + add(img); + + newIcons.put(icon, img); + } + } + + for (Integer key : icons.keyArray()) { + if (newIcons.get(key) == null) { + Image icon = icons.get(key); + icon.origin.set(SIZE / 2); + add(icon); + add(new AlphaTweener(icon, 0, 0.6f) { + @Override + protected void updateValues(float progress) { + super.updateValues(progress); + image.scale.set(1 + 5 * progress); + }; + }); + } + } + + icons = newIcons; + } + + public static void refreshHero() { + if (heroInstance != null) { + heroInstance.layout(); + } + }*/ + private static BuffIndicator heroInstance; + + private SmartTexture texture; + private TextureFilm film; + + private SparseArray icons = new SparseArray(); + + private Char ch; + + public BuffIndicator( Char ch ) { + super(); + + this.ch = ch; + if (ch == Dungeon.hero) { + heroInstance = this; + } + } + + @Override + public void destroy() { + super.destroy(); + + if (this == heroInstance) { + heroInstance = null; + } + } + + @Override + protected void createChildren() { + texture = TextureCache.get( Assets.BUFFS_SMALL ); + film = new TextureFilm( texture, SIZE, SIZE ); + } + + @Override + protected void layout() { + clear(); + + SparseArray newIcons = new SparseArray(); + + for (Buff buff : ch.buffs()) { + if (buff.icon() != NONE) { + BuffIcon icon = new BuffIcon( buff ); + icon.setRect(x + members.size() * (SIZE + 2), y, 9, 12); + add(icon); + newIcons.put( buff.icon(), icon ); + } + } + + for (Integer key : icons.keyArray()) { + if (newIcons.get( key ) == null) { + Image icon = icons.get( key ).icon; + icon.origin.set( SIZE / 2 ); + add( icon ); + add( new AlphaTweener( icon, 0, 0.6f ) { + @Override + protected void updateValues( float progress ) { + super.updateValues( progress ); + image.scale.set( 1 + 5 * progress ); + }; + } ); + } + } + + icons = newIcons; + } + + private class BuffIcon extends Button { + + private Buff buff; + + public Image icon; + + public BuffIcon( Buff buff ){ + super(); + this.buff = buff; + + icon = new Image( texture ); + icon.frame( film.get( buff.icon() ) ); + add( icon ); + } + + @Override + protected void layout() { + super.layout(); + icon.x = this.x+1; + icon.y = this.y+2; + } + + @Override + protected void onClick() { + GameScene.show(new WndInfoBuff(buff)); + } + } + + public static void refreshHero() { + if (heroInstance != null) { + heroInstance.layout(); + } + } + +} diff --git a/java/com/hmdzl/spspd/ui/BusyIndicator.java b/java/com/hmdzl/spspd/ui/BusyIndicator.java new file mode 100644 index 00000000..f77728b5 --- /dev/null +++ b/java/com/hmdzl/spspd/ui/BusyIndicator.java @@ -0,0 +1,38 @@ +/* + * 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 + */ +package com.hmdzl.spspd.ui; + +import com.hmdzl.spspd.Dungeon; +import com.watabou.noosa.Image; + +public class BusyIndicator extends Image { + + public BusyIndicator() { + super(); + copy(Icons.BUSY.get()); + + origin.set(width / 2, height / 2); + angularSpeed = 720; + } + + @Override + public void update() { + super.update(); + visible = Dungeon.hero.isAlive() && !Dungeon.hero.ready; + } +} diff --git a/java/com/hmdzl/spspd/ui/ChangesButton.java b/java/com/hmdzl/spspd/ui/ChangesButton.java new file mode 100644 index 00000000..81e9ec4a --- /dev/null +++ b/java/com/hmdzl/spspd/ui/ChangesButton.java @@ -0,0 +1,72 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2015 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.ui; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.ShatteredPixelDungeon; +import com.hmdzl.spspd.scenes.WelcomeScene; +import com.watabou.noosa.Image; +import com.watabou.noosa.audio.Sample; +import com.watabou.noosa.ui.Button; + +public class ChangesButton extends Button { + + protected Image image; + + public ChangesButton() { + super(); + + width = image.width; + height = image.height; + } + + @Override + protected void createChildren() { + super.createChildren(); + + image = Icons.NOTES.get(); + add( image ); + } + + @Override + protected void layout() { + super.layout(); + + image.x = x; + image.y = y; + } + + @Override + protected void onTouchDown() { + image.brightness( 1.5f ); + Sample.INSTANCE.play( Assets.SND_CLICK ); + } + + @Override + protected void onTouchUp() { + image.resetColor(); + } + + @Override + protected void onClick() { + ShatteredPixelDungeon.switchNoFade(WelcomeScene.class); + } +} diff --git a/java/com/hmdzl/spspd/ui/CharHealthIndicator.java b/java/com/hmdzl/spspd/ui/CharHealthIndicator.java new file mode 100644 index 00000000..ad51eccf --- /dev/null +++ b/java/com/hmdzl/spspd/ui/CharHealthIndicator.java @@ -0,0 +1,72 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2019 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ + +package com.hmdzl.spspd.ui; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.CharSprite; + +public class CharHealthIndicator extends HealthBar { + + private static final int HEIGHT = 1; + + private Char target; + + public CharHealthIndicator( Char c ){ + target = c; + GameScene.add(this); + } + + @Override + protected void createChildren() { + super.createChildren(); + height = HEIGHT; + } + + @Override + public void update() { + super.update(); + + if (target != null && target.isAlive() && target.sprite.visible) { + CharSprite sprite = target.sprite; + width = sprite.width()*(4/6f); + x = sprite.x + sprite.width()/6f; + y = sprite.y - 2; + level( target ); + visible = target.HP < target.HT; + } else { + visible = false; + } + } + + public void target( Char ch ) { + if (ch != null && ch.isAlive()) { + target = ch; + } else { + target = null; + } + } + + public Char target() { + return target; + } +} diff --git a/java/com/hmdzl/spspd/ui/CheckBox.java b/java/com/hmdzl/spspd/ui/CheckBox.java new file mode 100644 index 00000000..916562a6 --- /dev/null +++ b/java/com/hmdzl/spspd/ui/CheckBox.java @@ -0,0 +1,64 @@ +/* + * 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 + */ +package com.hmdzl.spspd.ui; + +import com.hmdzl.spspd.scenes.PixelScene; + +public class CheckBox extends RedButton { + + private boolean checked = false; + + public CheckBox(String label) { + super(label); + + icon(Icons.get(Icons.UNCHECKED)); + } + + @Override + protected void layout() { + super.layout(); + + float margin = (height - text.baseLine()) / 2; + + text.x = PixelScene.align(PixelScene.uiCamera, x + margin); + text.y = PixelScene.align(PixelScene.uiCamera, y + margin); + + margin = (height - icon.height) / 2; + + icon.x = PixelScene.align(PixelScene.uiCamera, x + width - margin + - icon.width); + icon.y = PixelScene.align(PixelScene.uiCamera, y + margin); + } + + public boolean checked() { + return checked; + } + + public void checked(boolean value) { + if (checked != value) { + checked = value; + icon.copy(Icons.get(checked ? Icons.CHECKED : Icons.UNCHECKED)); + } + } + + @Override + protected void onClick() { + super.onClick(); + checked(!checked); + } +} diff --git a/java/com/hmdzl/spspd/ui/Compass.java b/java/com/hmdzl/spspd/ui/Compass.java new file mode 100644 index 00000000..8f379199 --- /dev/null +++ b/java/com/hmdzl/spspd/ui/Compass.java @@ -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 + */ +package com.hmdzl.spspd.ui; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.DungeonTilemap; +import com.watabou.noosa.Camera; +import com.watabou.noosa.Image; +import com.watabou.utils.PointF; + +public class Compass extends Image { + + private static final float RAD_2_G = 180f / 3.1415926f; + private static final float RADIUS = 12; + + private int cell; + private PointF cellCenter; + + private PointF lastScroll = new PointF(); + + public Compass(int cell) { + + super(); + copy(Icons.COMPASS.get()); + origin.set(width / 2, RADIUS); + + this.cell = cell; + cellCenter = DungeonTilemap.tileCenterToWorld(cell); + visible = false; + } + + @Override + public void update() { + super.update(); + + if (!visible) { + visible = Dungeon.level.visited[cell] || Dungeon.level.mapped[cell]; + } + + if (visible) { + PointF scroll = Camera.main.scroll; + if (!scroll.equals(lastScroll)) { + lastScroll.set(scroll); + PointF center = Camera.main.center().offset(scroll); + angle = (float) Math.atan2(cellCenter.x - center.x, center.y + - cellCenter.y) + * RAD_2_G; + } + } + } +} diff --git a/java/com/hmdzl/spspd/ui/CustomTileVisual.java b/java/com/hmdzl/spspd/ui/CustomTileVisual.java new file mode 100644 index 00000000..94d005b3 --- /dev/null +++ b/java/com/hmdzl/spspd/ui/CustomTileVisual.java @@ -0,0 +1,123 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2015 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.ui; + +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.Room; +import com.watabou.noosa.Image; +import com.watabou.utils.Bundlable; +import com.watabou.utils.Bundle; + +import java.util.ArrayList; + +public abstract class CustomTileVisual extends Image implements Bundlable { + + protected static final int TILE_SIZE = 16; + + public String name; + + protected String tx; //string for resource file + protected int txX, txY; //position(in tiles) within resource file + //bundleable offsets from the standard texture xy, useful for mapping larger than 1x1 textures to many tiles + //(e.g. mapping a 3x3 texture to a room, where the corners are walls and the center is the floor) + protected int ofsX = 0, ofsY = 0; + + public int tileX, tileY; //x and y coords for texture within a level + public int tileW = 1, tileH = 1; //width and height in tiles + + public void pos(int pos) { + pos( pos%Level.WIDTH, pos/Level.WIDTH ); + } + + public void pos(int tileX, int tileY){ + this.tileX = tileX; + this.tileY = tileY; + } + + public String desc(){ + return null; + } + + public CustomTileVisual create() { + texture(tx); + frame(texture.uvRect((txX + ofsX) * TILE_SIZE, (txY + ofsY) * TILE_SIZE, + (txX + ofsX + tileW) * TILE_SIZE, (txY + ofsY + tileH) * TILE_SIZE)); + + x = tileX*TILE_SIZE; + y = tileY*TILE_SIZE; + + return this; + } + + //returns a number of 1x1 tiles to fill a room, based on a 3x3 texture, not dissimilar to a ninepatch. + public static ArrayList CustomTilesForRoom(Room r, Class c){ + ArrayList result = new ArrayList<>(); + + try { + for (int x = r.left; x <= r.right; x++) { + for (int y = r.top; y <= r.bottom; y++) { + CustomTileVisual vis = c.newInstance(); + + if (x == r.right) vis.ofsX = 2; + else if (x != r.left) vis.ofsX = 1; + + if (y == r.bottom) vis.ofsY = 2; + else if (y != r.top) vis.ofsY = 1; + + vis.pos(x, y); + result.add(vis); + } + } + } catch (InstantiationException | IllegalAccessException e) { + throw new RuntimeException("Something went wrong while making a bunch of tile visuals for a room!", e); + } + + return result; + } + + private static final String TILE_X = "tileX"; + private static final String TILE_Y = "tileY"; + + private static final String OFS_X = "ofsX"; + private static final String OFS_Y = "ofsY"; + + @Override + public void restoreFromBundle(Bundle bundle) { + tileX = bundle.getInt(TILE_X); + tileY = bundle.getInt(TILE_Y); + + //if these weren't stored they will default to 0 + ofsX = bundle.getInt(OFS_X); + ofsY = bundle.getInt(OFS_Y); + } + + @Override + public void storeInBundle(Bundle bundle) { + bundle.put(TILE_X, tileX); + bundle.put(TILE_Y, tileY); + + //don't need to store this in all cases + if (ofsX != 0 || ofsY != 0){ + bundle.put(OFS_X, ofsX); + bundle.put(OFS_Y, ofsY); + } + } +} diff --git a/java/com/hmdzl/spspd/ui/DangerIndicator.java b/java/com/hmdzl/spspd/ui/DangerIndicator.java new file mode 100644 index 00000000..eec31785 --- /dev/null +++ b/java/com/hmdzl/spspd/ui/DangerIndicator.java @@ -0,0 +1,107 @@ +/* + * 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 + */ +package com.hmdzl.spspd.ui; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.scenes.PixelScene; +import com.watabou.noosa.BitmapText; +import com.watabou.noosa.Camera; +import com.watabou.noosa.Image; + +public class DangerIndicator extends Tag { + + public static final int COLOR = 0xFF4C4C; + + private BitmapText number; + private Image icon; + + private int enemyIndex = 0; + + private int lastNumber = -1; + + public DangerIndicator() { + super(0xFF4C4C); + + setSize(24, 16); + + visible = false; + } + + @Override + protected void createChildren() { + super.createChildren(); + + number = new BitmapText(PixelScene.font1x); + add(number); + + icon = Icons.SKULL.get(); + add(icon); + } + + @Override + protected void layout() { + super.layout(); + + icon.x = right() - 10; + icon.y = y + (height - icon.height) / 2; + + placeNumber(); + } + + private void placeNumber() { + number.x = right() - 11 - number.width(); + number.y = PixelScene.align(y + (height - number.baseLine()) / 2); + } + + @Override + public void update() { + + if (Dungeon.hero.isAlive()) { + int v = Dungeon.hero.visibleEnemies(); + if (v != lastNumber) { + lastNumber = v; + if (visible = lastNumber > 0) { + number.text(Integer.toString(lastNumber)); + number.measure(); + placeNumber(); + + flash(); + } + } + } else { + visible = false; + } + + super.update(); + } + + @Override + protected void onClick() { + + Mob target = Dungeon.hero.visibleEnemy(enemyIndex++); + + HealthIndicator.instance.target(target == HealthIndicator.instance + .target() ? null : target); + + if (Dungeon.hero.curAction == null) { + Camera.main.target = null; + Camera.main.focusOn(target.sprite); + } + } +} diff --git a/java/com/hmdzl/spspd/ui/ExitButton.java b/java/com/hmdzl/spspd/ui/ExitButton.java new file mode 100644 index 00000000..172225b5 --- /dev/null +++ b/java/com/hmdzl/spspd/ui/ExitButton.java @@ -0,0 +1,74 @@ +/* + * 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 + */ +package com.hmdzl.spspd.ui; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.ShatteredPixelDungeon; +import com.hmdzl.spspd.scenes.TitleScene; +import com.watabou.noosa.Game; +import com.watabou.noosa.Image; +import com.watabou.noosa.audio.Sample; +import com.watabou.noosa.ui.Button; + +public class ExitButton extends Button { + + protected Image image; + + public ExitButton() { + super(); + + width = image.width; + height = image.height; + } + + @Override + protected void createChildren() { + super.createChildren(); + + image = Icons.EXIT.get(); + add(image); + } + + @Override + protected void layout() { + super.layout(); + + image.x = x; + image.y = y; + } + + @Override + protected void onTouchDown() { + image.brightness(1.5f); + Sample.INSTANCE.play(Assets.SND_CLICK); + } + + @Override + protected void onTouchUp() { + image.resetColor(); + } + + @Override + protected void onClick() { + if (Game.scene() instanceof TitleScene) { + Game.instance.finish(); + } else { + ShatteredPixelDungeon.switchNoFade(TitleScene.class); + } + } +} diff --git a/java/com/hmdzl/spspd/ui/GameLog.java b/java/com/hmdzl/spspd/ui/GameLog.java new file mode 100644 index 00000000..71b355e7 --- /dev/null +++ b/java/com/hmdzl/spspd/ui/GameLog.java @@ -0,0 +1,157 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2016 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.ui; + +import com.hmdzl.spspd.scenes.PixelScene; +import com.hmdzl.spspd.sprites.CharSprite; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.noosa.ui.Component; +import com.watabou.utils.Signal; + +import java.util.ArrayList; +import java.util.regex.Pattern; + +public class GameLog extends Component implements Signal.Listener { + + private static final int MAX_LINES = 3; + + private static final Pattern PUNCTUATION = Pattern.compile( ".*[.,;?! ]$" ); + + private RenderedTextMultiline lastEntry; + private int lastColor; + + private static ArrayList entries = new ArrayList(); + + public GameLog() { + super(); + GLog.update.replace( this ); + + recreateLines(); + } + + private void recreateLines() { + for (Entry entry : entries) { + lastEntry = PixelScene.renderMultiline( entry.text, 6 ); + lastEntry.hardlight( lastColor = entry.color ); + add( lastEntry ); + } + } + + public void newLine() { + lastEntry = null; + } + + @Override + public void onSignal( String text ) { + + if (length != entries.size()){ + clear(); + recreateLines(); + } + + int color = CharSprite.DEFAULT; + if (text.startsWith( GLog.POSITIVE )) { + text = text.substring( GLog.POSITIVE.length() ); + color = CharSprite.POSITIVE; + } else + if (text.startsWith( GLog.NEGATIVE )) { + text = text.substring( GLog.NEGATIVE.length() ); + color = CharSprite.NEGATIVE; + } else + if (text.startsWith( GLog.WARNING )) { + text = text.substring( GLog.WARNING.length() ); + color = CharSprite.WARNING; + } else + if (text.startsWith( GLog.HIGHLIGHT )) { + text = text.substring( GLog.HIGHLIGHT.length() ); + color = CharSprite.NEUTRAL; + } + + if (lastEntry != null && color == lastColor && lastEntry.nLines < MAX_LINES) { + + String lastMessage = lastEntry.text(); + lastEntry.text( lastMessage.length() == 0 ? text : lastMessage + " " + text ); + + entries.get( entries.size() - 1 ).text = lastEntry.text(); + + } else { + + lastEntry = PixelScene.renderMultiline( text, 6 ); + lastEntry.hardlight( color ); + lastColor = color; + add( lastEntry ); + + entries.add( new Entry( text, color ) ); + + } + + if (length > 0) { + int nLines; + do { + nLines = 0; + for (int i = 0; i < length-1; i++) { + nLines += ((RenderedTextMultiline) members.get(i)).nLines; + } + + if (nLines > MAX_LINES) { + remove(members.get(0)); + + entries.remove( 0 ); + } + } while (nLines > MAX_LINES); + if (entries.isEmpty()) { + lastEntry = null; + } + } + + layout(); + } + + @Override + protected void layout() { + float pos = y; + for (int i=length-1; i >= 0; i--) { + RenderedTextMultiline entry = (RenderedTextMultiline)members.get( i ); + entry.maxWidth((int)width); + entry.setPos(x, pos-entry.height()); + pos -= entry.height(); + } + } + + @Override + public void destroy() { + GLog.update.remove( this ); + super.destroy(); + } + + private static class Entry { + public String text; + public int color; + public Entry( String text, int color ) { + this.text = text; + this.color = color; + } + } + + public static void wipe() { + entries.clear(); + } +} diff --git a/java/com/hmdzl/spspd/ui/GoldIndicator.java b/java/com/hmdzl/spspd/ui/GoldIndicator.java new file mode 100644 index 00000000..66c54b0e --- /dev/null +++ b/java/com/hmdzl/spspd/ui/GoldIndicator.java @@ -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 + */ +package com.hmdzl.spspd.ui; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.scenes.PixelScene; +import com.watabou.noosa.BitmapText; +import com.watabou.noosa.Game; +import com.watabou.noosa.ui.Component; + +public class GoldIndicator extends Component { + + private static final float TIME = 2f; + + private int lastValue = 0; + + private BitmapText tf; + + private float time; + + @Override + protected void createChildren() { + tf = new BitmapText(PixelScene.font1x); + tf.hardlight(0xFFFF00); + add(tf); + + visible = false; + } + + @Override + protected void layout() { + tf.x = x + (width - tf.width()) / 2; + tf.y = bottom() - tf.height(); + } + + @Override + public void update() { + super.update(); + + if (visible) { + + time -= Game.elapsed; + if (time > 0) { + tf.alpha(time > TIME / 2 ? 1f : time * 2 / TIME); + } else { + visible = false; + } + + } + + if (Dungeon.gold != lastValue) { + + lastValue = Dungeon.gold; + + tf.text(Integer.toString(lastValue)); + tf.measure(); + + visible = true; + time = TIME; + + layout(); + } + } +} diff --git a/java/com/hmdzl/spspd/ui/HealthBar.java b/java/com/hmdzl/spspd/ui/HealthBar.java new file mode 100644 index 00000000..7f48575b --- /dev/null +++ b/java/com/hmdzl/spspd/ui/HealthBar.java @@ -0,0 +1,122 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 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 + */ +package com.hmdzl.spspd.ui; + +import com.hmdzl.spspd.actors.Char; +import com.watabou.noosa.ColorBlock; +import com.watabou.noosa.ui.Component; + +public class HealthBar extends Component { + + /*private static final int COLOR_BG = 0xFFCC0000; + private static final int COLOR_LVL = 0xFF00EE00; + + private static final int HEIGHT = 2; + + private ColorBlock hpBg; + private ColorBlock hpLvl; + + private float level; + + @Override + protected void createChildren() { + hpBg = new ColorBlock(1, 1, COLOR_BG); + add(hpBg); + + hpLvl = new ColorBlock(1, 1, COLOR_LVL); + add(hpLvl); + + height = HEIGHT; + } + + @Override + protected void layout() { + + hpBg.x = hpLvl.x = x; + hpBg.y = hpLvl.y = y; + + hpBg.size(width, HEIGHT); + hpLvl.size(width * level, HEIGHT); + + height = HEIGHT; + } + + public void level(float value) { + level = value; + layout(); + }*/ + + private static final int COLOR_BG = 0xFFCC0000; + private static final int COLOR_HP = 0xFF00EE00; + private static final int COLOR_SHLD = 0xFFBBEEBB; + + private static final int HEIGHT = 2; + + private ColorBlock Bg; + private ColorBlock Shld; + private ColorBlock Hp; + + private float health; + private float shield; + + @Override + protected void createChildren() { + Bg = new ColorBlock( 1, 1, COLOR_BG ); + add( Bg ); + + Shld = new ColorBlock( 1, 1, COLOR_SHLD ); + add( Shld ); + + Hp = new ColorBlock( 1, 1, COLOR_HP ); + add( Hp ); + + height = HEIGHT; + } + + @Override + protected void layout() { + + Bg.x = Shld.x = Hp.x = x; + Bg.y = Shld.y = Hp.y = y; + + Bg.size( width, height ); + + //logic here rounds up to the nearest pixel + float pixelWidth = width; + if (camera() != null) pixelWidth *= camera().zoom; + Shld.size( width * (float)Math.ceil(shield * pixelWidth)/pixelWidth, height ); + Hp.size( width * (float)Math.ceil(health * pixelWidth)/pixelWidth, height ); + } + + public void level( float value ) { + level( value, 0f ); + } + + public void level( float health, float shield ){ + this.health = health; + this.shield = shield; + layout(); + } + + public void level(Char c){ + float health = c.HP; + float max = Math.max(health+shield, c.HT); + + level(health/max, (health+shield)/max); + } +} diff --git a/java/com/hmdzl/spspd/ui/HealthIndicator.java b/java/com/hmdzl/spspd/ui/HealthIndicator.java new file mode 100644 index 00000000..e4840023 --- /dev/null +++ b/java/com/hmdzl/spspd/ui/HealthIndicator.java @@ -0,0 +1,82 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2014 Oleg Dolya + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.ui; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.sprites.CharSprite; +import com.watabou.gltextures.TextureCache; +import com.watabou.noosa.Image; +import com.watabou.noosa.ui.Component; + +public class HealthIndicator extends Component { + + private static final float HEIGHT = 2; + + public static HealthIndicator instance; + + private Char target; + + private Image bg; + private Image level; + + public HealthIndicator() { + super(); + + instance = this; + } + + @Override + protected void createChildren() { + bg = new Image(TextureCache.createSolid(0xFFcc0000)); + bg.scale.y = HEIGHT; + add(bg); + + level = new Image(TextureCache.createSolid(0xFF00cc00)); + level.scale.y = HEIGHT; + add(level); + } + + @Override + public void update() { + super.update(); + + if (target != null && target.isAlive() && target.sprite.visible) { + CharSprite sprite = target.sprite; + bg.scale.x = sprite.width; + level.scale.x = sprite.width * target.HP / target.HT; + bg.x = level.x = sprite.x; + bg.y = level.y = sprite.y - HEIGHT - 1; + + visible = true; + } else { + visible = false; + } + } + + public void target(Char ch) { + if (ch != null && ch.isAlive()) { + target = ch; + } else { + target = null; + } + } + + public Char target() { + return target; + } +} diff --git a/java/com/hmdzl/spspd/ui/IconButton.java b/java/com/hmdzl/spspd/ui/IconButton.java new file mode 100644 index 00000000..b9deb592 --- /dev/null +++ b/java/com/hmdzl/spspd/ui/IconButton.java @@ -0,0 +1,84 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2018 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ + +package com.hmdzl.spspd.ui; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.scenes.PixelScene; +import com.watabou.noosa.Image; +import com.watabou.noosa.audio.Sample; +import com.watabou.noosa.ui.Button; + +public class IconButton extends Button { + + protected Image icon; + + public IconButton(){ + super(); + } + + public IconButton( Image icon ){ + super(); + icon( icon ); + } + + @Override + protected void layout() { + super.layout(); + + if (icon != null) { + icon.x = x + (width - icon.width()) / 2f; + icon.y = y + (height - icon.height()) / 2f; + PixelScene.align(icon); + } + } + + @Override + protected void onTouchDown() { + if (icon != null) icon.brightness( 1.5f ); + Sample.INSTANCE.play( Assets.SND_CLICK ); + } + + @Override + protected void onTouchUp() { + if (icon != null) icon.resetColor(); + } + + public void enable( boolean value ) { + active = value; + if (icon != null) icon.alpha( value ? 1.0f : 0.3f ); + } + + public void icon( Image icon ) { + if (this.icon != null) { + remove( this.icon ); + } + this.icon = icon; + if (this.icon != null) { + add( this.icon ); + layout(); + } + } + + public Image icon(){ + return icon; + } +} diff --git a/java/com/hmdzl/spspd/ui/Icons.java b/java/com/hmdzl/spspd/ui/Icons.java new file mode 100644 index 00000000..dbb31b0b --- /dev/null +++ b/java/com/hmdzl/spspd/ui/Icons.java @@ -0,0 +1,178 @@ +/* + * 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 + */ +package com.hmdzl.spspd.ui; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.actors.hero.HeroClass; +import com.watabou.noosa.Image; + +public enum Icons { + + SKULL, BUSY, COMPASS, INFO, PREFS, WARNING, TARGET, MASTERY, WATA, SHPX, WARRIOR, MAGE, ROGUE, HUNTRESS, PERFORMER, SOLDIER, FOLLOWER, CLOSE, DEPTH, SLEEP, ALERT, + BACKPACK, SEED_POUCH, SCROLL_HOLDER, POTION_BANDOLIER, WAND_HOLSTER, CHECKED, UNCHECKED, EXIT, CHALLENGE_OFF, CHALLENGE_ON, RESUME, SHOP_CART, KEYRING, + LAN, NOTES, SAVELOAD, HOS, LOST; + + public Image get() { + return get(this); + } + + public static Image get(Icons type) { + Image icon = new Image(Assets.ICONS); + switch (type) { + case SKULL: + icon.frame(icon.texture.uvRect(0, 0, 8, 8)); + break; + case BUSY: + icon.frame(icon.texture.uvRect(8, 0, 16, 8)); + break; + case COMPASS: + icon.frame(icon.texture.uvRect(0, 8, 7, 13)); + break; + case INFO: + icon.frame(icon.texture.uvRect(16, 0, 30, 14)); + break; + case PREFS: + icon.frame(icon.texture.uvRect(30, 0, 46, 16)); + break; + case WARNING: + icon.frame(icon.texture.uvRect(46, 0, 58, 12)); + break; + case TARGET: + icon.frame(icon.texture.uvRect(0, 13, 16, 29)); + break; + case MASTERY: + icon.frame(icon.texture.uvRect(16, 14, 30, 28)); + break; + case WATA: + icon.frame(icon.texture.uvRect(30, 16, 45, 26)); + break; + case SHPX: + icon.frame(icon.texture.uvRect(64, 44, 80, 60)); + break; + case WARRIOR: + icon.frame(icon.texture.uvRect(0, 29, 16, 45)); + break; + case MAGE: + icon.frame(icon.texture.uvRect(16, 29, 32, 45)); + break; + case ROGUE: + icon.frame(icon.texture.uvRect(32, 29, 48, 45)); + break; + case HUNTRESS: + icon.frame(icon.texture.uvRect(48, 29, 64, 45)); + break; + case PERFORMER: + icon.frame(icon.texture.uvRect(48, 65, 60, 74)); + break; + case SOLDIER: + icon.frame(icon.texture.uvRect(64, 64, 78, 78)); + break; + case FOLLOWER: + icon.frame(icon.texture.uvRect(86, 62, 97, 73)); + break; + case CLOSE: + icon.frame(icon.texture.uvRect(0, 45, 13, 58)); + break; + case DEPTH: + icon.frame( icon.texture.uvRect( 38, 46, 54, 62 ) ); + break; + case SLEEP: + icon.frame(icon.texture.uvRect(13, 45, 22, 53)); + break; + case ALERT: + icon.frame(icon.texture.uvRect(22, 45, 30, 53)); + break; + case LOST: + icon.frame( icon.texture.uvRect( 30, 45, 38, 53 ) ); + break; + case BACKPACK: + icon.frame(icon.texture.uvRect(58, 0, 68, 10)); + break; + case SCROLL_HOLDER: + icon.frame(icon.texture.uvRect(68, 0, 78, 10)); + break; + case SEED_POUCH: + icon.frame(icon.texture.uvRect(78, 0, 88, 10)); + break; + case WAND_HOLSTER: + icon.frame(icon.texture.uvRect(88, 0, 98, 10)); + break; + case POTION_BANDOLIER: + icon.frame(icon.texture.uvRect(98, 0, 108, 10)); + break; + case CHECKED: + icon.frame(icon.texture.uvRect(54, 12, 66, 24)); + break; + case UNCHECKED: + icon.frame(icon.texture.uvRect(66, 12, 78, 24)); + break; + case EXIT: + icon.frame(icon.texture.uvRect(108, 0, 124, 16)); + break; + case CHALLENGE_OFF: + icon.frame(icon.texture.uvRect(78, 16, 102, 40)); + break; + case CHALLENGE_ON: + icon.frame(icon.texture.uvRect(102, 16, 126, 40)); + break; + case RESUME: + icon.frame(icon.texture.uvRect(13, 53, 24, 64)); + break; + case SHOP_CART: + icon.frame(icon.texture.uvRect(82, 47, 92, 57)); + break; + case KEYRING: + icon.frame(icon.texture.uvRect(66, 29, 72, 39)); + break; + case LAN: + icon.frame(icon.texture.uvRect(2, 65, 25, 77)); + break; + case NOTES: + icon.frame( icon.texture.uvRect( 110, 43, 125, 59 )); + break; + case SAVELOAD: + icon.frame( icon.texture.uvRect( 97, 46, 108, 56 )); + break; + case HOS: + icon.frame( icon.texture.uvRect( 30, 65, 41, 75 )); + break; + } + return icon; + } + + public static Image get(HeroClass cl) { + switch (cl) { + case WARRIOR: + return get(WARRIOR); + case MAGE: + return get(MAGE); + case ROGUE: + return get(ROGUE); + case HUNTRESS: + return get(HUNTRESS); + case PERFORMER: + return get(PERFORMER); + case SOLDIER: + return get(SOLDIER); + case FOLLOWER: + return get(FOLLOWER); + default: + return null; + } + } +} diff --git a/java/com/hmdzl/spspd/ui/ItemSlot.java b/java/com/hmdzl/spspd/ui/ItemSlot.java new file mode 100644 index 00000000..f07928f3 --- /dev/null +++ b/java/com/hmdzl/spspd/ui/ItemSlot.java @@ -0,0 +1,295 @@ +/* + * 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 + */ +package com.hmdzl.spspd.ui; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.armor.Armor; +import com.hmdzl.spspd.items.keys.Key; +import com.hmdzl.spspd.items.keys.SkeletonKey; +import com.hmdzl.spspd.items.potions.Potion; +import com.hmdzl.spspd.items.scrolls.Scroll; +import com.hmdzl.spspd.items.weapon.Weapon; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.items.weapon.melee.MeleeWeapon; +import com.hmdzl.spspd.scenes.PixelScene; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; + +import com.watabou.noosa.BitmapText; +import com.watabou.noosa.Image; +import com.watabou.noosa.ui.Button; + +public class ItemSlot extends Button { + + public static final int DEGRADED = 0xFF4444; + public static final int UPGRADED = 0x44FF44; + public static final int WARNING = 0xFF8800; + + private static final float ENABLED = 1.0f; + private static final float DISABLED = 0.3f; + + protected ItemSprite icon; + protected BitmapText topLeft; + protected BitmapText topRight; + protected BitmapText bottomRight; + protected Image bottomRightIcon; + protected BitmapText bottomLeft; + protected Image bottomLeftIcon; + protected boolean iconVisible = true; + protected boolean iconVisible2 = true; + + private static final String TXT_STRENGTH = ":%d"; + private static final String TXT_TYPICAL_STR = "%d?"; + private static final String TXT_KEY_DEPTH = "\u007F%d"; + + private static final String TXT_LEVEL = "%+d"; + private static final String TXT_CURSED = "";// "-"; + + // Special "virtual items" + public static final Item CHEST = new Item() { + @Override + public int image() { + return ItemSpriteSheet.CHEST; + }; + }; + public static final Item LOCKED_CHEST = new Item() { + @Override + public int image() { + return ItemSpriteSheet.LOCKED_CHEST; + }; + }; + public static final Item CRYSTAL_CHEST = new Item() { + @Override + public int image() { + return ItemSpriteSheet.CRYSTAL_CHEST; + }; + }; + public static final Item TOMB = new Item() { + @Override + public int image() { + return ItemSpriteSheet.TOMB; + }; + }; + public static final Item SKELETON = new Item() { + @Override + public int image() { + return ItemSpriteSheet.BONES; + }; + }; + public static final Item REMAINS = new Item() { + @Override + public int image() { + return ItemSpriteSheet.REMAINS; + }; + }; + + public ItemSlot() { + super(); + } + + public ItemSlot(Item item) { + this(); + item(item); + } + + @Override + protected void createChildren() { + + super.createChildren(); + + icon = new ItemSprite(); + add(icon); + + topLeft = new BitmapText(PixelScene.font1x); + add(topLeft); + + topRight = new BitmapText(PixelScene.font1x); + add(topRight); + + bottomRight = new BitmapText(PixelScene.font1x); + add(bottomRight); + + bottomLeft = new BitmapText(PixelScene.font1x); + add(bottomLeft); + } + + @Override + protected void layout() { + super.layout(); + + icon.x = x + (width - icon.width) / 2; + icon.y = y + (height - icon.height) / 2; + + if (topLeft != null) { + topLeft.x = x; + topLeft.y = y; + } + + if (topRight != null) { + topRight.x = x + (width - topRight.width()); + topRight.y = y; + } + + if (bottomRight != null) { + bottomRight.x = x + (width - bottomRight.width()); + bottomRight.y = y + (height - bottomRight.height()); + } + + if (bottomRightIcon != null) { + bottomRightIcon.x = x + (width - bottomRightIcon.width()) -1; + bottomRightIcon.y = y + (height - bottomRightIcon.height()); + } + + if (bottomLeft != null) { + bottomLeft.x = x ; + bottomLeft.y = y + (height - bottomLeft.height()); + } + + if (bottomLeftIcon != null) { + bottomLeftIcon.x = x + 1; + bottomLeftIcon.y = y + (height - bottomLeftIcon.height()); + } + } + + public void item(Item item ) { + + if (bottomRightIcon != null){ + remove(bottomRightIcon); + bottomRightIcon = null; + } + + if (bottomLeftIcon != null){ + remove(bottomLeftIcon); + bottomLeftIcon = null; + } + + if (item == null) { + + active = false; + icon.visible = topLeft.visible = topRight.visible = bottomRight.visible = bottomLeft.visible = false; + + } else { + + active = true; + icon.visible = topLeft.visible = topRight.visible = bottomRight.visible = bottomLeft.visible = true; + + icon.view(item.image(), item.glowing()); + + topLeft.text(item.status()); + + boolean isArmor = item instanceof Armor; + boolean isWeapon = item instanceof Weapon; + if (isArmor || isWeapon) { + + if (item.levelKnown + || (isWeapon && !(item instanceof MeleeWeapon))) { + + int str = isArmor ? ((Armor) item).STR() + : ((Weapon) item).STR(); + topRight.text( Messages.format( TXT_STRENGTH, str )); + if (str > Dungeon.hero.STR()) { + topRight.hardlight(DEGRADED); + } else { + topRight.resetColor(); + } + + } else { + + topRight.text(Messages.format(TXT_TYPICAL_STR, + isArmor ? ((Armor) item).STR() + : ((MeleeWeapon) item).typicalSTR())); + topRight.hardlight(WARNING); + + } + topRight.measure(); + + } else if (item instanceof Key && !(item instanceof SkeletonKey)) { + topRight.text(Messages.format(TXT_KEY_DEPTH, ((Key) item).depth)); + topRight.measure(); + } else { + + topRight.text(null); + + } + + int level = item.visiblyUpgraded(); + + if (level != 0) { + bottomRight.text(item.levelKnown ? Messages.format(TXT_LEVEL, + level) : TXT_CURSED); + bottomRight.measure(); + bottomRight.hardlight(level > 0 ? UPGRADED : DEGRADED); + + } else if (item instanceof Scroll || item instanceof Potion) { + + bottomRight.text( null ); + + Integer iconInt; + if (item instanceof Scroll){ + iconInt = ((Scroll) item).initials(); + } else { + iconInt = ((Potion) item).initials(); + } + if (iconInt != null && iconVisible) { + bottomRightIcon = new Image(Assets.CONS_ICONS); + int left = iconInt*7; + int top = item instanceof Potion ? 0 : 7; + bottomRightIcon.frame(left, top, 7, 7); + add(bottomRightIcon); + } else { + bottomRight.text( null ); + } + + } + layout(); + } + } + + public void enable(boolean value) { + + active = value; + + float alpha = value ? ENABLED : DISABLED; + icon.alpha(alpha); + topLeft.alpha(alpha); + topRight.alpha(alpha); + bottomRight.alpha(alpha); + bottomLeft.alpha(alpha); + if (bottomLeftIcon != null) bottomRightIcon.alpha( alpha ); + if (bottomLeftIcon != null) bottomLeftIcon.alpha( alpha ); + } + + public void showParams( boolean TL, boolean TR, boolean BR, boolean BF ) { + if (TL) add( topLeft ); + else remove( topLeft ); + + if (TR) add( topRight ); + else remove( topRight ); + + if (BR) add( bottomRight ); + else remove( bottomRight ); + + if (BF) add( bottomLeft ); + else remove( bottomLeft ); + + iconVisible = BR; + iconVisible2 = BF; + } +} diff --git a/java/com/hmdzl/spspd/ui/LanguageButton.java b/java/com/hmdzl/spspd/ui/LanguageButton.java new file mode 100644 index 00000000..e627c02b --- /dev/null +++ b/java/com/hmdzl/spspd/ui/LanguageButton.java @@ -0,0 +1,87 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2017 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ + +package com.hmdzl.spspd.ui; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.windows.WndLangs; +import com.watabou.noosa.Image; +import com.watabou.noosa.audio.Sample; +import com.watabou.noosa.ui.Button; + +public class LanguageButton extends Button { + + private Image image; + + public LanguageButton() { + super(); + + width = image.width; + height = image.height; + } + + @Override + protected void createChildren() { + super.createChildren(); + + image = Icons.get(Icons.LAN); + add( image ); + updateIcon(); + } + + private void updateIcon(){ + switch(Messages.lang().status()){ + case INCOMPLETE: + image.tint(1, 0, 0, .5f); + break; + case UNREVIEWED: + image.tint(1, .5f, 0, .5f); + break; + } + } + + @Override + protected void layout() { + super.layout(); + + image.x = x; + image.y = y; + } + + @Override + protected void onTouchDown() { + image.brightness( 1.5f ); + Sample.INSTANCE.play( Assets.SND_CLICK ); + } + + @Override + protected void onTouchUp() { + image.resetColor(); + updateIcon(); + } + + @Override + protected void onClick() { + parent.add(new WndLangs()); + } + +} diff --git a/java/com/hmdzl/spspd/ui/LootIndicator.java b/java/com/hmdzl/spspd/ui/LootIndicator.java new file mode 100644 index 00000000..4f6b47df --- /dev/null +++ b/java/com/hmdzl/spspd/ui/LootIndicator.java @@ -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 + */ +package com.hmdzl.spspd.ui; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.items.Heap; +import com.hmdzl.spspd.items.Item; + +public class LootIndicator extends Tag { + + private ItemSlot slot; + + private Item lastItem = null; + private int lastQuantity = 0; + + public LootIndicator() { + super(0x1F75CC); + + setSize(24, 24); + + visible = false; + } + + @Override + protected void createChildren() { + super.createChildren(); + + slot = new ItemSlot() { + + protected void onClick() { + Dungeon.hero.handle(Dungeon.hero.pos); + }; + }; + slot.showParams(true, false, false, false); + add(slot); + } + + @Override + protected void layout() { + super.layout(); + + slot.setRect(x + 2, y + 3, width - 2, height - 6); + } + + @Override + public void update() { + + if (Dungeon.hero.ready) { + Heap heap = Dungeon.level.heaps.get(Dungeon.hero.pos); + if (heap != null) { + + Item item = + heap.type == Heap.Type.CHEST || heap.type == Heap.Type.MIMIC ? ItemSlot.CHEST : + heap.type == Heap.Type.LOCKED_CHEST ? ItemSlot.LOCKED_CHEST: + heap.type == Heap.Type.CRYSTAL_CHEST ? ItemSlot.CRYSTAL_CHEST: + heap.type == Heap.Type.TOMB ? ItemSlot.TOMB: + heap.type == Heap.Type.SKELETON ? ItemSlot.SKELETON: + heap.type == Heap.Type.REMAINS ? ItemSlot.REMAINS: + heap.peek(); + if (item != lastItem || item.quantity() != lastQuantity) { + lastItem = item; + lastQuantity = item.quantity(); + + slot.item(item); + flash(); + } + visible = true; + + } else { + + lastItem = null; + visible = false; + + } + } + + slot.enable(visible && Dungeon.hero.ready); + + super.update(); + } +} diff --git a/java/com/hmdzl/spspd/ui/MemoryButton.java b/java/com/hmdzl/spspd/ui/MemoryButton.java new file mode 100644 index 00000000..c62f5804 --- /dev/null +++ b/java/com/hmdzl/spspd/ui/MemoryButton.java @@ -0,0 +1,80 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2015 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.ui; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.scenes.LoadSaveScene; +import com.watabou.noosa.Game; +import com.watabou.noosa.Image; +import com.watabou.noosa.audio.Sample; +import com.watabou.noosa.ui.Button; + +import java.io.IOException; + +public class MemoryButton extends Button { + + protected Image image; + + public MemoryButton() { + super(); + + width = image.width; + height = image.height; + } + + @Override + protected void createChildren() { + super.createChildren(); + + image = Icons.SAVELOAD.get(); + add( image ); + } + + @Override + protected void layout() { + super.layout(); + + image.x = x; + image.y = y; + } + + @Override + protected void onTouchDown() { + image.brightness( 1.5f ); + Sample.INSTANCE.play( Assets.SND_CLICK ); + } + + @Override + protected void onTouchUp() { + image.resetColor(); + } + + @Override + protected void onClick() { + try { + Dungeon.saveAll(); + } catch (IOException e) { + // + } + Game.switchScene(LoadSaveScene.class); + } +} diff --git a/java/com/hmdzl/spspd/ui/PrefsButton.java b/java/com/hmdzl/spspd/ui/PrefsButton.java new file mode 100644 index 00000000..1b0831a5 --- /dev/null +++ b/java/com/hmdzl/spspd/ui/PrefsButton.java @@ -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 + */ +package com.hmdzl.spspd.ui; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.windows.WndSettings; +import com.watabou.noosa.Image; +import com.watabou.noosa.audio.Sample; +import com.watabou.noosa.ui.Button; + +public class PrefsButton extends Button { + + private Image image; + + public PrefsButton() { + super(); + + width = image.width; + height = image.height; + } + + @Override + protected void createChildren() { + super.createChildren(); + + image = Icons.PREFS.get(); + add(image); + } + + @Override + protected void layout() { + super.layout(); + + image.x = x; + image.y = y; + } + + @Override + protected void onTouchDown() { + image.brightness(1.5f); + Sample.INSTANCE.play(Assets.SND_CLICK); + } + + @Override + protected void onTouchUp() { + image.resetColor(); + } + + @Override + protected void onClick() { + parent.add(new WndSettings(false)); + } +} diff --git a/java/com/hmdzl/spspd/ui/QuickSlotButton.java b/java/com/hmdzl/spspd/ui/QuickSlotButton.java new file mode 100644 index 00000000..df3f6e3f --- /dev/null +++ b/java/com/hmdzl/spspd/ui/QuickSlotButton.java @@ -0,0 +1,250 @@ +/* + * 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 + */ +package com.hmdzl.spspd.ui; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.DungeonTilemap; +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.mechanics.Ballistica; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.scenes.PixelScene; +import com.hmdzl.spspd.windows.WndBag; +import com.watabou.noosa.Image; +import com.watabou.noosa.ui.Button; +import com.hmdzl.spspd.messages.Messages; + +public class QuickSlotButton extends Button implements WndBag.Listener { + + private static final String TXT_SELECT_ITEM = "Select an item for the quickslot"; + + private static QuickSlotButton[] instance = new QuickSlotButton[6]; + private int slotNum; + + private ItemSlot slot; + + private static Image crossB; + private static Image crossM; + + private static boolean targeting = false; + public static Char lastTarget = null; + + public QuickSlotButton(int slotNum) { + super(); + this.slotNum = slotNum; + item(select(slotNum)); + + instance[slotNum] = this; + } + + @Override + public void destroy() { + super.destroy(); + + reset(); + } + + public static void reset() { + instance = new QuickSlotButton[6]; + + lastTarget = null; + } + + @Override + protected void createChildren() { + super.createChildren(); + + slot = new ItemSlot() { + @Override + protected void onClick() { + if (targeting) { + int cell = autoAim(lastTarget); + + if (cell != -1){ + GameScene.handleCell(cell); + } else { + //couldn't auto-aim, just target the position and hope for the best. + GameScene.handleCell( lastTarget.pos ); + } + //GameScene.handleCell(lastTarget.pos); + } else { + Item item = select(slotNum); + if (item.usesTargeting) + useTargeting(); + item.execute(Dungeon.hero); + } + } + + @Override + protected boolean onLongClick() { + return QuickSlotButton.this.onLongClick(); + } + + @Override + protected void onTouchDown() { + icon.lightness(0.7f); + } + + @Override + protected void onTouchUp() { + icon.resetColor(); + } + }; + slot.showParams( true, false, true, false ); + add(slot); + + crossB = Icons.TARGET.get(); + crossB.visible = false; + add(crossB); + + + crossM = new Image(); + crossM.copy(crossB); + } + + @Override + protected void layout() { + super.layout(); + + slot.fill(this); + + //crossB.x = PixelScene.align(x + (width - crossB.width) / 2); + //crossB.y = PixelScene.align(y + (height - crossB.height) / 2); + crossB.x = x + (width - crossB.width) / 2; + crossB.y = y + (height - crossB.height) / 2; + PixelScene.align(crossB); + + } + + @Override + protected void onClick() { + GameScene.selectItem(this, WndBag.Mode.QUICKSLOT,Messages.get(this, "select_item")); + } + + @Override + protected boolean onLongClick() { + GameScene.selectItem(this, WndBag.Mode.QUICKSLOT,Messages.get(this, "select_item")); + return true; + } + + private static Item select(int slotNum) { + return Dungeon.quickslot.getItem(slotNum); + } + + @Override + public void onSelect(Item item) { + if (item != null) { + Dungeon.quickslot.setSlot(slotNum, item); + refresh(); + } + } + + public void item(Item item) { + slot.item(item); + enableSlot(); + } + + public void enable(boolean value) { + active = value; + if (value) { + enableSlot(); + } else { + slot.enable(false); + } + } + + private void enableSlot() { + slot.enable(Dungeon.quickslot.isNonePlaceholder(slotNum)); + } + + private void useTargeting() { + + //if (lastTarget != null && lastTarget.isAlive() && + //Dungeon.visible[lastTarget.pos]) { + + //targeting = true; + //lastTarget.sprite.parent.add( crossM ); + //crossM.point( DungeonTilemap.tileToWorld( lastTarget.pos ) ); + //crossB.x = x + (width - crossB.width) / 2; + //crossB.y = y + (height - crossB.height) / 2; + //crossB.visible = true; + + if (lastTarget != null && + //Actor.chars().contains( lastTarget ) && + lastTarget.isAlive() && + Dungeon.visible[lastTarget.pos]) { + + targeting = true; + lastTarget.sprite.parent.add( crossM ); + crossM.point( DungeonTilemap.tileToWorld( lastTarget.pos ) ); + crossB.x = x + (width - crossB.width) / 2; + crossB.y = y + (height - crossB.height) / 2; + crossB.visible = true; + + } else { + + lastTarget = null; + targeting = false; + + } + + + } + + public static int autoAim(Char target){ + //first try to directly target + if (new Ballistica(Dungeon.hero.pos, target.pos, Ballistica.PROJECTILE).collisionPos == target.pos) { + return target.pos; + } + + //Otherwise pick nearby tiles to try and 'angle' the shot, auto-aim basically. + for (int i : Level.NEIGHBOURS9DIST2) { + if (new Ballistica(Dungeon.hero.pos, target.pos+i, Ballistica.PROJECTILE).collisionPos == target.pos){ + return target.pos+i; + } + } + + //couldn't find a cell, give up. + return -1; + } + + public static void refresh() { + for (int i = 0; i < instance.length; i++) { + if (instance[i] != null) { + instance[i].item(select(i)); + } + } + } + + public static void target(Char target) { + if (target != Dungeon.hero) { + lastTarget = target; + + HealthIndicator.instance.target(target); + } + } + + public static void cancel() { + if (targeting) { + crossB.visible = false; + crossM.remove(); + targeting = false; + } + } +} diff --git a/java/com/hmdzl/spspd/ui/RedButton.java b/java/com/hmdzl/spspd/ui/RedButton.java new file mode 100644 index 00000000..b56df4d3 --- /dev/null +++ b/java/com/hmdzl/spspd/ui/RedButton.java @@ -0,0 +1,121 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2016 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.ui; + +import com.hmdzl.spspd.scenes.PixelScene; +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Chrome; +import com.watabou.noosa.Image; +import com.watabou.noosa.NinePatch; +import com.watabou.noosa.RenderedText; +import com.watabou.noosa.audio.Sample; +import com.watabou.noosa.ui.Button; + +public class RedButton extends Button { + + protected NinePatch bg; + protected RenderedText text; + protected Image icon; + + public RedButton(String label ) { + this(label, 9); + } + + public RedButton(String label, int size ){ + super(); + + text = PixelScene.renderText( size ); + text.text( label ); + add( text ); + } + + @Override + protected void createChildren() { + super.createChildren(); + + bg = Chrome.get( Chrome.Type.BUTTON ); + add( bg ); + } + + @Override + protected void layout() { + + super.layout(); + + bg.x = x; + bg.y = y; + bg.size( width, height ); + + text.x = x + (width - text.width()) / 2; + text.y = y + (height - text.baseLine()) / 2; + PixelScene.align(text); + + if (icon != null) { + icon.x = x + text.x - icon.width() - 2; + icon.y = y + (height - icon.height()) / 2; + PixelScene.align(icon); + } + } + + @Override + protected void onTouchDown() { + bg.brightness( 1.2f ); + Sample.INSTANCE.play( Assets.SND_CLICK ); + } + + @Override + protected void onTouchUp() { + bg.resetColor(); + } + + public void enable( boolean value ) { + active = value; + text.alpha( value ? 1.0f : 0.3f ); + } + + public void text( String value ) { + text.text( value ); + layout(); + } + + public void textColor( int value ) { + text.hardlight( value ); + } + + public void icon( Image icon ) { + if (this.icon != null) { + remove( this.icon ); + } + this.icon = icon; + if (this.icon != null) { + add( this.icon ); + layout(); + } + } + + public float reqWidth() { + return text.width() + 2f; + } + + public float reqHeight() { + return text.baseLine() + 4; + } +} diff --git a/java/com/hmdzl/spspd/ui/RenderedTextMultiline.java b/java/com/hmdzl/spspd/ui/RenderedTextMultiline.java new file mode 100644 index 00000000..31d02930 --- /dev/null +++ b/java/com/hmdzl/spspd/ui/RenderedTextMultiline.java @@ -0,0 +1,197 @@ +/* + * Copyright (C) 2012-2015 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 + */ + +package com.hmdzl.spspd.ui; + +import com.hmdzl.spspd.scenes.PixelScene; +import com.watabou.noosa.RenderedText; +import com.watabou.noosa.ui.Component; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class RenderedTextMultiline extends Component { + + private int maxWidth = Integer.MAX_VALUE; + public int nLines; + + private String text; + private List tokens; + private ArrayList words = new ArrayList<>(); + + private int size; + private float zoom; + private int color = -1; + + private static final String SPACE = " "; + private static final String NEWLINE = "\n"; + private static final String UNDERSCORE = "_"; + + private boolean chinese = false; + + public RenderedTextMultiline(int size){ + this.size = size; + } + + public RenderedTextMultiline(String text, int size){ + this.size = size; + text(text); + } + + public void text(String text){ + this.text = text; + + if (text != null && !text.equals("")) { + //conversion for chinese text + + chinese = text.replaceAll("\\p{Han}", "").length() != text.length(); + + if (chinese){ + tokens = Arrays.asList(text.split("")); + } else { + tokens = Arrays.asList(text.split("(?<= )|(?= )|(?<=\n)|(?=\n)")); + } + build(); + } + } + + public void text(String text, int maxWidth){ + this.maxWidth = maxWidth; + text(text); + } + + public String text(){ + return text; + } + + public void maxWidth(int maxWidth){ + if (this.maxWidth != maxWidth){ + this.maxWidth = maxWidth; + layout(); + } + } + + public int maxWidth(){ + return maxWidth; + } + + private void build(){ + clear(); + words = new ArrayList<>(); + boolean highlighting = false; + for (String str : tokens){ + if (str.equals(UNDERSCORE)){ + highlighting = !highlighting; + } else if (str.equals(NEWLINE)){ + words.add(null); + } else if (!str.equals(SPACE)){ + RenderedText word; + if (str.startsWith(UNDERSCORE) && str.endsWith(UNDERSCORE)){ + word = new RenderedText(str.substring(1, str.length()-1), size); + word.hardlight(0xFFFF44); + } else { + if (str.startsWith(UNDERSCORE)){ + highlighting = !highlighting; + word = new RenderedText(str.substring(1, str.length()), size); + } else if (str.endsWith(UNDERSCORE)) { + word = new RenderedText(str.substring(0, str.length()-1), size); + } else { + word = new RenderedText(str, size); + } + if (highlighting) word.hardlight(0xFFFF44); + else if (color != -1) word.hardlight(color); + + if (str.endsWith(UNDERSCORE)) highlighting = !highlighting; + } + word.scale.set(zoom); + words.add(word); + add(word); + + if (height < word.baseLine()) height = word.baseLine(); + + } + } + layout(); + } + + public void zoom(float zoom){ + this.zoom = zoom; + for (RenderedText word : words) { + if (word != null) word.scale.set(zoom); + } + } + + public void hardlight(int color){ + this.color = color; + for (RenderedText word : words) { + if (word != null) word.hardlight( color ); + } + } + + public void invert(){ + if (words != null) { + for (RenderedText word : words) { + if (word != null) { + word.ra = 0.77f; + word.ga = 0.73f; + word.ba = 0.62f; + word.rm = -0.77f; + word.gm = -0.73f; + word.bm = -0.62f; + } + } + } + } + + @Override + protected void layout() { + super.layout(); + float x = this.x; + float y = this.y; + float height = 0; + nLines = 1; + + for (RenderedText word : words){ + if (word == null) { + //newline + y += height+0.5f; + x = this.x; + nLines++; + } else { + if (word.height() > height) height = word.baseLine(); + + if ((x - this.x) + word.width() > maxWidth){ + y += height+0.5f; + x = this.x; + nLines++; + } + + word.x = x; + word.y = y; + PixelScene.align(word); + x += word.width(); + if (!chinese) x ++; + else x--; + + if ((x - this.x) > width) width = (x - this.x); + + } + } + this.height = (y - this.y) + height+0.5f; + } +} diff --git a/java/com/hmdzl/spspd/ui/ResumeButton.java b/java/com/hmdzl/spspd/ui/ResumeButton.java new file mode 100644 index 00000000..c06bc54d --- /dev/null +++ b/java/com/hmdzl/spspd/ui/ResumeButton.java @@ -0,0 +1,67 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 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 + */ +package com.hmdzl.spspd.ui; + +import com.watabou.noosa.Image; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.scenes.PixelScene; + +public class ResumeButton extends Tag { + + private Image icon; + + public ResumeButton() { + super( 0xCDD5C0 ); + + setSize( 24, 22 ); + + visible = false; + } + + @Override + protected void createChildren() { + super.createChildren(); + + icon = Icons.get( Icons.RESUME ); + add( icon ); + } + + @Override + protected void layout() { + super.layout(); + + icon.x = PixelScene.align( PixelScene.uiCamera, x+1 + (width - icon.width) / 2 ); + icon.y = PixelScene.align( PixelScene.uiCamera, y + (height - icon.height) / 2 ); + } + + @Override + public void update() { + boolean prevVisible = visible; + visible = (Dungeon.hero.lastAction != null); + if (visible && !prevVisible) { + flash(); + } + + super.update(); + } + + @Override + protected void onClick() { + Dungeon.hero.resume(); + } +} diff --git a/java/com/hmdzl/spspd/ui/ResumeIndicator.java b/java/com/hmdzl/spspd/ui/ResumeIndicator.java new file mode 100644 index 00000000..65cbca6c --- /dev/null +++ b/java/com/hmdzl/spspd/ui/ResumeIndicator.java @@ -0,0 +1,57 @@ +package com.hmdzl.spspd.ui; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.scenes.PixelScene; +import com.watabou.noosa.Image; + +/** + * Created by Evan on 21/01/2015. + */ +public class ResumeIndicator extends Tag { + + private Image icon; + + public ResumeIndicator() { + super(0xCDD5C0); + + setSize(24, 24); + + visible = false; + + } + + @Override + protected void createChildren() { + super.createChildren(); + + icon = Icons.get(Icons.RESUME); + add(icon); + } + + @Override + protected void layout() { + super.layout(); + + icon.x = PixelScene.align(PixelScene.uiCamera, x + 1 + + (width - icon.width) / 2); + icon.y = PixelScene.align(PixelScene.uiCamera, y + + (height - icon.height) / 2); + } + + @Override + protected void onClick() { + Dungeon.hero.resume(); + } + + @Override + public void update() { + if (!Dungeon.hero.isAlive()) + visible = false; + else if (visible != (Dungeon.hero.lastAction != null)) { + visible = Dungeon.hero.lastAction != null; + if (visible) + flash(); + } + super.update(); + } +} diff --git a/java/com/hmdzl/spspd/ui/ScrollPane.java b/java/com/hmdzl/spspd/ui/ScrollPane.java new file mode 100644 index 00000000..ba9300ca --- /dev/null +++ b/java/com/hmdzl/spspd/ui/ScrollPane.java @@ -0,0 +1,148 @@ +/* + * 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 + */ +package com.hmdzl.spspd.ui; + +import com.hmdzl.spspd.scenes.PixelScene; +import com.watabou.input.Touchscreen.Touch; +import com.watabou.noosa.Camera; +import com.watabou.noosa.TouchArea; +import com.watabou.noosa.ui.Component; +import com.watabou.utils.Point; +import com.watabou.utils.PointF; + +public class ScrollPane extends Component { + + protected TouchController controller; + protected Component content; + + protected float minX; + protected float minY; + protected float maxX; + protected float maxY; + + public ScrollPane(Component content) { + super(); + + this.content = content; + addToBack(content); + + width = content.width(); + height = content.height(); + + content.camera = new Camera(0, 0, 1, 1, PixelScene.defaultZoom); + Camera.add(content.camera); + } + + @Override + public void destroy() { + super.destroy(); + Camera.remove(content.camera); + } + + public void scrollTo(float x, float y) { + content.camera.scroll.set(x, y); + } + + @Override + protected void createChildren() { + controller = new TouchController(); + add(controller); + } + + @Override + protected void layout() { + + content.setPos(0, 0); + controller.x = x; + controller.y = y; + controller.width = width; + controller.height = height; + + Point p = camera().cameraToScreen(x, y); + Camera cs = content.camera; + cs.x = p.x; + cs.y = p.y; + cs.resize((int) width, (int) height); + } + + public Component content() { + return content; + } + + public void onClick(float x, float y) { + } + + public class TouchController extends TouchArea { + + private float dragThreshold; + + public TouchController() { + super(0, 0, 0, 0); + dragThreshold = PixelScene.defaultZoom * 8; + } + + @Override + protected void onClick(Touch touch) { + if (dragging) { + + dragging = false; + + } else { + + PointF p = content.camera.screenToCamera((int) touch.current.x, + (int) touch.current.y); + ScrollPane.this.onClick(p.x, p.y); + + } + } + + private boolean dragging = false; + private PointF lastPos = new PointF(); + + @Override + protected void onDrag(Touch t) { + if (dragging) { + + Camera c = content.camera; + + c.scroll.offset(PointF.diff(lastPos, t.current) + .invScale(c.zoom)); + if (c.scroll.x + width > content.width()) { + c.scroll.x = content.width() - width; + } + if (c.scroll.x < 0) { + c.scroll.x = 0; + } + if (c.scroll.y + height > content.height()) { + c.scroll.y = content.height() - height; + } + if (c.scroll.y < 0) { + c.scroll.y = 0; + } + + lastPos.set(t.current); + + } else if (PointF.distance(t.current, t.start) > dragThreshold) { + + dragging = true; + lastPos.set(t.current); + + } + } + } +} diff --git a/java/com/hmdzl/spspd/ui/SimpleButton.java b/java/com/hmdzl/spspd/ui/SimpleButton.java new file mode 100644 index 00000000..708010e6 --- /dev/null +++ b/java/com/hmdzl/spspd/ui/SimpleButton.java @@ -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 + */ +package com.hmdzl.spspd.ui; + +import com.watabou.input.Touchscreen.Touch; +import com.watabou.noosa.Image; +import com.watabou.noosa.TouchArea; +import com.watabou.noosa.ui.Component; + +public class SimpleButton extends Component { + + private Image image; + + public SimpleButton(Image image) { + super(); + + this.image.copy(image); + width = image.width; + height = image.height; + } + + @Override + protected void createChildren() { + image = new Image(); + add(image); + + add(new TouchArea(image) { + @Override + protected void onTouchDown(Touch touch) { + image.brightness(1.2f); + }; + + @Override + protected void onTouchUp(Touch touch) { + image.brightness(1.0f); + }; + + @Override + protected void onClick(Touch touch) { + SimpleButton.this.onClick(); + }; + }); + } + + @Override + protected void layout() { + image.x = x; + image.y = y; + } + + protected void onClick() { + }; +} diff --git a/java/com/hmdzl/spspd/ui/SpellButton.java b/java/com/hmdzl/spspd/ui/SpellButton.java new file mode 100644 index 00000000..707554ad --- /dev/null +++ b/java/com/hmdzl/spspd/ui/SpellButton.java @@ -0,0 +1,135 @@ +/* + * 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 + */ +package com.hmdzl.spspd.ui; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Chrome; +import com.hmdzl.spspd.scenes.PixelScene; +import com.watabou.noosa.Image; +import com.watabou.noosa.NinePatch; +import com.watabou.noosa.audio.Sample; +import com.watabou.noosa.ui.Button; +import com.watabou.noosa.RenderedText; + +public class SpellButton extends Button { + + protected NinePatch bg; + protected RenderedText text; + protected Image icon1; + protected Image icon2; + protected Image icon3; + protected Image icon4; + protected Image icon5; + + public SpellButton(String label) { + super(); + + text.text(label); + //text.measure(); + } + + @Override + protected void createChildren() { + super.createChildren(); + + bg = Chrome.get(Chrome.Type.BUTTON); + add(bg); + + text = PixelScene.renderText(9); + add(text); + } + + @Override + protected void layout() { + + super.layout(); + + bg.x = x; + bg.y = y; + bg.size(width, height); + + text.x = x + (int) (width - text.width()) / 2; + text.y = y + (int) (height - text.baseLine()) / 2; + + if (icon1 != null) { + icon1.x = x + text.x - icon1.width() - 2; + icon1.y = y + (height - icon1.height()) / 2; + } + if (icon2 != null) { + icon2.x = x + text.x - icon2.width() - 2; + icon2.y = y + (height - icon2.height()) / 2; + } + if (icon3 != null) { + icon3.x = x + text.x - icon3.width() - 2; + icon3.y = y + (height - icon3.height()) / 2; + } + if (icon4 != null) { + icon4.x = x + text.x - icon4.width() - 2; + icon4.y = y + (height - icon4.height()) / 2; + } + if (icon5 != null) { + icon5.x = x + text.x - icon5.width() - 2; + icon5.y = y + (height - icon5.height()) / 2; + } + } + + @Override + protected void onTouchDown() { + bg.brightness(1.2f); + Sample.INSTANCE.play(Assets.SND_CLICK); + } + + @Override + protected void onTouchUp() { + bg.resetColor(); + } + + public void enable(boolean value) { + active = value; + text.alpha(value ? 1.0f : 0.3f); + } + + public void text(String value) { + text.text(value); + //text.measure(); + layout(); + } + + public void textColor(int value) { + text.hardlight(value); + } + + public void icon(Image icon) { + if (this.icon1 != null) { + remove(this.icon1); + } + this.icon1 = icon; + if (this.icon1 != null) { + add(this.icon1); + layout(); + } + } + + public float reqWidth() { + return text.width() + 4; + } + + public float reqHeight() { + return text.baseLine() + 4; + } +} diff --git a/java/com/hmdzl/spspd/ui/StatusPane.java b/java/com/hmdzl/spspd/ui/StatusPane.java new file mode 100644 index 00000000..93b703f0 --- /dev/null +++ b/java/com/hmdzl/spspd/ui/StatusPane.java @@ -0,0 +1,262 @@ +/* + * 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 + */ +package com.hmdzl.spspd.ui; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.effects.particles.BloodParticle; +import com.hmdzl.spspd.items.keys.IronKey; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.scenes.PixelScene; +import com.hmdzl.spspd.sprites.HeroSprite; +import com.hmdzl.spspd.windows.WndGame; +import com.hmdzl.spspd.windows.WndHero; +import com.watabou.input.Touchscreen.Touch; +import com.watabou.noosa.BitmapText; +import com.watabou.noosa.Camera; +import com.watabou.noosa.Game; +import com.watabou.noosa.Image; +import com.watabou.noosa.NinePatch; +import com.watabou.noosa.TouchArea; +import com.watabou.noosa.audio.Sample; +import com.watabou.noosa.particles.Emitter; +import com.watabou.noosa.ui.Button; +import com.watabou.noosa.ui.Component; + +public class StatusPane extends Component { + + private NinePatch shield; + private Image avatar; + private Emitter blood; + + private int lastTier = 0; + + private Image hp; + private Image exp; + + private int lastLvl = -1; + private int lastKeys = -1; + + private BitmapText level; + private BitmapText depth; + private BitmapText keys; + + private DangerIndicator danger; + private BuffIndicator buffs; + private Compass compass; + + private MenuButton btnMenu; + private BitmapText version; + + @Override + protected void createChildren() { + + shield = new NinePatch(Assets.STATUS, 80, 0, 30 + 18, 0); + add(shield); + + add(new TouchArea(0, 1, 30, 30) { + @Override + protected void onClick(Touch touch) { + Image sprite = Dungeon.hero.sprite; + if (!sprite.isVisible()) { + Camera.main.focusOn(sprite); + } + GameScene.show(new WndHero()); + }; + }); + + btnMenu = new MenuButton(); + add(btnMenu); + + avatar = HeroSprite.avatar(Dungeon.hero.heroClass, 7-Dungeon.skins); + add(avatar); + + blood = new Emitter(); + blood.pos(avatar); + blood.pour(BloodParticle.FACTORY, 0.3f); + blood.autoKill = false; + blood.on = false; + add(blood); + + compass = new Compass(Dungeon.level.exit); + add(compass); + + hp = new Image(Assets.HP_BAR); + add(hp); + + exp = new Image(Assets.XP_BAR); + add(exp); + + level = new BitmapText(PixelScene.font1x); + level.hardlight(0xFFEBA4); + add(level); + + depth = new BitmapText(Integer.toString(Dungeon.depth), + PixelScene.font1x); + depth.hardlight(0xCACFC2); + depth.measure(); + add(depth); + + Dungeon.hero.belongings.countIronKeys(); + keys = new BitmapText(PixelScene.font1x); + keys.hardlight(0xCACFC2); + add(keys); + + danger = new DangerIndicator(); + add(danger); + + buffs = new BuffIndicator(Dungeon.hero); + add(buffs); + + version = new BitmapText( "v" + Game.version, /*PixelScene.pixelFont*/PixelScene.font1x); + version.alpha( 0.5f ); + add(version); + } + + @Override + protected void layout() { + + height = 32; + + shield.size(width, shield.height); + + avatar.x = PixelScene.align(camera(), shield.x + 15 - avatar.width / 2); + avatar.y = PixelScene + .align(camera(), shield.y + 16 - avatar.height / 2); + + compass.x = avatar.x + avatar.width / 2 - compass.origin.x; + compass.y = avatar.y + avatar.height / 2 - compass.origin.y; + + hp.x = 30; + hp.y = 3; + + depth.x = width - 24 - depth.width() - 18; + depth.y = 6; + + keys.y = 6; + + danger.setPos(width - danger.width(), 18); + + buffs.setPos(32, 11); + + btnMenu.setPos(width - btnMenu.width(), 1); + + version.scale.set(PixelScene.align(0.5f)); + version.measure(); + version.x = width - version.width(); + version.y = btnMenu.bottom() + (4 - version.baseLine()); + PixelScene.align(version); + } + + @Override + public void update() { + super.update(); + + float health = (float) Dungeon.hero.HP / Dungeon.hero.HT; + + if (health == 0) { + avatar.tint(0x000000, 0.6f); + blood.on = false; + } else if (health < 0.25f) { + avatar.tint(0xcc0000, 0.4f); + blood.on = true; + } else { + avatar.resetColor(); + blood.on = false; + } + + hp.scale.x = health; + exp.scale.x = (width / exp.width) * Dungeon.hero.exp + / Dungeon.hero.maxExp(); + + if (Dungeon.hero.lvl != lastLvl) { + + if (lastLvl != -1) { + Emitter emitter = (Emitter) recycle(Emitter.class); + emitter.revive(); + emitter.pos(27, 27); + emitter.burst(Speck.factory(Speck.STAR), 12); + } + + lastLvl = Dungeon.hero.lvl; + level.text(Integer.toString(lastLvl)); + level.measure(); + level.x = PixelScene.align(27.0f - level.width() / 2); + level.y = PixelScene.align(27.5f - level.baseLine() / 2); + } + + int k = IronKey.curDepthQuantity; + if (k != lastKeys) { + lastKeys = k; + keys.text(Integer.toString(lastKeys)); + keys.measure(); + keys.x = width - 8 - keys.width() - 18; + } + + //int tier = Dungeon.hero.tier(); + //if (tier != lastTier) { + //lastTier = tier; + //avatar.copy(HeroSprite.avatar(Dungeon.hero.heroClass, tier)); + //} + } + + private static class MenuButton extends Button { + + private Image image; + + public MenuButton() { + super(); + + width = image.width + 4; + height = image.height + 4; + } + + @Override + protected void createChildren() { + super.createChildren(); + + image = new Image(Assets.STATUS, 114, 3, 12, 11); + add(image); + } + + @Override + protected void layout() { + super.layout(); + + image.x = x + 2; + image.y = y + 2; + } + + @Override + protected void onTouchDown() { + image.brightness(1.5f); + Sample.INSTANCE.play(Assets.SND_CLICK); + } + + @Override + protected void onTouchUp() { + image.resetColor(); + } + + @Override + protected void onClick() { + GameScene.show(new WndGame()); + } + } +} diff --git a/java/com/hmdzl/spspd/ui/Tag.java b/java/com/hmdzl/spspd/ui/Tag.java new file mode 100644 index 00000000..8d986fe0 --- /dev/null +++ b/java/com/hmdzl/spspd/ui/Tag.java @@ -0,0 +1,80 @@ +/* + * 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 + */ +package com.hmdzl.spspd.ui; + +import com.hmdzl.spspd.Chrome; +import com.watabou.noosa.Game; +import com.watabou.noosa.NinePatch; +import com.watabou.noosa.ui.Button; + +public class Tag extends Button { + + private float r; + private float g; + private float b; + protected NinePatch bg; + + protected float lightness = 0; + + public Tag(int color) { + super(); + + this.r = (color >> 16) / 255f; + this.g = ((color >> 8) & 0xFF) / 255f; + this.b = (color & 0xFF) / 255f; + } + + @Override + protected void createChildren() { + + super.createChildren(); + + bg = Chrome.get(Chrome.Type.TAG); + add(bg); + } + + @Override + protected void layout() { + + super.layout(); + + bg.x = x; + bg.y = y; + bg.size(width, height); + } + + public void flash() { + lightness = 1f; + } + + @Override + public void update() { + super.update(); + + if (visible && lightness > 0.5) { + if ((lightness -= Game.elapsed) > 0.5) { + bg.ra = bg.ga = bg.ba = 2 * lightness - 1; + bg.rm = 2 * r * (1 - lightness); + bg.gm = 2 * g * (1 - lightness); + bg.bm = 2 * b * (1 - lightness); + } else { + bg.hardlight(r, g, b); + } + } + } +} diff --git a/java/com/hmdzl/spspd/ui/TargetHealthIndicator.java b/java/com/hmdzl/spspd/ui/TargetHealthIndicator.java new file mode 100644 index 00000000..7bc6f990 --- /dev/null +++ b/java/com/hmdzl/spspd/ui/TargetHealthIndicator.java @@ -0,0 +1,66 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2019 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ + +package com.hmdzl.spspd.ui; + +import com.hmdzl.spspd.actors.Char; +import com.hmdzl.spspd.sprites.CharSprite; + +public class TargetHealthIndicator extends HealthBar { + + public static TargetHealthIndicator instance; + + private Char target; + + public TargetHealthIndicator() { + super(); + + instance = this; + } + + @Override + public void update() { + super.update(); + + if (target != null && target.isAlive() && target.sprite.visible) { + CharSprite sprite = target.sprite; + width = sprite.width; + x = sprite.x; + y = sprite.y - 3; + level( target ); + visible = true; + } else { + visible = false; + } + } + + public void target( Char ch ) { + if (ch != null && ch.isAlive()) { + target = ch; + } else { + target = null; + } + } + + public Char target() { + return target; + } +} diff --git a/java/com/hmdzl/spspd/ui/Toast.java b/java/com/hmdzl/spspd/ui/Toast.java new file mode 100644 index 00000000..2d140aa7 --- /dev/null +++ b/java/com/hmdzl/spspd/ui/Toast.java @@ -0,0 +1,87 @@ +/* + * 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 + */ +package com.hmdzl.spspd.ui; + +import com.hmdzl.spspd.Chrome; +import com.hmdzl.spspd.scenes.PixelScene; +import com.watabou.noosa.RenderedText; +import com.watabou.noosa.NinePatch; +import com.watabou.noosa.ui.Component; + +public class Toast extends Component { + + private static final float MARGIN_HOR = 2; + private static final float MARGIN_VER = 2; + + protected NinePatch bg; + protected SimpleButton close; + protected RenderedText text; + + public Toast(String text) { + super(); + text(text); + + width = this.text.width() + close.width() + bg.marginHor() + MARGIN_HOR + * 3; + height = Math.max(this.text.height(), close.height()) + bg.marginVer() + + MARGIN_VER * 2; + } + + @Override + protected void createChildren() { + super.createChildren(); + + bg = Chrome.get(Chrome.Type.TOAST_TR); + add(bg); + + close = new SimpleButton(Icons.get(Icons.CLOSE)) { + @Override + protected void onClick() { + onClose(); + }; + }; + add(close); + + text = PixelScene.renderText(8); + add(text); + } + + @Override + protected void layout() { + super.layout(); + + bg.x = x; + bg.y = y; + bg.size(width, height); + + close.setPos(bg.x + bg.width() - bg.marginHor() / 2 - MARGIN_HOR + - close.width(), y + (height - close.height()) / 2); + + text.x = close.left() - MARGIN_HOR - text.width(); + text.y = y + (height - text.height()) / 2; + PixelScene.align(text); + } + + public void text(String txt) { + text.text(txt); + //text.measure(); + } + + protected void onClose() { + }; +} diff --git a/java/com/hmdzl/spspd/ui/Toolbar.java b/java/com/hmdzl/spspd/ui/Toolbar.java new file mode 100644 index 00000000..b2ff3ffc --- /dev/null +++ b/java/com/hmdzl/spspd/ui/Toolbar.java @@ -0,0 +1,388 @@ +/* + * 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 + */ +package com.hmdzl.spspd.ui; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.DungeonTilemap; +import com.hmdzl.spspd.ShatteredPixelDungeon; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.scenes.CellSelector; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.windows.WndBag; +import com.hmdzl.spspd.windows.WndCatalogus; +import com.hmdzl.spspd.messages.Messages; +import com.watabou.noosa.Game; +import com.watabou.noosa.Gizmo; +import com.watabou.noosa.Image; +import com.watabou.noosa.ui.Button; +import com.watabou.noosa.ui.Component; + +public class Toolbar extends Component { + + private Tool btnWait; + private Tool btnSearch; + //private Tool btnInfo; + private Tool btnResume; + //private Tool btnJump; + private Tool btnInventory; + private Tool btnQuick; + private Tool btnQuick2; + private Tool btnQuick3; + private Tool btnQuick4; + private Tool btnQuick5; + private Tool btnQuick6; + public static int QuickSlots; + + private PickedUpItem pickedUp; + + private boolean lastEnabled = true; + public boolean examining = false; + + + public Toolbar() { + super(); + + QuickSlots = ShatteredPixelDungeon.quickSlots(); + + height = btnInventory.height(); + } + + + + @Override + protected void createChildren() { + + add(btnWait = new Tool(0, 7, 20, 24) { + @Override + protected void onClick() { + examining = false; + Dungeon.hero.rest(false); + }; + + @Override + protected boolean onLongClick() { + examining = false; + Dungeon.hero.rest(true); + return true; + }; + }); + + add(btnSearch = new Tool(20, 7, 20, 24) { + @Override + protected void onClick() { + + if(!examining) { + GameScene.selectCell(informer); + examining = true; + } else { + informer.onSelect(null); + Dungeon.hero.search(true); + } + } + @Override + protected boolean onLongClick() { + Dungeon.hero.search(true); + return true; + }; + } ); + + /*add(btnInfo = new Tool(40, 7, 21, 24) { + @Override + protected void onClick() { + GameScene.selectCell(informer); + }; + + @Override + protected boolean onLongClick() { + Dungeon.hero.rest(true); + return true; + }; + + }); + + * add( btnResume = new Tool( 61, 7, 21, 24 ) { + * + * @Override protected void onClick() { Dungeon.hero.resume(); } } ); + */ + + /*add(btnJump = new Tool(40,7,21,24){ + @Override + protected void onClick() { + GameScene.selectCell(jumper); + }; + @Override + protected boolean onLongClick() { + Dungeon.hero.search(true); + return true; + }; + });*/ + + + add(btnInventory = new Tool(82, 7, 23, 24) { + private GoldIndicator gold; + + @Override + protected void onClick() { + GameScene.show(new WndBag(Dungeon.hero.belongings.backpack, + null, WndBag.Mode.ALL, null)); + } + + @Override + protected boolean onLongClick() { + GameScene.show(new WndCatalogus()); + return true; + }; + + @Override + protected void createChildren() { + super.createChildren(); + gold = new GoldIndicator(); + add(gold); + }; + + @Override + protected void layout() { + super.layout(); + gold.fill(this); + }; + }); + + add(btnQuick = new QuickslotTool(105, 7, 22, 24, 0)); + + btnQuick2 = new QuickslotTool(105, 7, 22, 24, 1); + + btnQuick3 = new QuickslotTool(105, 7, 22, 24, 2); + + add(btnQuick4 = new QuickslotTool(105, 7, 22, 24, 3)); + + btnQuick5 = new QuickslotTool(105, 7, 22, 24, 4); + + add(btnQuick6 = new QuickslotTool(105, 7, 22, 24, 5)); + + add(pickedUp = new PickedUpItem()); + + + } + + @Override + protected void layout() { + btnWait.setPos(x, y); + btnSearch.setPos(btnWait.right(), y); + //btnInfo.setPos(btnSearch.right(), y); + //btnResume.setPos(btnInfo.right(), y); + //btnRoll.setPos(btnSearch.right(), y); + btnInventory.setPos( width - btnInventory.width(), y ); + btnQuick.setPos(width - btnInventory.width()*2+2, y); + btnQuick2.setPos(width - btnQuick.width(), btnQuick.height()*3-2); + btnQuick3.setPos(width - btnQuick.width(), btnQuick.height()*4-3); + btnQuick4.setPos(width - btnQuick.width(), btnQuick.height()*2); + btnQuick5.setPos(width - btnInventory.width()*4+4, y); + btnQuick6.setPos(width - btnInventory.width()*3+3, y); + if (QuickSlots == 2) { + add(btnQuick2); + btnQuick2.visible = btnQuick2.active = true; + add(btnQuick3); + btnQuick3.visible = btnQuick3.active = true; + add(btnQuick5); + btnQuick5.visible = btnQuick5.active = true; + } else { + remove(btnQuick2); + btnQuick2.visible = btnQuick2.active = false; + remove(btnQuick5); + btnQuick5.visible = btnQuick5.active = false; + remove(btnQuick3); + btnQuick3.visible = btnQuick3.active = false; + } + } + + @Override + public void update() { + super.update(); + + if (lastEnabled != Dungeon.hero.ready) { + lastEnabled = Dungeon.hero.ready; + + for (Gizmo tool : members) { + if (tool instanceof Tool) { + ((Tool) tool).enable(lastEnabled); + } + } + } + + // btnResume.visible = Dungeon.hero.lastAction != null; + + if (!Dungeon.hero.isAlive()) { + btnInventory.enable(true); + } + + // If we have 2 slots, and 2nd one isn't visible, or we have 1, and 2nd + // one is visible... + if ((QuickSlots == 1) == btnQuick2.visible) { + layout(); + } + } + + public void pickup(Item item) { + pickedUp.reset(item, btnInventory.centerX(), btnInventory.centerY()); + } + + private static CellSelector.Listener informer = new CellSelector.Listener() { + @Override + public void onSelect(Integer cell) { + //instance.examining = false; + GameScene.examineCell( cell ); + } + + @Override + public String prompt() { + return Messages.get(Toolbar.class, "examine_prompt"); + } + }; + + private static class Tool extends Button { + + private static final int BGCOLOR = 0x7B8073; + + private Image base; + + public Tool(int x, int y, int width, int height) { + super(); + + base.frame(x, y, width, height); + + this.width = width; + this.height = height; + } + + @Override + protected void createChildren() { + super.createChildren(); + + base = new Image(Assets.TOOLBAR); + add(base); + } + + @Override + protected void layout() { + super.layout(); + + base.x = x; + base.y = y; + } + + @Override + protected void onTouchDown() { + base.brightness(1.4f); + } + + @Override + protected void onTouchUp() { + if (active) { + base.resetColor(); + } else { + base.tint(BGCOLOR, 0.7f); + } + } + + public void enable(boolean value) { + if (value != active) { + if (value) { + base.resetColor(); + } else { + base.tint(BGCOLOR, 0.7f); + } + active = value; + } + } + }; + + private static class QuickslotTool extends Tool { + + private QuickSlotButton slot; + + public QuickslotTool(int x, int y, int width, int height, int slotNum) { + super(x, y, width, height); + + slot = new QuickSlotButton(slotNum); + add(slot); + } + + @Override + protected void layout() { + super.layout(); + slot.setRect(x + 1, y + 2, width - 2, height - 2); + } + + @Override + public void enable(boolean value) { + super.enable(value); + slot.enable(value); + } + } + + private static class PickedUpItem extends ItemSprite { + + private static final float DISTANCE = DungeonTilemap.SIZE; + private static final float DURATION = 0.2f; + + private float dstX; + private float dstY; + private float left; + + public PickedUpItem() { + super(); + + originToCenter(); + + active = visible = false; + } + + public void reset(Item item, float dstX, float dstY) { + view(item.image(), item.glowing()); + + active = visible = true; + + this.dstX = dstX - ItemSprite.SIZE / 2; + this.dstY = dstY - ItemSprite.SIZE / 2; + left = DURATION; + + x = this.dstX - DISTANCE; + y = this.dstY - DISTANCE; + alpha(1); + } + + @Override + public void update() { + super.update(); + + if ((left -= Game.elapsed) <= 0) { + + visible = active = false; + + } else { + float p = left / DURATION; + scale.set((float) Math.sqrt(p)); + float offset = DISTANCE * p; + x = dstX - offset; + y = dstY - offset; + } + } + } +} diff --git a/java/com/hmdzl/spspd/ui/Window.java b/java/com/hmdzl/spspd/ui/Window.java new file mode 100644 index 00000000..1f8d30be --- /dev/null +++ b/java/com/hmdzl/spspd/ui/Window.java @@ -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 + */ +package com.hmdzl.spspd.ui; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import com.hmdzl.spspd.Chrome; +import com.hmdzl.spspd.effects.ShadowBox; +import com.hmdzl.spspd.scenes.PixelScene; +import com.watabou.input.Keys; +import com.watabou.input.Keys.Key; +import com.watabou.input.Touchscreen.Touch; +import com.watabou.noosa.Camera; +import com.watabou.noosa.Game; +import com.watabou.noosa.Group; +import com.watabou.noosa.NinePatch; +import com.watabou.noosa.TouchArea; +import com.watabou.utils.Signal; + +public class Window extends Group implements Signal.Listener { + + protected int width; + protected int height; + + protected int yOffset; + + protected TouchArea blocker; + protected ShadowBox shadow; + protected NinePatch chrome; + + public static final int TITLE_COLOR = 0xFFFF44; + public static final int SHPX_COLOR = 0xCCFFCC; + + public Window() { + this(0, 0, Chrome.get(Chrome.Type.WINDOW)); + } + + public Window(int width, int height) { + this(width, height, Chrome.get(Chrome.Type.WINDOW)); + } + + public Window(int width, int height, NinePatch chrome) { + super(); + + blocker = new TouchArea(0, 0, PixelScene.uiCamera.width, + PixelScene.uiCamera.height) { + @Override + protected void onClick(Touch touch) { + if (!Window.this.chrome.overlapsScreenPoint( + (int) touch.current.x, (int) touch.current.y)) { + + onBackPressed(); + } + } + }; + blocker.camera = PixelScene.uiCamera; + add(blocker); + + this.chrome = chrome; + + this.width = width; + this.height = height; + + shadow = new ShadowBox(); + shadow.am = 0.5f; + shadow.camera = PixelScene.uiCamera.visible ? PixelScene.uiCamera + : Camera.main; + add(shadow); + + chrome.x = -chrome.marginLeft(); + chrome.y = -chrome.marginTop(); + chrome.size(width - chrome.x + chrome.marginRight(), height - chrome.y + + chrome.marginBottom()); + add(chrome); + + camera = new Camera(0, 0, (int) chrome.width, (int) chrome.height, + PixelScene.defaultZoom); + camera.x = (int) (Game.width - camera.width * camera.zoom) / 2; + camera.y = (int) (Game.height - camera.height * camera.zoom) / 2; + camera.scroll.set(chrome.x, chrome.y); + Camera.add(camera); + + shadow.boxRect(camera.x / camera.zoom, camera.y / camera.zoom, + chrome.width(), chrome.height); + + Keys.event.add(this); + } + + public void resize(int w, int h) { + this.width = w; + this.height = h; + + chrome.size(width + chrome.marginHor(), height + chrome.marginVer()); + + camera.resize((int) chrome.width, (int) chrome.height); + camera.x = (int) (Game.width - camera.screenWidth()) / 2; + camera.y = (int) (Game.height - camera.screenHeight()) / 2; + + shadow.boxRect(camera.x / camera.zoom, camera.y / camera.zoom, + chrome.width(), chrome.height); + } + + public void offset( int yOffset ){ + camera.y -= this.yOffset * camera.zoom; + this.yOffset = yOffset; + camera.y += yOffset * camera.zoom; + + shadow.boxRect( camera.x / camera.zoom, camera.y / camera.zoom, chrome.width(), chrome.height ); + } + + public void hide() { + parent.erase(this); + destroy(); + } + + @Override + public void destroy() { + super.destroy(); + + Camera.remove(camera); + Keys.event.remove(this); + } + + @Override + public void onSignal(Key key) { + if (key.pressed) { + switch (key.code) { + case Keys.BACK: + onBackPressed(); + break; + case Keys.MENU: + onMenuPressed(); + break; + } + } + + Keys.event.cancel(); + } + + public void onBackPressed() { + hide(); + } + + public void onMenuPressed() { + } + + protected static class Highlighter { + + private static final Pattern HIGHLIGHTER = Pattern.compile("_(.*?)_"); + private static final Pattern STRIPPER = Pattern.compile("[ \n]"); + + public String text; + + public boolean[] mask; + + public Highlighter(String text) { + + String stripped = STRIPPER.matcher(text).replaceAll(""); + mask = new boolean[stripped.length()]; + + Matcher m = HIGHLIGHTER.matcher(stripped); + + int pos = 0; + int lastMatch = 0; + + while (m.find()) { + pos += (m.start() - lastMatch); + int groupLen = m.group(1).length(); + for (int i = pos; i < pos + groupLen; i++) { + mask[i] = true; + } + pos += groupLen; + lastMatch = m.end(); + } + + m.reset(text); + StringBuffer sb = new StringBuffer(); + while (m.find()) { + m.appendReplacement(sb, m.group(1)); + } + m.appendTail(sb); + + this.text = sb.toString(); + } + + public boolean[] inverted() { + boolean[] result = new boolean[mask.length]; + for (int i = 0; i < result.length; i++) { + result[i] = !mask[i]; + } + return result; + } + + public boolean isHighlighted() { + for (int i = 0; i < mask.length; i++) { + if (mask[i]) { + return true; + } + } + return false; + } + } +} diff --git a/java/com/hmdzl/spspd/utils/BArray.java b/java/com/hmdzl/spspd/utils/BArray.java new file mode 100644 index 00000000..1cfbf749 --- /dev/null +++ b/java/com/hmdzl/spspd/utils/BArray.java @@ -0,0 +1,163 @@ +/* + * 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 + */ +package com.hmdzl.spspd.utils; + +public class BArray { + + private static boolean[] falseArray; + + //This is MUCH faster than making a new boolean[] or using Arrays.fill; + public static void setFalse( boolean[] toBeFalse ){ + if (falseArray == null || falseArray.length < toBeFalse.length) + falseArray = new boolean[toBeFalse.length]; + + System.arraycopy(falseArray, 0, toBeFalse, 0, toBeFalse.length); + } + + public static boolean[] and(boolean[] a, boolean[] b, boolean[] result) { + + int length = a.length; + + if (result == null) { + result = new boolean[length]; + } + + for (int i = 0; i < length; i++) { + result[i] = a[i] && b[i]; + } + + return result; + } + + public static boolean[] or(boolean[] a, boolean[] b, boolean[] result) { + + int length = a.length; + + if (result == null) { + result = new boolean[length]; + } + + for (int i = 0; i < length; i++) { + result[i] = a[i] || b[i]; + } + + return result; + } + + public static boolean[] or( boolean[] a, boolean[] b, int offset, int length, boolean[] result ) { + + if (result == null) { + result = new boolean[length]; + } + + for (int i=offset; i < offset+length; i++) { + result[i] = a[i] || b[i]; + } + + return result; + } + + public static boolean[] not(boolean[] a, boolean[] result) { + + int length = a.length; + + if (result == null) { + result = new boolean[length]; + } + + for (int i = 0; i < length; i++) { + result[i] = !a[i]; + } + + return result; + } + + public static boolean[] is(int[] a, boolean[] result, int v1) { + + int length = a.length; + + if (result == null) { + result = new boolean[length]; + } + + for (int i = 0; i < length; i++) { + result[i] = a[i] == v1; + } + + return result; + } + + public static boolean[] isOneOf(int[] a, boolean[] result, int... v) { + + int length = a.length; + int nv = v.length; + + if (result == null) { + result = new boolean[length]; + } + + for (int i = 0; i < length; i++) { + result[i] = false; + for (int j = 0; j < nv; j++) { + if (a[i] == v[j]) { + result[i] = true; + break; + } + } + } + + return result; + } + + public static boolean[] isNot(int[] a, boolean[] result, int v1) { + + int length = a.length; + + if (result == null) { + result = new boolean[length]; + } + + for (int i = 0; i < length; i++) { + result[i] = a[i] != v1; + } + + return result; + } + + public static boolean[] isNotOneOf(int[] a, boolean[] result, int... v) { + + int length = a.length; + int nv = v.length; + + if (result == null) { + result = new boolean[length]; + } + + for (int i = 0; i < length; i++) { + result[i] = true; + for (int j = 0; j < nv; j++) { + if (a[i] == v[j]) { + result[i] = false; + break; + } + } + } + + return result; + } +} diff --git a/java/com/hmdzl/spspd/utils/GLog.java b/java/com/hmdzl/spspd/utils/GLog.java new file mode 100644 index 00000000..629a9bd6 --- /dev/null +++ b/java/com/hmdzl/spspd/utils/GLog.java @@ -0,0 +1,61 @@ +/* + * 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 + */ +package com.hmdzl.spspd.utils; + +import android.util.Log; + +import com.watabou.utils.Signal; +import com.hmdzl.spspd.messages.Messages; + +public class GLog { + + public static final String TAG = "GAME"; + + public static final String POSITIVE = "++ "; + public static final String NEGATIVE = "-- "; + public static final String WARNING = "** "; + public static final String HIGHLIGHT = "@@ "; + + public static Signal update = new Signal(); + + public static void i(String text, Object... args) { + + if (args.length > 0) { + text = Messages.format(text, args); + } + + Log.i(TAG, text); + update.dispatch(text); + } + + public static void p(String text, Object... args) { + i(POSITIVE + text, args); + } + + public static void n(String text, Object... args) { + i(NEGATIVE + text, args); + } + + public static void w(String text, Object... args) { + i(WARNING + text, args); + } + + public static void h(String text, Object... args) { + i(HIGHLIGHT + text, args); + } +} diff --git a/java/com/hmdzl/spspd/utils/Utils.java b/java/com/hmdzl/spspd/utils/Utils.java new file mode 100644 index 00000000..1b339235 --- /dev/null +++ b/java/com/hmdzl/spspd/utils/Utils.java @@ -0,0 +1,47 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2015 Evan Debenham + * + * Goblins Pixel Dungeon + * Copyright (C) 2016 Mario Braun + * + * 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 + */ +package com.hmdzl.spspd.utils; + +import java.util.Locale; + +public class Utils { + + public static String capitalize( String str ) { + return Character.toUpperCase( str.charAt( 0 ) ) + str.substring( 1 ); + } + + public static String format( String format, Object...args ) { + return String.format( Locale.ENGLISH, format, args ); + } + + public static String VOWELS = "aoeiu"; + + public static String indefinite( String noun ) { + if (noun.length() == 0) { + return "a"; + } else { + return (VOWELS.indexOf( Character.toLowerCase( noun.charAt( 0 ) ) ) != -1 ? "an " : "a ") + noun; + } + } +} diff --git a/java/com/hmdzl/spspd/windows/IconTitle.java b/java/com/hmdzl/spspd/windows/IconTitle.java new file mode 100644 index 00000000..8c9546cb --- /dev/null +++ b/java/com/hmdzl/spspd/windows/IconTitle.java @@ -0,0 +1,115 @@ +/* + * 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 + */ +package com.hmdzl.spspd.windows; + +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.scenes.PixelScene; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.ui.HealthBar; +import com.hmdzl.spspd.ui.RenderedTextMultiline; +import com.hmdzl.spspd.ui.Window; +import com.hmdzl.spspd.messages.Messages; +import com.watabou.noosa.Image; +import com.watabou.noosa.ui.Component; + +public class IconTitle extends Component { + + private static final int FONT_SIZE = 9; + + private static final float GAP = 2; + + protected Image imIcon; + protected RenderedTextMultiline tfLabel; + protected HealthBar health; + + private float healthLvl = Float.NaN; + + public IconTitle() { + super(); + } + + public IconTitle(Item item) { + this(new ItemSprite(item.image(), item.glowing()),Messages.titleCase( item.toString() ) ); + + } + + public IconTitle(Image icon, String label) { + super(); + + icon(icon); + label(label); + } + + @Override + protected void createChildren() { + imIcon = new Image(); + add(imIcon); + + tfLabel = PixelScene.renderMultiline(FONT_SIZE); + tfLabel.hardlight(Window.TITLE_COLOR); + add(tfLabel); + + health = new HealthBar(); + add(health); + } + + @Override + protected void layout() { + + health.visible = !Float.isNaN( healthLvl ); + + imIcon.x = x; + imIcon.y = y; + + tfLabel.maxWidth((int)(width - (imIcon.x + imIcon.width() + GAP))); + tfLabel.setPos(imIcon.x + imIcon.width() + GAP, imIcon.height > tfLabel.height() ? + imIcon.y + (imIcon.height() - tfLabel.height()) / 2 : + imIcon.y); + PixelScene.align(tfLabel); + + if (health.visible) { + health.setRect( tfLabel.left(), Math.max( tfLabel.top() + tfLabel.height(), imIcon.y + imIcon.height() - health.height() ), tfLabel.maxWidth(), 0 ); + height = health.bottom(); + } else { + height = Math.max( imIcon.height(), tfLabel.height() ); + } + } + + public void icon(Image icon) { + remove(imIcon); + add(imIcon = icon); + } + + public void label(String label) { + tfLabel.text(label); + } + + public void label(String label, int color) { + tfLabel.text(label); + tfLabel.hardlight(color); + } + + public void color(int color) { + tfLabel.hardlight(color); + } + + public void health(float value) { + health.level(healthLvl = value); + layout(); + } +} diff --git a/java/com/hmdzl/spspd/windows/WndAflyInfo.java b/java/com/hmdzl/spspd/windows/WndAflyInfo.java new file mode 100644 index 00000000..8a8631fc --- /dev/null +++ b/java/com/hmdzl/spspd/windows/WndAflyInfo.java @@ -0,0 +1,253 @@ +package com.hmdzl.spspd.windows; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.armor.normalarmor.LifeArmor; +import com.hmdzl.spspd.items.food.completefood.AflyFood; +import com.hmdzl.spspd.items.food.completefood.Garbage; +import com.hmdzl.spspd.items.food.fruit.Fruit; +import com.hmdzl.spspd.items.food.meatfood.MeatFood; +import com.hmdzl.spspd.items.food.staplefood.StapleFood; +import com.hmdzl.spspd.items.food.vegetable.Vegetable; +import com.hmdzl.spspd.items.weapon.melee.block.GoblinShield; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.scenes.PixelScene; +import com.hmdzl.spspd.sprites.HeroSprite; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.ui.Icons; +import com.hmdzl.spspd.ui.ItemSlot; +import com.hmdzl.spspd.ui.RedButton; +import com.hmdzl.spspd.ui.RenderedTextMultiline; +import com.hmdzl.spspd.ui.Window; +import com.watabou.noosa.ColorBlock; +import com.watabou.noosa.Image; +import com.watabou.noosa.audio.Sample; +import com.watabou.noosa.particles.Emitter; + +import java.util.ArrayList; + +import static com.hmdzl.spspd.Dungeon.hero; + + +public class WndAflyInfo extends Window { + + private WndBlacksmith.ItemButton[] inputs = new WndBlacksmith.ItemButton[3]; + private ItemSlot output; + + private Emitter smokeEmitter; + private Emitter bubbleEmitter; + + private RedButton btnCombine; + + private static final int WIDTH_P = 116; + private static final int WIDTH_L = 160; + + private static final int BTN_SIZE = 28; + + public WndAflyInfo(){ + + int w = WIDTH_P; + + int h = 0; + + + AflyFood key = new AflyFood(); + IconTitle titlebar = new IconTitle(); + titlebar.icon(new ItemSprite(key.image(), null)); + titlebar.label( Messages.get(this, "title") ); + titlebar.setRect( 0, 0, w, 0 ); + add( titlebar ); + + h += titlebar.height() + 2; + + RenderedTextMultiline desc = PixelScene.renderMultiline(6); + desc.text( Messages.get(this, "text") ); + desc.setPos(0, h); + desc.maxWidth(w); + add(desc); + + h += desc.height() + 6; + + for (int i = 0; i < (inputs.length); i++) { + inputs[i] = new WndBlacksmith.ItemButton(){ + @Override + protected void onClick() { + super.onClick(); + if (item != null){ + if (!item.collect()){ + Dungeon.level.drop(item, hero.pos); + } + item = null; + slot.item(new WndBag.Placeholder(ItemSpriteSheet.SOMETHING)); + } + GameScene.selectItem( itemSelector, WndBag.Mode.COOKING, Messages.get(WndAlchemy.class, "select") ); + } + }; + inputs[i].setRect(15, h, BTN_SIZE, BTN_SIZE); + add(inputs[i]); + h += BTN_SIZE + 2; + } + + Image arrow = Icons.get(Icons.RESUME); + arrow.hardlight(0, 0, 0); + arrow.x = (w - arrow.width)/2f; + arrow.y = inputs[1].top() + (inputs[1].height() - arrow.height)/2f; + PixelScene.align(arrow); + add(arrow); + + output = new ItemSlot(){ + @Override + protected void onClick() { + super.onClick(); + /*if (visible){ + GameScene.show(new WndInfoItem); + }*/ + } + }; + output.setRect(w - BTN_SIZE - 15, inputs[1].top(), BTN_SIZE, BTN_SIZE); + + ColorBlock outputBG = new ColorBlock(output.width(), output.height(), 0x9991938C); + outputBG.x = output.left(); + outputBG.y = output.top(); + add(outputBG); + + add(output); + output.visible = false; + + bubbleEmitter = new Emitter(); + smokeEmitter = new Emitter(); + bubbleEmitter.pos(outputBG.x + (BTN_SIZE-16)/2f, outputBG.y + (BTN_SIZE-16)/2f, 16, 16); + smokeEmitter.pos(bubbleEmitter.x, bubbleEmitter.y, bubbleEmitter.width, bubbleEmitter.height); + bubbleEmitter.autoKill = false; + smokeEmitter.autoKill = false; + add(bubbleEmitter); + add(smokeEmitter); + + h += 4; + + float btnWidth = (w-14)/2f; + + btnCombine = new RedButton(Messages.get(this, "combine")){ + @Override + protected void onClick() { + super.onClick(); + combine(); + } + }; + btnCombine.setRect(5, h, btnWidth, 18); + PixelScene.align(btnCombine); + btnCombine.enable(false); + add(btnCombine); + + RedButton btnCancel = new RedButton(Messages.get(this, "cancel")){ + @Override + protected void onClick() { + super.onClick(); + onBackPressed(); + } + }; + btnCancel.setRect(w - 5 - btnWidth, h, btnWidth, 18); + PixelScene.align(btnCancel); + add(btnCancel); + + h += btnCancel.height(); + + resize(w, h); + } + + protected WndBag.Listener itemSelector = new WndBag.Listener() { + @Override + public void onSelect( Item item ) { + if (item != null) { + for (int i = 0; i < (inputs.length); i++) { + if (inputs[i].item == null){ + //inputs[i].item(hero.belongings.misc1 = null); + //inputs[i].item(hero.belongings.misc2 = null); + //inputs[i].item(hero.belongings.misc3 = null); + inputs[i].item(item.detach(hero.belongings.backpack)); + break; + } + } + } + updateState(); + } + }; + + private ArrayList filterInput(Class itemClass){ + ArrayList filtered = new ArrayList<>(); + for (int i = 0; i < (inputs.length); i++){ + Item item = inputs[i].item; + if (item != null && itemClass.isInstance(item)){ + filtered.add((T)item); + } + } + return filtered; + } + + private void updateState(){ + //potion creation + if(filterInput(Item.class).size() > 0){ + output.item(new WndBag.Placeholder(ItemSpriteSheet.SOMETHING)); + output.visible = true; + btnCombine.enable(true); + } else { + btnCombine.enable(false); + output.visible = false; + } + } + + private void combine(){ + + ArrayList vegetables = filterInput(Vegetable.class); + ArrayList fruits = filterInput(Fruit.class); + ArrayList staplefoods = filterInput(StapleFood.class); + ArrayList meatfoods = filterInput(MeatFood.class); + + Item result = null; + + if (fruits.size() == 1 && staplefoods.size() == 1 && meatfoods.size() == 1 ){ + + result = new AflyFood(); + + } else if (fruits.size() == 1 && vegetables.size() == 2 ){ + + result = new LifeArmor(); + + } else result = new Garbage(); + + if (result != null){ + bubbleEmitter.start(Speck.factory( Speck.BUBBLE ), 0.2f, 10 ); + smokeEmitter.burst(Speck.factory( Speck.WOOL ), 10 ); + Sample.INSTANCE.play( Assets.SND_PUFF ); + + output.item(result); + if (!result.collect()){ + Dungeon.level.drop(result, hero.pos); + } + for (int i = 0; i < (inputs.length ); i++){ + inputs[i].slot.item(new WndBag.Placeholder(ItemSpriteSheet.SOMETHING)); + inputs[i].item = null; + } + + btnCombine.enable(false); + } + + } + + @Override + public void onBackPressed() { + for (int i = 0; i < (inputs.length ); i++) { + if (inputs[i].item != null){ + if (!inputs[i].item.collect()){ + Dungeon.level.drop(inputs[i].item, hero.pos); + } + } + } + super.onBackPressed(); + } +} + diff --git a/java/com/hmdzl/spspd/windows/WndAlchemy.java b/java/com/hmdzl/spspd/windows/WndAlchemy.java new file mode 100644 index 00000000..6ab76c2b --- /dev/null +++ b/java/com/hmdzl/spspd/windows/WndAlchemy.java @@ -0,0 +1,567 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2018 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ + +package com.hmdzl.spspd.windows; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.ShatteredPixelDungeon; +import com.hmdzl.spspd.Statistics; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.StoneOre; +import com.hmdzl.spspd.items.Torch; +import com.hmdzl.spspd.items.food.WaterItem; +import com.hmdzl.spspd.items.Weightstone; +import com.hmdzl.spspd.items.artifacts.AlchemistsToolkit; +import com.hmdzl.spspd.items.bombs.BuildBomb; +import com.hmdzl.spspd.items.food.completefood.Chocolate; +import com.hmdzl.spspd.items.food.completefood.FoodFans; +import com.hmdzl.spspd.items.food.completefood.Frenchfries; +import com.hmdzl.spspd.items.food.staplefood.NormalRation; +import com.hmdzl.spspd.items.food.vegetable.NutVegetable; +import com.hmdzl.spspd.items.medicine.BlueMilk; +import com.hmdzl.spspd.items.medicine.DeathCap; +import com.hmdzl.spspd.items.medicine.Earthstar; +import com.hmdzl.spspd.items.medicine.GoldenJelly; +import com.hmdzl.spspd.items.medicine.GreenSpore; +import com.hmdzl.spspd.items.medicine.Hardpill; +import com.hmdzl.spspd.items.medicine.JackOLantern; +import com.hmdzl.spspd.items.medicine.Magicpill; +import com.hmdzl.spspd.items.medicine.Musicpill; +import com.hmdzl.spspd.items.medicine.PixieParasol; +import com.hmdzl.spspd.items.medicine.Powerpill; +import com.hmdzl.spspd.items.medicine.Shootpill; +import com.hmdzl.spspd.items.medicine.Smashpill; +import com.hmdzl.spspd.items.summon.Honeypot; +import com.hmdzl.spspd.items.bombs.HugeBomb; +import com.hmdzl.spspd.items.food.completefood.Chickennugget; +import com.hmdzl.spspd.items.food.completefood.Crystalnucleus; +import com.hmdzl.spspd.items.food.completefood.Foamedbeverage; +import com.hmdzl.spspd.items.food.completefood.Fruitsalad; +import com.hmdzl.spspd.items.food.completefood.Garbage; +import com.hmdzl.spspd.items.food.completefood.Gel; +import com.hmdzl.spspd.items.food.completefood.Hamburger; +import com.hmdzl.spspd.items.food.completefood.Herbmeat; +import com.hmdzl.spspd.items.food.completefood.HoneyGel; +import com.hmdzl.spspd.items.food.completefood.HoneyWater; +import com.hmdzl.spspd.items.food.completefood.Honeymeat; +import com.hmdzl.spspd.items.food.completefood.Honeyrice; +import com.hmdzl.spspd.items.food.completefood.Icecream; +import com.hmdzl.spspd.items.food.completefood.Kebab; +import com.hmdzl.spspd.items.food.completefood.Meatroll; +import com.hmdzl.spspd.items.food.completefood.Porksoup; +import com.hmdzl.spspd.items.food.completefood.Ricefood; +import com.hmdzl.spspd.items.food.completefood.Vegetablekebab; +import com.hmdzl.spspd.items.food.completefood.Vegetableroll; +import com.hmdzl.spspd.items.food.completefood.Vegetablesoup; +import com.hmdzl.spspd.items.food.fruit.Blandfruit; +import com.hmdzl.spspd.items.food.fruit.Fruit; +import com.hmdzl.spspd.items.food.meatfood.MeatFood; +import com.hmdzl.spspd.items.food.Nut; +import com.hmdzl.spspd.items.food.completefood.PerfectFood; +import com.hmdzl.spspd.items.food.completefood.PetFood; +import com.hmdzl.spspd.items.food.Honey; +import com.hmdzl.spspd.items.food.staplefood.OverpricedRation; +import com.hmdzl.spspd.items.food.staplefood.StapleFood; +import com.hmdzl.spspd.items.food.vegetable.Vegetable; +import com.hmdzl.spspd.items.potions.Potion; +import com.hmdzl.spspd.items.scrolls.Scroll; +import com.hmdzl.spspd.items.scrolls.ScrollOfMagicalInfusion; +import com.hmdzl.spspd.items.weapon.spammo.BattleAmmo; +import com.hmdzl.spspd.items.weapon.spammo.BlindAmmo; +import com.hmdzl.spspd.items.weapon.spammo.DewAmmo; +import com.hmdzl.spspd.items.weapon.spammo.DreamAmmo; +import com.hmdzl.spspd.items.weapon.spammo.EmptyAmmo; +import com.hmdzl.spspd.items.weapon.spammo.EvolveAmmo; +import com.hmdzl.spspd.items.weapon.spammo.FireAmmo; +import com.hmdzl.spspd.items.weapon.spammo.GoldAmmo; +import com.hmdzl.spspd.items.weapon.spammo.HeavyAmmo; +import com.hmdzl.spspd.items.weapon.spammo.IceAmmo; +import com.hmdzl.spspd.items.weapon.spammo.MossAmmo; +import com.hmdzl.spspd.items.weapon.spammo.RotAmmo; +import com.hmdzl.spspd.items.weapon.spammo.SandAmmo; +import com.hmdzl.spspd.items.weapon.spammo.StarAmmo; +import com.hmdzl.spspd.items.weapon.spammo.StormAmmo; +import com.hmdzl.spspd.items.weapon.spammo.SunAmmo; +import com.hmdzl.spspd.items.weapon.spammo.ThornAmmo; +import com.hmdzl.spspd.items.weapon.spammo.WoodenAmmo; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.plants.BlandfruitBush; +import com.hmdzl.spspd.plants.Blindweed; +import com.hmdzl.spspd.plants.Dewcatcher; +import com.hmdzl.spspd.plants.Dreamfoil; +import com.hmdzl.spspd.plants.Earthroot; +import com.hmdzl.spspd.plants.Fadeleaf; +import com.hmdzl.spspd.plants.Firebloom; +import com.hmdzl.spspd.plants.Flytrap; +import com.hmdzl.spspd.plants.Icecap; +import com.hmdzl.spspd.plants.NutPlant; +import com.hmdzl.spspd.plants.Phaseshift; +import com.hmdzl.spspd.plants.Plant; +import com.hmdzl.spspd.plants.Rotberry; +import com.hmdzl.spspd.plants.Seedpod; +import com.hmdzl.spspd.plants.Sorrowmoss; +import com.hmdzl.spspd.plants.Starflower; +import com.hmdzl.spspd.plants.Stormvine; +import com.hmdzl.spspd.plants.Sungrass; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.scenes.PixelScene; +import com.hmdzl.spspd.sprites.HeroSprite; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.ui.Icons; +import com.hmdzl.spspd.ui.ItemSlot; +import com.hmdzl.spspd.ui.RedButton; +import com.hmdzl.spspd.ui.RenderedTextMultiline; +import com.hmdzl.spspd.ui.Window; +import com.watabou.noosa.ColorBlock; +import com.watabou.noosa.Image; +import com.watabou.noosa.audio.Sample; +import com.watabou.noosa.particles.Emitter; +import com.watabou.utils.Random; + +import java.util.ArrayList; + +import static com.hmdzl.spspd.Dungeon.hero; + +public class WndAlchemy extends Window { + + private WndBlacksmith.ItemButton[] inputs = new WndBlacksmith.ItemButton[5]; + private ItemSlot output; + + private Emitter smokeEmitter; + private Emitter bubbleEmitter; + + private RedButton btnCombine; + + private static final int WIDTH_P = 116; + private static final int WIDTH_L = 160; + + private static final int BTN_SIZE = 28; + + public WndAlchemy(){ + + int w = WIDTH_P; + + int h = 0; + + IconTitle titlebar = new IconTitle(); + titlebar.icon(HeroSprite.avatar(hero.heroClass, hero.useskin())); + titlebar.label( Messages.get(this, "title") ); + titlebar.setRect( 0, 0, w, 0 ); + add( titlebar ); + + h += titlebar.height() + 2; + + RenderedTextMultiline desc = PixelScene.renderMultiline(6); + desc.text( Messages.get(this, "text") ); + desc.setPos(0, h); + desc.maxWidth(w); + add(desc); + + h += desc.height() + 6; + + AlchemistsToolkit.alchemy alchemytool = Dungeon.hero.buff(AlchemistsToolkit.alchemy.class); + int bonus = alchemytool != null ? alchemytool.level()/5 : 0; + for (int i = 0; i < (inputs.length - 2 + bonus ); i++) { + inputs[i] = new WndBlacksmith.ItemButton(){ + @Override + protected void onClick() { + super.onClick(); + if (item != null){ + if (!item.collect()){ + Dungeon.level.drop(item, hero.pos); + } + item = null; + slot.item(new WndBag.Placeholder(ItemSpriteSheet.SOMETHING)); + } + GameScene.selectItem( itemSelector, WndBag.Mode.COOKING, Messages.get(WndAlchemy.class, "select") ); + } + }; + inputs[i].setRect(15, h, BTN_SIZE, BTN_SIZE); + add(inputs[i]); + h += BTN_SIZE + 2; + } + + Image arrow = Icons.get(Icons.RESUME); + arrow.hardlight(0, 0, 0); + arrow.x = (w - arrow.width)/2f; + arrow.y = inputs[1].top() + (inputs[1].height() - arrow.height)/2f; + PixelScene.align(arrow); + add(arrow); + + output = new ItemSlot(){ + @Override + protected void onClick() { + super.onClick(); + /*if (visible){ + GameScene.show(new WndInfoItem); + }*/ + } + }; + output.setRect(w - BTN_SIZE - 15, inputs[1].top(), BTN_SIZE, BTN_SIZE); + + ColorBlock outputBG = new ColorBlock(output.width(), output.height(), 0x9991938C); + outputBG.x = output.left(); + outputBG.y = output.top(); + add(outputBG); + + add(output); + output.visible = false; + + bubbleEmitter = new Emitter(); + smokeEmitter = new Emitter(); + bubbleEmitter.pos(outputBG.x + (BTN_SIZE-16)/2f, outputBG.y + (BTN_SIZE-16)/2f, 16, 16); + smokeEmitter.pos(bubbleEmitter.x, bubbleEmitter.y, bubbleEmitter.width, bubbleEmitter.height); + bubbleEmitter.autoKill = false; + smokeEmitter.autoKill = false; + add(bubbleEmitter); + add(smokeEmitter); + + h += 4; + + float btnWidth = (w-14)/2f; + + btnCombine = new RedButton(Messages.get(this, "combine")){ + @Override + protected void onClick() { + super.onClick(); + combine(); + } + }; + btnCombine.setRect(5, h, btnWidth, 18); + PixelScene.align(btnCombine); + btnCombine.enable(false); + add(btnCombine); + + RedButton btnCancel = new RedButton(Messages.get(this, "cancel")){ + @Override + protected void onClick() { + super.onClick(); + onBackPressed(); + } + }; + btnCancel.setRect(w - 5 - btnWidth, h, btnWidth, 18); + PixelScene.align(btnCancel); + add(btnCancel); + + h += btnCancel.height(); + + resize(w, h); + } + + protected WndBag.Listener itemSelector = new WndBag.Listener() { + @Override + public void onSelect( Item item ) { + if (item != null) { + AlchemistsToolkit.alchemy alchemytool = Dungeon.hero.buff(AlchemistsToolkit.alchemy.class); + int bonus = alchemytool != null ? alchemytool.level()/5 : 0; + for (int i = 0; i < (inputs.length - 2 + bonus ); i++) { + if (inputs[i].item == null){ + inputs[i].item(item.detach(hero.belongings.backpack)); + break; + } + } + } + updateState(); + } + }; + + private ArrayList filterInput(Class itemClass){ + ArrayList filtered = new ArrayList<>(); + AlchemistsToolkit.alchemy alchemytool = Dungeon.hero.buff(AlchemistsToolkit.alchemy.class); + int bonus = alchemytool != null ? alchemytool.level()/5 : 0; + for (int i = 0; i < (inputs.length - 2 + bonus ); i++){ + Item item = inputs[i].item; + if (item != null && itemClass.isInstance(item)){ + filtered.add((T)item); + } + } + return filtered; + } + + private void updateState(){ + //potion creation + if (filterInput(Plant.Seed.class).size() == 3){ + output.item(new WndBag.Placeholder(ItemSpriteSheet.POTION)); + output.visible = true; + btnCombine.enable(true); + + //blandfruit cooking + } else if(filterInput(Blandfruit.class).size() == 1 && filterInput(Plant.Seed.class).size() == 1){ + output.item(new WndBag.Placeholder(ItemSpriteSheet.SOMETHING)); + output.visible = true; + btnCombine.enable(true); + + /*} else if (filterInput(Honeypot.class).size() == 1 || filterInput(Honeypot.ShatteredPot.class).size() == 1 ){ + output.item(new WndBag.Placeholder(ItemSpriteSheet.SOMETHING)); + output.visible = true; + btnCombine.enable(true);*/ + } else if(filterInput(Item.class).size() > 0){ + output.item(new WndBag.Placeholder(ItemSpriteSheet.SOMETHING)); + output.visible = true; + btnCombine.enable(true); + } else { + btnCombine.enable(false); + output.visible = false; + } + } + + private void combine(){ + ArrayList seeds = filterInput(Plant.Seed.class); + ArrayList blandfruits = filterInput(Blandfruit.class); + ArrayList honeypot = filterInput(Honeypot.class); + ArrayList honey = filterInput(Honey.class); + ArrayList shatteredpot = filterInput(Honeypot.ShatteredPot.class); + ArrayList water = filterInput(WaterItem.class); + ArrayList vegetables = filterInput(Vegetable.class); + ArrayList ore = filterInput(StoneOre.class); + ArrayList nut = filterInput(Nut.class); + ArrayList fruits = filterInput(Fruit.class); + ArrayList staplefoods = filterInput(StapleFood.class); + ArrayList meatfoods = filterInput(MeatFood.class); + + ArrayList potions = filterInput(Potion.class); + ArrayList scrolls = filterInput(Scroll.class); + ArrayList gels = filterInput(Gel.class); + ArrayList bbomb = filterInput(BuildBomb.class); + ArrayList miscroll = filterInput(ScrollOfMagicalInfusion.class); + + ArrayList iceseed = filterInput(Icecap.Seed.class); + ArrayList fireseed = filterInput(Firebloom.Seed.class); + ArrayList blindseed = filterInput(Blindweed.Seed.class); + ArrayList stormseed = filterInput(Stormvine.Seed.class); + ArrayList dreamseed = filterInput(Dreamfoil.Seed.class); + ArrayList mossseed = filterInput(Sorrowmoss.Seed.class); + ArrayList starseed = filterInput(Starflower.Seed.class); + ArrayList sunseed = filterInput(Sungrass.Seed.class); + ArrayList dewseed = filterInput(Dewcatcher.Seed.class); + ArrayList sandseed = filterInput(Fadeleaf.Seed.class); + ArrayList seedseed = filterInput(Seedpod.Seed.class); + ArrayList rotseed = filterInput(Rotberry.Seed.class); + ArrayList rootseed = filterInput(Earthroot.Seed.class); + ArrayList blandseed = filterInput(BlandfruitBush.Seed.class); + ArrayList trapseed = filterInput(Flytrap.Seed.class); + ArrayList phaseseed = filterInput(Phaseshift.Seed.class); + ArrayList nutseed = filterInput(NutPlant.Seed.class); + + Item result = null; + + if (honey.size() == 1 && ore.size() == 1 && staplefoods.size() ==1 && water.size() == 1 && seeds.size() == 1 ){ + result = new PerfectFood(); + } else if (vegetables.size() == 1 && ore.size() == 1 && staplefoods.size() ==1 && water.size() == 1 && fruits.size() == 1 ){ + result = new PerfectFood(); + } else if ( ore.size() == 3 && water.size() == 1 && seeds.size() == 1 ){ + result = new Crystalnucleus(); + } else if ( staplefoods.size() ==2 && vegetables.size() == 1 && meatfoods.size() == 2 ){ + result = new Hamburger(); + } else if ( meatfoods.size() ==3 && vegetables.size() == 1 ){ + result = new Powerpill(); + } else if ( meatfoods.size() ==2 && ore.size() == 1 && vegetables.size() ==1 ){ + result = new Hardpill(); + } else if (meatfoods.size() ==2 && potions.size() == 1 && vegetables.size() ==1 ){ + result = new Smashpill(); + } else if ( meatfoods.size() ==3 && seeds.size() == 1 ){ + result = new Shootpill(); + } else if ( meatfoods.size() ==2 && ore.size() == 1 && seeds.size() ==1 ){ + result = new Musicpill(); + } else if (meatfoods.size() ==2 && potions.size() == 1 && seeds.size() ==1 ){ + result = new Magicpill(); + + } else if (water.size() ==1 && vegetables.size() == 1 && dewseed.size() ==1 ){ + result = new GreenSpore(); + } else if (water.size() ==1 && vegetables.size() == 1 && stormseed.size() ==1 ){ + result = new GoldenJelly(); + } else if (water.size() ==1 && vegetables.size() == 1 && rootseed.size() ==1 ){ + result = new Earthstar(); + } else if (water.size() ==1 && vegetables.size() == 1 && fireseed.size() ==1 ){ + result = new JackOLantern(); + } else if (water.size() ==1 && vegetables.size() == 1 && dreamseed.size() ==1 ){ + result = new PixieParasol(); + } else if (water.size() ==1 && vegetables.size() == 1 && sunseed.size() ==1 ){ + result = new BlueMilk(); + } else if (water.size() ==1 && vegetables.size() == 1 && mossseed.size() ==1 ) { + result = new DeathCap(); + + //potion creation + } else if (seeds.size() == 3){ + + if (Random.Int( 3 ) == 0) { + + result = Generator.random( Generator.Category.POTION ); + + } else { + + Class itemClass = Random.element(seeds).alchemyClass; + try { + result = itemClass.newInstance(); + } catch (Exception e) { + ShatteredPixelDungeon.reportException(e); + result = Generator.random( Generator.Category.POTION ); + } + + } + + Statistics.potionsCooked++; + Badges.validatePotionsCooked(); + + //blandfruit cooking + } else if (blandfruits.size() == 1 && seeds.size() == 1) { + result = fruits.get(0); + ((Blandfruit)result).cook(seeds.get(0)); + + } else if (honeypot.size() == 1 || shatteredpot.size() == 1) { + result = new Honey(); + } else if (honey.size() == 1 && water.size() == 1 && iceseed.size() == 1 ){ + result = new Icecream(); + } else if (meatfoods.size() ==1 && water.size() == 1 && vegetables.size() ==1 ){ + result = new Porksoup(); + } else if ( ore.size() == 1 && water.size() == 2 && seeds.size() == 1 && fruits.size() == 1){ + result = new Foamedbeverage(); + } else if (fruits.size() == 2 && water.size() == 1 ){ + result = new Fruitsalad(); + } else if (vegetables.size() == 2 && meatfoods.size() == 1){ + result = new Vegetablekebab(); + } else if ( honey.size() == 1 && water.size() == 2 ){ + result = new HoneyWater(); + } else if (vegetables.size() == 1 && meatfoods.size() == 2 ){ + result = new Kebab(); + } else if (water.size() == 1 && vegetables.size() == 2 ){ + result = new Vegetablesoup(); + } else if (honey.size() == 1 && staplefoods.size() ==1 ){ + result = new Honeyrice(); + } else if (honey.size() == 1 && meatfoods.size() ==1 ){ + result = new Honeymeat(); + } else if ( meatfoods.size() == 1 && seeds.size() == 1 ){ + result = new Herbmeat(); + } else if ( ore.size() == 1 && meatfoods.size() == 1 ){ + result = new Chickennugget(); + } else if ( staplefoods.size() == 1 && water.size() == 1 ){ + result = new Ricefood(); + } else if ( scrolls.size() == 1 && meatfoods.size() == 1 ){ + result = new Meatroll(); + } else if ( scrolls.size() == 1 && vegetables.size() == 1 ){ + result = new Vegetableroll(); + } else if ( ore.size() == 1 && water.size() == 1 ){ + result = new Gel(); + } else if ( nut.size() == 5 ){ + result = new Chocolate(); + } else if ( nut.size() == 4 ){ + result = new NormalRation(); + } else if ( nut.size() == 3 ){ + result = new OverpricedRation(); + } else if (nut.size() == 2 && water.size() == 1){ + result = new PetFood(); + } else if ( nut.size() == 2 && potions.size()==1){ + result = new FoodFans(); + } else if ( nut.size() == 2 && scrolls.size()==1){ + result = new Frenchfries(); + } else if ( honey.size() == 1 && gels.size() == 1 ){ + result = new HoneyGel(); + + } else if ( ore.size() == 1 && seeds.size() == 1 && scrolls.size() == 1 ){ + result = new BuildBomb(); + } else if ( bbomb.size() == 1 && seeds.size() == 2 ){ + result = Generator.random( Generator.Category.BOMBS ); + } else if ( bbomb.size() == 2 ){ + result = new HugeBomb(); + + } else if ( ore.size() == 2 ){ + result = new HeavyAmmo(); + } else if ( ore.size() == 1 && nutseed.size()==1){ + result = new WoodenAmmo(); + } else if ( ore.size() == 1 && fireseed.size() == 1 ){ + result = new FireAmmo(); + } else if ( ore.size() == 1 && iceseed.size() == 1 ){ + result = new IceAmmo(); + } else if (ore.size() == 1 && stormseed.size() == 1 ){ + result = new StormAmmo(); + } else if (ore.size() == 1 && mossseed.size() == 1 ){ + result = new MossAmmo(); + } else if ( ore.size() == 1 && blindseed.size() == 1 ){ + result = new BlindAmmo(); + } else if ( ore.size() == 1 && starseed.size() == 1 ){ + result = new StarAmmo(); + } else if ( ore.size() == 1 && dreamseed.size() == 1 ){ + result = new DreamAmmo(); + } else if ( ore.size() == 1 && dewseed.size() == 1 ){ + result = new DewAmmo(); + } else if ( ore.size() == 1 && sunseed.size() == 1 ){ + result = new SunAmmo(); + } else if ( ore.size() == 1 && sandseed.size() == 1 ){ + result = new SandAmmo(); + } else if ( ore.size() == 1 && seedseed.size() == 1 ){ + result = new GoldAmmo(); + } else if ( ore.size() == 1 && rotseed.size() == 1 ){ + result = new RotAmmo(); + } else if ( ore.size() == 1 && rootseed.size() == 1 ){ + result = new ThornAmmo(); + } else if ( ore.size() == 1 && blandseed.size() == 1 ){ + result = new EmptyAmmo(); + } else if ( ore.size() == 1 && phaseseed.size() == 1 ){ + result = new EvolveAmmo(); + } else if ( ore.size() == 1 && trapseed.size() == 1 ){ + result = new BattleAmmo(); + } else if ( miscroll.size() == 1 ){ + result = new Weightstone(); + } else if ( gels.size() == 1 ){ + result = new Torch(); + } else if ( nut.size() == 1 ){ + result = new NutVegetable(); + } else result = new Garbage(); + + if (result != null){ + bubbleEmitter.start(Speck.factory( Speck.BUBBLE ), 0.2f, 10 ); + smokeEmitter.burst(Speck.factory( Speck.WOOL ), 10 ); + Sample.INSTANCE.play( Assets.SND_PUFF ); + + output.item(result); + if (!result.collect()){ + Dungeon.level.drop(result, hero.pos); + } + AlchemistsToolkit.alchemy alchemytool = Dungeon.hero.buff(AlchemistsToolkit.alchemy.class); + int bonus = alchemytool != null ? alchemytool.level()/5 : 0; + for (int i = 0; i < (inputs.length - 2 + bonus ); i++){ + inputs[i].slot.item(new WndBag.Placeholder(ItemSpriteSheet.SOMETHING)); + inputs[i].item = null; + } + + btnCombine.enable(false); + } + + } + + @Override + public void onBackPressed() { + AlchemistsToolkit.alchemy alchemytool = Dungeon.hero.buff(AlchemistsToolkit.alchemy.class); + int bonus = alchemytool != null ? alchemytool.level()/5 : 0; + for (int i = 0; i < (inputs.length - 2 + bonus ); i++) { + if (inputs[i].item != null){ + if (!inputs[i].item.collect()){ + Dungeon.level.drop(inputs[i].item, hero.pos); + } + } + } + super.onBackPressed(); + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/windows/WndAscend.java b/java/com/hmdzl/spspd/windows/WndAscend.java new file mode 100644 index 00000000..930c0d55 --- /dev/null +++ b/java/com/hmdzl/spspd/windows/WndAscend.java @@ -0,0 +1,73 @@ +/* + * 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 + */ +package com.hmdzl.spspd.windows; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.items.DewVial; +import com.hmdzl.spspd.scenes.PixelScene; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.RedButton; +import com.hmdzl.spspd.ui.RenderedTextMultiline; +import com.hmdzl.spspd.ui.Window; + + +public class WndAscend extends Window { + + private static final String TXT_MESSAGE = "Are you sure you want to ascend? " + +"Ascending here will end your game. "; + private static final String TXT_REWARD = "Ascend"; + + private static final int WIDTH = 120; + private static final int BTN_HEIGHT = 20; + private static final int GAP = 2; + + public WndAscend() { + + super(); + + DewVial dewvial = new DewVial(); + + IconTitle titlebar = new IconTitle(); + titlebar.icon(new ItemSprite(dewvial.image(), null)); + titlebar.label(Messages.titleCase(dewvial.name())); + titlebar.setRect(0, 0, WIDTH, 0); + add(titlebar); + + RenderedTextMultiline message = PixelScene + .renderMultiline(TXT_MESSAGE, 6); + message.maxWidth(WIDTH); + message.setPos(0, titlebar.bottom() + GAP); + add(message); + + RedButton btnReward = new RedButton(TXT_REWARD) { + @Override + protected void onClick() { + Dungeon.level.forcedone=true; + hide(); + } + }; + btnReward.setRect(0, message.top() + message.height() + GAP, WIDTH, + BTN_HEIGHT); + add(btnReward); + + resize(WIDTH, (int) btnReward.bottom()); + } + + +} diff --git a/java/com/hmdzl/spspd/windows/WndBadge.java b/java/com/hmdzl/spspd/windows/WndBadge.java new file mode 100644 index 00000000..597046bf --- /dev/null +++ b/java/com/hmdzl/spspd/windows/WndBadge.java @@ -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 + */ +package com.hmdzl.spspd.windows; + +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.effects.BadgeBanner; +import com.hmdzl.spspd.scenes.PixelScene; +import com.hmdzl.spspd.ui.RenderedTextMultiline; +import com.hmdzl.spspd.ui.Window; +import com.watabou.noosa.Image; + +public class WndBadge extends Window { + + private static final int WIDTH = 120; + private static final int MARGIN = 4; + + public WndBadge(Badges.Badge badge) { + + super(); + + Image icon = BadgeBanner.image(badge.image); + icon.scale.set(2); + add(icon); + + RenderedTextMultiline info = PixelScene.renderMultiline( badge.desc(), 8 ); + info.maxWidth(WIDTH - MARGIN * 2); + PixelScene.align(info); + add(info); + + float w = Math.max( icon.width(), info.width() ) + MARGIN * 2; + + icon.x = (w - icon.width()) / 2f; + icon.y = MARGIN; + PixelScene.align(icon); + + info.setPos((w - info.width()) / 2, icon.y + icon.height() + MARGIN); + resize( (int)w, (int)(info.bottom() + MARGIN) ); + + BadgeBanner.highlight( icon, badge.image ); + } +} diff --git a/java/com/hmdzl/spspd/windows/WndBag.java b/java/com/hmdzl/spspd/windows/WndBag.java new file mode 100644 index 00000000..6a010915 --- /dev/null +++ b/java/com/hmdzl/spspd/windows/WndBag.java @@ -0,0 +1,563 @@ +/* + * 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 + */ +package com.hmdzl.spspd.windows; + +import android.graphics.RectF; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.ShatteredPixelDungeon; +import com.hmdzl.spspd.Statistics; +import com.hmdzl.spspd.actors.hero.Belongings; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.hero.HeroClass; +import com.hmdzl.spspd.items.AdamantArmor; +import com.hmdzl.spspd.items.AdamantRing; +import com.hmdzl.spspd.items.AdamantWand; +import com.hmdzl.spspd.items.AdamantWeapon; +import com.hmdzl.spspd.items.EquipableItem; +import com.hmdzl.spspd.items.Gold; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.StoneOre; +import com.hmdzl.spspd.items.artifacts.Artifact; +import com.hmdzl.spspd.items.food.WaterItem; +import com.hmdzl.spspd.items.bags.HeartOfScarecrow; +import com.hmdzl.spspd.items.nornstone.NornStone; +import com.hmdzl.spspd.items.rings.Ring; +import com.hmdzl.spspd.items.summon.Honeypot; +import com.hmdzl.spspd.items.bombs.BuildBomb; +import com.hmdzl.spspd.items.challengelists.ChallengeList; +import com.hmdzl.spspd.items.misc.JumpH; +import com.hmdzl.spspd.items.misc.JumpM; +import com.hmdzl.spspd.items.misc.JumpR; +import com.hmdzl.spspd.items.misc.JumpS; +import com.hmdzl.spspd.items.misc.JumpW; +import com.hmdzl.spspd.items.misc.Jumpshoes; +import com.hmdzl.spspd.items.weapon.melee.special.Handcannon; +import com.hmdzl.spspd.items.weapon.missiles.ManyKnive; +import com.hmdzl.spspd.items.weapon.missiles.TaurcenBow; +import com.hmdzl.spspd.items.weapon.spammo.SpAmmo; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.items.armor.Armor; +import com.hmdzl.spspd.items.bags.ShoppingCart; +import com.hmdzl.spspd.items.bags.Bag; +import com.hmdzl.spspd.items.bags.KeyRing; +import com.hmdzl.spspd.items.bags.PotionBandolier; +import com.hmdzl.spspd.items.bags.ScrollHolder; +import com.hmdzl.spspd.items.bags.SeedPouch; +import com.hmdzl.spspd.items.bags.WandHolster; +import com.hmdzl.spspd.items.food.Food; +import com.hmdzl.spspd.items.journalpages.JournalPage; +import com.hmdzl.spspd.items.potions.Potion; +import com.hmdzl.spspd.items.scrolls.Scroll; +import com.hmdzl.spspd.items.wands.Wand; +import com.hmdzl.spspd.items.weapon.melee.MeleeWeapon; +import com.hmdzl.spspd.items.weapon.missiles.Boomerang; +import com.hmdzl.spspd.plants.Plant; +import com.hmdzl.spspd.plants.Plant.Seed; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.scenes.PixelScene; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.ui.Icons; +import com.hmdzl.spspd.ui.ItemSlot; +import com.hmdzl.spspd.ui.QuickSlotButton; + +import com.watabou.gltextures.TextureCache; +import com.watabou.noosa.ColorBlock; +import com.watabou.noosa.RenderedText; +import com.watabou.noosa.Image; +import com.watabou.noosa.audio.Sample; + +import java.util.ArrayList; + +import static com.hmdzl.spspd.Dungeon.hero; + +public class WndBag extends WndTabbed { + + public static enum Mode { + ALL, + UNIDENTIFED, + UPGRADEABLE, + QUICKSLOT, + FOR_SALE, + WEAPON, + ARMOR, + ENCHANTABLE, + WAND, + SEED, + FOOD, + POTION, + SCROLL, + EQUIPMENT, + ADAMANT, + REINFORCED, + UPGRADEABLESIMPLE, + NOTREINFORCED, + UPGRADEDEW, + JOURNALPAGES, + SHOES, + COOKING, + CHALLENGELIST, + CANBEMIX, + STONE, + TRANMSUTABLE, + AMMO, + EATABLE; + } + + protected static final int COLS_P = 5; + protected static final int COLS_L = 6; + + //protected static final int SLOT_SIZE = 26; + protected static final int SLOT_SIZE = 24; + protected static final int SLOT_MARGIN = 1; + + protected static final int TITLE_HEIGHT = 12; + + private Listener listener; + private WndBag.Mode mode; + private String title; + + private int nCols; + private int nRows; + + protected int count; + protected int col; + protected int row; + + private static Mode lastMode; + private static Bag lastBag; + + public WndBag(Bag bag, Listener listener, Mode mode, String title) { + + super(); + + this.listener = listener; + this.mode = mode; + this.title = title; + + lastMode = mode; + lastBag = bag; + + nCols = ShatteredPixelDungeon.landscape() ? COLS_L : COLS_P; + nRows = (Belongings.BACKPACK_SIZE + 5 + 1) / nCols + + ((Belongings.BACKPACK_SIZE + 5 + 1) % nCols > 0 ? 1 : 0); + + int slotsWidth = SLOT_SIZE * nCols + SLOT_MARGIN * (nCols - 1); + int slotsHeight = SLOT_SIZE * nRows + SLOT_MARGIN * (nRows - 1); + + RenderedText txtTitle = PixelScene.renderText(title != null ? title + : Messages.titleCase( bag.name() ), 9); + txtTitle.hardlight(TITLE_COLOR); + txtTitle.x = (int) (slotsWidth - txtTitle.width()) / 2; + txtTitle.y = (int) (TITLE_HEIGHT - txtTitle.height()) / 2; + add(txtTitle); + + placeItems(bag); + + resize(slotsWidth, slotsHeight + TITLE_HEIGHT); + + Belongings stuff = hero.belongings; + + ArrayList bags = new ArrayList<>(); + + bags.add( stuff.backpack ); + bags.add( stuff.getItem(SeedPouch.class)); + bags.add( stuff.getItem(ScrollHolder.class)); + bags.add( stuff.getItem(PotionBandolier.class) ); + bags.add( stuff.getItem(WandHolster.class) ); + bags.add( stuff.getItem(KeyRing.class)); + bags.add( stuff.getItem(ShoppingCart.class)); + bags.add( stuff.getItem(HeartOfScarecrow.class)); + + while(bags.remove(null)); + + int tabWidth = ( slotsWidth + 12 ) / bags.size() ; + + for (Bag b : bags) { + BagTab tab = new BagTab( b ); + tab.setSize( tabWidth, tabHeight() ); + add( tab ); + + tab.select( b == bag ); + } + + /*Bag[] bags = { stuff.backpack, stuff.getItem(SeedPouch.class), + stuff.getItem(ScrollHolder.class), + stuff.getItem(PotionBandolier.class), + stuff.getItem(WandHolster.class), + stuff.getItem(KeyRing.class), + stuff.getItem(ShoppingCart.class), + stuff.getItem(HeartOfScarecrow.class)}; + + for (Bag b : bags) { + if (b != null) { + BagTab tab = new BagTab(b); + add(tab); + tab.select(b == bag); + } + } + + layoutTabs();*/ + } + + public static WndBag lastBag(Listener listener, Mode mode, String title) { + + if (mode == lastMode && lastBag != null + && hero.belongings.backpack.contains(lastBag)) { + + return new WndBag(lastBag, listener, mode, title); + + } else { + + return new WndBag(hero.belongings.backpack, listener, mode, + title); + + } + } + + public static WndBag getBag(Class bagClass, + Listener listener, Mode mode, String title) { + Bag bag = hero.belongings.getItem(bagClass); + return bag != null ? new WndBag(bag, listener, mode, title) : lastBag( + listener, mode, title); + } + + protected void placeItems(Bag container) { + + // Equipped items + Belongings stuff = hero.belongings; + placeItem(stuff.weapon != null ? stuff.weapon : new Placeholder( + ItemSpriteSheet.WEAPON_HOLDER)); + placeItem(stuff.armor != null ? stuff.armor : new Placeholder( + ItemSpriteSheet.ARMOR_HOLDER)); + placeItem(stuff.misc1 != null ? stuff.misc1 : new Placeholder( + ItemSpriteSheet.RING_HOLDER)); + placeItem(stuff.misc2 != null ? stuff.misc2 : new Placeholder( + ItemSpriteSheet.RING_HOLDER)); + placeItem(stuff.misc3 != null ? stuff.misc3 : new Placeholder( + ItemSpriteSheet.RING_HOLDER)); + + boolean backpack = (container == hero.belongings.backpack); + if (!backpack) { + count = nCols; + col = 0; + row = 1; + } + + // Items in the bag + for (Item item : container.items) { + placeItem(item); + } + + // Free Space + while (count - (backpack ? 5 : nCols) < container.size) { + placeItem(null); + } + + // Gold + if (container == hero.belongings.backpack) { + row = nRows - 1; + col = nCols - 1; + placeItem(new Gold(Dungeon.gold)); + } + } + + protected void placeItem(final Item item) { + + int x = col * (SLOT_SIZE + SLOT_MARGIN); + int y = TITLE_HEIGHT + row * (SLOT_SIZE + SLOT_MARGIN); + + add(new ItemButton(item).setPos(x, y)); + + if (++col >= nCols) { + col = 0; + row++; + } + + count++; + } + + @Override + public void onMenuPressed() { + if (listener == null) { + hide(); + } + } + + @Override + public void onBackPressed() { + if (listener != null) { + listener.onSelect(null); + } + super.onBackPressed(); + } + + @Override + protected void onClick(Tab tab) { + hide(); + GameScene.show(new WndBag(((BagTab) tab).bag, listener, mode, title)); + } + + @Override + protected int tabHeight() { + //return 20; + return 24; + } + + private class BagTab extends Tab { + + private Image icon; + + private Bag bag; + + public BagTab(Bag bag) { + super(); + + this.bag = bag; + + icon = icon(); + add(icon); + } + + @Override + protected void select(boolean value) { + super.select(value); + icon.am = selected ? 1.0f : 0.6f; + } + + @Override + protected void layout() { + super.layout(); + + icon.copy(icon()); + icon.x = x + (width - icon.width) / 2; + icon.y = y + (height - icon.height) / 2 - 2 - (selected ? 0 : 1); + if (!selected && icon.y < y + CUT) { + RectF frame = icon.frame(); + frame.top += (y + CUT - icon.y) / icon.texture.height; + icon.frame(frame); + icon.y = y + CUT; + } + } + + private Image icon() { + if (bag instanceof SeedPouch) { + return Icons.get(Icons.SEED_POUCH); + } else if (bag instanceof ScrollHolder) { + return Icons.get(Icons.SCROLL_HOLDER); + } else if (bag instanceof WandHolster) { + return Icons.get(Icons.WAND_HOLSTER); + } else if (bag instanceof PotionBandolier) { + return Icons.get(Icons.POTION_BANDOLIER); + } else if (bag instanceof ShoppingCart) { + return Icons.get(Icons.SHOP_CART); + } else if (bag instanceof KeyRing) { + return Icons.get(Icons.KEYRING); + } else if (bag instanceof HeartOfScarecrow) { + return Icons.get(Icons.HOS); + } else { + return Icons.get(Icons.BACKPACK); + } + } + } + + public static class Placeholder extends Item { + { + name = null; + } + + public Placeholder(int image) { + this.image = image; + } + + @Override + public boolean isIdentified() { + return true; + } + + @Override + public boolean isEquipped(Hero hero) { + return true; + } + } + + private class ItemButton extends ItemSlot { + + private static final int NORMAL = 0xFF4A4D44; + private static final int EQUIPPED = 0xFF63665B; + + private Item item; + private ColorBlock bg; + + public ItemButton(Item item) { + + super(item); + + this.item = item; + if (item instanceof Gold) { + bg.visible = false; + } + + width = height = SLOT_SIZE; + } + + @Override + protected void createChildren() { + bg = new ColorBlock(SLOT_SIZE, SLOT_SIZE, NORMAL); + add(bg); + + super.createChildren(); + } + + @Override + protected void layout() { + bg.x = x; + bg.y = y; + + super.layout(); + } + + @Override + public void item(Item item) { + + super.item(item); + if (item != null) { + + bg.texture(TextureCache.createSolid(item + .isEquipped(hero) ? EQUIPPED : NORMAL)); + if (item.cursed && item.cursedKnown) { + bg.ra = +0.2f; + bg.ga = -0.1f; + } else if (!item.isIdentified()) { + bg.ra = 0.1f; + bg.ba = 0.1f; + } + + if (item.name() == null) { + enable(false); + } else { + + int levelLimit = Math.max(2, 2+Math.round(Statistics.deepestFloor/3)); + if (hero.heroClass == HeroClass.MAGE){levelLimit++;} + + enable( + mode == Mode.FOR_SALE + && (item.price() > 0) && (!item.isEquipped(hero) || !item.cursed) + || mode == Mode.UPGRADEABLE + && ((item.isUpgradable() && item.level<15 && !item.isReinforced()) || item.isUpgradable() && item.isReinforced()) + || mode == Mode.UPGRADEDEW + && (item.isUpgradable() && item.level < levelLimit) + || mode == Mode.UPGRADEABLESIMPLE + && item.isUpgradable() + || mode == Mode.ADAMANT + && (item instanceof AdamantArmor || item instanceof AdamantRing || item instanceof AdamantWand || item instanceof AdamantWeapon) + || mode == Mode.REINFORCED + && item.isReinforced() + || mode == Mode.NOTREINFORCED + && (!item.isReinforced() && item.isUpgradable()) + || mode == Mode.UNIDENTIFED + && !item.isIdentified() + || mode == Mode.QUICKSLOT + && (item.defaultAction != null) + || mode == Mode.WEAPON + && ((item instanceof MeleeWeapon || item instanceof Boomerang)&& !(item instanceof Handcannon)) + || mode == Mode.ARMOR + && (item instanceof Armor) + || mode == Mode.ENCHANTABLE + && (item instanceof MeleeWeapon || item instanceof Boomerang || item instanceof Armor || item instanceof ManyKnive || item instanceof TaurcenBow) + + || mode == Mode.JOURNALPAGES + && (item instanceof JournalPage) + || mode == Mode.SHOES + && (item instanceof JumpW || item instanceof JumpM || item instanceof JumpR || item instanceof JumpH || item instanceof JumpS || item instanceof Jumpshoes) + || mode == Mode.WAND + && (item instanceof Wand) + || mode == Mode.SEED + && (item instanceof Seed) + || mode == Mode.FOOD + && (item instanceof Food) + || mode == Mode.POTION + && (item instanceof Potion) + || mode == Mode.SCROLL + && (item instanceof Scroll) + || mode == Mode.EQUIPMENT + && (item instanceof EquipableItem) + || mode == Mode.COOKING + && (item instanceof Food ||item instanceof Plant.Seed ||item instanceof WaterItem ||item instanceof StoneOre || item instanceof Honeypot || item instanceof Honeypot.ShatteredPot || item instanceof Potion || item instanceof Scroll || item instanceof BuildBomb) + || mode == Mode.CHALLENGELIST + && (item instanceof ChallengeList) + || mode == Mode.CANBEMIX + && ( !item.isEquipped(hero) && (item instanceof Ring || item instanceof Wand)) + || mode == Mode.STONE + && ( item instanceof NornStone || item instanceof StoneOre) + || mode == Mode.TRANMSUTABLE + && (!item.isEquipped(hero) && ( item instanceof MeleeWeapon || item instanceof Ring || item instanceof Wand || item instanceof Artifact || item instanceof Armor )) + || mode == Mode.AMMO + && (item instanceof SpAmmo) + || mode == Mode.EATABLE + && (!item.isEquipped(hero) && (item instanceof MeleeWeapon || item instanceof Ring || item instanceof Wand || item instanceof Armor)) + || mode == Mode.ALL); + } + } else { + bg.color(NORMAL); + } + } + + @Override + protected void onTouchDown() { + bg.brightness(1.5f); + Sample.INSTANCE.play(Assets.SND_CLICK, 0.7f, 0.7f, 1.2f); + }; + + @Override + protected void onTouchUp() { + bg.brightness(1.0f); + }; + + @Override + protected void onClick() { + if (listener != null) { + + hide(); + listener.onSelect(item); + + } else { + + WndBag.this.add(new WndItem(WndBag.this, item)); + + } + } + + @Override + protected boolean onLongClick() { + if (listener == null && item.defaultAction != null) { + hide(); + Dungeon.quickslot.setSlot(0, item); + QuickSlotButton.refresh(); + return true; + } else { + return false; + } + } + } + + public interface Listener { + void onSelect(Item item); + } +} diff --git a/java/com/hmdzl/spspd/windows/WndBlacksmith.java b/java/com/hmdzl/spspd/windows/WndBlacksmith.java new file mode 100644 index 00000000..b09e6650 --- /dev/null +++ b/java/com/hmdzl/spspd/windows/WndBlacksmith.java @@ -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 + */ +package com.hmdzl.spspd.windows; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Chrome; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.mobs.npcs.Blacksmith; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.scenes.PixelScene; +import com.hmdzl.spspd.ui.ItemSlot; +import com.hmdzl.spspd.ui.RedButton; +import com.hmdzl.spspd.ui.Window; + +import com.hmdzl.spspd.ui.RenderedTextMultiline; +import com.watabou.noosa.NinePatch; +import com.watabou.noosa.audio.Sample; +import com.watabou.noosa.ui.Component; + +public class WndBlacksmith extends Window { + + private static final int BTN_SIZE = 36; + private static final float GAP = 2; + private static final float BTN_GAP = 10; + private static final int WIDTH = 116; + + private ItemButton btnPressed; + + private ItemButton btnItem1; + private ItemButton btnItem2; + private RedButton btnReforge; + + public WndBlacksmith(Blacksmith troll, Hero hero) { + + super(); + + IconTitle titlebar = new IconTitle(); + titlebar.icon(troll.sprite()); + titlebar.label(Messages.titleCase( troll.name )); + titlebar.setRect(0, 0, WIDTH, 0); + add(titlebar); + + RenderedTextMultiline message = PixelScene.renderMultiline( Messages.get(WndBlacksmith.class, "prompt"), 6 ); + message.maxWidth( WIDTH); + message.setPos(0, titlebar.bottom() + GAP); + add( message ); + + btnItem1 = new ItemButton() { + @Override + protected void onClick() { + btnPressed = btnItem1; + GameScene.selectItem( itemSelector, WndBag.Mode.UPGRADEABLESIMPLE, Messages.get(WndBlacksmith.class, "select1") ); + } + }; + btnItem1.setRect( (WIDTH - BTN_GAP) / 2 - BTN_SIZE, message.top() + message.height() + BTN_GAP, BTN_SIZE, BTN_SIZE ); + add( btnItem1 ); + + btnItem2 = new ItemButton() { + @Override + protected void onClick() { + btnPressed = btnItem2; + GameScene.selectItem(itemSelector, WndBag.Mode.UPGRADEABLESIMPLE, + Messages.get(WndBlacksmith.class,"select2")); + } + }; + btnItem2.setRect(btnItem1.right() + BTN_GAP, btnItem1.top(), BTN_SIZE, + BTN_SIZE); + add(btnItem2); + + btnReforge = new RedButton(Messages.get(WndBlacksmith.class,"reforge")) { + @Override + protected void onClick() { + Blacksmith.upgrade(btnItem1.item, btnItem2.item); + hide(); + } + }; + btnReforge.enable(false); + btnReforge.setRect(0, btnItem1.bottom() + BTN_GAP, WIDTH, 20); + add(btnReforge); + + resize(WIDTH, (int) btnReforge.bottom()); + } + + protected WndBag.Listener itemSelector = new WndBag.Listener() { + @Override + public void onSelect(Item item) { + if (item != null) { + btnPressed.item(item); + + if (btnItem1.item != null && btnItem2.item != null) { + String result = Blacksmith.verify(btnItem1.item, + btnItem2.item); + if (result != null) { + GameScene.show(new WndMessage(result)); + btnReforge.enable(false); + } else { + btnReforge.enable(true); + } + } + } + } + }; + + public static class ItemButton extends Component { + + protected NinePatch bg; + protected ItemSlot slot; + + public Item item = null; + + @Override + protected void createChildren() { + super.createChildren(); + + bg = Chrome.get(Chrome.Type.BUTTON); + add(bg); + + slot = new ItemSlot() { + @Override + protected void onTouchDown() { + bg.brightness(1.2f); + Sample.INSTANCE.play(Assets.SND_CLICK); + } + + @Override + protected void onTouchUp() { + bg.resetColor(); + } + + @Override + protected void onClick() { + ItemButton.this.onClick(); + } + }; + add(slot); + } + + protected void onClick() { + } + + @Override + protected void layout() { + super.layout(); + + bg.x = x; + bg.y = y; + bg.size(width, height); + + slot.setRect(x + 2, y + 2, width - 4, height - 4); + } + + public void item(Item item) { + slot.item(this.item = item); + } + } +} diff --git a/java/com/hmdzl/spspd/windows/WndBlacksmith2.java b/java/com/hmdzl/spspd/windows/WndBlacksmith2.java new file mode 100644 index 00000000..022bd40e --- /dev/null +++ b/java/com/hmdzl/spspd/windows/WndBlacksmith2.java @@ -0,0 +1,186 @@ +/* + * 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 + */ +package com.hmdzl.spspd.windows; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Chrome; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.mobs.npcs.Blacksmith2; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.scenes.PixelScene; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.ItemSlot; +import com.hmdzl.spspd.ui.RedButton; +import com.hmdzl.spspd.ui.RenderedTextMultiline; +import com.hmdzl.spspd.ui.Window; + +import com.watabou.noosa.NinePatch; +import com.watabou.noosa.audio.Sample; +import com.watabou.noosa.ui.Component; + +public class WndBlacksmith2 extends Window { + + private static final int BTN_SIZE = 36; + private static final float GAP = 2; + private static final float BTN_GAP = 10; + private static final int WIDTH = 116; + + private ItemButton btnPressed; + + private ItemButton btnItem1; + private ItemButton btnItem2; + private RedButton btnReforge; + + private static final String TXT_PROMPT = "Listen up, here's what I can do. " + +"I can reinforce an item with adamantite. " + +"Reinforced items can be upgraded to extreme levels. " + +"You have to have the right kind of adamantite and it'll cost you some dark gold. "; + + private static final String TXT_SELECT1 = "Select an item to reinforce."; + private static final String TXT_SELECT2 = "Select your adamantite."; + private static final String TXT_REFORGE = "Reforge them"; + private static final String TXT_WORK = "Great! Let's reinforce it!"; + + public WndBlacksmith2(Blacksmith2 troll, Hero hero) { + + super(); + + IconTitle titlebar = new IconTitle(); + titlebar.icon(troll.sprite()); + titlebar.label(Messages.titleCase( troll.name )); + titlebar.setRect(0, 0, WIDTH, 0); + add(titlebar); + + RenderedTextMultiline message = PixelScene.renderMultiline(Messages.get(WndBlacksmith2.class, "prompt"), 6); + message.maxWidth(WIDTH); + message.setPos(0, titlebar.bottom() + GAP); + add(message); + + btnItem1 = new ItemButton() { + @Override + protected void onClick() { + btnPressed = btnItem1; + GameScene.selectItem(itemSelector, WndBag.Mode.NOTREINFORCED, + Messages.get(WndBlacksmith2.class, "select1")); + } + }; + btnItem1.setRect((WIDTH - BTN_GAP) / 2 - BTN_SIZE, + message.top() + message.height() + BTN_GAP, BTN_SIZE, BTN_SIZE); + add(btnItem1); + + btnItem2 = new ItemButton() { + @Override + protected void onClick() { + btnPressed = btnItem2; + GameScene.selectItem(itemSelector, WndBag.Mode.ADAMANT, + Messages.get(WndBlacksmith2.class,"select2")); + } + }; + btnItem2.setRect(btnItem1.right() + BTN_GAP, btnItem1.top(), BTN_SIZE, + BTN_SIZE); + add(btnItem2); + + btnReforge = new RedButton(Messages.get(WndBlacksmith2.class,"reforge")) { + @Override + protected void onClick() { + Blacksmith2.upgrade(btnItem1.item, btnItem2.item); + hide(); + } + }; + btnReforge.enable(false); + btnReforge.setRect(0, btnItem1.bottom() + BTN_GAP, WIDTH, 20); + add(btnReforge); + + resize(WIDTH, (int) btnReforge.bottom()); + } + + protected WndBag.Listener itemSelector = new WndBag.Listener() { + @Override + public void onSelect(Item item) { + if (item != null) { + btnPressed.item(item); + + if (btnItem1.item != null && btnItem2.item != null) { + String result = Blacksmith2.verify(btnItem1.item, + btnItem2.item); + if (result != null) { + GameScene.show(new WndMessage(result)); + btnReforge.enable(false); + } else { + btnReforge.enable(true); + GameScene.show(new WndMessage(Messages.get(WndBlacksmith2.class,"success"))); + } + } + } + } + }; + + public static class ItemButton extends Component { + + protected NinePatch bg; + protected ItemSlot slot; + + public Item item = null; + + @Override + protected void createChildren() { + super.createChildren(); + + bg = Chrome.get(Chrome.Type.BUTTON); + add(bg); + + slot = new ItemSlot() { + @Override + protected void onTouchDown() { + bg.brightness(1.2f); + Sample.INSTANCE.play(Assets.SND_CLICK); + } + + @Override + protected void onTouchUp() { + bg.resetColor(); + } + + @Override + protected void onClick() { + ItemButton.this.onClick(); + } + }; + add(slot); + } + + protected void onClick() { + } + + @Override + protected void layout() { + super.layout(); + + bg.x = x; + bg.y = y; + bg.size(width, height); + + slot.setRect(x + 2, y + 2, width - 4, height - 4); + } + + public void item(Item item) { + slot.item(this.item = item); + } + } +} diff --git a/java/com/hmdzl/spspd/windows/WndCatalogus.java b/java/com/hmdzl/spspd/windows/WndCatalogus.java new file mode 100644 index 00000000..8168a347 --- /dev/null +++ b/java/com/hmdzl/spspd/windows/WndCatalogus.java @@ -0,0 +1,202 @@ +/* + * 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 + */ +package com.hmdzl.spspd.windows; + +import java.util.ArrayList; + +import com.hmdzl.spspd.ShatteredPixelDungeon; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.potions.Potion; +import com.hmdzl.spspd.items.scrolls.Scroll; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.scenes.PixelScene; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.ScrollPane; +import com.hmdzl.spspd.ui.Window; + +import com.watabou.noosa.RenderedText; +import com.watabou.noosa.ui.Component; + +public class WndCatalogus extends WndTabbed { + + private static final int WIDTH_P = 112; + private static final int HEIGHT_P = 160; + + private static final int WIDTH_L = 128; + private static final int HEIGHT_L = 128; + + private static final int ITEM_HEIGHT = 18; + + private static final int TAB_WIDTH = 50; + + private static final String TXT_POTIONS = "Potions"; + private static final String TXT_SCROLLS = "Scrolls"; + private static final String TXT_TITLE = "Catalogus"; + + private RenderedText txtTitle; + private ScrollPane list; + + private ArrayList items = new ArrayList(); + + private static boolean showPotions = true; + + public WndCatalogus() { + + super(); + + if (ShatteredPixelDungeon.landscape()) { + resize(WIDTH_L, HEIGHT_L); + } else { + resize(WIDTH_P, HEIGHT_P); + } + + txtTitle = PixelScene.renderText(Messages.get(this, "title"), 9); + txtTitle.hardlight(Window.TITLE_COLOR); + //txtTitle.measure(); + add(txtTitle); + + list = new ScrollPane(new Component()) { + @Override + public void onClick(float x, float y) { + int size = items.size(); + for (int i = 0; i < size; i++) { + if (items.get(i).onClick(x, y)) { + break; + } + } + } + }; + add(list); + list.setRect(0, txtTitle.height(), width, height - txtTitle.height()); + + boolean showPotions = WndCatalogus.showPotions; + Tab[] tabs = { new LabeledTab(Messages.get(this, "potions")) { + @Override + protected void select(boolean value) { + super.select(value); + WndCatalogus.showPotions = value; + updateList(); + }; + }, new LabeledTab(Messages.get(this, "scrolls")) { + @Override + protected void select(boolean value) { + super.select(value); + WndCatalogus.showPotions = !value; + updateList(); + }; + } }; + for (Tab tab : tabs) { + add(tab); + } + + layoutTabs(); + + select(showPotions ? 0 : 1); + } + + private void updateList() { + + txtTitle.text(Messages.get(this, "title", showPotions ? Messages.get(this, "potions") : Messages.get(this, "scrolls") )); + //txtTitle.measure(); + txtTitle.x = PixelScene.align(PixelScene.uiCamera, + (width - txtTitle.width()) / 2); + + items.clear(); + + Component content = list.content(); + content.clear(); + list.scrollTo(0, 0); + + float pos = 0; + for (Class itemClass : showPotions ? Potion.getKnown() + : Scroll.getKnown()) { + ListItem item = new ListItem(itemClass); + item.setRect(0, pos, width, ITEM_HEIGHT); + content.add(item); + items.add(item); + + pos += item.height(); + } + + for (Class itemClass : showPotions ? Potion + .getUnknown() : Scroll.getUnknown()) { + ListItem item = new ListItem(itemClass); + item.setRect(0, pos, width, ITEM_HEIGHT); + content.add(item); + items.add(item); + + pos += item.height(); + } + + content.setSize(width, pos); + } + + private static class ListItem extends Component { + + private Item item; + private boolean identified; + + private ItemSprite sprite; + private RenderedText label; + + public ListItem(Class cl) { + super(); + + try { + item = cl.newInstance(); + if (identified = item.isIdentified()) { + sprite.view(item.image(), null); + label.text(item.name()); + } else { + sprite.view(127, null); + label.text(item.trueName()); + label.hardlight(0xCCCCCC); + } + } catch (Exception e) { + // Do nothing + } + } + + @Override + protected void createChildren() { + sprite = new ItemSprite(); + add(sprite); + + label = PixelScene.renderText(8); + add(label); + } + + @Override + protected void layout() { + sprite.y = PixelScene.align(y + (height - sprite.height) / 2); + + label.x = sprite.x + sprite.width; + label.y = PixelScene.align(y + (height - label.baseLine()) / 2); + } + + public boolean onClick(float x, float y) { + if (identified && inside(x, y)) { + GameScene.show(new WndInfoItem(item)); + return true; + } else { + return false; + } + } + } +} diff --git a/java/com/hmdzl/spspd/windows/WndChallengeBook.java b/java/com/hmdzl/spspd/windows/WndChallengeBook.java new file mode 100644 index 00000000..93ace39b --- /dev/null +++ b/java/com/hmdzl/spspd/windows/WndChallengeBook.java @@ -0,0 +1,137 @@ +/* + * 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 + */ +package com.hmdzl.spspd.windows; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.items.ChallengeBook; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.items.artifacts.TimekeepersHourglass; +import com.hmdzl.spspd.scenes.InterlevelScene; +import com.hmdzl.spspd.scenes.PixelScene; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.ui.RedButton; +import com.hmdzl.spspd.ui.Window; + +import com.watabou.noosa.Game; +import com.hmdzl.spspd.ui.RenderedTextMultiline; + +public class WndChallengeBook extends Window { + + + + private static final String TXT_FARAWELL = Messages.get(WndChallengeBook.class,"title"); + public static final float TIME_TO_USE = 1; + + + private static final int PAGES = 10; + private static final int WIDTH = 120; + private static final int BTN_HEIGHT = 20; + private static final float GAP = 2; + + public WndChallengeBook(final boolean[] rooms, final ChallengeBook item) { + + super(); + + String[] roomNames = new String[PAGES]; + roomNames[0] = Messages.get(this,"room0"); + roomNames[1] = Messages.get(this,"room1"); + roomNames[2] = Messages.get(this,"room2"); + roomNames[3] = Messages.get(this,"room3"); + roomNames[4] = Messages.get(this,"room4"); + roomNames[5] = Messages.get(this,"room5"); + roomNames[6] = Messages.get(this,"room6"); + roomNames[7] = Messages.get(this,"room7"); + + IconTitle titlebar = new IconTitle(); + titlebar.icon(new ItemSprite(item.image(), null)); + titlebar.label(Messages.titleCase(item.name())); + titlebar.setRect(0, 0, WIDTH, 0); + add(titlebar); + + RenderedTextMultiline message = PixelScene.renderMultiline(TXT_FARAWELL, 6); + message.maxWidth(WIDTH); + message.setPos(0,titlebar.bottom() + GAP); + add(message); + + //add each button + //after n*BTN_HEIGHT+GAP + //add port function + + if (rooms[0]){ + RedButton btn1 = new RedButton(roomNames[0]) { + @Override + protected void onClick() { + item.returnDepth = Dungeon.depth; + item.returnPos = Dungeon.hero.pos; + port(0, item.firsts[0]); + item.firsts[0]=false; + } + }; + btn1.setRect(0, message.top() + message.height() + GAP, WIDTH, BTN_HEIGHT); + add(btn1); + resize(WIDTH, (int) btn1.bottom()); + } + + int buttons=1; + + for (int i=1; i + */ +package com.hmdzl.spspd.windows; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Challenges; +import com.hmdzl.spspd.ShatteredPixelDungeon; +import com.hmdzl.spspd.scenes.PixelScene; +import com.hmdzl.spspd.ui.CheckBox; +import com.hmdzl.spspd.ui.IconButton; +import com.hmdzl.spspd.ui.Icons; +import com.hmdzl.spspd.ui.Window; +import com.hmdzl.spspd.messages.Messages; +import com.watabou.noosa.RenderedText; + +public class WndChallenges extends Window { + + private static final int WIDTH = 108; + private static final int TTL_HEIGHT = 12; + private static final int BTN_HEIGHT = 18; + private static final int GAP = 1; + + private boolean editable; + private ArrayList boxes; + + public WndChallenges( int checked, boolean editable ) { + + super(); + + this.editable = editable; + + RenderedText title = PixelScene.renderText( Messages.get(this, "title"), 9 ); + title.hardlight( TITLE_COLOR ); + title.x = (WIDTH - title.width()) / 2; + title.y = (TTL_HEIGHT - title.height()) / 2; + PixelScene.align(title); + add( title ); + + boxes = new ArrayList<>(); + + float pos = TTL_HEIGHT; + for (int i=0; i < Challenges.NAME_IDS.length; i++) { + + final String challenge = Challenges.NAME_IDS[i]; + + CheckBox cb = new CheckBox( Messages.get(Challenges.class, challenge) ); + cb.checked( (checked & Challenges.MASKS[i]) != 0 ); + cb.active = editable; + + if (i > 0) { + pos += GAP; + } + cb.setRect( 0, pos, WIDTH-16, BTN_HEIGHT ); + + add( cb ); + boxes.add( cb ); + + IconButton info = new IconButton(Icons.get(Icons.INFO)){ + @Override + protected void onClick() { + super.onClick(); + ShatteredPixelDungeon.scene().add( + new WndMessage(Messages.get(Challenges.class, challenge+"_desc")) + ); + } + }; + info.setRect(cb.right(), pos, 16, BTN_HEIGHT); + add(info); + + pos = cb.bottom(); + + + } + + resize( WIDTH, (int)pos ); + } + + @Override + public void onBackPressed() { + + if (editable) { + int value = 0; + for (int i=0; i < boxes.size(); i++) { + if (boxes.get( i ).checked()) { + value |= Challenges.MASKS[i]; + } + } + ShatteredPixelDungeon.challenges( value ); + } + + super.onBackPressed(); + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/windows/WndChooseWay.java b/java/com/hmdzl/spspd/windows/WndChooseWay.java new file mode 100644 index 00000000..d45afd7c --- /dev/null +++ b/java/com/hmdzl/spspd/windows/WndChooseWay.java @@ -0,0 +1,87 @@ +/* + * 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 + */ +package com.hmdzl.spspd.windows; + +import com.hmdzl.spspd.actors.hero.HeroSubClass; +import com.hmdzl.spspd.items.TomeOfMastery; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.PixelScene; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.ui.RedButton; +import com.hmdzl.spspd.ui.Window; + +import com.hmdzl.spspd.ui.RenderedTextMultiline; + +public class WndChooseWay extends Window { + + private static final String TXT_MESSAGE = "Which way will you follow?"; + private static final String TXT_CANCEL = "I'll decide later"; + + private static final int WIDTH = 120; + private static final int BTN_HEIGHT = 18; + private static final float GAP = 2; + + public WndChooseWay(final TomeOfMastery tome, final HeroSubClass way1, + final HeroSubClass way2) { + + super(); + + IconTitle titlebar = new IconTitle(); + titlebar.icon(new ItemSprite(tome.image(), null)); + titlebar.label(tome.name()); + titlebar.setRect(0, 0, WIDTH, 0); + add(titlebar); + + RenderedTextMultiline hl = PixelScene.renderMultiline( 6 ); + hl.text( way1.desc() + "\n\n" + way2.desc() + "\n\n" + Messages.get(this, "message"), WIDTH ); + hl.setPos( titlebar.left(), titlebar.bottom() + GAP ); + add( hl ); + + RedButton btnWay1 = new RedButton(way1.title().toUpperCase()) { + @Override + protected void onClick() { + hide(); + tome.choose(way1); + } + }; + btnWay1.setRect( 0, hl.bottom() + GAP, (WIDTH - GAP) / 2, BTN_HEIGHT ); + add( btnWay1 ); + + RedButton btnWay2 = new RedButton(way2.title().toUpperCase()) { + @Override + protected void onClick() { + hide(); + tome.choose(way2); + } + }; + btnWay2.setRect(btnWay1.right() + GAP, btnWay1.top(), btnWay1.width(), + BTN_HEIGHT); + add(btnWay2); + + RedButton btnCancel = new RedButton(Messages.get(this, "cancel")) { + @Override + protected void onClick() { + hide(); + } + }; + btnCancel.setRect(0, btnWay2.bottom() + GAP, WIDTH, BTN_HEIGHT); + add(btnCancel); + + resize(WIDTH, (int) btnCancel.bottom()); + } +} diff --git a/java/com/hmdzl/spspd/windows/WndClass.java b/java/com/hmdzl/spspd/windows/WndClass.java new file mode 100644 index 00000000..6b80e11e --- /dev/null +++ b/java/com/hmdzl/spspd/windows/WndClass.java @@ -0,0 +1,181 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2016 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.windows; + +import com.hmdzl.spspd.actors.hero.HeroClass; +import com.hmdzl.spspd.actors.hero.HeroSubClass; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.PixelScene; +import com.hmdzl.spspd.ui.RenderedTextMultiline; +import com.watabou.noosa.BitmapText; +import com.watabou.noosa.Group; + +public class WndClass extends WndTabbed { + + private static final int WIDTH = 110; + + private static final int TAB_WIDTH = 50; + + private HeroClass cl; + + private PerksTab tabPerks; + private MasteryTab tabMastery; + + public WndClass( HeroClass cl ) { + + super(); + + this.cl = cl; + + tabPerks = new PerksTab(); + add( tabPerks ); + + Tab tab = new RankingTab( cl.title().toUpperCase(), tabPerks ); + tab.setSize( TAB_WIDTH, tabHeight() ); + add( tab ); + + tabMastery = new MasteryTab(); + add( tabMastery ); + + tab = new RankingTab( Messages.get(this, "mastery"), tabMastery ); + add( tab ); + + resize( + (int)Math.max( tabPerks.width, tabMastery.width ), + (int)Math.max( tabPerks.height, tabMastery.height ) ); + + + layoutTabs(); + + select( 0 ); + } + + private class RankingTab extends LabeledTab { + + private Group page; + + public RankingTab( String label, Group page ) { + super( label ); + this.page = page; + } + + @Override + protected void select( boolean value ) { + super.select( value ); + if (page != null) { + page.visible = page.active = selected; + } + } + } + + private class PerksTab extends Group { + + private static final int MARGIN = 4; + private static final int GAP = 4; + + public float height; + public float width; + + public PerksTab() { + super(); + + float dotWidth = 0; + + String[] items = cl.perks(); + float pos = MARGIN; + + for (int i=0; i < items.length; i++) { + + if (i > 0) { + pos += GAP; + } + + BitmapText dot = PixelScene.createText( "-", 6 ); + dot.x = MARGIN; + dot.y = pos; + if (dotWidth == 0) { + dot.measure(); + dotWidth = dot.width(); + } + add( dot ); + + RenderedTextMultiline item = PixelScene.renderMultiline( items[i], 6 ); + item.maxWidth((int)(WIDTH - MARGIN * 2 - dotWidth)); + item.setPos(dot.x + dotWidth, pos); + add( item ); + + pos += item.height(); + float w = item.width(); + if (w > width) { + width = w; + } + } + + width += MARGIN + dotWidth; + height = pos + MARGIN; + } + } + + private class MasteryTab extends Group { + + private static final int MARGIN = 4; + + public float height; + public float width; + + public MasteryTab() { + super(); + + String message = null; + switch (cl) { + case WARRIOR: + message = HeroSubClass.GLADIATOR.desc() + "\n\n" + HeroSubClass.BERSERKER.desc(); + break; + case MAGE: + message = HeroSubClass.BATTLEMAGE.desc() + "\n\n" + HeroSubClass.WARLOCK.desc(); + break; + case ROGUE: + message = HeroSubClass.FREERUNNER.desc() + "\n\n" + HeroSubClass.ASSASSIN.desc(); + break; + case HUNTRESS: + message = HeroSubClass.SNIPER.desc() + "\n\n" + HeroSubClass.WARDEN.desc(); + break; + case PERFORMER: + message = HeroSubClass.SUPERSTAR.desc() + "\n\n" + HeroSubClass.JOKER.desc(); + break; + case SOLDIER: + message = HeroSubClass.AGENT.desc() + "\n\n" + HeroSubClass.LEADER.desc(); + break; + case FOLLOWER: + message = HeroSubClass.PASTOR.desc() + "\n\n" + HeroSubClass.ARTISAN.desc(); + break; + } + + RenderedTextMultiline text = PixelScene.renderMultiline( 6 ); + text.text( message, WIDTH - MARGIN * 2 ); + text.setPos( MARGIN, MARGIN ); + add( text ); + + height = text.bottom() + MARGIN; + width = text.right() + MARGIN; + } + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/windows/WndDescend.java b/java/com/hmdzl/spspd/windows/WndDescend.java new file mode 100644 index 00000000..4ef86c3b --- /dev/null +++ b/java/com/hmdzl/spspd/windows/WndDescend.java @@ -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 + */ +package com.hmdzl.spspd.windows; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.items.DewVial; +import com.hmdzl.spspd.scenes.PixelScene; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.RedButton; +import com.hmdzl.spspd.ui.RenderedTextMultiline; +import com.hmdzl.spspd.ui.Window; + + +public class WndDescend extends Window { + + private static final String TXT_MESSAGE = "Are you sure you want to descend? " + +"Any dew on this level will evaporate and your dew charge might be wasted. " + +"If you have not cleared the level, you will forfeit any additional dew charge for the next level. " + +"If you really want to descend click the button below then try the stairs again. "; + private static final String TXT_REWARD = "Descend"; + + private static final int WIDTH = 120; + private static final int BTN_HEIGHT = 20; + private static final int GAP = 2; + + public WndDescend() { + + super(); + + DewVial dewvial = new DewVial(); + + IconTitle titlebar = new IconTitle(); + titlebar.icon(new ItemSprite(dewvial.image(), null)); + titlebar.label(Messages.titleCase(dewvial.name())); + titlebar.setRect(0, 0, WIDTH, 0); + add(titlebar); + + RenderedTextMultiline message = PixelScene + .renderMultiline(Messages.get(this,"message"), 6); + message.maxWidth(WIDTH); + message.setPos(0, titlebar.bottom() + GAP); + add(message); + + RedButton btnReward = new RedButton(Messages.get(this,"reward")) { + @Override + protected void onClick() { + Dungeon.level.forcedone=true; + hide(); + } + }; + btnReward.setRect(0, message.top() + message.height() + GAP, WIDTH, + BTN_HEIGHT); + add(btnReward); + + resize(WIDTH, (int) btnReward.bottom()); + } + + +} diff --git a/java/com/hmdzl/spspd/windows/WndDewDrawInfo.java b/java/com/hmdzl/spspd/windows/WndDewDrawInfo.java new file mode 100644 index 00000000..b6231ee4 --- /dev/null +++ b/java/com/hmdzl/spspd/windows/WndDewDrawInfo.java @@ -0,0 +1,103 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2014 Oleg Dolya + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.windows; + +import com.hmdzl.spspd.items.DewVial; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.scenes.PixelScene; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.RedButton; +import com.hmdzl.spspd.ui.RenderedTextMultiline; +import com.hmdzl.spspd.ui.Window; + + +public class WndDewDrawInfo extends Window { + + //if people don't get it after this, I quit. I just quit. + + private static final String TXT_MESSAGE = "Drawing out dew makes it so that mobs on special levels drop dew to fill your vial. " + +"Additionally, your character is buffed with dew charge at the start of each normal level. " + +"As long as you are dew charged, enemies drop dew to fill your vial. "; + + private static final String TXT_MESSAGE2 = "Each level dew charges you for a set amount of moves. " + +"Each level also has a move goal for killing all regular generated enemies. (Not special enemies like statues and piranha) " + +"Killing all regular enemies that were generated with the level clears that level. "; + + private static final String TXT_MESSAGE3 = "If you clear a level in less moves than the goal, the additional moves are added to your dew charge for the next level. " + +"You will need to clear the levels as fast as you can to get dew upgrades. "; + + private static final String TXT_MESSAGE4 = "The dew vial will also allow you to choose which item you apply upgrades to when blessing. "; + + private static final String TXT_WATER = "Okay! Thanks for that!"; + + + private static final int WIDTH = 120; + private static final int BTN_HEIGHT = 20; + private static final float GAP = 2; + + public WndDewDrawInfo(final Item item) { + + super(); + + Item dewvial = new DewVial(); + + IconTitle titlebar = new IconTitle(); + titlebar.icon(new ItemSprite(dewvial.image(), null)); + titlebar.label(Messages.titleCase(dewvial.name())); + titlebar.setRect(0, 0, WIDTH, 0); + add(titlebar); + + RenderedTextMultiline message = PixelScene.renderMultiline(Messages.get(this, "info1"), 6); + message.maxWidth(WIDTH); + message.setPos(0,titlebar.bottom() + GAP); + add(message); + + RenderedTextMultiline message2 = PixelScene.renderMultiline(Messages.get(this, "info2"), 6); + message2.maxWidth(WIDTH); + message2.setPos(0,message.top() + message.height() + GAP); + add(message2); + + RenderedTextMultiline message3 = PixelScene.renderMultiline(Messages.get(this, "info3"), 6); + message3.maxWidth(WIDTH); + message3.setPos(0, message2.top() + message2.height() + GAP); + add(message3); + + RenderedTextMultiline message4 = PixelScene.renderMultiline(Messages.get(this, "info4"), 6); + message4.maxWidth(WIDTH); + message4.setPos(0,message3.top() + message3.height() + GAP); + add(message4); + + + RedButton btnBattle = new RedButton(Messages.get(this, "ok")) { + @Override + protected void onClick() { + hide(); + } + }; + btnBattle.setRect(0, message4.top() + message4.height() + GAP, WIDTH, + BTN_HEIGHT); + add(btnBattle); + + + + resize(WIDTH, (int) btnBattle.bottom()); + } + + +} diff --git a/java/com/hmdzl/spspd/windows/WndDream.java b/java/com/hmdzl/spspd/windows/WndDream.java new file mode 100644 index 00000000..6608b094 --- /dev/null +++ b/java/com/hmdzl/spspd/windows/WndDream.java @@ -0,0 +1,74 @@ +/* + * 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 + */ +package com.hmdzl.spspd.windows; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.items.PuddingCup; +import com.hmdzl.spspd.items.keys.IronKey; +import com.hmdzl.spspd.items.weapon.melee.block.GoblinShield; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.PixelScene; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.ui.RedButton; +import com.hmdzl.spspd.ui.RenderedTextMultiline; +import com.hmdzl.spspd.ui.Window; +import com.hmdzl.spspd.utils.GLog; + + +public class WndDream extends Window { + + private static final int WIDTH = 120; + private static final int BTN_HEIGHT = 20; + private static final int GAP = 2; + + public WndDream() { + + super(); + + PuddingCup key = new PuddingCup(); + + + IconTitle titlebar = new IconTitle(); + titlebar.icon(new ItemSprite(key.image(), null)); + titlebar.label(Messages.titleCase(key.name())); + titlebar.setRect(0, 0, WIDTH, 0); + add(titlebar); + + RenderedTextMultiline message = PixelScene + .renderMultiline(Messages.get(this, "message"), 6); + message.maxWidth(WIDTH); + message.setPos(0, titlebar.bottom() + GAP); + add(message); + + RedButton btnReward = new RedButton(Messages.get(this, "buy")) { + @Override + protected void onClick() { + Dungeon.hero.HT = 50; + Dungeon.hero.hitSkill -= (Dungeon.hero.lvl-1); + Dungeon.hero.evadeSkill -= (Dungeon.hero.lvl-1); + Dungeon.hero.lvl = 1; + hide(); + } + }; + btnReward.setRect(0, message.top() + message.height() + GAP, WIDTH, + BTN_HEIGHT); + add(btnReward); + + resize(WIDTH, (int) btnReward.bottom()); + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/windows/WndEgoalInfo.java b/java/com/hmdzl/spspd/windows/WndEgoalInfo.java new file mode 100644 index 00000000..43c3c3f4 --- /dev/null +++ b/java/com/hmdzl/spspd/windows/WndEgoalInfo.java @@ -0,0 +1,63 @@ +package com.hmdzl.spspd.windows; + +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.weapon.melee.special.ErrorW; +import com.hmdzl.spspd.scenes.PixelScene; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.RedButton; +import com.hmdzl.spspd.ui.RenderedTextMultiline; +import com.hmdzl.spspd.ui.Window; +import com.hmdzl.spspd.utils.GLog; + + +public class WndEgoalInfo extends Window { + + private static final int WIDTH = 120; + private static final int BTN_HEIGHT = 20; + private static final float GAP = 2; + + public WndEgoalInfo(final Item item) { + + super(); + + Item dewvial = new ErrorW(); + + IconTitle titlebar = new IconTitle(); + titlebar.icon(new ItemSprite(dewvial.image(), null)); + titlebar.label(Messages.titleCase(Messages.get(this, "title"))); + titlebar.setRect(0, 0, WIDTH, 0); + add(titlebar); + + RenderedTextMultiline message = PixelScene.renderMultiline(Messages.get(this, "info1"), 6); + message.maxWidth(WIDTH); + message.setPos(0,titlebar.bottom() + GAP); + add(message); + + RedButton btnYes = new RedButton(Messages.get(this, "yes")) { + @Override + protected void onClick() { + hide(); + GLog.n(Messages.get(WndEgoalInfo.class, "tell1")); + } + }; + btnYes.setRect(0, message.top() + message.height() + GAP, WIDTH, + BTN_HEIGHT); + add(btnYes); + + RedButton btnNo = new RedButton(Messages.get(this, "no")) { + @Override + protected void onClick() { + hide(); + GLog.n(Messages.get(WndEgoalInfo.class, "tell2")); + } + }; + btnNo.setRect(0, btnYes.top() + btnYes.height() + GAP, WIDTH, + BTN_HEIGHT); + add(btnNo); + + resize(WIDTH, (int) btnNo.bottom()); + } + + +} diff --git a/java/com/hmdzl/spspd/windows/WndError.java b/java/com/hmdzl/spspd/windows/WndError.java new file mode 100644 index 00000000..710ff186 --- /dev/null +++ b/java/com/hmdzl/spspd/windows/WndError.java @@ -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 + */ +package com.hmdzl.spspd.windows; + +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.Icons; + +public class WndError extends WndTitledMessage { + + private static final String TXT_TITLE = "ERROR"; + + public WndError(String message) { + super(Icons.WARNING.get(), Messages.get(WndError.class, "title"), message); + } + +} diff --git a/java/com/hmdzl/spspd/windows/WndGame.java b/java/com/hmdzl/spspd/windows/WndGame.java new file mode 100644 index 00000000..d5ff7185 --- /dev/null +++ b/java/com/hmdzl/spspd/windows/WndGame.java @@ -0,0 +1,151 @@ +/* + * 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 + */ +package com.hmdzl.spspd.windows; + +import java.io.IOException; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.ShatteredPixelDungeon; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.scenes.InterlevelScene; +import com.hmdzl.spspd.scenes.LoadSaveScene; +import com.hmdzl.spspd.scenes.RankingsScene; +import com.hmdzl.spspd.scenes.TitleScene; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.Icons; +import com.hmdzl.spspd.ui.RedButton; +import com.hmdzl.spspd.ui.Window; +import com.watabou.noosa.Game; + +public class WndGame extends Window { + + private static final int WIDTH = 120; + private static final int BTN_HEIGHT = 20; + private static final int GAP = 2; + + private int pos; + + public WndGame() { + + super(); + + addButton(new RedButton( Messages.get(this, "settings")) { + @Override + protected void onClick() { + hide(); + GameScene.show(new WndSettings(true)); + } + }); + + // Challenges window + if (Dungeon.challenges > 0) { + addButton(new RedButton( Messages.get(this, "challenges")) { + @Override + protected void onClick() { + hide(); + GameScene + .show(new WndChallenges(Dungeon.challenges, false)); + } + }); + } + + // Restart + if (!Dungeon.hero.isAlive()) { + + RedButton btnStart; + addButton(btnStart = new RedButton( Messages.get(this, "start") ) { + @Override + protected void onClick() { + //GameLog.wipe(); + Dungeon.hero = null; + ShatteredPixelDungeon.challenges(Dungeon.challenges); + InterlevelScene.mode = InterlevelScene.Mode.DESCEND; + InterlevelScene.noStory = true; + Game.switchScene(InterlevelScene.class); + } + }); + btnStart.icon(Icons.get(Dungeon.hero.heroClass)); + + addButton(new RedButton(Messages.get(this, "rankings")) { + @Override + protected void onClick() { + InterlevelScene.mode = InterlevelScene.Mode.DESCEND; + Game.switchScene(RankingsScene.class); + } + }); + } + + addButton(new RedButton(Messages.get(this, "loadsave") ) { + @Override + protected void onClick() { + try { + Dungeon.saveAll(); + } catch (IOException e) { + ShatteredPixelDungeon.reportException(e); + } + Game.switchScene( LoadSaveScene.class ); + } + }); + + addButtons( + // Main menu + new RedButton( Messages.get(this, "menu")) { + @Override + protected void onClick() { + try { + Dungeon.saveAll(); + } catch (IOException e) { + //ShatteredPixelDungeon.reportException(e); + } + Game.switchScene(TitleScene.class); + } + }, + // Quit + new RedButton( Messages.get(this, "exit")) { + @Override + protected void onClick() { + Game.instance.finish(); + } + }); + + // Cancel + addButton(new RedButton(Messages.get(this, "return")) { + @Override + protected void onClick() { + hide(); + } + }); + + resize(WIDTH, pos); + } + + private void addButton(RedButton btn) { + add(btn); + btn.setRect(0, pos > 0 ? pos += GAP : 0, WIDTH, BTN_HEIGHT); + pos += BTN_HEIGHT; + } + + private void addButtons(RedButton btn1, RedButton btn2) { + add(btn1); + btn1.setRect(0, pos > 0 ? pos += GAP : 0, (WIDTH - GAP) / 2, BTN_HEIGHT); + add(btn2); + btn2.setRect(btn1.right() + GAP, btn1.top(), + WIDTH - btn1.right() - GAP, BTN_HEIGHT); + pos += BTN_HEIGHT; + } +} diff --git a/java/com/hmdzl/spspd/windows/WndGoblin.java b/java/com/hmdzl/spspd/windows/WndGoblin.java new file mode 100644 index 00000000..98c3b66d --- /dev/null +++ b/java/com/hmdzl/spspd/windows/WndGoblin.java @@ -0,0 +1,77 @@ +/* + * 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 + */ +package com.hmdzl.spspd.windows; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.items.keys.IronKey; +import com.hmdzl.spspd.items.weapon.melee.block.GoblinShield; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.PixelScene; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.ui.RedButton; +import com.hmdzl.spspd.ui.RenderedTextMultiline; +import com.hmdzl.spspd.ui.Window; +import com.hmdzl.spspd.utils.GLog; + + +public class WndGoblin extends Window { + + private static final int WIDTH = 120; + private static final int BTN_HEIGHT = 20; + private static final int GAP = 2; + + public WndGoblin() { + + super(); + + GoblinShield key = new GoblinShield(); + + + IconTitle titlebar = new IconTitle(); + titlebar.icon(new ItemSprite(key.image(), null)); + titlebar.label(Messages.titleCase(key.name())); + titlebar.setRect(0, 0, WIDTH, 0); + add(titlebar); + + RenderedTextMultiline message = PixelScene + .renderMultiline(Messages.get(this, "message"), 6); + message.maxWidth(WIDTH); + message.setPos(0, titlebar.bottom() + GAP); + add(message); + + RedButton btnReward = new RedButton(Messages.get(this, "buy")) { + @Override + protected void onClick() { + if (Dungeon.gold > 3000){ + Dungeon.gold-=3000; + GoblinShield gs = new GoblinShield(); + gs.doPickUp(Dungeon.hero); + hide(); + } else { + GLog.w(Messages.get(WndHotel.class,"more_gold")); + hide(); + } + } + }; + btnReward.setRect(0, message.top() + message.height() + GAP, WIDTH, + BTN_HEIGHT); + add(btnReward); + + resize(WIDTH, (int) btnReward.bottom()); + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/windows/WndHate.java b/java/com/hmdzl/spspd/windows/WndHate.java new file mode 100644 index 00000000..95ada461 --- /dev/null +++ b/java/com/hmdzl/spspd/windows/WndHate.java @@ -0,0 +1,78 @@ +/* + * 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 + */ +package com.hmdzl.spspd.windows; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.items.keys.IronKey; +import com.hmdzl.spspd.items.wands.WandOfFlock; +import com.hmdzl.spspd.items.weapon.melee.block.GoblinShield; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.PixelScene; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.ui.RedButton; +import com.hmdzl.spspd.ui.RenderedTextMultiline; +import com.hmdzl.spspd.ui.Window; +import com.hmdzl.spspd.utils.GLog; + + +public class WndHate extends Window { + + private static final int WIDTH = 120; + private static final int BTN_HEIGHT = 20; + private static final int GAP = 2; + + public WndHate() { + + super(); + + WandOfFlock key = new WandOfFlock(); + + + IconTitle titlebar = new IconTitle(); + titlebar.icon(new ItemSprite(key.image(), null)); + titlebar.label(Messages.titleCase(key.name())); + titlebar.setRect(0, 0, WIDTH, 0); + add(titlebar); + + RenderedTextMultiline message = PixelScene + .renderMultiline(Messages.get(this, "message"), 6); + message.maxWidth(WIDTH); + message.setPos(0, titlebar.bottom() + GAP); + add(message); + + RedButton btnReward = new RedButton(Messages.get(this, "buy")) { + @Override + protected void onClick() { + if (Dungeon.gold > 3000){ + Dungeon.gold-=3000; + WandOfFlock gs = new WandOfFlock(); + gs.doPickUp(Dungeon.hero); + hide(); + } else { + GLog.w(Messages.get(WndHotel.class,"more_gold")); + hide(); + } + } + }; + btnReward.setRect(0, message.top() + message.height() + GAP, WIDTH, + BTN_HEIGHT); + add(btnReward); + + resize(WIDTH, (int) btnReward.bottom()); + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/windows/WndHero.java b/java/com/hmdzl/spspd/windows/WndHero.java new file mode 100644 index 00000000..8a23e952 --- /dev/null +++ b/java/com/hmdzl/spspd/windows/WndHero.java @@ -0,0 +1,781 @@ +/* + * 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 + */ +package com.hmdzl.spspd.windows; + +import java.util.Locale; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.Statistics; +import com.hmdzl.spspd.actors.Actor; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Hunger; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.actors.mobs.pets.PET; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.food.completefood.PetFood; +import com.hmdzl.spspd.items.potions.Potion; +import com.hmdzl.spspd.items.potions.PotionOfFrost; +import com.hmdzl.spspd.items.potions.PotionOfLiquidFlame; +import com.hmdzl.spspd.items.potions.PotionOfToxicGas; +import com.hmdzl.spspd.items.scrolls.Scroll; +import com.hmdzl.spspd.items.scrolls.ScrollOfRecharging; +import com.hmdzl.spspd.items.food.completefood.Garbage; +import com.hmdzl.spspd.items.weapon.missiles.EscapeKnive; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.items.food.meatfood.Meat; +import com.hmdzl.spspd.items.food.meatfood.MysteryMeat; +import com.hmdzl.spspd.items.food.Nut; +import com.hmdzl.spspd.items.StoneOre; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.plants.Plant; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.scenes.PixelScene; +import com.hmdzl.spspd.sprites.CharSprite; +import com.hmdzl.spspd.sprites.HeroSprite; +import com.hmdzl.spspd.ui.BuffIndicator; +import com.hmdzl.spspd.ui.HealthBar; +import com.hmdzl.spspd.ui.RedButton; +import com.hmdzl.spspd.ui.Window; +import com.hmdzl.spspd.utils.GLog; + +import com.watabou.gltextures.SmartTexture; +import com.watabou.gltextures.TextureCache; +import com.watabou.noosa.Group; +import com.watabou.noosa.Image; +import com.watabou.noosa.TextureFilm; +import com.watabou.noosa.RenderedText; +import com.watabou.noosa.ui.Button; + +public class WndHero extends WndTabbed { + + private static final String TXT_STATS = "Stats"; + private static final String TXT_LEVELSTATS = "Level"; + private static final String TXT_BUFFS = "Buffs"; + private static final String TXT_PET = "Pet"; + + private static final String TXT_HEALS = "%+dHP"; + + private static final String TXT_EXP = "Experience"; + private static final String TXT_STR = "Strength"; + private static final String TXT_BREATH = "Breath Weapon"; + private static final String TXT_SPIN = "Spinneretes"; + private static final String TXT_STING = "Stinger"; + private static final String TXT_FEATHERS = "Feathers"; + private static final String TXT_SPARKLE = "Wand Attack"; + private static final String TXT_FANGS = "Fangs"; + private static final String TXT_ATTACK = "Attack Skill"; + private static final String TXT_HEALTH = "Health"; + private static final String TXT_GOLD = "Gold Collected"; + private static final String TXT_DEPTH = "Maximum Depth"; + private static final String TXT_MOVES = "Game Moves"; + private static final String TXT_MOVES2 = "Floor Moves"; + private static final String TXT_MOVES3 = "Floor Move Goal"; + private static final String TXT_MOVES4 = "Prev Under Goal"; + private static final String TXT_HUNGER = "Hunger"; + private static final String TXT_MOVES_DEW = "Dew Charge Moves"; + private static final String TXT_PETS = "Pets Lost"; + + private static final int WIDTH = 100; + private static final int TAB_WIDTH = 40; + + private StatsTab stats; + private LevelStatsTab levelstats; + private PetTab pet; + private BuffsTab buffs; + + private SmartTexture icons; + private TextureFilm film; + + + private PET checkpet(){ + for (Mob mob : Dungeon.level.mobs) { + if(mob instanceof PET) { + return (PET) mob; + } + } + return null; + } + + public WndHero() { + + super(); + + icons = TextureCache.get(Assets.BUFFS_LARGE); + film = new TextureFilm(icons, 16, 16); + + stats = new StatsTab(); + add(stats); + + if(Dungeon.dewDraw || Dungeon.dewWater){ + levelstats = new LevelStatsTab(); + add(levelstats); + } + PET heropet = checkpet(); + + if (heropet!=null){ + pet = new PetTab(heropet); + add(pet); + } + + buffs = new BuffsTab(); + add(buffs); + + + add(new LabeledTab(Messages.get(this, "stats")) { + @Override + protected void select(boolean value) { + super.select(value); + stats.visible = stats.active = selected; + }; + }); + + if(Dungeon.dewDraw || Dungeon.dewWater){ + add(new LabeledTab(Messages.get(this, "dew")) { + @Override + protected void select(boolean value) { + super.select(value); + levelstats.visible = levelstats.active = selected; + }; + }); + } + + if (heropet!=null){ + add(new LabeledTab(Messages.get(this, "pet")) { + @Override + protected void select(boolean value) { + super.select(value); + pet.visible = pet.active = selected; + }; + }); + } + + add(new LabeledTab(Messages.get(this, "buffs")) { + @Override + protected void select(boolean value) { + super.select(value); + buffs.visible = buffs.active = selected; + }; + }); + + resize(WIDTH, (int) Math.max(stats.height(), buffs.height())); + + layoutTabs(); + + select(0); + } + + private class StatsTab extends Group { + + private static final String TXT_TITLE = "Level %d %s"; + private static final String TXT_CATALOGUS = "Catalogus"; + private static final String TXT_JOURNAL = "Journal"; + + private static final int GAP = 4; + + private float pos; + + public StatsTab() { + + Hero hero = Dungeon.hero; + + IconTitle title = new IconTitle(); + title.icon(HeroSprite.avatar(hero.heroClass, hero.useskin())); + title.label( Messages.get(this, "title", hero.lvl, hero.className() ) + .toUpperCase(Locale.ENGLISH)); + title.color(Window.SHPX_COLOR); + title.setRect(0, 0, WIDTH, 0); + add(title); + + /*MemoryButton btnmemory = new MemoryButton(); + btnmemory.setRect(60,0,0,0); + add(btnmemory);*/ + + RedButton btnCatalogus = new RedButton(Messages.get(this, "catalogs")) { + @Override + protected void onClick() { + hide(); + GameScene.show(new WndCatalogus()); + }; + }; + btnCatalogus.setRect(0, title.height(), + btnCatalogus.reqWidth() + 2, btnCatalogus.reqHeight() + 2); + add(btnCatalogus); + + RedButton btnJournal = new RedButton(Messages.get(this, "journal")) { + @Override + protected void onClick() { + hide(); + GameScene.show(new WndJournal()); + } + }; + btnJournal.setRect(btnCatalogus.right() + 1, btnCatalogus.top(), + btnJournal.reqWidth() + 2, btnJournal.reqHeight() + 2); + add(btnJournal); + + pos = btnJournal.bottom() + GAP; + + statSlot(Messages.get(this, "str"), hero.STR()); + statSlot(Messages.get(this, "health"), hero.HP + "/" + hero.HT ); + statSlot(Messages.get(this, "exp"), hero.exp + "/" + hero.maxExp()); + + statSlot(Messages.get(this, "time"), ((int)(Statistics.time/60) + ":" + (int)(Statistics.time%60))); + + pos += GAP; + + statSlot(Messages.get(this, "gold"), Statistics.goldCollected); + statSlot(Messages.get(this, "depth"), Statistics.deepestFloor); + statSlot(Messages.get(this, "atkskill"), hero.hitSkill); + statSlot(Messages.get(this, "defskill"), hero.evadeSkill); + statSlot(Messages.get(this, "magskill"), hero.magicSkill()); + + if(Dungeon.hero.buff(Hunger.class) != null){ + statSlot(Messages.get(this, "hunger") , Dungeon.hero.buff(Hunger.class).hungerLevel()); + } + + + pos += GAP; + } + + private void statSlot(String label, String value) { + + RenderedText txt = PixelScene.renderText(label, 8); + txt.y = pos; + add(txt); + + txt = PixelScene.renderText(value, 8); + //txt.measure(); + txt.x = PixelScene.align(WIDTH * 0.5f); + txt.y = pos; + add(txt); + + pos += GAP + txt.baseLine(); + } + + private void statSlot(String label, int value) { + statSlot(label, Integer.toString(value)); + } + + public float height() { + return pos; + } + } + + private class LevelStatsTab extends Group { + + private static final String TXT_TITLE = "Level %d %s"; + private static final String TXT_CATALOGUS = "Catalogus"; + private static final String TXT_JOURNAL = "Journal"; + + private static final int GAP = 4; + + private float pos; + + public LevelStatsTab() { + + Hero hero = Dungeon.hero; + + IconTitle title = new IconTitle(); + title.icon(HeroSprite.avatar(hero.heroClass, hero.useskin())); + title.label( Messages.get(this, "title", hero.lvl, hero.className()) + .toUpperCase(Locale.ENGLISH)); + title.color(Window.SHPX_COLOR); + title.setRect(0, 0, WIDTH, 0); + add(title); + + RedButton btnCatalogus = new RedButton(Messages.get(this, "catalogs")) { + @Override + protected void onClick() { + hide(); + GameScene.show(new WndCatalogus()); + }; + }; + btnCatalogus.setRect(0, title.height(), + btnCatalogus.reqWidth() + 2, btnCatalogus.reqHeight() + 2); + add(btnCatalogus); + + RedButton btnJournal = new RedButton(Messages.get(this, "journal")) { + @Override + protected void onClick() { + hide(); + GameScene.show(new WndJournal()); + } + }; + btnJournal.setRect(btnCatalogus.right() + 1, btnCatalogus.top(), + btnJournal.reqWidth() + 2, btnJournal.reqHeight() + 2); + add(btnJournal); + + pos = btnCatalogus.bottom() + GAP; + + + if (Dungeon.depth<26 && (Dungeon.dewDraw || Dungeon.dewWater)){ + statSlot(Messages.get(this, "level_move"), Dungeon.level.currentmoves); + statSlot(Messages.get(this, "level_max"), Dungeon.pars[Dungeon.depth]); + statSlot(Messages.get(this, "level_prefect"),Statistics.prevfloormoves); + /*if (Dungeon.hero.buff(Dewcharge.class) != null) { + float dewration = Dungeon.hero.buff(Dewcharge.class).dispTurns(); + statSlot(Messages.get(this, "level_left"), dewration); + }*/ + } + + + pos += GAP; + } + + private void statSlot(String label, String value) { + + RenderedText txt = PixelScene.renderText(label, 8); + txt.y = pos; + add(txt); + + txt = PixelScene.renderText(value, 8); + //txt.measure(); + txt.x = PixelScene.align(WIDTH * 0.5f); + txt.y = pos; + add(txt); + + pos += GAP + txt.baseLine(); + } + + private void statSlot(String label, int value) { + statSlot(label, Integer.toString(value)); + } + + public float height() { + return pos; + } + } + + + + + private class BuffsTab extends Group { + + private static final int GAP = 4; + + private float pos; + + public BuffsTab() { + for (Buff buff : Dungeon.hero.buffs()) { + if (buff.icon() != BuffIndicator.NONE) { + BuffSlot slot = new BuffSlot(buff); + slot.setRect(0, pos, WIDTH, slot.icon.height()); + add(slot); + pos += GAP + slot.height(); + } + } + } + + public float height() { + return pos; + } + + private class BuffSlot extends Button { + + private Buff buff; + + Image icon; + RenderedText txt; + + public BuffSlot( Buff buff ){ + super(); + this.buff = buff; + int index = buff.icon(); + + icon = new Image( icons ); + icon.frame( film.get( index ) ); + icon.y = this.y; + add( icon ); + + txt = PixelScene.renderText( buff.toString(), 8 ); + txt.x = icon.width + GAP; + txt.y = this.y + (int)(icon.height - txt.baseLine()) / 2; + add( txt ); + + } + + @Override + protected void layout() { + super.layout(); + icon.y = this.y; + txt.x = icon.width + GAP; + txt.y = pos + (int)(icon.height - txt.baseLine()) / 2; + } + + @Override + protected void onClick() { + GameScene.show( new WndInfoBuff( buff )); + } + } + /*private void buffSlot(Buff buff) { + + int index = buff.icon(); + + if (index != BuffIndicator.NONE) { + + Image icon = new Image(icons); + icon.frame(film.get(index)); + icon.y = pos; + add(icon); + + RenderedText txt = PixelScene.renderText(buff.toString(), 8); + txt.x = icon.width + GAP; + txt.y = pos + (int) (icon.height - txt.baseLine()) / 2; + add(txt); + + pos += GAP + icon.height; + } + } + + public float height() { + return pos; + }*/ + } + + private class PetTab extends Group { + + private static final String TXT_TITLE = "Level %d %s"; + private static final String TXT_FEED = "Feed"; + private static final String TXT_CALL = "Call"; + private static final String TXT_STAY = "Stay"; + private static final String TXT_RELEASE = "Release"; + private static final String TXT_SELECT = "What do you want to feed your pet?"; + + private CharSprite image; + private RenderedText name; + private HealthBar health; + private BuffIndicator buffs; + + private static final int GAP = 4; + + private float pos; + + + public PetTab(final PET heropet) { + + //name = PixelScene.renderText(heropet.name); + //name.hardlight(TITLE_COLOR); + //name.measure(); + //add(name); + + image = heropet.sprite(); + add(image); + + health = new HealthBar(); + health.level((float) heropet.HP / heropet.HT); + add(health); + + buffs = new BuffIndicator(heropet); + add(buffs); + + + + IconTitle title = new IconTitle(); + title.icon(image); + title.label( Messages.get(this, "title", heropet.level, heropet.name).toUpperCase(Locale.ENGLISH), 9); + title.color(Window.SHPX_COLOR); + title.setRect(0, 0, WIDTH, 0); + add(title); + + RedButton btnFeed = new RedButton(Messages.get(this, "pet_feed")) { + @Override + protected void onClick() { + hide(); + GameScene.selectItem(itemSelector, WndBag.Mode.ALL, Messages.get(WndHero.class, "choose_food")); + } + }; + btnFeed.setRect(0, title.height(), + btnFeed.reqWidth() + 2, btnFeed.reqHeight() + 2); + add(btnFeed); + + RedButton btnCall = new RedButton(Messages.get(this, "pet_call")) { + @Override + protected void onClick() { + hide(); + heropet.callback = true; + heropet.stay = false; + } + }; + btnCall.setRect(btnFeed.right() + 1, btnFeed.top(), + btnCall.reqWidth() + 2, btnCall.reqHeight() + 2); + add(btnCall); + + RedButton btnStay = new RedButton(heropet.stay ? Messages.get(this, "pet_move") : Messages.get(this, "pet_stay")) { + @Override + protected void onClick() { + hide(); + if (heropet.stay){ + heropet.stay = false; + } else { + heropet.stay = true; + } + } + }; + + btnStay.setRect(btnCall.right() + 1, btnCall.top(), + btnStay.reqWidth() + 2, btnStay.reqHeight() + 2); + + add(btnStay); + + pos = btnStay.bottom() + GAP; + + statSlot(Messages.get(this, "pet_attack"), heropet.hitSkill(null)); + statSlot(Messages.get(this, "pet_hp"), heropet.HP + "/" + heropet.HT); + statSlot(Messages.get(this, "pet_exp"), heropet.level<30 ? heropet.experience + "/" + (heropet.level*(heropet.level+1) ): "MAX"); + statSlot(Messages.get(this, "pet_skills"), heropet.cooldown==0 ? Messages.get(this, "pet_skills_ready") : heropet.cooldown + Messages.get(this, "pet_skills_turn")); + + pos += GAP; + + + } + + private void statSlot(String label, String value) { + + RenderedText txt = PixelScene.renderText(label, 8); + txt.y = pos; + add(txt); + + txt = PixelScene.renderText(value, 8); + //txt.measure(); + txt.x = PixelScene.align(WIDTH * 0.5f); + txt.y = pos; + add(txt); + + pos += GAP + txt.baseLine(); + } + + private void statSlot(String label, int value) { + statSlot(label, Integer.toString(value)); + } + + public float height() { + return pos; + } + } + + private final WndBag.Listener itemSelector = new WndBag.Listener() { + @Override + public void onSelect(Item item) { + if (item != null) { + feed(item); + } + } + }; + + private boolean checkpetNear(){ + for (int n : Level.NEIGHBOURS8) { + int c = Dungeon.hero.pos + n; + if (Actor.findChar(c) instanceof PET) { + return true; + } + } + return false; + } + + private void feed(Item item) { + + PET heropet = checkpet(); + boolean nomnom = checkFood(heropet.type, item); + boolean nearby = checkpetNear(); + + if (nomnom && nearby){ + int effect = heropet.HT-heropet.HP; + if (effect > 0){ + heropet.HP+= (int)(effect*0.8); + heropet.sprite.emitter().burst(Speck.factory(Speck.HEALING),2); + heropet.sprite.showStatus(CharSprite.POSITIVE,Messages.get(WndHero.class,"heals", effect)); + } + heropet.cooldown=1; + heropet.experience+= 120; + item.detach(Dungeon.hero.belongings.backpack); + Dungeon.hero.spend(1f); + Dungeon.hero.busy(); + Dungeon.hero.sprite.operate(Dungeon.hero.pos); + GLog.n(Messages.get(WndHero.class, "pet_eat",item.name())); + }else if (!nearby){ + GLog.n(Messages.get(WndHero.class, "pet_faraway")); + } else { + GLog.n(Messages.get(WndHero.class, "pet_noeat",item.name())); + + } + } + + private boolean checkFood(Integer petType, Item item){ + boolean nomnom = false; + + if (petType==1){ //Spider + if (item instanceof Meat + || item instanceof MysteryMeat + || item instanceof PetFood){ + nomnom=true; + } + } + + if (petType==3){//Velocirooster + if (item instanceof Plant.Seed + || item instanceof Nut + || item instanceof PetFood){ + nomnom=true; + } + } + if (petType==4){//red dragon - fire + if (item instanceof Meat + || item instanceof PotionOfLiquidFlame + || item instanceof MysteryMeat + || item instanceof PetFood){ + nomnom=true; + } + } + + if (petType==5){//green dragon - lit + if (item instanceof Meat + || item instanceof ScrollOfRecharging + || item instanceof MysteryMeat + || item instanceof PetFood){ + nomnom=true; + } + } + + if (petType==6){//violet dragon - poison + if (item instanceof Meat + || item instanceof PotionOfToxicGas + || item instanceof MysteryMeat + || item instanceof PetFood){ + nomnom=true; + } + } + if (petType==7){//blue dragon - ice + if (item instanceof Meat + || item instanceof PotionOfFrost + || item instanceof MysteryMeat + || item instanceof PetFood){ + nomnom=true; + } + } + + if (petType==8){ //scorpion + if (item instanceof Meat + || item instanceof MysteryMeat + || item instanceof PetFood){ + nomnom=true; + } + } + + if (petType==9){//Vorpal Bunny + if (item instanceof Plant.Seed + || item instanceof PetFood){ + nomnom=true; + } + } + if (petType==10){//Fairy + if (item instanceof Potion + || item instanceof PetFood){ + nomnom=true; + } + } + if (petType==11){//Sugarplum Fairy + if (item instanceof Potion + || item instanceof PetFood){ + nomnom=true; + } + } + if (petType==12){//shadow dragon + if (item instanceof Meat + || item instanceof MysteryMeat + || item instanceof PetFood){ + nomnom=true; + } + } + if (petType==13){//CocoCat + if (item instanceof Nut + || item instanceof Nut + || item instanceof PetFood){ + nomnom=true; + } + } + if (petType==14){//LeryFire + if (item instanceof Scroll + || item instanceof PetFood){ + nomnom=true; + } + } + if (petType==15){//GoldDragon + if (item instanceof Meat + || item instanceof MysteryMeat + || item instanceof PetFood){ + nomnom=true; + } + } + if (petType==16){//snake + if (item instanceof Meat + || item instanceof MysteryMeat + || item instanceof PetFood){ + nomnom=true; + } + } + if (petType==17){//fly + if (item instanceof Meat + || item instanceof MysteryMeat + || item instanceof PetFood){ + nomnom=true; + } + } + if (petType==18){//stone + if (item instanceof EscapeKnive + || item instanceof PetFood + || item instanceof StoneOre + || item instanceof Garbage){ + nomnom=true; + } + } + if (petType==19){//monkey + if (item instanceof Plant.Seed + || item instanceof Nut + || item instanceof PetFood){ + nomnom=true; + } + } + if (petType==20){//GentleCrab + if (item instanceof Meat + || item instanceof MysteryMeat + || item instanceof Plant.Seed + || item instanceof PetFood){ + nomnom=true; + } + } + if (petType==21){//RibbonRat + if (item instanceof Plant.Seed + || item instanceof Nut + || item instanceof Meat + || item instanceof PetFood){ + nomnom=true; + } + } + if (petType==22){//YearPet + if (item instanceof Meat + || item instanceof PetFood){ + nomnom=true; + } + } + + return nomnom; + } + +} diff --git a/java/com/hmdzl/spspd/windows/WndHotel.java b/java/com/hmdzl/spspd/windows/WndHotel.java new file mode 100644 index 00000000..29643723 --- /dev/null +++ b/java/com/hmdzl/spspd/windows/WndHotel.java @@ -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 + */ +package com.hmdzl.spspd.windows; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.items.keys.IronKey; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.PixelScene; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.ui.RedButton; +import com.hmdzl.spspd.ui.RenderedTextMultiline; +import com.hmdzl.spspd.ui.Window; +import com.hmdzl.spspd.utils.GLog; + + +public class WndHotel extends Window { + + private static final int WIDTH = 120; + private static final int BTN_HEIGHT = 20; + private static final int GAP = 2; + + public WndHotel() { + + super(); + + IronKey key = new IronKey(Dungeon.depth); + + + IconTitle titlebar = new IconTitle(); + titlebar.icon(new ItemSprite(key.image(), null)); + titlebar.label(Messages.titleCase(key.name())); + titlebar.setRect(0, 0, WIDTH, 0); + add(titlebar); + + RenderedTextMultiline message = PixelScene + .renderMultiline(Messages.get(this, "message"), 6); + message.maxWidth(WIDTH); + message.setPos(0, titlebar.bottom() + GAP); + add(message); + + RedButton btnReward = new RedButton(Messages.get(this, "buy")) { + @Override + protected void onClick() { + if (Dungeon.gold > 100){ + Dungeon.gold-=100; + IronKey key = new IronKey(Dungeon.depth); + key.doPickUp(Dungeon.hero); + hide(); + } else { + GLog.w(Messages.get(this,"more_gold")); + hide(); + } + } + }; + btnReward.setRect(0, message.top() + message.height() + GAP, WIDTH, + BTN_HEIGHT); + add(btnReward); + + resize(WIDTH, (int) btnReward.bottom()); + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/windows/WndImp.java b/java/com/hmdzl/spspd/windows/WndImp.java new file mode 100644 index 00000000..20988ad5 --- /dev/null +++ b/java/com/hmdzl/spspd/windows/WndImp.java @@ -0,0 +1,81 @@ +/* + * 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 + */ +package com.hmdzl.spspd.windows; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.mobs.npcs.Imp; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.quest.DwarfToken; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.PixelScene; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.ui.RedButton; +import com.hmdzl.spspd.ui.RenderedTextMultiline; +import com.hmdzl.spspd.ui.Window; + + +public class WndImp extends Window { + + private static final int WIDTH = 120; + private static final int BTN_HEIGHT = 20; + private static final int GAP = 2; + + public WndImp(final Imp imp, final DwarfToken tokens) { + + super(); + + IconTitle titlebar = new IconTitle(); + titlebar.icon(new ItemSprite(tokens.image(), null)); + titlebar.label(Messages.titleCase( tokens.name() )); + titlebar.setRect(0, 0, WIDTH, 0); + add(titlebar); + + RenderedTextMultiline message = PixelScene + .renderMultiline( Messages.get(this, "message"), 6); + message.maxWidth(WIDTH); + message.setPos(0,titlebar.bottom() + GAP); + add(message); + + RedButton btnReward = new RedButton(Messages.get(this, "reward")) { + @Override + protected void onClick() { + takeReward(imp, tokens, Imp.Quest.reward); + } + }; + btnReward.setRect(0, message.top() + message.height() + GAP, WIDTH, + BTN_HEIGHT); + add(btnReward); + + resize(WIDTH, (int) btnReward.bottom()); + } + + private void takeReward(Imp imp, DwarfToken tokens, Item reward) { + + hide(); + + tokens.detachAll(Dungeon.hero.belongings.backpack); + + reward.identify(); + + Dungeon.level.drop(reward, imp.pos).sprite.drop(); + + imp.flee(); + + Imp.Quest.complete(); + } +} diff --git a/java/com/hmdzl/spspd/windows/WndInfoBuff.java b/java/com/hmdzl/spspd/windows/WndInfoBuff.java new file mode 100644 index 00000000..403cc50f --- /dev/null +++ b/java/com/hmdzl/spspd/windows/WndInfoBuff.java @@ -0,0 +1,66 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2015 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.windows; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.PixelScene; +import com.hmdzl.spspd.ui.RenderedTextMultiline; +import com.hmdzl.spspd.ui.Window; +import com.watabou.gltextures.SmartTexture; +import com.watabou.gltextures.TextureCache; +import com.watabou.noosa.Image; +import com.watabou.noosa.TextureFilm; + +public class WndInfoBuff extends Window { + + private static final float GAP = 2; + + private static final int WIDTH = 120; + + private SmartTexture icons; + private TextureFilm film; + + public WndInfoBuff(Buff buff){ + super(); + + IconTitle titlebar = new IconTitle(); + + icons = TextureCache.get( Assets.BUFFS_LARGE ); + film = new TextureFilm( icons, 16, 16 ); + + Image buffIcon = new Image( icons ); + buffIcon.frame( film.get(buff.icon()) ); + + titlebar.icon( buffIcon ); + titlebar.label( Messages.titleCase(buff.toString()), Window.TITLE_COLOR ); + titlebar.setRect( 0, 0, WIDTH, 0 ); + add( titlebar ); + + RenderedTextMultiline txtInfo = PixelScene.renderMultiline(buff.desc(), 6); + txtInfo.maxWidth(WIDTH); + txtInfo.setPos(titlebar.left(), titlebar.bottom() + GAP); + add( txtInfo ); + + resize( WIDTH, (int)(txtInfo.top() + txtInfo.height()) ); + } +} diff --git a/java/com/hmdzl/spspd/windows/WndInfoCell.java b/java/com/hmdzl/spspd/windows/WndInfoCell.java new file mode 100644 index 00000000..6fd584a5 --- /dev/null +++ b/java/com/hmdzl/spspd/windows/WndInfoCell.java @@ -0,0 +1,82 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2014 Oleg Dolya + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.windows; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.DungeonTilemap; +import com.hmdzl.spspd.actors.blobs.Blob; +import com.hmdzl.spspd.levels.Level; +import com.hmdzl.spspd.levels.Terrain; +import com.hmdzl.spspd.scenes.PixelScene; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.Window; +import com.hmdzl.spspd.ui.RenderedTextMultiline; +import com.watabou.noosa.Image; + +public class WndInfoCell extends Window { + + private static final float GAP = 2; + + private static final int WIDTH = 120; + + private static final String TXT_NOTHING = "There is nothing here."; + + public WndInfoCell(int cell) { + + super(); + + int tile = Dungeon.level.map[cell]; + if (Level.water[cell]) { + tile = Terrain.WATER; + } else if (Level.pit[cell]) { + tile = Terrain.CHASM; + } + + IconTitle titlebar = new IconTitle(); + if (tile == Terrain.WATER) { + Image water = new Image(Dungeon.level.waterTex()); + water.frame(0, 0, DungeonTilemap.SIZE, DungeonTilemap.SIZE); + titlebar.icon(water); + } else { + titlebar.icon(DungeonTilemap.tile(tile)); + } + titlebar.label(Dungeon.level.tileName(tile)); + titlebar.setRect(0, 0, WIDTH, 0); + add(titlebar); + + RenderedTextMultiline info = PixelScene.renderMultiline(6); + add(info); + + StringBuilder desc = new StringBuilder(Dungeon.level.tileDesc(tile)); + + for (Blob blob : Dungeon.level.blobs.values()) { + if (blob.cur[cell] > 0 && blob.tileDesc() != null) { + if (desc.length() > 0) { + desc.append("\n\n"); + } + desc.append(blob.tileDesc()); + } + } + + info.text(desc.length() > 0 ? desc.toString() : Messages.get("nothing")); + info.maxWidth(WIDTH); + info.setPos(titlebar.left(), titlebar.bottom() + GAP); + + resize( WIDTH, (int)(info.top() + info.height()) ); + } +} diff --git a/java/com/hmdzl/spspd/windows/WndInfoItem.java b/java/com/hmdzl/spspd/windows/WndInfoItem.java new file mode 100644 index 00000000..21f84792 --- /dev/null +++ b/java/com/hmdzl/spspd/windows/WndInfoItem.java @@ -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 + */ +package com.hmdzl.spspd.windows; + +import com.hmdzl.spspd.items.Heap; +import com.hmdzl.spspd.items.Heap.Type; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.artifacts.Artifact; +import com.hmdzl.spspd.items.wands.Wand; +import com.hmdzl.spspd.items.rings.Ring; +import com.hmdzl.spspd.scenes.PixelScene; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.ItemSlot; +import com.hmdzl.spspd.ui.RenderedTextMultiline; +import com.hmdzl.spspd.ui.Window; + + +public class WndInfoItem extends Window { + + private static final String TTL_CHEST = "Chest"; + private static final String TTL_LOCKED_CHEST = "Locked chest"; + private static final String TTL_CRYSTAL_CHEST = "Crystal chest"; + private static final String TTL_TOMB = "Tomb"; + private static final String TTL_SKELETON = "Skeletal remains"; + private static final String TTL_REMAINS = "Heroes remains"; + private static final String TXT_WONT_KNOW = "You won't know what's inside until you open it!"; + private static final String TXT_NEED_KEY = TXT_WONT_KNOW + + " But to open it you need a golden key."; + private static final String TXT_INSIDE = "You can see %s inside, but to open the chest you need a golden key."; + private static final String TXT_OWNER = "This ancient tomb may contain something useful, " + + "but its owner will most certainly object to checking."; + private static final String TXT_SKELETON = "This is all that's left of some unfortunate adventurer. " + + "Maybe it's worth checking for any valuables."; + private static final String TXT_REMAINS = "This is all that's left from one of your predecessors. " + + "Maybe it's worth checking for any valuables."; + + private static final float GAP = 2; + + private static final int WIDTH = 120; + + public WndInfoItem(Heap heap) { + + super(); + + if (heap.type == Heap.Type.HEAP || heap.type == Heap.Type.FOR_SALE) { + + Item item = heap.peek(); + + int color = TITLE_COLOR; + if (item.levelKnown && item.level > 0) { + color = ItemSlot.UPGRADED; + } else if (item.levelKnown && item.level < 0) { + color = ItemSlot.DEGRADED; + } + fillFields(item.image(), item.glowing(), color, item.toString(), + item.info()); + + } else { + + String title; + String info; + + if (heap.type == Type.CHEST || heap.type == Type.MIMIC) { + title = Messages.get(this, "chest"); + info = Messages.get(this, "wont_know"); + } else if (heap.type == Type.TOMB) { + title = Messages.get(this, "tomb"); + info = Messages.get(this, "owner"); + } else if (heap.type == Type.SKELETON) { + title = Messages.get(this, "skeleton"); + info = Messages.get(this, "skeleton_desc"); + } else if (heap.type == Type.REMAINS) { + title = Messages.get(this, "remains"); + info = Messages.get(this, "remains_desc"); + } else if (heap.type == Type.CRYSTAL_CHEST) { + title = Messages.get(this, "crystal_chest"); + if (heap.peek() instanceof Artifact) + info = Messages.get(this, "inside", Messages.get(this, "artifact") ); + else if (heap.peek() instanceof Wand) + info = Messages.get(this, "inside", Messages.get(this, "wand") ); + else if (heap.peek() instanceof Ring) + info = Messages.get(this, "inside", Messages.get(this, "ring") ); + else + info = ""; //This shouldn't happen + } else { + title = Messages.get(this, "locked_chest"); + info = Messages.get(this, "need_key"); + } + + fillFields(heap.image(), heap.glowing(), TITLE_COLOR, title, info); + + } + } + + public WndInfoItem(Item item) { + + super(); + + int color = TITLE_COLOR; + if (item.levelKnown && item.level > 0) { + color = ItemSlot.UPGRADED; + } else if (item.levelKnown && item.level < 0) { + color = ItemSlot.DEGRADED; + } + + fillFields(item.image(), item.glowing(), color, item.toString(), + item.info()); + } + + private void fillFields(int image, ItemSprite.Glowing glowing, + int titleColor, String title, String info) { + + IconTitle titlebar = new IconTitle(); + titlebar.icon(new ItemSprite(image, glowing)); + titlebar.label(Messages.titleCase( title ), titleColor); + titlebar.setRect(0, 0, WIDTH, 0); + add(titlebar); + + RenderedTextMultiline txtInfo = PixelScene.renderMultiline( info, 6 ); + txtInfo.maxWidth(WIDTH); + txtInfo.setPos(titlebar.left(), titlebar.bottom() + GAP); + add( txtInfo ); + + resize( WIDTH, (int)(txtInfo.top() + txtInfo.height()) ); + } +} diff --git a/java/com/hmdzl/spspd/windows/WndInfoMob.java b/java/com/hmdzl/spspd/windows/WndInfoMob.java new file mode 100644 index 00000000..84d9240f --- /dev/null +++ b/java/com/hmdzl/spspd/windows/WndInfoMob.java @@ -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 + */ +package com.hmdzl.spspd.windows; + +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.scenes.PixelScene; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.CharSprite; +import com.hmdzl.spspd.ui.BuffIndicator; +import com.hmdzl.spspd.ui.HealthBar; + +import com.watabou.noosa.ui.Component; +import com.watabou.noosa.RenderedText; + +public class WndInfoMob extends WndTitledMessage { + + public WndInfoMob(Mob mob) { + + super(new MobTitle(mob), desc(mob)); + + } + + private static String desc(Mob mob) { + + StringBuilder builder = new StringBuilder(mob.description()); + + builder.append("\n\n" + mob.state.status()); + + return builder.toString(); + } + + private static class MobTitle extends Component { + + private static final int GAP = 2; + + private CharSprite image; + private RenderedText name; + private HealthBar health; + private BuffIndicator buffs; + + public MobTitle(Mob mob) { + + name = PixelScene.renderText(Messages.titleCase(mob.name), 9); + name.hardlight(TITLE_COLOR); + //name.measure(); + add(name); + + image = mob.sprite(); + add(image); + + health = new HealthBar(); + health.level((float) mob.HP / mob.HT); + add(health); + + buffs = new BuffIndicator(mob); + add(buffs); + } + + @Override + protected void layout() { + + image.x = 0; + image.y = Math.max(0, name.height() + GAP + health.height() + - image.height); + + name.x = image.width + GAP; + name.y = image.height - health.height() - GAP - name.baseLine(); + + float w = width - image.width - GAP; + + health.setRect(image.width + GAP, image.height - health.height(), + w, health.height()); + + buffs.setPos( name.x + name.width() + GAP-1, + name.y + name.baseLine() - BuffIndicator.SIZE-2 ); + + + height = health.bottom(); + } + } +} diff --git a/java/com/hmdzl/spspd/windows/WndInfoPlant.java b/java/com/hmdzl/spspd/windows/WndInfoPlant.java new file mode 100644 index 00000000..a497e0b0 --- /dev/null +++ b/java/com/hmdzl/spspd/windows/WndInfoPlant.java @@ -0,0 +1,30 @@ +/* + * 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 + */ +package com.hmdzl.spspd.windows; + +import com.hmdzl.spspd.plants.Plant; +import com.hmdzl.spspd.sprites.PlantSprite; + +public class WndInfoPlant extends WndTitledMessage { + + public WndInfoPlant(Plant plant) { + + super(new PlantSprite(plant.image), plant.plantName, plant.desc()); + + } +} diff --git a/java/com/hmdzl/spspd/windows/WndInfoTrap.java b/java/com/hmdzl/spspd/windows/WndInfoTrap.java new file mode 100644 index 00000000..ed21d3de --- /dev/null +++ b/java/com/hmdzl/spspd/windows/WndInfoTrap.java @@ -0,0 +1,37 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2015 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.windows; + +import com.hmdzl.spspd.levels.traps.Trap; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.sprites.TrapSprite; + +public class WndInfoTrap extends WndTitledMessage { + + public WndInfoTrap(Trap trap) { + + super(new TrapSprite( trap.color + (trap.shape * 16) ), + trap.name, + (!trap.active ? Messages.get(WndInfoTrap.class, "inactive") + "\n\n" : "") + trap.desc()); + + } + +} diff --git a/java/com/hmdzl/spspd/windows/WndIssic.java b/java/com/hmdzl/spspd/windows/WndIssic.java new file mode 100644 index 00000000..fd55bcb9 --- /dev/null +++ b/java/com/hmdzl/spspd/windows/WndIssic.java @@ -0,0 +1,80 @@ +/* + * 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 + */ +package com.hmdzl.spspd.windows; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.items.Gold; +import com.hmdzl.spspd.items.keys.IronKey; +import com.hmdzl.spspd.items.medicine.Powerpill; +import com.hmdzl.spspd.items.weapon.melee.block.GoblinShield; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.PixelScene; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.ui.RedButton; +import com.hmdzl.spspd.ui.RenderedTextMultiline; +import com.hmdzl.spspd.ui.Window; +import com.hmdzl.spspd.utils.GLog; +import com.watabou.utils.Random; + + +public class WndIssic extends Window { + + private static final int WIDTH = 120; + private static final int BTN_HEIGHT = 20; + private static final int GAP = 2; + + public WndIssic() { + + super(); + + Powerpill key = new Powerpill(); + + + IconTitle titlebar = new IconTitle(); + titlebar.icon(new ItemSprite(key.image(), null)); + titlebar.label(Messages.titleCase(key.name())); + titlebar.setRect(0, 0, WIDTH, 0); + add(titlebar); + + RenderedTextMultiline message = PixelScene + .renderMultiline(Messages.get(this, "message"), 6); + message.maxWidth(WIDTH); + message.setPos(0, titlebar.bottom() + GAP); + add(message); + + RedButton btnReward = new RedButton(Messages.get(this, "buy")) { + @Override + protected void onClick() { + if (Dungeon.hero.HP > 150){ + Dungeon.hero.HP-=100; + Gold gs = new Gold(Random.Int(500,3000)); + gs.doPickUp(Dungeon.hero); + hide(); + } else { + GLog.w(Messages.get(WndHotel.class,"more_gold")); + hide(); + } + } + }; + btnReward.setRect(0, message.top() + message.height() + GAP, WIDTH, + BTN_HEIGHT); + add(btnReward); + + resize(WIDTH, (int) btnReward.bottom()); + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/windows/WndItem.java b/java/com/hmdzl/spspd/windows/WndItem.java new file mode 100644 index 00000000..2e363b10 --- /dev/null +++ b/java/com/hmdzl/spspd/windows/WndItem.java @@ -0,0 +1,161 @@ +/* + * 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 + */ +package com.hmdzl.spspd.windows; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.scenes.PixelScene; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.ui.ItemSlot; +import com.hmdzl.spspd.ui.RedButton; +import com.hmdzl.spspd.ui.Window; +import com.hmdzl.spspd.ui.RenderedTextMultiline; +import com.hmdzl.spspd.messages.Messages; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; + +public class WndItem extends Window { + + private static final float BUTTON_WIDTH = 36; + private static final float BUTTON_HEIGHT = 16; + + private static final float GAP = 2; + + private static final int WIDTH = 120; + + public WndItem( final WndBag owner, final Item item ){ + this( owner, item, owner != null ); + } + + public WndItem(final WndBag owner, final Item item , final boolean options) { + + super(); + + IconTitle titlebar = new IconTitle(); + titlebar.icon(new ItemSprite(item.image(), item.glowing())); + titlebar.label(Messages.titleCase(item.toString())); + titlebar.setRect(0, 0, WIDTH, 0); + add(titlebar); + + if (item.levelKnown && item.level > 0) { + titlebar.color(ItemSlot.UPGRADED); + } else if (item.levelKnown && item.level < 0) { + titlebar.color(ItemSlot.DEGRADED); + } + + RenderedTextMultiline info = PixelScene.renderMultiline( item.info(), 6 ); + info.maxWidth(WIDTH); + info.setPos(titlebar.left(), titlebar.bottom() + GAP); + add( info ); + + float y = info.top() + info.height() + GAP; + float x = 0; + + if (Dungeon.hero.isAlive() && /*owner != null*/ options) { + ArrayList line = new ArrayList<>(); + for (final String action : item.actions(Dungeon.hero)) { + + RedButton btn = new RedButton(Messages.get(item, "ac_" + action), 8 ) { + @Override + protected void onClick() { + //item.execute(Dungeon.hero, action); + //hide(); + //owner.hide(); + hide(); + if (owner != null && owner.parent != null) owner.hide(); + if (Dungeon.hero.isAlive()) item.execute( Dungeon.hero, action ); + }; + }; + btn.setSize(Math.max(BUTTON_WIDTH, btn.reqWidth()), + BUTTON_HEIGHT); + if (x + btn.width() > WIDTH) { + x = 0; + y += BUTTON_HEIGHT + GAP; + } + btn.setPos(x, y); + add(btn); + + if (action == item.defaultAction) { + btn.textColor(TITLE_COLOR); + } + + x += btn.width() + GAP; + } + } + + resize(WIDTH, (int) (y + (x > 0 ? BUTTON_HEIGHT : 0))); + } + private static void layoutButtons(ArrayList line, float extraWidth, float y){ + if (line == null || line.size() == 0 || extraWidth == 0) return; + if (line.size() == 1){ + line.get(0).setSize(line.get(0).width()+extraWidth, BUTTON_HEIGHT); + line.get(0).setPos( 0 , y ); + return; + } + ArrayList lineByWidths = new ArrayList<>(line); + Collections.sort(lineByWidths, widthComparator); + RedButton smallest, middle, largest; + smallest = lineByWidths.get(0); + middle = lineByWidths.get(1); + largest = null; + if (lineByWidths.size() == 3) { + largest = lineByWidths.get(2); + } + + float btnDiff = middle.width() - smallest.width(); + smallest.setSize(smallest.width() + Math.min(btnDiff, extraWidth), BUTTON_HEIGHT); + extraWidth -= btnDiff; + if (extraWidth > 0) { + if (largest == null) { + smallest.setSize(smallest.width() + extraWidth / 2, BUTTON_HEIGHT); + middle.setSize(middle.width() + extraWidth / 2, BUTTON_HEIGHT); + } else { + btnDiff = largest.width() - smallest.width(); + smallest.setSize(smallest.width() + Math.min(btnDiff, extraWidth/2), BUTTON_HEIGHT); + middle.setSize(middle.width() + Math.min(btnDiff, extraWidth/2), BUTTON_HEIGHT); + extraWidth -= btnDiff*2; + if (extraWidth > 0){ + smallest.setSize(smallest.width() + extraWidth / 3, BUTTON_HEIGHT); + middle.setSize(middle.width() + extraWidth / 3, BUTTON_HEIGHT); + largest.setSize(largest.width() + extraWidth / 3, BUTTON_HEIGHT); + } + } + } + + float x = 0; + for (RedButton btn : line){ + btn.setPos( x , y ); + x += btn.width()+1; + } + } + + private static Comparator widthComparator = new Comparator() { + @Override + public int compare(RedButton lhs, RedButton rhs) { + if (lhs.width() < rhs.width()){ + return -1; + } else if (lhs.width() == rhs.width()){ + return 0; + } else { + return 1; + } + } + }; +} diff --git a/java/com/hmdzl/spspd/windows/WndJournal.java b/java/com/hmdzl/spspd/windows/WndJournal.java new file mode 100644 index 00000000..07027061 --- /dev/null +++ b/java/com/hmdzl/spspd/windows/WndJournal.java @@ -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 + */ +package com.hmdzl.spspd.windows; + +import java.util.Collections; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.Journal; +import com.hmdzl.spspd.ShatteredPixelDungeon; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.PixelScene; +import com.hmdzl.spspd.ui.Icons; +import com.hmdzl.spspd.ui.ScrollPane; +import com.hmdzl.spspd.ui.Window; +import com.watabou.noosa.BitmapText; +import com.watabou.noosa.Image; +import com.watabou.noosa.ui.Component; +import com.watabou.noosa.RenderedText; + +public class WndJournal extends Window { + + private static final int WIDTH = 112; + private static final int HEIGHT_P = 160; + private static final int HEIGHT_L = 144; + + private static final int ITEM_HEIGHT = 18; + + private static final String TXT_TITLE = "Journal"; + + private RenderedText txtTitle; + private ScrollPane list; + + public WndJournal() { + + super(); + resize(WIDTH, ShatteredPixelDungeon.landscape() ? HEIGHT_L : HEIGHT_P); + + txtTitle = PixelScene.renderText(Messages.get(this, "title"), 9); + txtTitle.hardlight(Window.TITLE_COLOR); + //txtTitle.measure(); + txtTitle.x = PixelScene.align(PixelScene.uiCamera, + (WIDTH - txtTitle.width()) / 2); + add(txtTitle); + + Component content = new Component(); + + Collections.sort(Journal.records); + + float pos = 0; + for (Journal.Record rec : Journal.records) { + ListItem item = new ListItem(rec.feature, rec.depth); + item.setRect(0, pos, WIDTH, ITEM_HEIGHT); + content.add(item); + + pos += item.height(); + } + + content.setSize(WIDTH, pos); + + list = new ScrollPane(content); + add(list); + + list.setRect(0, txtTitle.height(), WIDTH, height - txtTitle.height()); + } + + private static class ListItem extends Component { + + private RenderedText feature; + private BitmapText depth; + + private Image icon; + + public ListItem(Journal.Feature f, int d) { + super(); + + feature.text(f.desc()); + //feature.measure(); + + depth.text(Integer.toString(d)); + depth.measure(); + + if (d == Dungeon.depth) { + feature.hardlight(TITLE_COLOR); + depth.hardlight(TITLE_COLOR); + } + } + + @Override + protected void createChildren() { + feature = PixelScene.renderText(9); + add(feature); + + depth = new BitmapText(PixelScene.font1x); + add(depth); + + icon = Icons.get(Icons.DEPTH); + add(icon); + } + + @Override + protected void layout() { + + icon.x = width - icon.width; + + depth.x = icon.x - 1 - depth.width(); + depth.y = PixelScene.align(y + (height - depth.height()) / 2); + + icon.y = depth.y - 1; + + feature.y = PixelScene.align(depth.y + depth.baseLine() + - feature.baseLine()); + } + } +} diff --git a/java/com/hmdzl/spspd/windows/WndLangs.java b/java/com/hmdzl/spspd/windows/WndLangs.java new file mode 100644 index 00000000..0336e151 --- /dev/null +++ b/java/com/hmdzl/spspd/windows/WndLangs.java @@ -0,0 +1,205 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2015 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.windows; + +import com.hmdzl.spspd.SPSSettings; +import com.hmdzl.spspd.ShatteredPixelDungeon; +import com.hmdzl.spspd.messages.Languages; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.PixelScene; +import com.hmdzl.spspd.scenes.TitleScene; +import com.hmdzl.spspd.ui.RedButton; +import com.hmdzl.spspd.ui.RenderedTextMultiline; +import com.hmdzl.spspd.ui.Window; +import com.watabou.noosa.ColorBlock; +import com.watabou.noosa.Game; +import com.watabou.noosa.RenderedText; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Locale; + +public class WndLangs extends Window { + + private int WIDTH_P = 120; + private int WIDTH_L = 171; + + private int MIN_HEIGHT = 110; + + private int BTN_WIDTH = 50; + private int BTN_HEIGHT = 14; + + public WndLangs(){ + + super(); + + final ArrayList langs = new ArrayList<>(Arrays.asList(Languages.values())); + + Languages nativeLang = Languages.matchLocale(Locale.getDefault()); + langs.remove(nativeLang); + //move the native language to the top. + langs.add(0, nativeLang); + + final Languages currLang = Messages.lang(); + + //language buttons layout + int y = 0; + for (int i = 0; i < langs.size(); i++){ + final int langIndex = i; + RedButton btn = new RedButton(Messages.titleCase(langs.get(i).nativeName())){ + @Override + protected void onClick() { + super.onClick(); + Messages.setup(langs.get(langIndex)); + ShatteredPixelDungeon.switchNoFade(TitleScene.class, new Game.SceneChangeCallback() { + @Override + public void beforeCreate() { + SPSSettings.language(langs.get(langIndex)); + RenderedText.clearCache(); + } + @Override + public void afterCreate() { + Game.scene().add(new WndLangs()); + } + }); + } + }; + if (currLang == langs.get(i)){ + btn.textColor(TITLE_COLOR); + } else { + switch (langs.get(i).status()) { + case INCOMPLETE: + btn.textColor(0x999999); + break; + case UNREVIEWED: + btn.textColor(0xCCCCCC); + break; + } + } + btn.setSize(BTN_WIDTH, BTN_HEIGHT); + if (ShatteredPixelDungeon.landscape() && i % 2 == 1){ + btn.setPos(BTN_WIDTH+1, y-15); + } else { + btn.setPos(0, y); + y += BTN_HEIGHT + 1; + } + + add(btn); + } + y = Math.max(MIN_HEIGHT, y+1); + resize(ShatteredPixelDungeon.landscape() ? WIDTH_L : WIDTH_P, y); + + int textLeft = width - 65; + int textWidth = width - textLeft; + + ColorBlock separator = new ColorBlock(1, y, 0xFF000000); + separator.x = textLeft - 2.5f; + add(separator); + + //language info layout. + RenderedText title = PixelScene.renderText( Messages.titleCase(currLang.nativeName()) , 9 ); + title.x = textLeft + (textWidth - title.width())/2f; + title.y = 0; + title.hardlight(TITLE_COLOR); + PixelScene.align(title); + add(title); + + if (currLang == Languages.ENGLISH){ + + RenderedTextMultiline info = PixelScene.renderMultiline(6); + info.text("This is the source language, written by the developer.", width - textLeft); + info.setPos(textLeft, title.height() + 2); + add(info); + + } else { + + RenderedTextMultiline info = PixelScene.renderMultiline(6); + switch (currLang.status()) { + case REVIEWED: + info.text(Messages.get(this, "completed"), width - textLeft); + break; + case UNREVIEWED: + info.text(Messages.get(this, "unreviewed"), width - textLeft); + break; + case INCOMPLETE: + info.text(Messages.get(this, "unfinished"), width - textLeft); + break; + } + info.setPos(textLeft, title.height() + 2); + add(info); + + RedButton creditsBtn = new RedButton(Messages.titleCase(Messages.get(this, "credits"))){ + @Override + protected void onClick() { + super.onClick(); + String creds = ""; + String[] reviewers = currLang.reviewers(); + String[] translators = currLang.translators(); + if (reviewers.length > 0){ + creds += "_" + Messages.titleCase(Messages.get(WndLangs.class, "reviewers")) + "_\n"; + for (String reviewer : reviewers){ + creds += "-" + reviewer + "\n"; + } + creds += "\n"; + } + + if (reviewers.length > 0 || translators.length > 0){ + creds += "_" + Messages.titleCase(Messages.get(WndLangs.class, "translators")) + "_"; + //reviewers are also translators + for (String reviewer : reviewers){ + creds += "\n-" + reviewer; + } + for (String translator : translators){ + creds += "\n-" + translator; + } + } + + Window credits = new Window(); + + RenderedTextMultiline title = PixelScene.renderMultiline(9); + title.text(Messages.titleCase(Messages.get(WndLangs.class, "credits")) , 65); + title.hardlight(SHPX_COLOR); + title.setPos((65 - title.width())/2, 0); + credits.add(title); + + RenderedTextMultiline text = PixelScene.renderMultiline(6); + text.text(creds, 65); + text.setPos(0, title.bottom() + 2); + credits.add(text); + + credits.resize(65, (int)text.bottom()); + parent.add(credits); + } + }; + creditsBtn.setSize(creditsBtn.reqWidth() + 2, 16); + creditsBtn.setPos(textLeft + (textWidth - creditsBtn.width()) / 2f, y - 18); + add(creditsBtn); + + RenderedTextMultiline transifex_text = PixelScene.renderMultiline(6); + transifex_text.text(Messages.get(this, "transifex"), width - textLeft); + transifex_text.setPos(textLeft, creditsBtn.top() - 2 - transifex_text.height()); + add(transifex_text); + + } + + } + +} diff --git a/java/com/hmdzl/spspd/windows/WndList.java b/java/com/hmdzl/spspd/windows/WndList.java new file mode 100644 index 00000000..71387647 --- /dev/null +++ b/java/com/hmdzl/spspd/windows/WndList.java @@ -0,0 +1,71 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2014 Oleg Dolya + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.windows; + +import com.hmdzl.spspd.scenes.PixelScene; +import com.hmdzl.spspd.ui.Window; +import com.watabou.noosa.RenderedText; +import com.watabou.noosa.BitmapTextMultiline; + +public class WndList extends Window { + + private static final int WIDTH = 120; + private static final int MARGIN = 4; + private static final int GAP = 4; + + //private static final String DOT = "\u007F"; + + public WndList(String[] items) { + + super(); + + float pos = MARGIN; + float dotWidth = 0; + float maxWidth = 0; + + for (int i = 0; i < items.length; i++) { + + if (i > 0) { + pos += GAP; + } + + RenderedText dot = PixelScene.renderText( "-", 6 ); + dot.x = MARGIN; + dot.y = pos; + if (dotWidth == 0) { + dotWidth = dot.width(); + } + add( dot ); + + BitmapTextMultiline item = PixelScene.createMultiline(items[i], 6); + item.x = dot.x + dotWidth; + item.y = pos; + item.maxWidth = (int) (WIDTH - MARGIN * 2 - dotWidth); + item.measure(); + add(item); + + pos += item.height(); + float w = item.width(); + if (w > maxWidth) { + maxWidth = w; + } + } + + resize((int) (maxWidth + dotWidth + MARGIN * 2), (int) (pos + MARGIN)); + } +} diff --git a/java/com/hmdzl/spspd/windows/WndMessage.java b/java/com/hmdzl/spspd/windows/WndMessage.java new file mode 100644 index 00000000..e602ca5c --- /dev/null +++ b/java/com/hmdzl/spspd/windows/WndMessage.java @@ -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 + */ +package com.hmdzl.spspd.windows; + +import com.hmdzl.spspd.ShatteredPixelDungeon; +import com.hmdzl.spspd.scenes.PixelScene; +import com.hmdzl.spspd.ui.RenderedTextMultiline; +import com.hmdzl.spspd.ui.Window; + +public class WndMessage extends Window { + + private static final int WIDTH_P = 120; + private static final int WIDTH_L = 144; + private static final int MARGIN = 4; + + public WndMessage( String text ) { + + super(); + + RenderedTextMultiline info = PixelScene.renderMultiline( text, 6 ); + info.maxWidth((ShatteredPixelDungeon.landscape() ? WIDTH_L : WIDTH_P) - MARGIN * 2); + info.setPos(MARGIN, MARGIN); + add( info ); + + resize( + (int)info.width() + MARGIN * 2, + (int)info.height() + MARGIN * 2 ); + } +} diff --git a/java/com/hmdzl/spspd/windows/WndMix.java b/java/com/hmdzl/spspd/windows/WndMix.java new file mode 100644 index 00000000..0d631556 --- /dev/null +++ b/java/com/hmdzl/spspd/windows/WndMix.java @@ -0,0 +1,295 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2018 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ + +package com.hmdzl.spspd.windows; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.effects.Speck; +import com.hmdzl.spspd.items.CurseBlood; +import com.hmdzl.spspd.items.Generator; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.rings.Ring; +import com.hmdzl.spspd.items.food.completefood.Garbage; +import com.hmdzl.spspd.items.wands.Wand; +import com.hmdzl.spspd.items.wands.WandOfMagicMissile; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.scenes.PixelScene; +import com.hmdzl.spspd.sprites.HeroSprite; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.sprites.ItemSpriteSheet; +import com.hmdzl.spspd.ui.Icons; +import com.hmdzl.spspd.ui.ItemSlot; +import com.hmdzl.spspd.ui.RedButton; +import com.hmdzl.spspd.ui.RenderedTextMultiline; +import com.hmdzl.spspd.ui.Window; +import com.watabou.noosa.ColorBlock; +import com.watabou.noosa.Image; +import com.watabou.noosa.audio.Sample; +import com.watabou.noosa.particles.Emitter; + +import java.util.ArrayList; + +import static com.hmdzl.spspd.Dungeon.hero; + +public class WndMix extends Window { + + private WndBlacksmith.ItemButton[] inputs = new WndBlacksmith.ItemButton[3]; + private ItemSlot output; + + private Emitter smokeEmitter; + private Emitter bubbleEmitter; + + private RedButton btnCombine; + + private static final int WIDTH_P = 116; + private static final int WIDTH_L = 160; + + private static final int BTN_SIZE = 28; + + public WndMix(){ + + int w = WIDTH_P; + + int h = 0; + + + WandOfMagicMissile key = new WandOfMagicMissile(); + IconTitle titlebar = new IconTitle(); + titlebar.icon(new ItemSprite(key.image(), null)); + titlebar.label( Messages.get(this, "title") ); + titlebar.setRect( 0, 0, w, 0 ); + add( titlebar ); + + h += titlebar.height() + 2; + + RenderedTextMultiline desc = PixelScene.renderMultiline(6); + desc.text( Messages.get(this, "text") ); + desc.setPos(0, h); + desc.maxWidth(w); + add(desc); + + h += desc.height() + 6; + + for (int i = 0; i < (inputs.length); i++) { + inputs[i] = new WndBlacksmith.ItemButton(){ + @Override + protected void onClick() { + super.onClick(); + if (item != null){ + Dungeon.gold-=1000; + if (!item.collect()){ + Dungeon.level.drop(item, hero.pos); + } + item = null; + slot.item(new WndBag.Placeholder(ItemSpriteSheet.SOMETHING)); + } + GameScene.selectItem( itemSelector, WndBag.Mode.CANBEMIX, Messages.get(WndAlchemy.class, "select") ); + } + }; + inputs[i].setRect(15, h, BTN_SIZE, BTN_SIZE); + add(inputs[i]); + h += BTN_SIZE + 2; + } + + Image arrow = Icons.get(Icons.RESUME); + arrow.hardlight(0, 0, 0); + arrow.x = (w - arrow.width)/2f; + arrow.y = inputs[1].top() + (inputs[1].height() - arrow.height)/2f; + PixelScene.align(arrow); + add(arrow); + + output = new ItemSlot(){ + @Override + protected void onClick() { + super.onClick(); + /*if (visible){ + GameScene.show(new WndInfoItem); + }*/ + } + }; + output.setRect(w - BTN_SIZE - 15, inputs[1].top(), BTN_SIZE, BTN_SIZE); + + ColorBlock outputBG = new ColorBlock(output.width(), output.height(), 0x9991938C); + outputBG.x = output.left(); + outputBG.y = output.top(); + add(outputBG); + + add(output); + output.visible = false; + + bubbleEmitter = new Emitter(); + smokeEmitter = new Emitter(); + bubbleEmitter.pos(outputBG.x + (BTN_SIZE-16)/2f, outputBG.y + (BTN_SIZE-16)/2f, 16, 16); + smokeEmitter.pos(bubbleEmitter.x, bubbleEmitter.y, bubbleEmitter.width, bubbleEmitter.height); + bubbleEmitter.autoKill = false; + smokeEmitter.autoKill = false; + add(bubbleEmitter); + add(smokeEmitter); + + h += 4; + + float btnWidth = (w-14)/2f; + + btnCombine = new RedButton(Messages.get(this, "combine")){ + @Override + protected void onClick() { + super.onClick(); + combine(); + } + }; + btnCombine.setRect(5, h, btnWidth, 18); + PixelScene.align(btnCombine); + btnCombine.enable(false); + add(btnCombine); + + RedButton btnCancel = new RedButton(Messages.get(this, "cancel")){ + @Override + protected void onClick() { + super.onClick(); + onBackPressed(); + } + }; + btnCancel.setRect(w - 5 - btnWidth, h, btnWidth, 18); + PixelScene.align(btnCancel); + add(btnCancel); + + h += btnCancel.height(); + + resize(w, h); + } + + protected WndBag.Listener itemSelector = new WndBag.Listener() { + @Override + public void onSelect( Item item ) { + if (item != null) { + for (int i = 0; i < (inputs.length); i++) { + if (inputs[i].item == null){ + //inputs[i].item(hero.belongings.misc1 = null); + //inputs[i].item(hero.belongings.misc2 = null); + //inputs[i].item(hero.belongings.misc3 = null); + inputs[i].item(item.detach(hero.belongings.backpack)); + break; + } + } + } + updateState(); + } + }; + + private ArrayList filterInput(Class itemClass){ + ArrayList filtered = new ArrayList<>(); + for (int i = 0; i < (inputs.length); i++){ + Item item = inputs[i].item; + if (item != null && itemClass.isInstance(item)){ + filtered.add((T)item); + } + } + return filtered; + } + + private void updateState(){ + //potion creation + if(filterInput(Item.class).size() > 0 && Dungeon.gold > 1000){ + output.item(new WndBag.Placeholder(ItemSpriteSheet.SOMETHING)); + output.visible = true; + btnCombine.enable(true); + } else { + btnCombine.enable(false); + output.visible = false; + } + } + + private void combine(){ + ArrayList rings = filterInput(Ring.class); + ArrayList wands = filterInput(Wand.class); + Item result = null; + + if (rings.size() == 3){ + + result = Generator.random( Generator.Category.ARTIFACT ); + + } else if (wands.size() == 3){ + + result = Generator.random( Generator.Category.ARTIFACT ); + + } else if (rings.size() == 2 && wands.size() == 1){ + + result = Generator.random( Generator.Category.EGGS ); + + } else if (rings.size() == 1 && wands.size() == 2){ + + result = Generator.random( Generator.Category.EGGS ); + + } else if (rings.size() == 1 && wands.size() == 1){ + + result = Generator.random( Generator.Category.SUMMONED); + + } else if (rings.size() == 2){ + + result = Generator.random( Generator.Category.RING); + + } else if (rings.size() == 1){ + + result = Generator.random( Generator.Category.WAND); + + } else if (wands.size() == 2){ + + result = Generator.random( Generator.Category.WAND ); + + } else if (wands.size() == 1){ + + result = Generator.random( Generator.Category.RING ); + + } else result = new Garbage(); + + if (result != null){ + bubbleEmitter.start(Speck.factory( Speck.BUBBLE ), 0.2f, 10 ); + smokeEmitter.burst(Speck.factory( Speck.WOOL ), 10 ); + Sample.INSTANCE.play( Assets.SND_PUFF ); + + output.item(result); + if (!result.collect()){ + Dungeon.level.drop(result, hero.pos); + } + for (int i = 0; i < (inputs.length ); i++){ + inputs[i].slot.item(new WndBag.Placeholder(ItemSpriteSheet.SOMETHING)); + inputs[i].item = null; + } + + btnCombine.enable(false); + } + + } + + @Override + public void onBackPressed() { + for (int i = 0; i < (inputs.length ); i++) { + if (inputs[i].item != null){ + if (!inputs[i].item.collect()){ + Dungeon.level.drop(inputs[i].item, hero.pos); + } + } + } + super.onBackPressed(); + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/windows/WndONS.java b/java/com/hmdzl/spspd/windows/WndONS.java new file mode 100644 index 00000000..716bccb2 --- /dev/null +++ b/java/com/hmdzl/spspd/windows/WndONS.java @@ -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 + */ +package com.hmdzl.spspd.windows; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.mobs.npcs.OldNewStwist; +import com.hmdzl.spspd.items.quest.GnollClothes; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.PixelScene; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.ui.RedButton; +import com.hmdzl.spspd.ui.RenderedTextMultiline; +import com.hmdzl.spspd.ui.Window; + + +public class WndONS extends Window { + + private static final int WIDTH = 120; + private static final int BTN_HEIGHT = 20; + private static final int GAP = 2; + + public WndONS(final OldNewStwist ONS, final GnollClothes clothes) { + + super(); + + IconTitle titlebar = new IconTitle(); + titlebar.icon(new ItemSprite(clothes.image(), null)); + titlebar.label(Messages.titleCase(clothes.name())); + titlebar.setRect(0, 0, WIDTH, 0); + add(titlebar); + + RenderedTextMultiline message = PixelScene + .renderMultiline(Messages.get(this, "message"), 6); + message.maxWidth(WIDTH); + message.setPos(0, titlebar.bottom() + GAP); + add(message); + + RedButton btnReward = new RedButton(Messages.get(this, "give")) { + @Override + protected void onClick() { + Dungeon.gnollmission = true; + clothes.detach(Dungeon.hero.belongings.backpack); + hide(); + } + }; + btnReward.setRect(0, message.top() + message.height() + GAP, WIDTH, + BTN_HEIGHT); + add(btnReward); + + resize(WIDTH, (int) btnReward.bottom()); + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/windows/WndOptions.java b/java/com/hmdzl/spspd/windows/WndOptions.java new file mode 100644 index 00000000..40b8f9ca --- /dev/null +++ b/java/com/hmdzl/spspd/windows/WndOptions.java @@ -0,0 +1,71 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2014 Oleg Dolya + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.windows; + +import com.hmdzl.spspd.ShatteredPixelDungeon; +import com.hmdzl.spspd.scenes.PixelScene; +import com.hmdzl.spspd.ui.RedButton; +import com.hmdzl.spspd.ui.Window; +import com.hmdzl.spspd.ui.RenderedTextMultiline; + +public class WndOptions extends Window { + + private static final int MARGIN = 2; + private static final int BUTTON_HEIGHT = 20; + + private static final int WIDTH_P = 120; + private static final int WIDTH_L = 144; + + public WndOptions( String title, String message, String... options ) { + super(); + + int width = ShatteredPixelDungeon.landscape() ? WIDTH_L : WIDTH_P; + + RenderedTextMultiline tfTitle = PixelScene.renderMultiline( title, 9 ); + tfTitle.hardlight( TITLE_COLOR ); + tfTitle.setPos(MARGIN, MARGIN); + tfTitle.maxWidth(width - MARGIN * 2); + add( tfTitle ); + + RenderedTextMultiline tfMesage = PixelScene.renderMultiline( 6 ); + tfMesage.text(message, width - MARGIN * 2); + tfMesage.setPos( MARGIN, tfTitle.top() + tfTitle.height() + MARGIN ); + add( tfMesage ); + + float pos = tfMesage.bottom() + MARGIN; + + for (int i=0; i < options.length; i++) { + final int index = i; + RedButton btn = new RedButton( options[i] ) { + @Override + protected void onClick() { + hide(); + onSelect( index ); + } + }; + btn.setRect( MARGIN, pos, width - MARGIN * 2, BUTTON_HEIGHT ); + add( btn ); + + pos += BUTTON_HEIGHT + MARGIN; + } + + resize( width, (int)pos ); + } + + protected void onSelect( int index ) {} +} diff --git a/java/com/hmdzl/spspd/windows/WndOtiluke.java b/java/com/hmdzl/spspd/windows/WndOtiluke.java new file mode 100644 index 00000000..83132a24 --- /dev/null +++ b/java/com/hmdzl/spspd/windows/WndOtiluke.java @@ -0,0 +1,140 @@ +/* + * 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 + */ +package com.hmdzl.spspd.windows; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.items.DolyaSlate; +import com.hmdzl.spspd.items.artifacts.TimekeepersHourglass; +import com.hmdzl.spspd.scenes.InterlevelScene; +import com.hmdzl.spspd.scenes.PixelScene; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.ui.RedButton; +import com.hmdzl.spspd.ui.Window; + +import com.watabou.noosa.Game; +import com.hmdzl.spspd.ui.RenderedTextMultiline; + +public class WndOtiluke extends Window { + + + + private static final String TXT_FARAWELL = Messages.get(WndOtiluke.class,"title"); + public static final float TIME_TO_USE = 1; + + + private static final int PAGES = 10; + private static final int WIDTH = 120; + private static final int BTN_HEIGHT = 20; + private static final float GAP = 2; + + public WndOtiluke(final boolean[] rooms, final DolyaSlate item) { + + super(); + + String[] roomNames = new String[PAGES]; + roomNames[0] = Messages.get(this,"room1"); + roomNames[1] = Messages.get(this,"room2"); + roomNames[2] = Messages.get(this,"room3"); + roomNames[3] = Messages.get(this,"room4"); + roomNames[4] = Messages.get(this,"room5"); + roomNames[5] = Messages.get(this,"room6"); + roomNames[6] = Messages.get(this,"room7"); + roomNames[7] = Messages.get(this,"room8"); + + IconTitle titlebar = new IconTitle(); + titlebar.icon(new ItemSprite(item.image(), null)); + titlebar.label(Messages.titleCase(item.name())); + titlebar.setRect(0, 0, WIDTH, 0); + add(titlebar); + + RenderedTextMultiline message = PixelScene.renderMultiline(TXT_FARAWELL, 6); + message.maxWidth(WIDTH); + message.setPos(0,titlebar.bottom() + GAP); + add(message); + + //add each button + //after n*BTN_HEIGHT+GAP + //add port function + + if (rooms[0]){ + RedButton btn1 = new RedButton(roomNames[0]) { + @Override + protected void onClick() { + item.returnDepth = Dungeon.depth; + item.returnPos = Dungeon.hero.pos; + port(0, item.firsts[0]); + item.firsts[0]=false; + if (item.charge> 500) {item.charge-=500;} + } + }; + btn1.setRect(0, message.top() + message.height() + GAP, WIDTH, BTN_HEIGHT); + add(btn1); + resize(WIDTH, (int) btn1.bottom()); + } + + int buttons=1; + + for (int i=1; i + */ +package com.hmdzl.spspd.windows; + +import com.hmdzl.spspd.items.Palantir; +import com.hmdzl.spspd.scenes.PixelScene; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.RedButton; +import com.hmdzl.spspd.ui.RenderedTextMultiline; +import com.hmdzl.spspd.ui.Window; + + +public class WndOtilukeMessage extends Window { + + private static final String TXT_MESSAGE = "The power of the Palantir has caused Zot to lose his mind. " + +"I have managed to trap him inside and set guardians. " + +"I will now sacrifice myself to create a powerful stone golem that will protect the Palantir, Zot's prison."; + private static final String TXT_REWARD = "Okay"; + + private static final int WIDTH = 120; + private static final int BTN_HEIGHT = 20; + private static final int GAP = 2; + + public WndOtilukeMessage() { + + super(); + + Palantir palantir = new Palantir(); + + IconTitle titlebar = new IconTitle(); + titlebar.icon(new ItemSprite(palantir.image(), null)); + titlebar.label(Messages.titleCase(palantir.name())); + titlebar.setRect(0, 0, WIDTH, 0); + add(titlebar); + + RenderedTextMultiline message = PixelScene + .renderMultiline(TXT_MESSAGE, 6); + message.maxWidth(WIDTH); + message.setPos(0,titlebar.bottom() + GAP); + add(message); + + RedButton btnReward = new RedButton(TXT_REWARD) { + @Override + protected void onClick() { + hide(); + } + }; + btnReward.setRect(0, message.top() + message.height() + GAP, WIDTH, + BTN_HEIGHT); + add(btnReward); + + resize(WIDTH, (int) btnReward.bottom()); + } + + +} diff --git a/java/com/hmdzl/spspd/windows/WndQuest.java b/java/com/hmdzl/spspd/windows/WndQuest.java new file mode 100644 index 00000000..e78e3989 --- /dev/null +++ b/java/com/hmdzl/spspd/windows/WndQuest.java @@ -0,0 +1,29 @@ +/* + * 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 + */ +package com.hmdzl.spspd.windows; + +import com.hmdzl.spspd.actors.mobs.npcs.NPC; +import com.hmdzl.spspd.messages.Messages; + + +public class WndQuest extends WndTitledMessage { + + public WndQuest(NPC questgiver, String text) { + super(questgiver.sprite(),Messages.titleCase( questgiver.name ), text ); + } +} diff --git a/java/com/hmdzl/spspd/windows/WndRanking.java b/java/com/hmdzl/spspd/windows/WndRanking.java new file mode 100644 index 00000000..ef3b94d5 --- /dev/null +++ b/java/com/hmdzl/spspd/windows/WndRanking.java @@ -0,0 +1,423 @@ +/* + * 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 + */ +package com.hmdzl.spspd.windows; + +import java.util.Locale; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Badges; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.Statistics; +import com.hmdzl.spspd.actors.hero.Belongings; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.scenes.PixelScene; +import com.hmdzl.spspd.sprites.HeroSprite; +import com.hmdzl.spspd.ui.BadgesList; +import com.hmdzl.spspd.ui.Icons; +import com.hmdzl.spspd.ui.ItemSlot; +import com.hmdzl.spspd.ui.RedButton; +import com.hmdzl.spspd.ui.ScrollPane; +import com.hmdzl.spspd.ui.Window; +import com.hmdzl.spspd.messages.Messages; + +import com.watabou.noosa.ColorBlock; +import com.watabou.noosa.Game; +import com.watabou.noosa.Group; +import com.watabou.noosa.Image; +import com.watabou.noosa.RenderedText; +import com.watabou.noosa.audio.Sample; +import com.watabou.noosa.ui.Button; + +public class WndRanking extends WndTabbed { + + private static final String TXT_ERROR = "Unable to load additional information"; + + private static final String TXT_STATS = "Stats"; + private static final String TXT_ITEMS = "Items"; + private static final String TXT_BADGES = "Badges"; + + private static final int WIDTH = 115; + private static final int HEIGHT = 180; + + private static final int TAB_WIDTH = 40; + + private Thread thread; + private String error = null; + + private Image busy; + + public WndRanking(final String gameFile) { + + super(); + resize(WIDTH, HEIGHT); + + thread = new Thread() { + @Override + public void run() { + try { + Badges.loadGlobal(); + Dungeon.loadGame(gameFile); + } catch (Exception e) { + error = Messages.get(WndRanking.class, "error"); + } + } + }; + thread.start(); + + busy = Icons.BUSY.get(); + busy.origin.set(busy.width / 2, busy.height / 2); + busy.angularSpeed = 720; + busy.x = (WIDTH - busy.width) / 2; + busy.y = (HEIGHT - busy.height) / 2; + add(busy); + } + + @Override + public void update() { + super.update(); + + if (thread != null && !thread.isAlive()) { + thread = null; + if (error == null) { + remove(busy); + createControls(); + } else { + hide(); + Game.scene().add(new WndError(error)); + } + } + } + + private void createControls() { + + String[] labels = + {Messages.get(this, "stats"), Messages.get(this, "items"), Messages.get(this, "badges")}; + Group[] pages = + { new StatsTab(), new ItemsTab(), new BadgesTab() }; + + for (int i = 0; i < pages.length; i++) { + + add(pages[i]); + + Tab tab = new RankingTab(labels[i], pages[i]); + add(tab); + } + + layoutTabs(); + + select(0); + } + + private class RankingTab extends LabeledTab { + + private Group page; + + public RankingTab(String label, Group page) { + super(label); + this.page = page; + } + + @Override + protected void select(boolean value) { + super.select(value); + if (page != null) { + page.visible = page.active = selected; + } + } + } + + private class StatsTab extends Group { + + private static final int GAP = 4; + + private static final String TXT_TITLE = "Level %d %s"; + + private static final String TXT_CHALLENGES = "Challenges"; + + private static final String TXT_HEALTH = "Health"; + private static final String TXT_STR = "Strength"; + //private static final String TXT_TEST = "Playtest Activated"; + + private static final String TXT_DURATION = "Game Duration"; + + private static final String TXT_DEPTH = "Maximum Depth"; + private static final String TXT_ENEMIES = "Mobs Killed"; + private static final String TXT_GOLD = "Gold Collected"; + + private static final String TXT_FOOD = "Food Eaten"; + private static final String TXT_ALCHEMY = "Potions Cooked"; + private static final String TXT_ANKHS = "Ankhs Used"; + private static final String TXT_WATERS = "Dew Waters"; + private static final String TXT_SHADOW = "Shadow Yogs Killed"; + + public StatsTab() { + super(); + + String heroClass = Dungeon.hero.className(); + + IconTitle title = new IconTitle(); + title.icon(HeroSprite.avatar(Dungeon.hero.heroClass, + Dungeon.hero.useskin())); + title.label( Messages.get(this, "title", Dungeon.hero.lvl, heroClass ).toUpperCase( Locale.ENGLISH ) ); + title.color(Window.SHPX_COLOR); + title.setRect(0, 0, WIDTH, 0); + add(title); + + float pos = title.bottom(); + + if (Dungeon.challenges > 0) { + RedButton btnCatalogus = new RedButton( Messages.get(this, "challenges")) { + @Override + protected void onClick() { + Game.scene().add( + new WndChallenges(Dungeon.challenges, false)); + } + }; + btnCatalogus.setRect(0, pos + GAP, btnCatalogus.reqWidth() + 2, + btnCatalogus.reqHeight() + 2); + add(btnCatalogus); + + pos = btnCatalogus.bottom(); + } + + pos += GAP + GAP; + + pos = statSlot(this, Messages.get(this, "str"), Integer.toString(Dungeon.hero.STR), + pos); + pos = statSlot(this, Messages.get(this, "health"), Integer.toString(Dungeon.hero.HT), + pos); + + pos += GAP; + + pos = statSlot(this, (Messages.get(this, "duration")),Integer.toString((int) Statistics.duration), pos); + + pos += GAP; + + pos = statSlot(this, Messages.get(this, "depth"), + Integer.toString(Statistics.deepestFloor), pos); + pos = statSlot(this, Messages.get(this, "enemies"), + Integer.toString(Statistics.enemiesSlain), pos); + pos = statSlot(this, Messages.get(this, "gold"), + Integer.toString(Statistics.goldCollected), pos); + + pos += GAP; + + pos = statSlot(this, Messages.get(this, "food"), + Integer.toString(Statistics.foodEaten), pos); + pos = statSlot(this, Messages.get(this, "alchemy"), + Integer.toString(Statistics.potionsCooked), pos); + pos = statSlot(this, Messages.get(this, "ankhs"), + Integer.toString(Statistics.ankhsUsed), pos); + + pos += GAP; + pos = statSlot(this, Messages.get(this, "water"), + Integer.toString(Statistics.waters), pos); + //pos = statSlot(this, TXT_SHADOW, + //Integer.toString(Statistics.shadowYogsKilled), pos); + } + + private float statSlot(Group parent, String label, String value, + float pos) { + + RenderedText txt = PixelScene.renderText( label, 7 ); + txt.y = pos; + parent.add( txt ); + + txt = PixelScene.renderText( value, 7 ); + txt.x = WIDTH * 0.65f; + txt.y = pos; + PixelScene.align(txt); + parent.add( txt ); + + return pos + GAP + txt.baseLine(); + } + } + + private class ItemsTab extends Group { + + private float pos; + + public ItemsTab() { + super(); + + Belongings stuff = Dungeon.hero.belongings; + if (stuff.weapon != null) { + addItem(stuff.weapon); + } + if (stuff.armor != null) { + addItem(stuff.armor); + } + if (stuff.misc1 != null) { + addItem(stuff.misc1); + } + if (stuff.misc2 != null) { + addItem(stuff.misc2); + } + if (stuff.misc3 != null) { + addItem(stuff.misc3); + } + } + + private void addItem( Item item ) { + ItemButton slot = new ItemButton( item ); + slot.setRect( 0, pos, width, ItemButton.HEIGHT ); + add( slot ); + + pos += slot.height() + 1; + } + } + + private class BadgesTab extends Group { + + public BadgesTab() { + super(); + + camera = WndRanking.this.camera; + + ScrollPane list = new BadgesList(false); + add(list); + + list.setSize(WIDTH, HEIGHT); + } + } + + private class ItemButton extends Button { + + public static final int HEIGHT = 28; + + private Item item; + + private ItemSlot slot; + private ColorBlock bg; + private RenderedText name; + + public ItemButton(Item item) { + + super(); + + this.item = item; + + slot.item(item); + if (item.cursed && item.cursedKnown) { + bg.ra = +0.2f; + bg.ga = -0.1f; + } else if (!item.isIdentified()) { + bg.ra = 0.1f; + bg.ba = 0.1f; + } + } + + @Override + protected void createChildren() { + + bg = new ColorBlock(HEIGHT, HEIGHT, 0xFF4A4D44); + add(bg); + + slot = new ItemSlot(); + add(slot); + + name = PixelScene.renderText("?", 7); + add(name); + + super.createChildren(); + } + + @Override + protected void layout() { + bg.x = x; + bg.y = y; + + slot.setRect(x, y, HEIGHT, HEIGHT); + + name.x = slot.right() + 2; + name.y = y + (height - name.baseLine()) / 2; + + String str = Messages.titleCase( item.name() ); + name.text(str); + if (name.width() > width - name.x) { + do { + str = str.substring(0, str.length() - 1); + name.text(str + "..."); + } while (name.width() > width - name.x); + } + + super.layout(); + } + + @Override + protected void onTouchDown() { + bg.brightness(1.5f); + Sample.INSTANCE.play(Assets.SND_CLICK, 0.7f, 0.7f, 1.2f); + }; + + @Override + protected void onTouchUp() { + bg.brightness(1.0f); + }; + + @Override + protected void onClick() { + Game.scene().add(new WndItem(null, item)); + } + } + + private class QuickSlotButton extends ItemSlot { + + public static final int HEIGHT = 28; + + private Item item; + private ColorBlock bg; + + QuickSlotButton(Item item) { + super(item); + this.item = item; + } + + @Override + protected void createChildren() { + bg = new ColorBlock(HEIGHT, HEIGHT, 0xFF4A4D44); + add(bg); + + super.createChildren(); + } + + @Override + protected void layout() { + bg.x = x; + bg.y = y; + + super.layout(); + } + + @Override + protected void onTouchDown() { + bg.brightness(1.5f); + Sample.INSTANCE.play(Assets.SND_CLICK, 0.7f, 0.7f, 1.2f); + }; + + @Override + protected void onTouchUp() { + bg.brightness(1.0f); + }; + + @Override + protected void onClick() { + Game.scene().add(new WndItem(null, item)); + } + } +} diff --git a/java/com/hmdzl/spspd/windows/WndResurrect.java b/java/com/hmdzl/spspd/windows/WndResurrect.java new file mode 100644 index 00000000..b0fc98b6 --- /dev/null +++ b/java/com/hmdzl/spspd/windows/WndResurrect.java @@ -0,0 +1,99 @@ +/* + * 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 + */ +package com.hmdzl.spspd.windows; + +import com.hmdzl.spspd.Rankings; +import com.hmdzl.spspd.Statistics; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.items.Ankh; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.InterlevelScene; +import com.hmdzl.spspd.scenes.PixelScene; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.ui.RedButton; +import com.hmdzl.spspd.ui.RenderedTextMultiline; +import com.hmdzl.spspd.ui.Window; +import com.watabou.noosa.Game; + +public class WndResurrect extends Window { + + private static final int WIDTH = 120; + private static final int BTN_HEIGHT = 20; + private static final float GAP = 2; + + public static WndResurrect instance; + public static Object causeOfDeath; + + public WndResurrect(final Ankh ankh, Object causeOfDeath) { + + super(); + + instance = this; + WndResurrect.causeOfDeath = causeOfDeath; + + IconTitle titlebar = new IconTitle(); + titlebar.icon(new ItemSprite(ankh.image(), null)); + titlebar.label(ankh.name()); + titlebar.setRect(0, 0, WIDTH, 0); + add(titlebar); + + RenderedTextMultiline message = PixelScene + .renderMultiline(Messages.get(this, "message"), 6 ); + message.maxWidth(WIDTH); + message.setPos(0, titlebar.bottom() + GAP); + add(message); + + RedButton btnYes = new RedButton( Messages.get(this, "yes")) { + @Override + protected void onClick() { + hide(); + + Statistics.ankhsUsed++; + + InterlevelScene.mode = InterlevelScene.Mode.RESURRECT; + Game.switchScene(InterlevelScene.class); + } + }; + btnYes.setRect(0, message.top() + message.height() + GAP, WIDTH, BTN_HEIGHT); + add(btnYes); + + RedButton btnNo = new RedButton( Messages.get(this, "no")) { + @Override + protected void onClick() { + hide(); + + Rankings.INSTANCE.submit(false); + Hero.reallyDie(WndResurrect.causeOfDeath); + } + }; + btnNo.setRect(0, btnYes.bottom() + GAP, WIDTH, BTN_HEIGHT); + add(btnNo); + + resize(WIDTH, (int) btnNo.bottom()); + } + + @Override + public void destroy() { + super.destroy(); + instance = null; + } + + @Override + public void onBackPressed() { + } +} diff --git a/java/com/hmdzl/spspd/windows/WndSadGhost.java b/java/com/hmdzl/spspd/windows/WndSadGhost.java new file mode 100644 index 00000000..280714f7 --- /dev/null +++ b/java/com/hmdzl/spspd/windows/WndSadGhost.java @@ -0,0 +1,106 @@ +/* + * 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 + */ +package com.hmdzl.spspd.windows; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.mobs.npcs.Ghost; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.PixelScene; +import com.hmdzl.spspd.sprites.FetidRatSprite; +import com.hmdzl.spspd.sprites.GnollTricksterSprite; +import com.hmdzl.spspd.sprites.GreatCrabSprite; +import com.hmdzl.spspd.ui.RedButton; +import com.hmdzl.spspd.ui.RenderedTextMultiline; +import com.hmdzl.spspd.ui.Window; + +public class WndSadGhost extends Window { + + private static final int WIDTH = 120; + private static final int BTN_HEIGHT = 20; + private static final float GAP = 2; + + public WndSadGhost(final Ghost ghost, final int type) { + + super(); + + IconTitle titlebar = new IconTitle(); + RenderedTextMultiline message; + switch (type) { + case 1: + default: + titlebar.icon(new FetidRatSprite()); + titlebar.label( Messages.get(this, "rat_title") ); + message = PixelScene.renderMultiline(Messages.get(this, "rat")+Messages.get(this, "give_item"), 6 ); + break; + case 2: + titlebar.icon(new GnollTricksterSprite()); + titlebar.label(Messages.get(this, "gnoll_title")); + message = PixelScene.renderMultiline( Messages.get(this, "gnoll")+Messages.get(this, "give_item"), 6 ); + break; + case 3: + titlebar.icon(new GreatCrabSprite()); + titlebar.label( Messages.get(this, "crab_title")); + message = PixelScene.renderMultiline( Messages.get(this, "crab")+Messages.get(this, "give_item"), 6 ); + break; + + } + + titlebar.setRect(0, 0, WIDTH, 0); + add(titlebar); + + message.maxWidth(WIDTH); + message.setPos(0,titlebar.bottom() + GAP); + add(message); + + RedButton btnWeapon = new RedButton( Messages.get(this, "weapon")) { + @Override + protected void onClick() { + selectReward(ghost, Ghost.Quest.weapon); + } + }; + btnWeapon.setRect(0, message.top() + message.height() + GAP, WIDTH, + BTN_HEIGHT); + add(btnWeapon); + + + RedButton btnArmor = new RedButton( Messages.get(this, "armor")) { + @Override + protected void onClick() { + selectReward(ghost, Ghost.Quest.armor); + } + }; + btnArmor.setRect(0, btnWeapon.bottom() + GAP, WIDTH, BTN_HEIGHT); + add(btnArmor); + + resize(WIDTH, (int) btnArmor.bottom()); + + } + + private void selectReward(Ghost ghost, Item reward) { + + hide(); + + Dungeon.level.drop(reward, ghost.pos).sprite.drop(); + + ghost.yell(Messages.get(this, "farewell")); + ghost.die(null); + + Ghost.Quest.complete(); + } +} diff --git a/java/com/hmdzl/spspd/windows/WndSaidBySun.java b/java/com/hmdzl/spspd/windows/WndSaidBySun.java new file mode 100644 index 00000000..fb891f27 --- /dev/null +++ b/java/com/hmdzl/spspd/windows/WndSaidBySun.java @@ -0,0 +1,78 @@ +/* + * 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 + */ +package com.hmdzl.spspd.windows; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.mobs.npcs.OldNewStwist; +import com.hmdzl.spspd.items.CurseBlood; +import com.hmdzl.spspd.items.keys.IronKey; +import com.hmdzl.spspd.items.quest.GnollClothes; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.PixelScene; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.ui.RedButton; +import com.hmdzl.spspd.ui.RenderedTextMultiline; +import com.hmdzl.spspd.ui.Window; +import com.hmdzl.spspd.utils.GLog; + + +public class WndSaidBySun extends Window { + + private static final int WIDTH = 120; + private static final int BTN_HEIGHT = 20; + private static final int GAP = 2; + + public WndSaidBySun() { + + super(); + + CurseBlood key = new CurseBlood(); + + IconTitle titlebar = new IconTitle(); + titlebar.icon(new ItemSprite(key.image(), null)); + titlebar.label(Messages.titleCase(key.name())); + titlebar.setRect(0, 0, WIDTH, 0); + add(titlebar); + + RenderedTextMultiline message = PixelScene + .renderMultiline(Messages.get(this, "message"), 6); + message.maxWidth(WIDTH); + message.setPos(0, titlebar.bottom() + GAP); + add(message); + + RedButton btnReward = new RedButton(Messages.get(this, "buy")) { + @Override + protected void onClick() { + if (Dungeon.gold > 100000){ + Dungeon.gold-=100000; + CurseBlood cb = new CurseBlood(); + cb.doPickUp(Dungeon.hero); + hide(); + } else { + GLog.w(Messages.get(WndHotel.class,"more_gold")); + hide(); + } + } + }; + btnReward.setRect(0, message.top() + message.height() + GAP, WIDTH, + BTN_HEIGHT); + add(btnReward); + + resize(WIDTH, (int) btnReward.bottom()); + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/windows/WndSettings.java b/java/com/hmdzl/spspd/windows/WndSettings.java new file mode 100644 index 00000000..f6b9d4a6 --- /dev/null +++ b/java/com/hmdzl/spspd/windows/WndSettings.java @@ -0,0 +1,241 @@ +/* + * 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 + */ +package com.hmdzl.spspd.windows; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.SPSSettings; +import com.hmdzl.spspd.ShatteredPixelDungeon; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.PixelScene; +import com.hmdzl.spspd.ui.CheckBox; +import com.hmdzl.spspd.ui.RedButton; +import com.hmdzl.spspd.ui.Toolbar; +import com.hmdzl.spspd.ui.Window; +import com.watabou.noosa.Game; +import com.watabou.noosa.audio.Sample; +import com.watabou.noosa.Camera; + +public class WndSettings extends Window { + + private static final String TXT_ZOOM_IN = "+"; + private static final String TXT_ZOOM_OUT = "-"; + private static final String TXT_ZOOM_DEFAULT = "Default Zoom"; + + private static final String TXT_SCALE_UP = "Scale up UI"; + private static final String TXT_IMMERSIVE = "Immersive mode"; + + private static final String TXT_MUSIC = "Music"; + + private static final String TXT_SOUND = "Sound FX"; + + private static final String TXT_BRIGHTNESS = "Brightness"; + + private static final String TXT_QUICKSLOT = "More QuickSlot"; + + private static final String TXT_SWITCH_PORT = "Switch to portrait"; + private static final String TXT_SWITCH_LAND = "Switch to landscape"; + + private static final String TXT_SYSTEM_FONT = "System Font"; + + private static final int WIDTH = 112; + private static final int BTN_HEIGHT = 20; + private static final int GAP = 2; + + private RedButton btnZoomOut; + private RedButton btnZoomIn; + + public WndSettings(boolean inGame) { + super(); + + CheckBox btnImmersive = null; + + if (inGame) { + int w = BTN_HEIGHT; + + // Zoom out + btnZoomOut = new RedButton(Messages.get(WndSettings.class, "zoom_out")) { + @Override + protected void onClick() { + zoom(Camera.main.zoom - 1); + } + }; + add(btnZoomOut.setRect(0, 0, w, BTN_HEIGHT)); + + // Zoom in + btnZoomIn = new RedButton(Messages.get(WndSettings.class, "zoom_in")) { + @Override + protected void onClick() { + zoom(Camera.main.zoom + 1); + } + }; + add(btnZoomIn.setRect(WIDTH - w, 0, w, BTN_HEIGHT)); + + // Default zoom + add(new RedButton(Messages.get(WndSettings.class, "zoom_default")) { + @Override + protected void onClick() { + zoom(PixelScene.defaultZoom); + } + }.setRect(btnZoomOut.right(), 0, WIDTH - btnZoomIn.width() + - btnZoomOut.width(), BTN_HEIGHT)); + + } else { + + CheckBox btnScaleUp = new CheckBox(Messages.get(WndSettings.class, "scale_up")) { + @Override + protected void onClick() { + super.onClick(); + ShatteredPixelDungeon.scaleUp(checked()); + } + }; + btnScaleUp.setRect(0, 0, WIDTH, BTN_HEIGHT); + btnScaleUp.checked(ShatteredPixelDungeon.scaleUp()); + add(btnScaleUp); + + btnImmersive = new CheckBox(Messages.get(WndSettings.class, "immersive")) { + @Override + protected void onClick() { + super.onClick(); + ShatteredPixelDungeon.immerse(checked()); + } + }; + btnImmersive.setRect(0, btnScaleUp.bottom() + GAP, WIDTH, + BTN_HEIGHT); + btnImmersive.checked(ShatteredPixelDungeon.immersed()); + btnImmersive.enable(android.os.Build.VERSION.SDK_INT >= 19); + add(btnImmersive); + + } + + CheckBox btnMusic = new CheckBox(Messages.get(WndSettings.class, "music")) { + @Override + protected void onClick() { + super.onClick(); + ShatteredPixelDungeon.music(checked()); + } + }; + btnMusic.setRect(0, (btnImmersive != null ? btnImmersive.bottom() + : BTN_HEIGHT) + GAP, WIDTH, BTN_HEIGHT); + btnMusic.checked(ShatteredPixelDungeon.music()); + add(btnMusic); + + CheckBox btnSound = new CheckBox(Messages.get(WndSettings.class, "sound")) { + @Override + protected void onClick() { + super.onClick(); + ShatteredPixelDungeon.soundFx(checked()); + Sample.INSTANCE.play(Assets.SND_CLICK); + } + }; + btnSound.setRect(0, btnMusic.bottom() + GAP, WIDTH, BTN_HEIGHT); + btnSound.checked(ShatteredPixelDungeon.soundFx()); + add(btnSound); + + if (!inGame) { + + RedButton btnOrientation = new RedButton(orientationText()) { + @Override + protected void onClick() { + ShatteredPixelDungeon.landscape(!ShatteredPixelDungeon + .landscape()); + } + }; + btnOrientation.setRect(0, btnSound.bottom() + GAP, WIDTH, + BTN_HEIGHT); + add(btnOrientation); + + resize(WIDTH, (int) btnOrientation.bottom()); + + } else { + + CheckBox btnBrightness = new CheckBox(Messages.get(WndSettings.class, "brightness")) { + @Override + protected void onClick() { + super.onClick(); + ShatteredPixelDungeon.brightness(checked()); + } + }; + btnBrightness + .setRect(0, btnSound.bottom() + GAP, WIDTH, BTN_HEIGHT); + btnBrightness.checked(ShatteredPixelDungeon.brightness()); + add(btnBrightness); + + CheckBox btnQuickSlot = new CheckBox(Messages.get(WndSettings.class, "quickslot")) { + @Override + protected void onClick() { + super.onClick(); + ShatteredPixelDungeon.quickSlots(checked() ? 2 : 1); + Toolbar.QuickSlots = checked() ? 2 : 1; + } + }; + btnQuickSlot.setRect(0, btnBrightness.bottom() + GAP, WIDTH, + BTN_HEIGHT); + btnQuickSlot.checked(ShatteredPixelDungeon.quickSlots() == 2); + add(btnQuickSlot); + + + + resize(WIDTH, (int) btnQuickSlot.bottom()); + + /*CheckBox chkFont = new CheckBox(Messages.get(WndSettings.class, "system_font")){ + @Override + protected void onClick() { + super.onClick(); + ShatteredPixelDungeon.switchNoFade((Class) ShatteredPixelDungeon.scene().getClass(), new Game.SceneChangeCallback() { + @Override + public void beforeCreate() { + SPSSettings.systemFont(checked()); + } + + @Override + public void afterCreate() { + Game.scene().add(new WndSettings(true)); + } + }); + } + }; + chkFont.setRect(0, btnQuickSlot.bottom() + GAP, WIDTH, BTN_HEIGHT); + chkFont.checked(SPSSettings.systemFont()); + add(chkFont); +*/ + //resize(WIDTH, (int) chkFont.bottom()); + + } + } + + + + private void zoom(float value) { + + Camera.main.zoom(value); + ShatteredPixelDungeon.zoom((int) (value - PixelScene.defaultZoom)); + + updateEnabled(); + } + + private void updateEnabled() { + float zoom = Camera.main.zoom; + btnZoomIn.enable(zoom < PixelScene.maxZoom); + btnZoomOut.enable(zoom > PixelScene.minZoom); + } + + private String orientationText() { + return ShatteredPixelDungeon.landscape() ? Messages.get(WndSettings.class, "switch_port") + : Messages.get(WndSettings.class, "switch_land"); + } +} diff --git a/java/com/hmdzl/spspd/windows/WndShower.java b/java/com/hmdzl/spspd/windows/WndShower.java new file mode 100644 index 00000000..8b81313b --- /dev/null +++ b/java/com/hmdzl/spspd/windows/WndShower.java @@ -0,0 +1,78 @@ +/* + * 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 + */ +package com.hmdzl.spspd.windows; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.items.keys.IronKey; +import com.hmdzl.spspd.items.weapon.melee.block.GoblinShield; +import com.hmdzl.spspd.items.weapon.melee.block.SpKnuckles; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.PixelScene; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.ui.RedButton; +import com.hmdzl.spspd.ui.RenderedTextMultiline; +import com.hmdzl.spspd.ui.Window; +import com.hmdzl.spspd.utils.GLog; + + +public class WndShower extends Window { + + private static final int WIDTH = 120; + private static final int BTN_HEIGHT = 20; + private static final int GAP = 2; + + public WndShower() { + + super(); + + SpKnuckles key = new SpKnuckles(); + + + IconTitle titlebar = new IconTitle(); + titlebar.icon(new ItemSprite(key.image(), null)); + titlebar.label(Messages.titleCase(key.name())); + titlebar.setRect(0, 0, WIDTH, 0); + add(titlebar); + + RenderedTextMultiline message = PixelScene + .renderMultiline(Messages.get(this, "message"), 6); + message.maxWidth(WIDTH); + message.setPos(0, titlebar.bottom() + GAP); + add(message); + + RedButton btnReward = new RedButton(Messages.get(this, "buy")) { + @Override + protected void onClick() { + if (Dungeon.gold > 3000){ + Dungeon.gold-=3000; + SpKnuckles gs = new SpKnuckles(); + gs.doPickUp(Dungeon.hero); + hide(); + } else { + GLog.w(Messages.get(WndHotel.class,"more_gold")); + hide(); + } + } + }; + btnReward.setRect(0, message.top() + message.height() + GAP, WIDTH, + BTN_HEIGHT); + add(btnReward); + + resize(WIDTH, (int) btnReward.bottom()); + } +} \ No newline at end of file diff --git a/java/com/hmdzl/spspd/windows/WndStory.java b/java/com/hmdzl/spspd/windows/WndStory.java new file mode 100644 index 00000000..85aa671c --- /dev/null +++ b/java/com/hmdzl/spspd/windows/WndStory.java @@ -0,0 +1,138 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2014 Oleg Dolya + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.hmdzl.spspd.windows; + +import com.hmdzl.spspd.Chrome; +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.ShatteredPixelDungeon; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.PixelScene; +import com.hmdzl.spspd.ui.Window; +import com.watabou.input.Touchscreen.Touch; +import com.hmdzl.spspd.ui.RenderedTextMultiline; +import com.watabou.noosa.Game; +import com.watabou.noosa.TouchArea; +import com.watabou.utils.SparseArray; + +public class WndStory extends Window { + + private static final int WIDTH_P = 120; + private static final int WIDTH_L = 144; + private static final int MARGIN = 6; + + private static final float bgR = 0.77f; + private static final float bgG = 0.73f; + private static final float bgB = 0.62f; + + public static final int ID_SEWERS = 0; + public static final int ID_PRISON = 1; + public static final int ID_CAVES = 2; + public static final int ID_CITY = 3; + public static final int ID_HALLS = 4; + public static final int ID_SOKOBAN1 = 5; + public static final int ID_SOKOBAN2 = 6; + public static final int ID_SOKOBAN3 = 7; + public static final int ID_SOKOBAN4 = 8; + public static final int ID_SAFELEVEL = 9; + public static final int ID_TOWN = 10; + public static final int ID_CHAOS = 11; + public static final int ID_ZOT = 12; + + private static final SparseArray CHAPTERS = new SparseArray(); + + static { + CHAPTERS.put( ID_SEWERS, "sewers" ); + CHAPTERS.put( ID_PRISON, "prison" ); + CHAPTERS.put( ID_CAVES, "caves" ); + CHAPTERS.put( ID_CITY, "city" ); + CHAPTERS.put( ID_HALLS, "halls" ); + CHAPTERS.put( ID_SOKOBAN1, "sokoban1"); + CHAPTERS.put( ID_SOKOBAN2,"sokoban2"); + CHAPTERS.put( ID_SOKOBAN3,"sokoban3"); + CHAPTERS.put( ID_SOKOBAN4,"sokoban4"); + CHAPTERS.put( ID_SAFELEVEL,"safelevel"); + CHAPTERS.put( ID_TOWN,"town"); + CHAPTERS.put( ID_CHAOS,"chaos"); + CHAPTERS.put( ID_ZOT,"zot"); + } + + private RenderedTextMultiline tf; + + private float delay; + + public WndStory(String text) { + super(0, 0, Chrome.get(Chrome.Type.SCROLL)); + + tf = PixelScene.renderMultiline( text, 7 ); + tf.maxWidth(ShatteredPixelDungeon.landscape() ? + WIDTH_L - MARGIN * 2: + WIDTH_P - MARGIN *2); + tf.invert(); + tf.setPos(MARGIN, 0); + add( tf ); + + add(new TouchArea(chrome) { + @Override + protected void onClick(Touch touch) { + hide(); + } + }); + + resize((int) (tf.width() + MARGIN * 2), + (int) Math.min(tf.height(), 180)); + } + + @Override + public void update() { + super.update(); + + if (delay > 0 && (delay -= Game.elapsed) <= 0) { + shadow.visible = chrome.visible = tf.visible = true; + } + } + + public static void showChapter(int id) { + + if (Dungeon.chapters.contains(id)) { + return; + } + + String text = Messages.get(WndStory.class, CHAPTERS.get( id )); + if (text != null) { + WndStory wnd = new WndStory(text); + if ((wnd.delay = 0.6f) > 0) { + wnd.shadow.visible = wnd.chrome.visible = wnd.tf.visible = false; + } + + Game.scene().add(wnd); + + Dungeon.chapters.add(id); + } + } + + public static void showChapter(String text) { + if (text != null) { + WndStory wnd = new WndStory( text ); + if ((wnd.delay = 0.6f) > 0) { + wnd.chrome.visible = wnd.tf.visible = false; + } + + Game.scene().add( wnd ); + } + } +} diff --git a/java/com/hmdzl/spspd/windows/WndTabbed.java b/java/com/hmdzl/spspd/windows/WndTabbed.java new file mode 100644 index 00000000..fd146aad --- /dev/null +++ b/java/com/hmdzl/spspd/windows/WndTabbed.java @@ -0,0 +1,225 @@ +/* + * 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 + */ +package com.hmdzl.spspd.windows; + +import java.util.ArrayList; + +import com.hmdzl.spspd.Assets; +import com.hmdzl.spspd.Chrome; +import com.hmdzl.spspd.scenes.PixelScene; +import com.hmdzl.spspd.ui.Window; +import com.watabou.noosa.Game; +import com.watabou.noosa.NinePatch; +import com.watabou.noosa.RenderedText; +import com.watabou.noosa.audio.Sample; +import com.watabou.noosa.ui.Button; + +public class WndTabbed extends Window { + + protected ArrayList tabs = new ArrayList(); + protected Tab selected; + + public WndTabbed() { + super(0, 0, Chrome.get(Chrome.Type.TAB_SET)); + } + + protected Tab add(Tab tab) { + + tab.setPos( + tabs.size() == 0 ? -chrome.marginLeft() + 1 : tabs.get( + tabs.size() - 1).right(), height); + tab.select(false); + super.add(tab); + + tabs.add(tab); + + return tab; + } + + public void select(int index) { + select(tabs.get(index)); + } + + public void select(Tab tab) { + if (tab != selected) { + for (Tab t : tabs) { + if (t == selected) { + t.select(false); + } else if (t == tab) { + t.select(true); + } + } + + selected = tab; + } + } + + @Override + public void resize(int w, int h) { + // -> super.resize(...) + this.width = w; + this.height = h; + + chrome.size(width + chrome.marginHor(), height + chrome.marginVer()); + + camera.resize((int) chrome.width, + chrome.marginTop() + height + tabHeight()); + camera.x = (int) (Game.width - camera.screenWidth()) / 2; + camera.y = (int) (Game.height - camera.screenHeight()) / 2; + + shadow.boxRect(camera.x / camera.zoom, camera.y / camera.zoom, + chrome.width(), chrome.height); + // <- super.resize(...) + + for (Tab tab : tabs) { + remove(tab); + } + + ArrayList tabs = new ArrayList(this.tabs); + this.tabs.clear(); + + for (Tab tab : tabs) { + add(tab); + } + } + + public void layoutTabs() { + // subract two as there's extra horizontal space for those nobs on the + // top. + int fullWidth = width + chrome.marginHor() - 2; + int numTabs = tabs.size(); + + if (numTabs == 0) + return; + if (numTabs == 1) { + tabs.get(0).setSize(fullWidth, tabHeight()); + return; + } + + int spaces = numTabs - 1; + int spacing = -1; + + while (spacing == -1) { + for (int i = 0; i <= 3; i++) { + if ((fullWidth - i * (spaces)) % numTabs == 0) { + spacing = i; + break; + } + } + if (spacing == -1) + fullWidth--; + } + + int tabWidth = (fullWidth - spacing * (numTabs - 1)) / numTabs; + + for (int i = 0; i < tabs.size(); i++) { + tabs.get(i).setSize(tabWidth, tabHeight()); + tabs.get(i).setPos( + i == 0 ? -chrome.marginLeft() + 1 : tabs.get(i - 1).right() + + spacing, height); + } + + } + + protected int tabHeight() { + return 25; + } + + protected void onClick(Tab tab) { + select(tab); + } + + protected class Tab extends Button { + + protected final int CUT = 5; + + protected boolean selected; + + protected NinePatch bg; + + @Override + protected void layout() { + super.layout(); + + if (bg != null) { + bg.x = x; + bg.y = y; + bg.size(width, height); + } + } + + protected void select(boolean value) { + + active = !(selected = value); + + if (bg != null) { + remove(bg); + } + + bg = Chrome.get(selected ? Chrome.Type.TAB_SELECTED + : Chrome.Type.TAB_UNSELECTED); + addToBack(bg); + + layout(); + } + + @Override + protected void onClick() { + Sample.INSTANCE.play(Assets.SND_CLICK, 0.7f, 0.7f, 1.2f); + WndTabbed.this.onClick(this); + } + } + + protected class LabeledTab extends Tab { + + private RenderedText btLabel; + + public LabeledTab(String label) { + + super(); + + btLabel.text(label); + } + + @Override + protected void createChildren() { + super.createChildren(); + + btLabel = PixelScene.renderText(9); + add(btLabel); + } + + @Override + protected void layout() { + super.layout(); + + btLabel.x = PixelScene.align(x + (width - btLabel.width()) / 2); + btLabel.y = PixelScene.align(y + (height - btLabel.baseLine()) / 2) - 1; + if (!selected) { + btLabel.y -= 2; + } + } + + @Override + protected void select(boolean value) { + super.select(value); + btLabel.am = selected ? 1.0f : 0.6f; + } + } + +} diff --git a/java/com/hmdzl/spspd/windows/WndTinkerer.java b/java/com/hmdzl/spspd/windows/WndTinkerer.java new file mode 100644 index 00000000..f045af12 --- /dev/null +++ b/java/com/hmdzl/spspd/windows/WndTinkerer.java @@ -0,0 +1,152 @@ +/* + * 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 + */ +package com.hmdzl.spspd.windows; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.Statistics; +import com.hmdzl.spspd.actors.buffs.Buff; +import com.hmdzl.spspd.actors.buffs.Dewcharge; +import com.hmdzl.spspd.actors.mobs.npcs.Tinkerer1; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.quest.Mushroom; +import com.hmdzl.spspd.scenes.GameScene; +import com.hmdzl.spspd.scenes.PixelScene; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.ui.RedButton; +import com.hmdzl.spspd.ui.RenderedTextMultiline; +import com.hmdzl.spspd.ui.Window; +import com.hmdzl.spspd.utils.GLog; + + +public class WndTinkerer extends Window { + + private static final String TXT_MESSAGE = "Thanks for the Toadstool Mushroom! " + +"I can upgrade your dew vial for you. " + +"I can make it either draw out dew from certain vanquished enemies, " + +"or I can make it able to regrow the surrounding dungeon by watering with dew. "; + + private static final String TXT_MESSAGE_WATER = "Water with dew allows you to grow high grass around you once you have 50 drops in your vial. " + +"Watering costs 2 drops but you will be able to find more drop, nuts, berries, and seeds by trampling the grass. "; + + + private static final String TXT_MESSAGE_DRAW = "Drawing out dew makes it so that mobs on special levels drop dew to fill your vial. " + +"Additionally, your character is buffed with dew charge at the start of each normal level. " + +"As long as you are dew charged, enemies drop dew to fill your vial. " + +"Each level dew charges you for a set amount of moves. " + +"Each level also has a move goal for killing all regular generated enemies. (Not special enemies like statues and piranha) " + +"Killing all regular enemies that were generated with the level clears that level. " + +"If you clear a level in less moves than the goal, the additional moves are added to your dew charge for the next level. " + +"You will need to clear the levels as fast as you can to get dew upgrades. " + +"The dew vial will also allow you to choose which item you apply upgrades to when blessing. "; + + private static final String TXT_WATER = "Water with Dew"; + private static final String TXT_DRAW = "Draw Out Dew"; + private static final String TXT_DRAW_INFO = "Tell me more about Draw Out Dew"; + + private static final String TXT_FARAWELL = "Good luck in your quest, %s!"; + private static final String TXT_FARAWELL_DRAW = "Good luck in your quest, %s! I'll give you a head start drawing out dew!"; + + + private static final int WIDTH = 120; + private static final int BTN_HEIGHT = 20; + private static final float GAP = 2; + + public WndTinkerer(final Tinkerer1 tinkerer, final Item item) { + + super(); + + IconTitle titlebar = new IconTitle(); + titlebar.icon(new ItemSprite(item.image(), null)); + titlebar.label(Messages.titleCase(item.name())); + titlebar.setRect(0, 0, WIDTH, 0); + add(titlebar); + + RenderedTextMultiline message = PixelScene + .renderMultiline(Messages.get(WndTinkerer.class, "info1"), 6); + message.maxWidth(WIDTH); + message.setPos(0, titlebar.bottom() + GAP); + add(message); + + RedButton btnBattle = new RedButton(Messages.get(WndTinkerer.class, "water")) { + @Override + protected void onClick() { + selectUpgrade(tinkerer, 1); + } + }; + btnBattle.setRect(0, message.top() + message.height() + GAP, WIDTH, + BTN_HEIGHT); + add(btnBattle); + + RedButton btnNonBattle = new RedButton(Messages.get(WndTinkerer.class, "draw")) { + @Override + protected void onClick() { + selectUpgrade(tinkerer, 2); + } + }; + + btnNonBattle.setRect(0, btnBattle.bottom() + GAP, WIDTH, BTN_HEIGHT); + add(btnNonBattle); + + RedButton btnNonBattle2 = new RedButton(Messages.get(WndTinkerer.class, "spinfo")) { + @Override + protected void onClick() { + GameScene.show(new WndDewDrawInfo(item)); + } + }; + btnNonBattle2.setRect(0, btnNonBattle.bottom() + GAP, WIDTH, BTN_HEIGHT); + add(btnNonBattle2); + + resize(WIDTH, (int) btnNonBattle2.bottom()); + } + + private void selectUpgrade(Tinkerer1 tinkerer, int type) { + + hide(); + + Mushroom mushroom = Dungeon.hero.belongings.getItem(Mushroom.class); + mushroom.detach(Dungeon.hero.belongings.backpack); + + if (type==1){ + + Dungeon.dewWater=true; + + } else if (type==2){ + + Dungeon.dewDraw=true; + } + + if (type==1){ + tinkerer.yell(Messages.get(this, "farewell", Dungeon.hero.givenName())); + Statistics.prevfloormoves=500; + Buff.prolong(Dungeon.hero, Dewcharge.class, Dewcharge.DURATION+50); + GLog.p(Messages.get(this,"dungeon")); + } else if (type==2){ + tinkerer.yell(Messages.get(this, "farewell", Dungeon.hero.givenName())); + Statistics.prevfloormoves=500; + Buff.prolong(Dungeon.hero, Dewcharge.class, Dewcharge.DURATION+50); + GLog.p(Messages.get(this,"dungeon")); + } + + tinkerer.destroy(); + + tinkerer.sprite.die(); + + //Wandmaker.Quest.complete(); + } +} diff --git a/java/com/hmdzl/spspd/windows/WndTinkerer2.java b/java/com/hmdzl/spspd/windows/WndTinkerer2.java new file mode 100644 index 00000000..b7faaf28 --- /dev/null +++ b/java/com/hmdzl/spspd/windows/WndTinkerer2.java @@ -0,0 +1,165 @@ +/* + * 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 + */ +package com.hmdzl.spspd.windows; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.mobs.npcs.Tinkerer2; +import com.hmdzl.spspd.items.summon.ActiveMrDestructo; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.quest.Mushroom; +import com.hmdzl.spspd.items.summon.FairyCard; +import com.hmdzl.spspd.items.summon.Mobile; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.PixelScene; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.ui.RedButton; +import com.hmdzl.spspd.ui.RenderedTextMultiline; +import com.hmdzl.spspd.ui.Window; + + +public class WndTinkerer2 extends Window { + + private static final String TXT_MESSAGE1 = "Thanks for the Toadstool Mushroom! " + +"In return, I can upgrade your mr destructo for you, " + +"or I can recharge your old one and give you another. "; + + private static final String TXT_MESSAGE2 = "Thanks for the Toadstool Mushroom! " + +"In return, I can upgrade your mr destructo for you. " + +"You can also have this other one I've managed to fix up. "; + + private static final String TXT_MESSAGE3 = "Thanks for the Toadstool Mushroom! " + +"In return, you can have this Mr Destructo if you like. "; + + private static final String TXT_UPGRADE = "Upgrade my Mr Destructo"; + private static final String TXT_RECHARGE = "Recharge my Mr Desructo"; + private static final String TXT_NEW = "I'll take the new Mr Desructo"; + + private static final String TXT_FARAWELL = "Good luck in your quest, %s!"; + + private static final int WIDTH = 120; + private static final int BTN_HEIGHT = 20; + private static final float GAP = 2; + + + public WndTinkerer2(final Tinkerer2 tinkerer, final Item item, final Item mrd) { + + super(); + + IconTitle titlebar = new IconTitle(); + titlebar.icon(new ItemSprite(item.image(), null)); + titlebar.label(Messages.titleCase(item.name())); + titlebar.setRect(0, 0, WIDTH, 0); + add(titlebar); + + RenderedTextMultiline message = PixelScene.renderMultiline(Messages.get(this, "info"), 6); + message.maxWidth(WIDTH); + message.setPos(0, titlebar.bottom() + GAP); + add(message); + + RedButton btnMr = new RedButton(Messages.get(this, "mr")) { + @Override + protected void onClick() { + selectMr(tinkerer); + } + }; + btnMr.setRect(0, message.top() + message.height() + GAP, WIDTH, BTN_HEIGHT); + add(btnMr); + + RedButton btnCall = new RedButton(Messages.get(this, "call")) { + @Override + protected void onClick() { + selectCall(tinkerer); + } + }; + btnCall.setRect(0, btnMr.bottom() + GAP, WIDTH, BTN_HEIGHT); + add(btnCall); + + RedButton btnMob = new RedButton(Messages.get(this, "mob")) { + @Override + protected void onClick() { + selectMob(tinkerer); + } + }; + btnMob.setRect(0, btnCall.bottom() + GAP, WIDTH, BTN_HEIGHT); + add(btnMob); + + resize(WIDTH, (int) btnMob.bottom()); + + } + + private void selectMr(Tinkerer2 tinkerer) { + + hide(); + + Mushroom mushroom = Dungeon.hero.belongings.getItem(Mushroom.class); + mushroom.detach(Dungeon.hero.belongings.backpack); + + Dungeon.dewNorn = true; + + ActiveMrDestructo mrd = new ActiveMrDestructo(); + + Dungeon.level.drop(mrd, Dungeon.hero.pos).sprite.drop(); + + tinkerer.yell( Messages.get(this, "farewell", Dungeon.hero.givenName())); + tinkerer.destroy(); + + tinkerer.sprite.die(); + + //Wandmaker.Quest.complete(); + } + private void selectCall(Tinkerer2 tinkerer) { + + hide(); + + Mushroom mushroom = Dungeon.hero.belongings.getItem(Mushroom.class); + mushroom.detach(Dungeon.hero.belongings.backpack); + + Dungeon.dewNorn = true; + + FairyCard fc = new FairyCard(); + + Dungeon.level.drop(fc, Dungeon.hero.pos).sprite.drop(); + + tinkerer.yell( Messages.get(this, "farewell", Dungeon.hero.givenName())); + tinkerer.destroy(); + + tinkerer.sprite.die(); + + //Wandmaker.Quest.complete(); + } + private void selectMob(Tinkerer2 tinkerer) { + + hide(); + + Mushroom mushroom = Dungeon.hero.belongings.getItem(Mushroom.class); + mushroom.detach(Dungeon.hero.belongings.backpack); + + Dungeon.dewNorn = true; + + Mobile mob = new Mobile(); + + Dungeon.level.drop(mob, Dungeon.hero.pos).sprite.drop(); + + tinkerer.yell( Messages.get(this, "farewell", Dungeon.hero.givenName())); + tinkerer.destroy(); + + tinkerer.sprite.die(); + + //Wandmaker.Quest.complete(); + } +} diff --git a/java/com/hmdzl/spspd/windows/WndTinkerer3.java b/java/com/hmdzl/spspd/windows/WndTinkerer3.java new file mode 100644 index 00000000..6abc261e --- /dev/null +++ b/java/com/hmdzl/spspd/windows/WndTinkerer3.java @@ -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 + */ +package com.hmdzl.spspd.windows; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.mobs.npcs.Tinkerer3; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.quest.Mushroom; +import com.hmdzl.spspd.scenes.PixelScene; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.ui.RedButton; +import com.hmdzl.spspd.ui.RenderedTextMultiline; +import com.hmdzl.spspd.ui.Window; +import com.hmdzl.spspd.messages.Messages; + + +public class WndTinkerer3 extends Window { + + private static final String TXT_MESSAGE = "Thanks for the Toadstool Mushroom! " + +"I can upgrade your dew vial for you. " + +"I can make it hold more and give you wings when you splash. "; + private static final String TXT_UPGRADE = "Upgrade my Vial!"; + + private static final String TXT_FARAWELL = "Good luck in your quest, %s!"; + + private static final int WIDTH = 120; + private static final int BTN_HEIGHT = 20; + private static final float GAP = 2; + + public WndTinkerer3(final Tinkerer3 tinkerer, final Item item) { + + super(); + + IconTitle titlebar = new IconTitle(); + titlebar.icon(new ItemSprite(item.image(), null)); + titlebar.label(Messages.titleCase(item.name())); + titlebar.setRect(0, 0, WIDTH, 0); + add(titlebar); + + RenderedTextMultiline message = PixelScene + .renderMultiline(Messages.get(this, "info"), 6); + message.maxWidth(WIDTH); + message.setPos(0, titlebar.bottom() + GAP); + add(message); + + RedButton btnUpgrade = new RedButton(Messages.get(this, "upgrade")) { + @Override + protected void onClick() { + selectUpgrade(tinkerer); + } + }; + btnUpgrade.setRect(0, message.top() + message.height() + GAP, WIDTH, + BTN_HEIGHT); + add(btnUpgrade); + + + resize(WIDTH, (int) btnUpgrade.bottom()); + } + + private void selectUpgrade(Tinkerer3 tinkerer) { + hide(); + + Mushroom mushroom = Dungeon.hero.belongings.getItem(Mushroom.class); + mushroom.detach(Dungeon.hero.belongings.backpack); + + //Dungeon.dewWater=true; + //Dungeon.dewDraw=true; + Dungeon.wings=true; + + + tinkerer.yell( Messages.get(this, "farewell", Dungeon.hero.givenName())); + tinkerer.destroy(); + + tinkerer.sprite.die(); + + //Wandmaker.Quest.complete(); + } +} diff --git a/java/com/hmdzl/spspd/windows/WndTitledMessage.java b/java/com/hmdzl/spspd/windows/WndTitledMessage.java new file mode 100644 index 00000000..285b3186 --- /dev/null +++ b/java/com/hmdzl/spspd/windows/WndTitledMessage.java @@ -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 + */ +package com.hmdzl.spspd.windows; + +import com.hmdzl.spspd.ShatteredPixelDungeon; +import com.hmdzl.spspd.scenes.PixelScene; +import com.hmdzl.spspd.ui.RenderedTextMultiline; +import com.hmdzl.spspd.ui.Window; +import com.watabou.noosa.Image; +import com.watabou.noosa.ui.Component; + +public class WndTitledMessage extends Window { + + protected static final int WIDTH_P = 120; + protected static final int WIDTH_L = 144; + protected static final int GAP = 2; + + public WndTitledMessage( Image icon, String title, String message ) { + + this( new IconTitle( icon, title ), message ); + + } + + public WndTitledMessage( Component titlebar, String message ) { + + super(); + + int width = ShatteredPixelDungeon.landscape() ? WIDTH_L : WIDTH_P; + + titlebar.setRect( 0, 0, width, 0 ); + add(titlebar); + + RenderedTextMultiline text = PixelScene.renderMultiline( 6 ); + text.text( message, width ); + text.setPos( titlebar.left(), titlebar.bottom() + GAP ); + add( text ); + + resize( width, (int)text.bottom() ); + } +} diff --git a/java/com/hmdzl/spspd/windows/WndTradeItem.java b/java/com/hmdzl/spspd/windows/WndTradeItem.java new file mode 100644 index 00000000..35eaa0f0 --- /dev/null +++ b/java/com/hmdzl/spspd/windows/WndTradeItem.java @@ -0,0 +1,285 @@ +/* + * 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 + */ +package com.hmdzl.spspd.windows; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.hero.Hero; +import com.hmdzl.spspd.actors.hero.HeroClass; +import com.hmdzl.spspd.actors.mobs.Mob; +import com.hmdzl.spspd.actors.mobs.npcs.Shopkeeper; +import com.hmdzl.spspd.items.ChallengeBook; +import com.hmdzl.spspd.items.EquipableItem; +import com.hmdzl.spspd.items.Gold; +import com.hmdzl.spspd.items.Heap; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.bags.HeartOfScarecrow; +import com.hmdzl.spspd.items.bags.ShoppingCart; +import com.hmdzl.spspd.items.bags.KeyRing; +import com.hmdzl.spspd.items.bags.PotionBandolier; +import com.hmdzl.spspd.items.bags.ScrollHolder; +import com.hmdzl.spspd.items.bags.SeedPouch; +import com.hmdzl.spspd.items.bags.WandHolster; +import com.hmdzl.spspd.items.challengelists.ChallengeList; +import com.hmdzl.spspd.items.journalpages.JournalPage; +import com.hmdzl.spspd.items.DolyaSlate; +import com.hmdzl.spspd.items.artifacts.MasterThievesArmband; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.PixelScene; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.ui.ItemSlot; +import com.hmdzl.spspd.ui.Window; +import com.hmdzl.spspd.utils.GLog; + +import com.hmdzl.spspd.ui.RedButton; +import com.hmdzl.spspd.ui.RenderedTextMultiline; + +public class WndTradeItem extends Window { + + private static final float GAP = 2; + private static final int WIDTH = 120; + private static final int BTN_HEIGHT = 16; + + private WndBag owner; + + public WndTradeItem(final Item item, WndBag owner) { + + super(); + + this.owner = owner; + + float pos = createDescription(item, false); + + if (item.quantity() == 1) { + + RedButton btnSell = new RedButton(Messages.get(this, "sell", item.price())) { + @Override + protected void onClick() { + sell(item); + hide(); + } + }; + btnSell.setRect(0, pos + GAP, WIDTH, BTN_HEIGHT); + add(btnSell); + + pos = btnSell.bottom(); + + } else { + + int priceAll = item.price(); + RedButton btnSell1 = new RedButton( Messages.get(this, "sell_1", priceAll / item.quantity()) ) { + @Override + protected void onClick() { + sellOne(item); + hide(); + } + }; + btnSell1.setRect(0, pos + GAP, WIDTH, BTN_HEIGHT); + add(btnSell1); + RedButton btnSellAll = new RedButton( Messages.get(this, "sell_all", priceAll )) { + @Override + protected void onClick() { + sell(item); + hide(); + } + }; + btnSellAll.setRect(0, btnSell1.bottom() + GAP, WIDTH, BTN_HEIGHT); + add(btnSellAll); + + pos = btnSellAll.bottom(); + + } + + RedButton btnCancel = new RedButton(Messages.get(this, "cancel")) { + @Override + protected void onClick() { + hide(); + } + }; + btnCancel.setRect(0, pos + GAP, WIDTH, BTN_HEIGHT); + add(btnCancel); + + resize(WIDTH, (int) btnCancel.bottom()); + } + + public WndTradeItem(final Heap heap, boolean canBuy) { + + super(); + + Item item = heap.peek(); + + float pos = createDescription(item, true); + + final int price = price(item); + + if (canBuy) { + + RedButton btnBuy = new RedButton( Messages.get(this, "buy", price)) { + @Override + protected void onClick() { + hide(); + buy(heap); + } + }; + btnBuy.setRect(0, pos + GAP, WIDTH, BTN_HEIGHT); + btnBuy.enable(price <= Dungeon.gold); + add(btnBuy); + + RedButton btnCancel = new RedButton(Messages.get(this, "cancel")) { + @Override + protected void onClick() { + hide(); + } + }; + + + final MasterThievesArmband.Thievery thievery = Dungeon.hero + .buff(MasterThievesArmband.Thievery.class); + if (thievery != null) { + final float chance = thievery.stealChance(price); + RedButton btnSteal = new RedButton( Messages.get(this, "steal", Math.min(100, (int)(chance*100)))) { + @Override + protected void onClick() { + if (thievery.steal(price)) { + Hero hero = Dungeon.hero; + Item item = heap.pickUp(); + int price = (int)Math.max((1 - chance) * price(item) , 0); + Dungeon.gold -= price; + hide(); + if (!item.doPickUp(hero)) { + Dungeon.level.drop(item, heap.pos).sprite.drop(); + } + } else { + for (Mob mob : Dungeon.level.mobs) { + } + hide(); + } + } + }; + btnSteal.setRect(0, btnBuy.bottom() + GAP, WIDTH, BTN_HEIGHT); + btnSteal.enable(price <= Dungeon.gold); + add(btnSteal); + + btnCancel + .setRect(0, btnSteal.bottom() + GAP, WIDTH, BTN_HEIGHT); + } else + btnCancel.setRect(0, btnBuy.bottom() + GAP, WIDTH, BTN_HEIGHT); + + add(btnCancel); + + resize(WIDTH, (int) btnCancel.bottom()); + + } else { + + resize(WIDTH, (int) pos); + + } + } + + @Override + public void hide() { + + super.hide(); + + if (owner != null) { + owner.hide(); + Shopkeeper.sell(); + } + } + + private float createDescription(Item item, boolean forSale) { + + // Title + IconTitle titlebar = new IconTitle(); + titlebar.icon(new ItemSprite(item.image(), item.glowing())); + titlebar.label(forSale ? + Messages.get(this, "sale", item.toString(), price( item ) ) : + Messages.titleCase( item.toString() ) ); + titlebar.setRect(0, 0, WIDTH, 0); + add(titlebar); + + // Upgraded / degraded + if (item.levelKnown && item.level > 0) { + titlebar.color(ItemSlot.UPGRADED); + } else if (item.levelKnown && item.level < 0) { + titlebar.color(ItemSlot.DEGRADED); + } + + // Description + RenderedTextMultiline info = PixelScene.renderMultiline( item.info(), 6 ); + info.maxWidth(WIDTH); + info.setPos(titlebar.left(), titlebar.bottom() + GAP); + add( info ); + + return info.bottom(); + } + + private void sell(Item item) { + + Hero hero = Dungeon.hero; + + if (item instanceof SeedPouch || item instanceof KeyRing || item instanceof ShoppingCart || item instanceof HeartOfScarecrow + || item instanceof PotionBandolier || item instanceof WandHolster || item instanceof ScrollHolder + || item instanceof JournalPage || item instanceof DolyaSlate || item instanceof ChallengeList || item instanceof ChallengeBook){ + GLog.w( Messages.get(this, "donot") ); + return ; + } else if (item.isEquipped(hero) + && !((EquipableItem) item).doUnequip(hero, false)) { + return; + } + + item.detachAll(hero.belongings.backpack); + + new Gold(item.price()).doPickUp(hero); + hero.spend(-hero.cooldown()); + + } + + private void sellOne(Item item) { + + if (item.quantity() <= 1) { + sell(item); + } else { + + Hero hero = Dungeon.hero; + item = item.detach( hero.belongings.backpack ); + + new Gold(item.price()).doPickUp(hero); + hero.spend(-hero.cooldown()); + } + } + + private int price(Item item) { + int price = Dungeon.hero.heroClass == HeroClass.FOLLOWER ? + Math.min(item.price() * 4 * (Dungeon.depth / 5 + 1), item.price() * 20) : + Math.min(item.price() * 5 * (Dungeon.depth / 5 + 1), item.price() * 25); + return price; + } + + private void buy(Heap heap) { + + Hero hero = Dungeon.hero; + Item item = heap.pickUp(); + + int price = price(item); + Dungeon.gold -= price; + + if (!item.doPickUp(hero)) { + Dungeon.level.drop(item, heap.pos).sprite.drop(); + } + } +} diff --git a/java/com/hmdzl/spspd/windows/WndWandmaker.java b/java/com/hmdzl/spspd/windows/WndWandmaker.java new file mode 100644 index 00000000..0287445b --- /dev/null +++ b/java/com/hmdzl/spspd/windows/WndWandmaker.java @@ -0,0 +1,100 @@ +/* + * 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 + */ +package com.hmdzl.spspd.windows; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.actors.mobs.npcs.Wandmaker; +import com.hmdzl.spspd.items.AdamantWand; +import com.hmdzl.spspd.items.Item; +import com.hmdzl.spspd.items.wands.Wand; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.PixelScene; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.ui.RedButton; +import com.hmdzl.spspd.ui.RenderedTextMultiline; +import com.hmdzl.spspd.ui.Window; + + +public class WndWandmaker extends Window { + + private static final String TXT_MESSAGE = "Oh, I see you have succeeded! I do hope it hasn't troubled you too much. " + + "As I promised, you can choose one of my high quality wands."; + private static final String TXT_BATTLE = "Battle wand"; + private static final String TXT_NON_BATTLE = "Non-battle wand"; + + private static final String TXT_ADAMANT = "You might find this raw material useful later on. I'm not powerful enough to work with it."; + private static final String TXT_WOW = "How did you make it all this way!? I have another reward for you. "; + private static final String TXT_FARAWELL = "Good luck in your quest, %s!"; + + private static final int WIDTH = 120; + private static final int BTN_HEIGHT = 20; + private static final float GAP = 2; + + public WndWandmaker(final Wandmaker wandmaker, final Item item) { + + super(); + + IconTitle titlebar = new IconTitle(); + titlebar.icon(new ItemSprite(item.image(), null)); + titlebar.label(Messages.titleCase(item.name())); + titlebar.setRect(0, 0, WIDTH, 0); + add(titlebar); + + RenderedTextMultiline message = PixelScene + .renderMultiline(Messages.get(this, "message"), 6); + message.maxWidth(WIDTH); + message.setPos(0,titlebar.bottom() + GAP); + add(message); + + RedButton btnBattle = new RedButton(Messages.get(this, "battle")) { + @Override + protected void onClick() { + selectReward(wandmaker, item, Wandmaker.Quest.wand1); + } + }; + btnBattle.setRect(0, message.top()+ message.height() + GAP, WIDTH, + BTN_HEIGHT); + add(btnBattle); + + RedButton btnNonBattle = new RedButton(Messages.get(this, "no_battle")) { + @Override + protected void onClick() { + selectReward(wandmaker, item, Wandmaker.Quest.wand2); + } + }; + btnNonBattle.setRect(0, btnBattle.bottom() + GAP, WIDTH, BTN_HEIGHT); + add(btnNonBattle); + + resize(WIDTH, (int) btnNonBattle.bottom()); + } + + private void selectReward(Wandmaker wandmaker, Item item, Wand reward) { + + hide(); + + item.detach(Dungeon.hero.belongings.backpack); + + reward.identify(); + Dungeon.level.drop(reward, wandmaker.pos).sprite.drop(); + wandmaker.yell(Messages.get(this, "farewell", Dungeon.hero.givenName())); + Dungeon.level.drop(new AdamantWand(), wandmaker.pos).sprite.drop(); + wandmaker.destroy(); + wandmaker.sprite.die(); + Wandmaker.Quest.complete(); + } +} diff --git a/java/com/hmdzl/spspd/windows/Wndice13.java b/java/com/hmdzl/spspd/windows/Wndice13.java new file mode 100644 index 00000000..12dea5e4 --- /dev/null +++ b/java/com/hmdzl/spspd/windows/Wndice13.java @@ -0,0 +1,80 @@ +/* + * 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 + */ +package com.hmdzl.spspd.windows; + +import com.hmdzl.spspd.Dungeon; +import com.hmdzl.spspd.items.ChaosPack; +import com.hmdzl.spspd.items.PowerHand; +import com.hmdzl.spspd.items.keys.IronKey; +import com.hmdzl.spspd.items.weapon.melee.block.GoblinShield; +import com.hmdzl.spspd.messages.Messages; +import com.hmdzl.spspd.scenes.PixelScene; +import com.hmdzl.spspd.sprites.ItemSprite; +import com.hmdzl.spspd.ui.RedButton; +import com.hmdzl.spspd.ui.RenderedTextMultiline; +import com.hmdzl.spspd.ui.Window; +import com.hmdzl.spspd.utils.GLog; + + +public class Wndice13 extends Window { + + private static final int WIDTH = 120; + private static final int BTN_HEIGHT = 20; + private static final int GAP = 2; + + public Wndice13() { + + super(); + + PowerHand key = new PowerHand(); + + + IconTitle titlebar = new IconTitle(); + titlebar.icon(new ItemSprite(key.image(), null)); + titlebar.label(Messages.titleCase(key.name())); + titlebar.setRect(0, 0, WIDTH, 0); + add(titlebar); + + RenderedTextMultiline message = PixelScene + .renderMultiline(Messages.get(this, "message"), 6); + message.maxWidth(WIDTH); + message.setPos(0, titlebar.bottom() + GAP); + add(message); + + RedButton btnReward = new RedButton(Messages.get(this, "buy")) { + @Override + protected void onClick() { + PowerHand clothes = Dungeon.hero.belongings.getItem(PowerHand.class); + if (clothes!=null){ + clothes.detach(Dungeon.hero.belongings.backpack); + ChaosPack gs = new ChaosPack(); + gs.doPickUp(Dungeon.hero); + hide(); + } else { + GLog.w(Messages.get(WndHotel.class,"more_gold")); + hide(); + } + } + }; + btnReward.setRect(0, message.top() + message.height() + GAP, WIDTH, + BTN_HEIGHT); + add(btnReward); + + resize(WIDTH, (int) btnReward.bottom()); + } +} \ No newline at end of file diff --git a/res/values/strings.xml b/res/values/strings.xml index f2968bdf..fded346e 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -1,4 +1,4 @@ - SPS-PD + SPSPD diff --git a/resources/com/hmdzl/spspd/messages/actors/actors.properties b/resources/com/hmdzl/spspd/messages/actors/actors.properties new file mode 100644 index 00000000..d5339786 --- /dev/null +++ b/resources/com/hmdzl/spspd/messages/actors/actors.properties @@ -0,0 +1,1343 @@ +###blobs +actors.blobs.confusiongas.desc=A cloud of confusion gas is swirling here, twisting the senses of anything caught within so that they are forced to walk in random directions. +actors.blobs.corruptgas.desc=A cloud of demon blood is swirling here, eviscerating any mortals within by causing bleeding and vertigo. +actors.blobs.darkgas.desc=A cloud of dark gas is swirling here, blocking the vision of anything trapped inside. +actors.blobs.electrishock.desc=A field of electricity is sparking brightly here. +actors.blobs.fire.desc=A fire is raging here, grilling flesh both living and dead within its path. +actors.blobs.foliage.desc=Shafts of light pierce the gloom of the underground garden. +actors.blobs.frostgas.desc=The air is unnaturally frigid here. +actors.blobs.goowarn.desc=Specks of dark energy are swarming here! +actors.blobs.heallight.desc=Shafts of light pierce the gloom of the underground, restoring life to all that it touches! +actors.blobs.memoryfire.desc=A blue fire is raging here. +actors.blobs.paralyticgas.desc=A cloud of paralytic gas is swirling here. +actors.blobs.regrowth.desc=Vegetative matter bursts to and from the ground here, rapidly growing and fertilizing plants to be ripe for immediate harvest. +actors.blobs.shockweb.desc=Everything is covered with a shock web here. +actors.blobs.stenchgas.desc=A cloud of fetid stench is swirling here. +actors.blobs.targas.desc=A cloud of sticky tar gas is swirling here, slowing down any people it touches while letting fires burn for much longer than normal. +actors.blobs.toxicgas.desc=A greenish cloud of toxic gas is swirling here. +actors.blobs.venomgas.desc=A cloud of foul acidic venom is swirling here. +actors.blobs.waterofawareness.desc=Power of knowledge radiates from the water of this well. \nTake a sip from it to reveal all secrets of equipped items. +actors.blobs.waterofawareness.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. +actors.blobs.waterofhealth.desc=Power of health radiates from the water of this well.\nTake a sip from it to heal your wounds and satisfy hunger. +actors.blobs.waterofhealth.procced=As you take a sip, you feel your wounds heal completely. +actors.blobs.wateroftransmutation.desc=Power of change radiates from the water of this well. \nThrow an item into the well to turn it into something else. +actors.blobs.weather.weatherofdead.desc=Ghost raise here. +actors.blobs.weather.weatherofquite.desc=It's very quiet here. +actors.blobs.weather.weatherofrain.desc=Rain is pouring endlessly here, reducing any creatures' ability to attack or dodge. +actors.blobs.weather.weatherofsand.desc=The air here is littered with particles of dust, drying out anyone within and reducing their damage. +actors.blobs.weather.weatherofsnow.desc=This room is incredibly cold, cold enough to swirl snow into the air while the low temperature slows everyone down. +actors.blobs.weather.weatherofsun.desc=Harsh sunlight beams down within this room, making everything unbearably hot while also reducing the effectiveness of armor. +actors.blobs.web.desc=Everything is covered with a thick web here. + +###buffs +actors.buffs.amok.desc=Amok causes a state of great rage and confusion in its target.\n\nWhen a creature is amoked, they will attack whatever is near them, whether they be friend or foe.\n\nTurns of amok remaining: %s. +actors.buffs.amok.name=Amok +actors.buffs.arcane.desc=Magical power radiates throughout your body, increasing your magic power by 10 points so that your wands deal extra damage.\nTurns of Arcane remaining: %s. +actors.buffs.arcane.name=Arcane +actors.buffs.armorbreak.desc=%s turns,taken more %s%% damage. +actors.buffs.armorbreak.name=Armor Break +actors.buffs.attackdown.desc=%s turns, reduce%s%% attack. +actors.buffs.attackdown.name=Attack dowm +actors.buffs.attackup.desc=%s turns, gain %s%% attack damage. +actors.buffs.attackup.name=Attack Up +actors.buffs.awareness.desc=Treasure serch allow you find every treasure in this floor.\n\n\nTurn of treasure search remaining: %s turns. +actors.buffs.awareness.name=Treasure serch +actors.buffs.barkskin.desc=Your skin is hardened, it feels rough and solid like bark.\n\nThe hardened skin increases your effective armor, allowing you to better defend against physical attack. The armor bonus will decrease by one point each turn until it expires.\n\nYour armor is currently increased by: %d. +actors.buffs.barkskin.name=Barkskin +actors.buffs.berryregeneration.desc=Regeneration make you health.\n\nTurn of regeneration left: %d turns. +actors.buffs.berryregeneration.name=Regeneration +actors.buffs.bleeding.desc=That wound is leaking a worrisome amount of blood.\n\nBleeding causes damage every turn. Each turn the damage decreases by a random amount, until the bleeding eventually stops.\n\nCurrent bleed damage: %d. +actors.buffs.bleeding.heromsg=You are bleeding. +actors.buffs.bleeding.name=Bleeding +actors.buffs.bless.desc=A great burst of focus, some say it is inspired by the gods.\n\nBlessing significantly increases accuracy and evasion, making the blessed much more effective in combat.\n\nTurns of bless remaining: %s. +actors.buffs.bless.name=Bless +actors.buffs.blindness.desc=Blinding turns the surrounding world into a dark haze.\n\nWhile blinded, a character can't see more than one tile infront of themselves, rendering ranged attacks useless and making it very easy to lose track of distant enemies. Additionally, a blinded hero is unable to read scrolls or books.\n\nTurns of blindness remaining: %s. +actors.buffs.blindness.heromsg=You are blinded! +actors.buffs.blindness.name=Blinded + +actors.buffs.burning.burnsup=%s burns up! +actors.buffs.burning.desc=Few things are more distressing than being engulfed in flames.\n\nFire will deal damage every turn until it is put out by water or it expires. Fire can be extinquished by stepping into water, or from the splash of a shattering potion.\n\nAdditionally, the fire may ignite flammable terrain or items that it comes into contact with.\n\nTurns of burning remaining: %s. +actors.buffs.burning.heromsg=You catch fire! +actors.buffs.burning.name=Burning +actors.buffs.charm.desc=A charm is manipulative magic that can make enemies temporarily adore eachother.\n\nCharacters affected by charm are unable to directly attack the enemy they are charmed by. Attacking other targets is still possible however.\n\nTurns of charm remaining: %s. +actors.buffs.charm.heromsg=You are charmed! +actors.buffs.charm.name=Charmed +actors.buffs.chill.desc=Not quite frozen, but still much too cold.\n\nChilled targets perform all actions more slowly, depending on how many turns are left in the effect. At it's worst, this is equivalent to being slowed.\n\nTurns of chill remaining: %s.\nSpeed is reduced by: %s%% +actors.buffs.chill.freezes=%s freezes! +actors.buffs.chill.name=Chilled +actors.buffs.cold.desc=Cold make you move slow. \n\nTurns of cold remaining: %s. +actors.buffs.cold.name=Cold +actors.buffs.combo.bonusdmg=\n\nCurrent combo bonus damage: %f%%. +actors.buffs.combo.combo=%d Combo +actors.buffs.combo.desc=Through building momentum, the gladiator deals bonus damage.\n\nYour combo will keep building with quick attacks. The higher your combo gets, the faster your attacks will need to be. Failing to land a hit quickly enough will reset the combo. +actors.buffs.combo.name=Combo +actors.buffs.combo.notenough=\n\nYour combo has not built up enough to give you bonus damage yet. +actors.buffs.countdown.desc=After some time you will take lots of damage.\n\ntime remain : %d +actors.buffs.countdown.name=Countdown +actors.buffs.cripple.desc=You're pretty sure legs aren't meant to bend that way.\n\nCrippled halves movement speed, making moving a tile usually take two turns instead of one.\n\nTurns of cripple remaining: %s. +actors.buffs.cripple.heromsg=You are crippled! +actors.buffs.cripple.name=Crippled +actors.buffs.deadraise.desc=You feel a strong sense of resentment around you, as if something is coming.\n\n Time left: %s turns +actors.buffs.deadraise.name=Dead Raise +actors.buffs.defenceup.desc=%s turns, reduce %s%% damage +actors.buffs.defenceup.name=Damage reduce +actors.buffs.dewcharge.desc=Whenever you kill mobs, drop dews beside thems.\n\nturn left : %s turns +actors.buffs.dewcharge.name=Dew drop +actors.buffs.disarm.desc=Can't attack, %s turns left +actors.buffs.disarm.name=Disarm +actors.buffs.drowsy.desc=A magical force is making it difficult to stay awake.\n\nThe hero can resist drowsiness by taking damage or by being at full health.\n\nAfter a few turns, the target will fall into a deep magical sleep. +actors.buffs.drowsy.name=Drowsy +actors.buffs.dry.desc=Drying makes you upset, unable to concentrate on fighting, and reduce your damage. \n\nTurns of dry remaining: %s. +actors.buffs.dry.name=Dry + +actors.buffs.exitfind.name=Exit Find + +actors.buffs.earthimbue.desc=You are imbued with the power of earth!\n\nAll physical attacks will command roots to lock the enemy in place while the effect lasts.\n\nTurns of earth imbue remaining: %s. +actors.buffs.earthimbue.name=Imbued with Earth + +actors.buffs.fireimbue.desc=You are imbued with the power of fire!\n\nAll physical attacks will have a chance to light enemies ablaze. Additionally, you are completely immune to the effects of fire.\n\nTurns of fire imbue remaining: %s. +actors.buffs.fireimbue.name=Imbued with Fire + +actors.buffs.frostimbue.desc=You are filled with the power of cold ice! All physical attacks have the opportunity to freeze the enemy. In the meantime, you're completely immune to freezing. The force effect of residual ice is left:%s turn +actors.buffs.frostimbue.name=Imbued with Ice + +actors.buffs.toxicimbue.desc=You are imbued with poisonous energy!\n\nAs you move around toxic gas will constantly billow forth from you, damaging your enemies. You are immune to toxic gas and poison for the duration of the effect.\n\nTurns of toxic imbue remaining: %s. +actors.buffs.toxicimbue.name=Imbued with Toxicity + +actors.buffs.bloodimbue.desc=Blood imbue will help you immune some debuff and improve your damage,\n\nBlood imbue left : %s turns +actors.buffs.bloodimbue.name=Blood imbue + +actors.buffs.frost.desc=Not to be confused with freezing solid, this more benign freezing simply encases the target in ice.\n\nFreezing acts similarly to paralysis, making it impossible for the target to act. Unlike paralysis, freezing is immediately cancelled if the target takes damage, as the ice will shatter.\n\nTurns of freeze remaining: %s. +actors.buffs.frost.freezes=%s freezes! +actors.buffs.frost.name=Frozen +actors.buffs.fullmoonstrength.desc=You become stronger, and you will deal 2.5 damage. +actors.buffs.fullmoonstrength.heromsg=You become stronger. +actors.buffs.fullmoonstrength.name=Moon power +actors.buffs.fury.desc=You are angry, enemies won't like you when you're angry.\n\nA great rage burns within you, increasing the damage you deal with physical attacks by 25%% and reduce damage you taken by 25%.\n\nThis rage will last as long as you are injured below 60% health. +actors.buffs.fury.heromsg=You become furious! +actors.buffs.fury.name=Furious +actors.buffs.gasesimmunity.desc=Some strange force is filtering out the air around you, it's not causing you any harm, but it blocks out everything but air so effectively you can't even smell anything!\n\nYou are immune to the effects of all gasses while this buff lasts.\n\nTurns of gas immunity remaining: %s. +actors.buffs.gasesimmunity.name=Immune to gases +actors.buffs.glassshield.desc=This buff is some kind of bless by god of glass, it will reduce any damage to 10 . Bless Left: %s. +actors.buffs.glassshield.name=Glass Shield +actors.buffs.growseed.desc=You will lost health, and heal others.\n\nleft time:%s turns +actors.buffs.growseed.heromsg=Strange seeds grow on you. +actors.buffs.growseed.name=Leech Seed +actors.buffs.haste.desc=You move fast, %s turns left. +actors.buffs.haste.name=Haste +actors.buffs.hot.desc=Hot make you easy to take damage. \n\nTurns of hot remaining: %s. +actors.buffs.hot.name=Hot +actors.buffs.hunger.cursedhorn=The cursed horn steals some of the food energy as you eat. +actors.buffs.hunger.desc=\n\nHunger slowly increases as you spend time in the dungeon, eventually you will begin to starve. While starving you will slowly lose health instead of regenerating it.\n\nRationing is important! If you have health to spare starving isn't a bad idea if it means there will be more food later. Effective rationing can make food last a lot longer! +actors.buffs.hunger.desc_intro_hungry=You can feel your stomach calling out for food, but it's not too urgent yet. +actors.buffs.hunger.desc_intro_overfed=Overfed fills you with determination and improves your damage. +actors.buffs.hunger.desc_intro_starving=You're so hungry it hurts. +actors.buffs.hunger.hungry=Hungry +actors.buffs.hunger.onhungry=You are hungry. +actors.buffs.hunger.onoverfed=You are overfed. +actors.buffs.hunger.onstarving=You are starving, +actors.buffs.hunger.overfed=Overfed +actors.buffs.hunger.starving=Starving +actors.buffs.invisibility.desc=You are completely blended into the surrounding terrain, making you impossible to see.\n\nWhile you are invisible enemies are unable to attack or follow you. Physical attacks and magical effects (such as scrolls and wands) will immediately cancel invisibility.\n\nTurns of invisibility remaining: %s. +actors.buffs.invisibility.name=Invisible +actors.buffs.levitation.desc=A magical force is levitating you over the ground, making you feel weightless.\n\nWhile levitating you ignore all ground-based effects. Traps won't trigger, water won't put out fire, plants won't be trampled, roots will miss you, and you will hover right over pits. Be careful, as all these things can come into effect the second the levitation ends!\n\nTurns of levitation remaining: %s. +actors.buffs.levitation.name=Levitating +actors.buffs.light.desc=Even in the Darkest Dungeon, a steady light at your side is always comforting.\n\nLight helps keep darkness at bay, allowing you to see a reasonable distance despite the environment.\n\nTurns of illumination remaining: %s. +actors.buffs.light.name=Illuminated +actors.buffs.highlight.desc=Even in the Darkest Dungeon, a steady light at your side is always comforting.\n\nLight helps keep darkness at bay, allowing you to see a unreasonable distance despite the environment.\n\nTurns of illumination remaining: %s. +actors.buffs.highlight.name=high light +actors.buffs.locked.desc=Invisible lock locked your backpack, so you can't use some items, left %s turns. +actors.buffs.locked.name=Locked +actors.buffs.lokispoison.desc=Poison works its way through the body, slowly impairing its internal functioning.\n\nPoison deals damage each turn proportional to how long until it expires.\n\nTurns of poison remaining: %s. +actors.buffs.lokispoison.heromsg=You are poisoned! +actors.buffs.lokispoison.name=Power poison +actors.buffs.magicalsleep.desc=This character has fallen into a deep magical sleep which they will not wake from naturally.\n\nMagical sleep is similar to regular sleep, except that only damage will cause the target to wake up.\n\nFor the hero, magical sleep has some restorative properties, allowing them to rapidly heal while resting. +actors.buffs.magicalsleep.fallasleep=You fall into a deep magical sleep. +actors.buffs.magicalsleep.name=Magical Sleep +actors.buffs.magicalsleep.toohealthy=You are too healthy, and resist the urge to sleep. +actors.buffs.magicalsleep.wakeup=You wake up feeling refreshed and healthy. +actors.buffs.magicimmunity.desc=Magic immunity can help you resistances some buffs.\n\nTurn left : %s +actors.buffs.magicimmunity.name=Magic shield +actors.buffs.mindvision.desc=Somehow you are able to see all creatures on this floor through your mind. It's a weird feeling.\n\nAll characters on this floor are visible to you as long as you have mind vision. Seeing a creature through mind vision counts as it being seen or nearby for the purposes of many magical effects.\n\nTurns of mind vision remaining: %s. +actors.buffs.mindvision.name=Mind vision +actors.buffs.muscle.desc=Gain 2 str. Left: %s turns. +actors.buffs.muscle.name=Muscle +actors.buffs.ooze.desc=This sticky acid clings to flesh, slowly melting it away.\n\nOoze will deal consistent damage until it is washed off in water.\n\nOoze does not expire on its own and must be removed with water. +actors.buffs.ooze.heromsg=Caustic ooze eats your flesh. Wash it away! +actors.buffs.ooze.name=Caustic ooze +actors.buffs.paralysis.desc=Oftentimes the worst thing to do is nothing at all.\n\nParalysis completely halts all actions, forcing the target to wait until the effect wears off. The pain from taking damage can also cause characters to snap out of paralysis.\n\nTurns of paralysis remaining: %s. +actors.buffs.paralysis.heromsg=You are paralysed! +actors.buffs.paralysis.name=Paralysed +actors.buffs.poison.desc=Poison works its way through the body, slowly impairing its internal functioning.\n\nPoison deals damage each turn proportional to how long until it expires.\n\nTurns of poison remaining: %s. +actors.buffs.poison.heromsg=You are poisoned! +actors.buffs.poison.name=Poisoned +actors.buffs.recharging.desc=Energy is coursing through you, improving the rate that your wands and staffs charge.\n\nEach turn this buff will increase current charge by one quarter, in addition to regular recharge.\n\nTurns of recharging remaining: %s. +actors.buffs.recharging.name=Recharging +actors.buffs.rhythm.desc=Your rhythm improve your hit skill and evade skill, left %s turns. +actors.buffs.rhythm.name=Rhythm +actors.buffs.rhythm2.desc=Your echo rhythm improve your speed, attack and defense, left %s turns. +actors.buffs.rhythm2.name=Echo +actors.buffs.roots.desc=Roots (magical or natural) grab at the feet, forcing them down to the ground.\n\nRoots lock a target in place, making it impossible for them to move, but other actions are not affected.\n\nTurns of root remaining: %s. +actors.buffs.roots.heromsg=You can't move! +actors.buffs.roots.name=Rooted +actors.buffs.shadows.desc=You are blended into the shadows around you, granting you invisibility and slowing your metabolism.\n\nWhile you are invisible enemies are unable to attack or follow you. Most physical attacks and magical effects (such as scrolls and wands) will immediately cancel invisibility. Additionally, while shadowmelded, your rate of hunger is slowed.\n\nYou will remain shadowmelded until you leave the shadows or an enemy comes into contact with you. +actors.buffs.shadows.name=Shadowmelded +actors.buffs.shield.desc=Super shield +actors.buffs.shield.name=Moon shield +actors.buffs.shieldblock.desc=This debuff is upgrade by stun.\n\nturn left : %s +actors.buffs.shieldblock.name=Holy stun +actors.buffs.shocked.desc=Lightning coarses through your body, waiting for a moment to be released, attack will discharge it, and disarm your hand. left %s turns.. +actors.buffs.shocked.name=Electrostatic turbulence +actors.buffs.silent.desc=Can't use scroll and wand, %s turns left. +actors.buffs.silent.name=silent +actors.buffs.slow.desc=Slowing magic affects the target's rate of time, to them everything is moving super-fast.\n\nA slowed character performs all actions in twice the amount of time they would normally take.\n\nTurns of slow remaining: %s. +actors.buffs.slow.name=Slowed +actors.buffs.snipersmark.desc=The sniper is honed in on a nearby target, gaining increased attack speed and armor penetration while attacking it.\n\nThe sniper will remain honed in until she switches targets, stops attacking, or the target dies. +actors.buffs.snipersmark.name=Sniper's mark +actors.buffs.soulmark.desc=The warlock has tapped into the soul of this creature. He will heal and satisfy his hunger as it takes physical damage.\n\nTurns of soul mark remaining: %s. +actors.buffs.soulmark.name=Soul Mark +actors.buffs.speed.desc=Move fast +actors.buffs.speed.name=Speed +actors.buffs.strength.desc=Next attack will be powerful. +actors.buffs.strength.name=Strength +actors.buffs.tar.desc=Tar make you slower and easy to fire. +actors.buffs.tar.heromsg=Tar is covered with your body. +actors.buffs.tar.name=Tar + +actors.buffs.terror.desc=Terror is manipulative magic which forces its target into an uncontrollable panic.\n\nTerrified characters are forced to run away from their opponent, trying to put as many doors and walls between them as possible. The shock of pain is enough to break this effect, however.\n\nTurns of terror remaining: %s. +actors.buffs.terror.name=Terrified + +actors.buffs.venom.desc=Venom is a extremely caustic and dangerous poison.\n\nUnlike poison, whose damage lowers over time, venom does increasing damage the longer it stays on a target.\n\nTurns of venom remaining: %s.\nCurrent venom damage: %d. +actors.buffs.venom.name=Venomed +actors.buffs.vertigo.desc=Walking in a straight line can be difficult when the whole world is spinning.\n\nWhile under the effects of vertigo, characters who attempt to move will go in a random direction, instead of the one they intended to go in.\n\nTurns of vertigo remaining: %s. +actors.buffs.vertigo.name=Vertigo +actors.buffs.weakness.desc=Your gear suddenly feels a lot heavier.\n\nWeakening magic is affecting you, reducing your effective strength by 2 points.\n\nTurns of weakness remaining: %s. +actors.buffs.weakness.heromsg=You feel weakened! +actors.buffs.weakness.name=Weakened +actors.buffs.wet.desc=Wet makes your body heavy, make your hard to hit target and dodge attack. \n\nTurns of wet remaining: %s. +actors.buffs.wet.name=Wet + +actors.buffs.shieldarmor.name=Alien Shield +actors.buffs.shieldarmor.desc=A kind of energy armor is protecting you.\n\nThis herbal armor will absorb 100%% of all damage you take, until it eventually runs out of durability and collapses.\n\nArmor remaining: %d. + +actors.buffs.feed.name=Feed +actors.buffs.feed.desc=You will gain more health limit from each mob you killed. %s turn left. + +actors.buffs.bloodangry.name=Blood Angry +actors.buffs.bloodangry.desc=It make you stronger. %s turns left. + +actors.buffs.soulbless.name=Soul Bless +actors.buffs.soulbless.desc=It wasn't be add yet. + +actors.buffs.goldtouch.name=Gold Touch +actors.buffs.goldtouch.desc=You will get gold when you are attacking. %s turns left. + +actors.buffs.needling.name=needling +actors.buffs.needling.desc=It will help you in battle. %s turns left. + +actors.buffs.forevershadow.name=Forever Shadow +actors.buffs.forevershadow.desc=You will can't be find until it disappare. %s turns left. + +actors.buffs.notice.name=notice +actors.buffs.notice.desc=Notice helps you find secret. %s turns left. + +actors.buffs.wargroove.name=War Groove +actors.buffs.wargroove.desc=It will improve you attack until you next melee attack. + +actors.buffs.targetshoot.name=target shoot +actors.buffs.targetshoot.desc=Range weapon skill + 10. \n\n %s turn left. + +actors.buffs.mecharmor.name=Drive MECH +actors.buffs.mecharmor.desc=You are drive MECH now. \n\n MECH's HP : %s. + +actors.buffs.spattack.name=Surprise attack +actors.buffs.spattack.desc=Deal more damage to enemy with full health or low health.\n\n%s turns left. + +actors.buffs.highattack.name=Climb higher +actors.buffs.highattack.desc=By climb higher, you can prepare for your next attack. The more time you climb, more damage you will deal in your next melee attack. away from wall will remove this buff.\n\nNext damage bound:%s. + +actors.buffs.paryattack.name=pray +actors.buffs.paryattack.desc=By stand, you can prepare for your battle. The more time you stand, more damage you will deal, and less damage you will taken. away from this place will remove this buff.\n\nDamage bound:%s. + + +actors.buffs.highvoice.name=Accompaniment +actors.buffs.highvoice.desc=Your fans accompany for you, make you feel safe.\n\n Left:%sturns. +actors.buffs.highvoice.atkup=%sYou're the best! +actors.buffs.highvoice.heal=%sI love you! +actors.buffs.highvoice.speed=Be careful%s! +actors.buffs.highvoice.save=I always behind you,%s + +actors.buffs.mirrorshield.name=Wisdom reflection +actors.buffs.mirrorshield.desc=The shield of wisdom protects you so that you can fully rebound the damage you suffer next. \n\nLeft:%s turns. + +actors.buffs.boxstar.name=Star +actors.buffs.boxstar.desc=You're invincible. \n\n%sturns left. + +actors.buffs.breakout.name=Eruption +actors.buffs.breakout.desc=You decide to attack with all your might, causing and suffering a 100% increase in damage at the same time. \n\nDuration%s. + +actors.buffs.aflybless.name=fushigi-no bless +actors.buffs.aflybless.desc=Fushigi-no bless improve your body and your luck\n\n%sturns left. + +actors.buffs.taunt.name=Question mark +actors.buffs.taunt.desc=??? + +actors.buffs.damageup.name=Counter attack +actors.buffs.damageup.desc=Attack damage improve %s. + +actors.buffs.newcombo.name=Fighter hit +actors.buffs.newcombo.combo=%dhit +actors.buffs.newcombo.bad_target= Your target must be an enemy within range. +actors.buffs.newcombo.clobber_prompt=Select a target to break and make it back and faint +actors.buffs.newcombo.clobber_desc= _ breakdown _ skill to be translated is currently available. This move can repel an enemy and make it faint, but the attack damage will be reduced. Beating up an enemy can give you a breath in a hard battle +actors.buffs.newcombo.cleave_prompt=Select a target to be chopped if this skill kill the enemy, the number of hits will be retained +actors.buffs.newcombo.cleave_desc=_ chopping _ skills are currently available. This attack deals more damage. If you succeed in killing the enemy by chopping, the serial strike count will be retained rather than reset. _ the number of hits can be effectively accumulated in the face of a large number of enemies. +actors.buffs.newcombo.slam_prompt=Select a target to hit according to your armor to decide on the damage and the added shield +actors.buffs.newcombo.slam_desc=_Slam_ is currently available. This attack deals _increased damage and shields you based on the blocking power of your armor._ It's great for finishing a fight, letting you carry over endurance to the next one. +actors.buffs.newcombo.crush_prompt=Select a target to Crush\nDeals lots of damage +actors.buffs.newcombo.crush_desc=_Crush_ is currently available. This devastating attack _deals massive damage very consistently._ It's great for taking down a powerful opponent from high health! +actors.buffs.newcombo.desc=The gladiator builds momentum as they land successful blows. Each attack increases the combo counter by one, but taking too long between attacks or missing twice in a row will reset the combo counter to 0.\n\nBuilding combo unlocks special finisher abilities: powerful attacks that cannot miss! A different finisher is available at 2, 4, 6, and 8 combo count, and using a finisher will reset your combo. + +actors.buffs.corruption.name=Dominate +actors.buffs.corruption.desc=It is been dominate, just like corruption. + +actors.buffs.faithbuff.mechfaith.name=Faith-Mech +actors.buffs.faithbuff.mechfaith.desc=Mech faith reduce damage from mech mobs, and make you deal more damage to nature mobs. + +actors.buffs.faithbuff.lifefaith.name=Faith-Nature +actors.buffs.faithbuff.lifefaith.desc=Nature faith reduce damage from nature mobs, and make you deal more damage to mech mobs. + +actors.buffs.faithbuff.demonfaith.name=Faith-Demon +actors.buffs.faithbuff.demonfaith.desc=Demon faith reduce damage from demon mobs, and make you deal more damage to holy mobs. + +actors.buffs.faithbuff.humanfaith.name=Faith-Holy +actors.buffs.faithbuff.humanfaith.desc=Holy faith reduce damage from holy mobs, and make you deal more damage to demon mobs. + +actors.buffs.faithbuff.balancefaith.name=Faith-Balance +actors.buffs.faithbuff.balancefaith.desc=Balance faith reduce damage from bosses, and make you deal more damage to them. +actors.buffs.stoneice.name=stone ice +actors.buffs.stoneice.desc=improve damage but slow speed. if you move you will taken lots of damage. \n\n %s turns left. +###hero +actors.char.def_verb=dodged +actors.char.out_of_paralysis=The pain snapped %s out of paralysis. + +actors.hero.hero.auto_potion=You drink a potion of healing by your auto potion. +actors.hero.hero.auto_potion_no=You don't have potion of healing. +actors.hero.hero.dewvial=It is different. +actors.hero.hero.leave=One does not simply leave Pixel Dungeon. +actors.hero.hero.level_up=Level up! +actors.hero.hero.locked_chest=This chest is locked and you don't have matching key. +actors.hero.hero.locked_door=You don't have a matching key. +actors.hero.hero.name=You +actors.hero.hero.new_level=Welcome to level %d! Now you are healthier and more focused. It's easier for you to hit enemies and dodge their attacks. +actors.hero.hero.noticed_smth=You noticed something. +actors.hero.hero.pain_resist=Pain resist you from your dream. +actors.hero.hero.revive=The ankh explodes with life-giving energy! +actors.hero.hero.search=search +actors.hero.hero.search_distracted=You can't concentrate, searching takes a while. +actors.hero.hero.something_else=There is something else here. +actors.hero.hero.wait=... +actors.hero.hero.you_now_have=You now have %s. + +actors.hero.heroclass.huntress=huntress +actors.hero.heroclass.huntress_desc_item=Huntress have _Knuckleduster_ and _EMP bola_.\n\n _Boomerang_ is her special item. +actors.hero.heroclass.huntress_desc_loadout=When using throwing weapons, Huntress will deal more damage based on melee weapon her use.\n\nHuntress senses neighbouring monsters even if they are hidden behind obstacles. +actors.hero.heroclass.huntress_desc_misc=_Potions of Mind Vision_ and _Scroll of Remove Curse_ are identified from the beginning. + +actors.hero.heroclass.mage=mage +actors.hero.heroclass.mage_desc_item=Mage have _magebook_ , _Wand of Magic Missile_ and _Wand of Disintegration_ .\n\n _Wonder Flask_ is his special item. +actors.hero.heroclass.mage_desc_loadout=Mage spend less time on using wand, and gain +3 magic power.\n\nMage have higher level limit when using dew upgrade, and gain one wand charge after eat anything. +actors.hero.heroclass.mage_desc_misc=_Scrolls of Identify_ and _Potion of Liquid Flame_ are identified from the beginning. + +actors.hero.heroclass.performer=Performer +actors.hero.heroclass.performer_desc_item=Performer have _triangolo_, _Scroll of Lullaby_ and _Bomb_ .\n\n _shovel_ is his special item. +actors.hero.heroclass.performer_desc_loadout=After kill or level up performer will gain rhythm buff, which can upgrade his accuracy and dexterity for a limit time.\n\nAfter level up performer will gain glass shield. which can reduce damage he taken. +actors.hero.heroclass.performer_desc_misc=_Scrolls of Lullaby_ and _Potion of Purity_ are identified from the beginning. + +actors.hero.heroclass.rogue=rogue +actors.hero.heroclass.rogue_desc_item=Rogue have _dagger_ and _Smoke Shuriken_ .\n\n_Cloak of Shadows_ is his special item. +actors.hero.heroclass.rogue_desc_loadout=When rogue equip weapon,ignore 2 strength to use it.\n\nRogue is more proficient in detecting hidden doors or traps. +actors.hero.heroclass.rogue_desc_misc=_Scroll of Magic Mapping_ and _Potion of Invisibility_ are identified from the beginning. + +actors.hero.heroclass.warrior=warrior +actors.hero.heroclass.warrior_desc_item=Warrior have _shortsword_ and three different _Pills_ .\n\n_shield_ is his special item. +actors.hero.heroclass.warrior_desc_loadout=When warrior equip armor,ignore 2 strength to use it.\n\nWarrior gain more health after eat anything. +actors.hero.heroclass.warrior_desc_misc=_Potions of Strength_ and _Scroll of Upgrade_ are identified from the beginning. + +actors.hero.heroclass.soldier=Soldier +actors.hero.heroclass.soldier_desc_item=Soldier have _sling_ and _Escape Knive_ .\n\n_pulse pistol_ is his special item. +actors.hero.heroclass.soldier_desc_loadout=Soldier has more ACU and DEX at the start, and gain more health limit when leveling up.\n\nSoldier is more luckily than other hero, and can notice curse items in backpack. +actors.hero.heroclass.soldier_desc_misc=_Scrolls of Rage_ and _Potion of Mending_ are identified from the beginning. + +actors.hero.heroclass.follower=follower +actors.hero.heroclass.follower_desc_item=Follower have _WoodenStaff_ and _Potion Of Healing_ .\n\n_sign box_ is his special item. +actors.hero.heroclass.follower_desc_loadout=Follower has chance to use a item with no cost, include potions, scrolls, foods, and enchanting items.\n\nFollower spend less gold in shop. +actors.hero.heroclass.follower_desc_misc=_Scrolls of Terror_ and _Potion of Healing_ are identified from the beginning. + +actors.hero.herosubclass.pastor=pastor +actors.hero.herosubclass.pastor_desc=_pastor_ heal himself fast, allowed his health more than health limit,and charm enemy after attack. +actors.hero.herosubclass.artisan=artisan +actors.hero.herosubclass.artisan_desc=_artisan_ will reduce his item's str require, and have chance to find a ex item drop after kill any mobs. +actors.hero.herosubclass.agent=agent +actors.hero.herosubclass.agent_desc=_Agent_ can use guns without equip them, and reload ammo quickly. He also has more stealth. +actors.hero.herosubclass.leader=leader +actors.hero.herosubclass.leader_desc=_Leader_ can upgrade everything he summoned, and harm enemy which attack him. He also can reduce damage he taken. +actors.hero.herosubclass.assassin=assassin +actors.hero.herosubclass.assassin_desc=When performing a surprise attack, the _Assassin_ inflicts additional damage to his target. +actors.hero.herosubclass.battlemage=battlemage +actors.hero.herosubclass.battlemage_desc=_Battlemage_ spend less time when using wand and gain more magic power. +actors.hero.herosubclass.berserker=berserker +actors.hero.herosubclass.berserker_desc=When severely wounded, the _Berserker_ enters a state of wild fury significantly increasing his damage output and reduces some damage when getting hurt. +actors.hero.herosubclass.freerunner=freerunner +actors.hero.herosubclass.freerunner_desc=The _Freerunner_ moves faster when he unencumbered and not starving, if he is invisible, this speed boost is increased. +actors.hero.herosubclass.gladiator=gladiator +actors.hero.herosubclass.gladiator_desc=A successful attack with a melee weapon allows the _Gladiator_ to start a combo, in which every next successful hit inflicts more damage. +actors.hero.herosubclass.joker=Joker +actors.hero.herosubclass.joker_desc=_Joker_ is good at battle. He can attack enemy on range and knock it back. +actors.hero.herosubclass.sniper=sniper +actors.hero.herosubclass.sniper_desc=The _Sniper_ is able to detect weak points in an enemy's armor, effectively ignoring it when using a missile weapon. +actors.hero.herosubclass.superstar=Super-Star +actors.hero.herosubclass.superstar_desc=_Super-Star_ is much powerful in music. He can upgrade his rhythm buff into echo-rhythm buff. +actors.hero.herosubclass.warden=warden +actors.hero.herosubclass.warden_desc=Having a strong connection with forces of nature allows the _Warden_ to gain additional health from dew, hiding in trampling grass, and seeds and dew from plants. +actors.hero.herosubclass.warlock=warlock +actors.hero.herosubclass.warlock_desc=After use wand attack an enemy the _Warlock_ will consumes its soul. It heals his wounds and satisfies his hunger. + +###really +###this is for save game +actors.hero.heroclass.warrior_name=warrior +actors.hero.heroclass.mage_name=mage +actors.hero.heroclass.rogue_name=rogue +actors.hero.heroclass.huntress_name=huntress +actors.hero.heroclass.performer_name=performer +actors.hero.heroclass.soldier_name=soldier +actors.hero.heroclass.follower_name=follower + +###mobs +actors.mobs.acidic.desc=Acidic scorpio is more dangerous than normal scorpio. The acid in its body releases when it is in danger, and protects itself against predators. +actors.mobs.acidic.name=Acidic scorpio +actors.mobs.adultdragonviolet.atk=Away from here! Intruder! +actors.mobs.adultdragonviolet.desc=Guard dungeon is summon by someone, but in peoples' eyes, it same as normal dungeon. +actors.mobs.adultdragonviolet.die=For Dolye town!! +actors.mobs.adultdragonviolet.name=Guard dungeon +actors.mobs.albino.desc=This is a rare breed of marsupial rat, with pure white fur and jagged teeth. Dark energy makes demon blood around it. +actors.mobs.albino.name=Albino rat +actors.mobs.albinopiranha.desc=The Albino giant piranha living in this place have been degenerating for hundreds of years. However, their other senses are unusually sensitive, and they can feel the changes of water flow around them, and they are also very ferocious. +actors.mobs.albinopiranha.name=Albino giant piranha +actors.mobs.assassin.def_verb=evaded +actors.mobs.assassin.desc=Assassin ninja are members of the Tengu assassin clan. They fight with ranged attacks at high speed. +actors.mobs.assassin.name=Assassin ninja +actors.mobs.bandit.desc=Crazy bandit can harm target when steal from it. +actors.mobs.bandit.name=Crazy bandit +actors.mobs.banditking.desc=This thief can put bombs on your body. +actors.mobs.banditking.die=Give you a break this time. +actors.mobs.banditking.dis=Life bandit disapper. +actors.mobs.banditking.name=Life bandit +actors.mobs.banditking.spork=Where is my treasure? +actors.mobs.bat.def_verb=evaded +actors.mobs.bat.desc=These brisk and tenacious inhabitants of cave domes may defeat much larger opponents by replenishing their health with each successful attack. +actors.mobs.bat.name=Vampire bat + +actors.mobs.bluecat.name=Blue*Cat +actors.mobs.bluewraith.def_verb=evaded +actors.mobs.bluewraith.desc=A Wraith warrior has been dispatched to avenge the dungeon. +actors.mobs.bluewraith.name=Wraith warrior +actors.mobs.brokenrobot.broken=System... down... +actors.mobs.brokenrobot.desc=A wandering robot unfinshed and broken down. You can feel its malice toward intruders. +actors.mobs.brokenrobot.explode=Explode on!! +actors.mobs.brokenrobot.name=Broken robot +actors.mobs.brownbat.def_verb=evaded +actors.mobs.brownbat.desc=Basically small, flying rats. Careful they don't get tangled in your hair. +actors.mobs.brownbat.die=The small bat's shrieks alert nearby enemies! +actors.mobs.brownbat.name=Small bat +actors.mobs.brute.desc=Brutes are the largest, strongest and toughest of all gnolls. When severely wounded, they go berserk, inflicting even more damage to their enemies. +actors.mobs.brute.enraged=Gnoll brute become enraged. +actors.mobs.brute.name=Gnoll brute +actors.mobs.crab.def_verb=parried +actors.mobs.crab.desc=These huge crabs are at the top of the food chain in the sewers. They are extremely fast and their thick carapace can withstand heavy blows. +actors.mobs.crab.name=Sewer crab +actors.mobs.crabking.desc=The crab king collects protective magical items to protect its childs away from dangerous. He is hiding himself in a powerful suit of armor. +actors.mobs.crabking.die=Sorry... my child... +actors.mobs.crabking.heal=Crab king draws power from the lightning shell! +actors.mobs.crabking.name=Crab king +actors.mobs.crabking.notice=Ah! Away from my children! +actors.mobs.demongoo.desc=Demon Goo is typically made up of a variety of substances, such as lava, slime, dark energy, malice; however, most of it is darkness. Be careful about letting it split itself, as even the weakest piece can become strong again with just a little bit of added lava. +actors.mobs.demongoo.divide=Demon Goo divides! +actors.mobs.demongoo.name=Demon goo + + +actors.mobs.dm300.desc=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. +actors.mobs.dm300.die=Mission failed. Shutting down. +actors.mobs.dm300.heal=DM-300 repairs itself! +actors.mobs.dm300.name=DM-300 +actors.mobs.dm300.notice=Unauthorised personnel detected. +actors.mobs.dm300$tower.alert=The production line is attacked! Emergency protection measures start! +actors.mobs.dm300$tower.desc=Many years ago, dwarves built a complete line of production, but their research on magic made this production line out of maintenance. At present, these devices are very old. +actors.mobs.dm300$tower.name=Old production +actors.mobs.dm300$tower.robots=Alert...Alert... + + +actors.mobs.dragonking.desc=A normal dragon. After kill it it will summon other boss from other wrold. +actors.mobs.dragonking.name=Dragon king +actors.mobs.dustelement.blind=Dust hinder your sight. +actors.mobs.dustelement.desc=It's a cloud of dust, made by time and dark magic power. +actors.mobs.dustelement.name=dust element + +actors.mobs.dwarflich.desc=A powerful wizard sacrificed to sustain the undead dwarf king, the wizard calls on the power of death to damage opponents. +actors.mobs.dwarflich.name=Dwarf lich +actors.mobs.eye.desc=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. +actors.mobs.eye.name=Evil eye +actors.mobs.fetidrat.desc=Something is clearly wrong with this rat. Its greasy black fur and rotting skin are very different from the healthy rats you've seen previously. It's pale green eyes make it seem especially menacing.\n\nThe rat carries a cloud of horrible stench with it, it's overpoweringly strong up close.\n\nDark ooze dribbles from the rat's mouth, it eats through the floor but seems to dissolve in water. +actors.mobs.fetidrat.name=fetid rat +actors.mobs.fiend.desc=Some demons seem to transcend their flesh and wear pure darkness as their form. Shadowy and menacing, these unholy abominations are born of malicious intent and are nothing more than incarnations of distilled evil, revelling only in death and pain. +actors.mobs.fiend.name=fiend +actors.mobs.fireelemental.desc==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. +actors.mobs.fireelemental.name=Fire elemental +actors.mobs.fishprotector.desc=It is cave protector. +actors.mobs.fishprotector.name=Cave protector +actors.mobs.flyingprotector.desc=Propector of the wisdom trial. +actors.mobs.flyingprotector.name=Wisdom protector +actors.mobs.forestprotector.desc=It is forest protector. +actors.mobs.forestprotector.name=Forest protecter +actors.mobs.gnoll.desc=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. +actors.mobs.gnoll.name=Gnoll scout +actors.mobs.gnollarcher.desc=This gnoll is camouflaged and hiding in the foliage. He's pretty upset you are here. +actors.mobs.gnollarcher.name=gnoll archer +actors.mobs.gnollking$gnollkeeper.desc=Treasure guarder for gnoll king. +actors.mobs.gnollking$gnollkeeper.name=Gnoll Keeper +actors.mobs.gnollking$gnollkeeper.safe=Away from our treasure! +actors.mobs.gnollking.angry=You make me angry! +actors.mobs.gnollking.desc=Gnoll have lots of treasure, and he can summon his propectors to help him in battle. He has more than 11 different names, but the most famous name is Hagger. +actors.mobs.gnollking.die=My...treasure... +actors.mobs.gnollking.name=Gnoll king +actors.mobs.gnollking.notice=Away from my treasure! +actors.mobs.gnollshaman.desc=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. +actors.mobs.gnollshaman.name=gnoll shaman +actors.mobs.gnolltrickster.desc=A strange looking creature, even by gnoll standards. It hunches forward with a wicked grin, almost cradling the satchel hanging over its shoulder. Its eyes are wide with a strange mix of fear and excitement.\n\nThere is a large collection of poorly made darts in its satchel, they all seem to be tipped with various harmful substances. +actors.mobs.gnolltrickster.name=gnoll trickster +actors.mobs.goldorc.def_verb=blocked +actors.mobs.goldorc.desc=Dark energy corrupt bokoblin, change them into dangerous mobs. +actors.mobs.goldorc.name=Gold eye Bokoblin +actors.mobs.goldthief.desc=Unlike other types of thieves, these only care for one specific thing: shiny, golden money. Be careful about letting them steal from you, as recovering lost gold from the tides of these like-minded thieves will be rather difficult. +actors.mobs.goldthief.name=Gold thief +actors.mobs.goldthief.stole=Gold thief steal %s golds from you! +actors.mobs.golem.def_verb=blocked +actors.mobs.golem.desc=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. +actors.mobs.golem.name=Golem + +actors.mobs.goo.atk=Goo is pumping itself up! +actors.mobs.goo.desc=Little is known about The Goo. It's quite possible that it is not even a creature, but rather a conglomerate of vile substances from the sewers that somehow gained basic intelligence. Regardless, dark magic is certainly what has allowed Goo to exist.\n\nIts gelatinous nature has let it absorb lots of dark energy, you feel a chill just from being near. If goo is able to attack with this energy you won't live for long. +actors.mobs.goo.die=glurp... glurp... +actors.mobs.goo.name=Sewer goo +actors.mobs.goo.notice=GLURP-GLURP! +actors.mobs.goo$poisongoo.create=Goo creates mini goo! +actors.mobs.goo$poisongoo.desc=Little is known about The Goo. It's quite possible that it is not even a creature, but rather a conglomerate of vile substances from the sewers that somehow gained basic intelligence. Regardless, dark magic is certainly what has allowed Goo to exist.\n\nIts gelatinous nature has let it absorb lots of dark energy, you feel a chill just from being near. If goo is able to attack with this energy you won't live for long. +actors.mobs.goo$poisongoo.divide=Mini Goo divides! +actors.mobs.goo$poisongoo.name=Mini Goo +actors.mobs.goo$poisongoo.squeeze=Goo is pumping itself up! + + +actors.mobs.graveprotector.desc=It is prison protector. +actors.mobs.graveprotector.name=Grave protecter +actors.mobs.greatcrab.noticed=The crab notices the attack and blocks with its massive claw. +actors.mobs.greatcrab.blocked=blocked +actors.mobs.greatcrab.def_verb=blocked +actors.mobs.greatcrab.desc=This crab is gigantic, even compared to other sewer crabs. Its blue shell is covered in cracks and barnacles, showing great age. It lumbers around slowly, barely keeping balance with its massive claw.\n\nWhile the crab only has one claw, its size easily compensates. The crab holds the claw infront of itself whenever it sees a threat, shielding itself behind an impenetrable wall of carapace. +actors.mobs.greatcrab.name=great crab +actors.mobs.greyrat.desc=Heartier cousins to Marsupial rats, Grey Rats have built up tolerances that allow them to live in the most polluted parts of the sewers. Probably still good to eat once cooked. +actors.mobs.greyrat.name=Grey rat +actors.mobs.guard.def_verb=blocked +actors.mobs.guard.desc=Once keepers of the prison, these guards have long since become no different than the inmates. They shamble like zombies, brainlessly roaming through the halls in search of anything out of place, like you!\n\nThey carry chains around their hip, possibly used to pull in enemies to close range. +actors.mobs.guard.name=prison guard +actors.mobs.guard.scorpion=Come over here! +actors.mobs.hermitcrab.absorb=Hermit Crab absorbed the attack in its shell. +actors.mobs.hermitcrab.charge=Lightning Shell charged by %s. +actors.mobs.hermitcrab.desc=Minions of the crab king, these tough crabs absorb all but the weakest attacks with their shells. The damage they absorb is used to charge the lightning shell. +actors.mobs.hermitcrab.name=hermit crab + + +actors.mobs.king$undead.def_verb=blocked +actors.mobs.king$undead.desc=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. +actors.mobs.king$undead.name=undead dwarf +actors.mobs.king.arise=Arise, slaves! +actors.mobs.king.cannot=I haven't lost it yet! +actors.mobs.king.def_verb=parried +actors.mobs.king.desc=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. +actors.mobs.king.die=You cannot kill me, %s... I am... immortal... +actors.mobs.king.liches=Liches, revive! +actors.mobs.king.meeting=Show your permission! +actors.mobs.king.name=King of Dwarves +actors.mobs.king.notice=How dare you! +actors.mobs.king$dwarfkingtomb.desc=This tomb is made by bone and something you don't know. +actors.mobs.king$dwarfkingtomb.impossible=That is useless. +actors.mobs.king$dwarfkingtomb.name=Eternal tomb + +actors.mobs.littower.desc=Otiluke use his slate to keep core safe, before his mirror died, this slate will keep work! +actors.mobs.littower.name=Otiluke lightning slate +actors.mobs.littower.zap=Away from core! +actors.mobs.livemoss.desc=One mob from slay the spire. +actors.mobs.livemoss.name=living moss +actors.mobs.magiceye.desc=This magic eye is made by ZOT's power. It is base on magic so it will die after it attack. +actors.mobs.magiceye.name=magic eye +actors.mobs.mimic.desc=Mimics are magical creatures which can take any shape they wish. In dungeons they almost always choose a shape of a treasure chest, because they know how to beckon an adventurer. +actors.mobs.mimic.name=mimic +actors.mobs.minesentinel.desc=Otiluke summon this to propect this place. It hands _%s_ , looks dangerous. +actors.mobs.minesentinel.name=animated steel +actors.mobs.mob$fleeing.status=This %s is fleeing. +actors.mobs.mob$hunting.status=This %s is hunting. +actors.mobs.mob$passive.status=This %s is passive. +actors.mobs.mob$sleeping.status=This %s is sleeping. +actors.mobs.mob$wandering.status=This %s is wandering. +actors.mobs.mob.clear1=Level cleared in %s moves under goal. +actors.mobs.mob.clear2=Level cleared in 1 move under goal. +actors.mobs.mob.clear3=Level cleared over goal moves. +actors.mobs.mob.died=You hear something died in the distance. +actors.mobs.mob.exp=%+dEXP +actors.mobs.mob.killcount=Kill count:%s +actors.mobs.mob.rage=\#$%^ +actors.mobs.mob.rankings_desc=Killed by:%s +actors.mobs.monk.def_verb=parried +actors.mobs.monk.desc=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. +actors.mobs.monk.disarm=The monk knocks the %s from your hands! +actors.mobs.monk.name=dwarf monk +actors.mobs.mossyskeleton.def_verb=blocked +actors.mobs.mossyskeleton.desc=This skeleton is covered by mossy. +actors.mobs.mossyskeleton.name=mossy skeleton + +actors.mobs.musketeer.desc=In the dwarven King dominated the parliament with necromancy after a general uprising led a striker, although the results of how to know, but after the dwarf shooter will officially joined the dwarven kingdom of the patrol. +actors.mobs.musketeer.name=Darwf Musketeer +actors.mobs.orbofzotmob.desc=You use this thing and it is attacking mobs. +actors.mobs.orbofzotmob.die=Energy down, waiting for charge. +actors.mobs.orbofzotmob.name=Zot destructo +actors.mobs.orc.def_verb=blocked +actors.mobs.orc.desc=A creature live in power trial. +actors.mobs.orc.name=Bokoblin +actors.mobs.otiluke.desc=This mirror is made by zot, based on otiluck. +actors.mobs.otiluke.name=Corrupted mirror +actors.mobs.otiluke.summon=Protect... here... +actors.mobs.piranha.desc=These carnivorous fish are not natural inhabitants of underground pools. They were bred specifically to protect flooded treasure vaults. +actors.mobs.piranha.name=giant piranha + +actors.mobs.plaguedoctor.crazy=plaguedoctor's resolve is tested......madness!!! +actors.mobs.plaguedoctor.desc=He is from remix. His idea is from darkest dungeon. +actors.mobs.plaguedoctor.name=plague doctor +actors.mobs.plaguedoctor.notice=so... can you help me with my research ? +actors.mobs.plaguedoctor.yell2=plague... they are everywhere... we will die here... +actors.mobs.plaguedoctor.yell=I will show you, this won't be hurt... +actors.mobs.plaguedoctor$shadowrat.desc=It is some kind of shadows. It looks like rat, +actors.mobs.plaguedoctor$shadowrat.name=shadow rat + +actors.mobs.prisonwander$seekbombp.name=Seeking bombs +actors.mobs.prisonwander$seekbombp.desc=Seeking bomb +actors.mobs.prisonwander.desc=It means he is the king of this prison. +actors.mobs.prisonwander.die=I will be back! +actors.mobs.prisonwander.name=prison warden +actors.mobs.prisonwander.notice=I see youuuuuuuu! +actors.mobs.prisonwander.scorpion=Noone can leave here! + +actors.mobs.rat.desc=Marsupial rats are aggressive but rather weak denizens of the sewers. They have a nasty bite, but are only life threatening in large numbers. +actors.mobs.rat.name=marsupial rat +actors.mobs.ratboss.desc=This is leader rat, it can summon other rats, +actors.mobs.ratboss.name=Leader rat +actors.mobs.ratboss.spawn=There's a group of mice here! +actors.mobs.redwraith.def_verb=evaded +actors.mobs.redwraith.desc=Kill it may find rings. +actors.mobs.redwraith.name=chaos wraith +actors.mobs.scorpio.desc=These huge arachnid-like demonic creatures avoid close combat by all means, firing crippling serrated spikes from long distances. +actors.mobs.scorpio.name=scorpio +actors.mobs.seekinbomb.desc=Just a bomb. + + +actors.mobs.senior.desc=He is stronger. +actors.mobs.senior.name=senior monk + +actors.mobs.sentinel.desc=You would think that it's just another one of this dungeon's ugly steel, but its red glowing eyes give it away.\n\nWhile the statue itself is made of stone, the _%s,_ it's wielding, looks real. +actors.mobs.sentinel.name=animated steel + +actors.mobs.sewerheart.atk=This plant seems to be preparing for something! +actors.mobs.sewerheart.blink=It disapper! +actors.mobs.sewerheart.desc=A Rotberry's fruit is very unique. Instead of rotting away and providing nutrients, the fruit grows, hardens, and encompasses the seed. It provides protection for the internal organs which grow inside the fruit. This giant orb is referred to as the heart of an adult rotberry plant. +actors.mobs.sewerheart.name=Sewer Heart +actors.mobs.sewerheart$sewerlasher.desc=The rot lasher is a part of a mature rotberry plant's root structure, and also their primary means of defence. Lashers are stuck into the ground, but will violently assault anything that gets near to them. When there is no nearby prey, they stand motionless, attempting to blend in with surrounding vegetation. +actors.mobs.sewerheart$sewerlasher.name=Sewer lasher + +actors.mobs.shadowyog.blink=Shadow Yog vanishes! +actors.mobs.shadowyog.desc=Shadow yog is soul of yog. +actors.mobs.shadowyog.die=... +actors.mobs.shadowyog.illusion=There is no light here, only our shadows to consume you... +actors.mobs.shadowyog.name=shadow Yog-Dzewa + +actors.mobs.shell.desc=The lightning shell crackles with electric power. It's powerful lightning attack is drawn to all living things in the lair. +actors.mobs.shell.name=lightning shell + +actors.mobs.shielded.def_verb=blocked +actors.mobs.shielded.desc=The gnoll was carrying a shield. Really it is with the sword point. +actors.mobs.shielded.name=shielded brute +actors.mobs.skeleton.def_verb=blocked +actors.mobs.skeleton.desc=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. +actors.mobs.skeleton.name=skeleton +actors.mobs.skeletonhand1.desc=This ancient giant hand belongs to the king of skeletons. +actors.mobs.skeletonhand1.name=skeleton hand +actors.mobs.skeletonhand2.desc=This ancient giant hand belongs to the king of skeletons. +actors.mobs.skeletonhand2.name=king hand +actors.mobs.skeletonking.desc=This ancient giant skull belongs to the king of skeletons. +actors.mobs.skeletonking.die=I need more mana... +actors.mobs.skeletonking.name=skeleton king +actors.mobs.skeletonking.notice=You will die screaming in flames, %s! +actors.mobs.sommonskeleton.name=summoned skeleton +actors.mobs.sommonskeleton.desc=It's just a summoned undead. +actors.mobs.sokobansentinel.desc=sokoban propector handle _%s_. +actors.mobs.sokobansentinel.name=sokoban propector +actors.mobs.spinner.desc=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. +actors.mobs.spinner.name=cave spinner +actors.mobs.statue.desc=You would think that it's just another one of this dungeon's ugly statues, but its red glowing eyes give it away.\n\nWhile the statue itself is made of stone, the _%s,_ it's wielding, looks real. +actors.mobs.statue.name=animated statue +actors.mobs.succubus.desc=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. +actors.mobs.succubus.name=succubus +actors.mobs.swarm.def_verb=evaded +actors.mobs.swarm.desc=The deadly swarm of flies buzzes angrily. Every non-magical attack will split it into two smaller but equally dangerous swarms. +actors.mobs.swarm.name=swarm of flies +actors.mobs.tengu.desc=A famous and enigmatic assassin, named for the mask grafted to his face.\n\nTengu is held down with large clasps on his wrists and knees, though he seems to have gotten rid of his chains long ago.\n\nHe will try to use traps, deceptive magic, and precise attacks to eliminate the only thing stopping his escape: you. +actors.mobs.tengu.die=I look down upon you. +actors.mobs.tengu.name=Tengu +actors.mobs.tengu.notice=You are mine, %s! +actors.mobs.tenguden.die=Curse you!!! +actors.mobs.tenguden.name=Hidden Tengu +actors.mobs.tenguden.notice=How can you find me?! +actors.mobs.tenguden.desc=A famous and enigmatic assassin, named for the mask grafted to his face.\n\nTengu is held down with large clasps on his wrists and knees, though he seems to have gotten rid of his chains long ago.\n\nHe will try to use traps, deceptive magic, and precise attacks to eliminate the only thing stopping his escape: you. +actors.mobs.testmob.desc=test mob +actors.mobs.testmob.name= Scarecrow +actors.mobs.testmob2.desc=This scarecrow is dangerous. Don't touch it. +actors.mobs.testmob2.name=Clockwork scarecrow +actors.mobs.thief.desc=Though these inmates roam free of their cells, this place is still their prison. Over time, this place has taken their minds as well as their freedom. Long ago, these crazy thieves and bandits have forgotten who they are and why they steal. +actors.mobs.thief.name=crazy thief +actors.mobs.thiefimp.carries=\n\nThe thief is carrying a _%s._ Stolen obviously. +actors.mobs.thiefimp.desc=Imps are lesser demons. They are notable neither for their strength nor their magic talent, but for their cruelty and greed. However, some of them are actually quite nice and sociable. Certainly not this one, though... +actors.mobs.thiefimp.name=Thief Imp +actors.mobs.thiefimp.stole=The thief imp stole %s from you! +actors.mobs.thiefking.desc=Leader of this city, a legendary thief. +actors.mobs.thiefking.die=You are better than I think... +actors.mobs.thiefking.name=The thief king +actors.mobs.thiefking.notice=Ready to die, %s? + +actors.mobs.trollwarrior.angry=You are attacking me?! +actors.mobs.trollwarrior.desc=Before the prison fall, they were the most powerful groups in the prison, and even the guards did not want to fight with them. +actors.mobs.trollwarrior.name=Troll Warrior + +actors.mobs.uamulet.desc=The end of bossrush. +actors.mobs.uamulet.name=Shadow of Amulet +actors.mobs.uamulet$darkmirror.name=Dark mirror +actors.mobs.uamulet$darkmirror.desc=??? + +actors.mobs.udm300$seekbomb.name=hunting bomb +actors.mobs.udm300.desc=A powerful kill machine. +actors.mobs.udm300.name=Killing machine + +actors.mobs.ugoo$earthgoo.name=earth goo +actors.mobs.ugoo$firegoo.name=fire goo +actors.mobs.ugoo$icegoo.name=ice goo +actors.mobs.ugoo$shockgoo.name=shock goo +actors.mobs.ugoo.desc=A goo from void. +actors.mobs.ugoo.name=Void goo + +actors.mobs.uicecorps.name=ice corps +actors.mobs.uicecrops.desc=Ice corps... + +actors.mobs.uking.desc=King of plant. +actors.mobs.uking.name=Plant king + +actors.mobs.utengu.desc=He is another Tengu. +actors.mobs.utengu.name=young tengu + +actors.mobs.uyog.desc=Original yog with tentacle. +actors.mobs.uyog.name=Original yog + +actors.mobs.vaultprotector.desc=It is city protector. +actors.mobs.vaultprotector.name=vault protector +actors.mobs.warlock.desc=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. +actors.mobs.warlock.name=dwarf warlock +actors.mobs.wraith.def_verb=evaded +actors.mobs.wraith.desc=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. +actors.mobs.wraith.name=wraith + +actors.mobs.yog$burningfist.name=burning fist +actors.mobs.yog$burningfist.desc=Fire fist +actors.mobs.yog$infectingfist.name=infecting fist +actors.mobs.yog$infectingfist.desc=Acid fist +actors.mobs.yog$larva.name=god's larva +actors.mobs.yog$larva.desc=larva +actors.mobs.yog$pinningfist.name=pinning fist +actors.mobs.yog$pinningfist.desc=prison fist +actors.mobs.yog$rottingfist.name=rotting fist +actors.mobs.yog$rottingfist.desc=earth fist +actors.mobs.yog.blink=Yog disappeared! +actors.mobs.yog.desc=Yog-Dzewa is an Old God, a powerful entity from the realms of chaos. A century ago, the ancient dwarves barely won the war against its army of demons, but were unable to kill the god itself. Instead, they then imprisoned it in the halls below their city, believing it to be too weak to rise ever again. +actors.mobs.yog.die=I will never die... +actors.mobs.yog.name=Yog-Dzewa + +actors.mobs.yog.notice=Hope is an illusion... +actors.mobs.zot.desc=Zot is one of the lords in the void. +actors.mobs.zot.die=... +actors.mobs.zot.name=Zot +actors.mobs.zot.notice=You will die! +actors.mobs.zot.pain=Feel my pain! +actors.mobs.zotphase.desc=Zot mirror, looks reall. +actors.mobs.zotphase.name=Zot mirror + +actors.mobs.virus.desc=virus +actors.mobs.virus.name=---!!!data delete!!!--- + +actors.mobs.zombie.desc=Zombie is... wait it is common infected. as their name implies, are the most commonly faced enemy and are the easiest to defeat. +actors.mobs.zombie.name=zombie +actors.mobs.patroluav.desc=It is robot used for cleaning sewer garbage. +actors.mobs.patroluav.name=patrol UAV +actors.mobs.sandmob.desc=This mob is made by sand. +actors.mobs.sandmob.name=sand mob +actors.mobs.sandmob$minisand.name=mini sand mob +actors.mobs.sandmob$minisand.desc=mini sand mob +actors.mobs.spiderbot.desc=This is a robot spider. It can use web and tar gas. +actors.mobs.spiderbot.name=spider bot + +actors.mobs.demonflower.desc=A flower from slay the spire. It can attack 3 time in one turns, +actors.mobs.demonflower.debuff=demon flower use weak spores. +actors.mobs.demonflower.name=Demon flower + +actors.mobs.sufferer.desc=Before he be corrupted by demon, he was a warlock. +actors.mobs.sufferer.name=sufferer + +actors.mobs.tank.desc=Usually undead is some weak, slow mob. But this one is stronger and powerful. Its name is tank. +actors.mobs.tank.notice=aaaaaaaaaaaaaaaaaaaa!!! +actors.mobs.tank.die=aaaaaaaaaaaaaaaaaaaaa..... +actors.mobs.tank.rock=TANK throw a stone! +actors.mobs.tank.name=TANK + +actors.mobs.spiderqueen.desc=She is from remixed, but she is stronger in here. Her egg can hatch more than 3 types of spider. +actors.mobs.spiderqueen.notice=Who is tearing my web?! +actors.mobs.spiderqueen.die=I lose... +actors.mobs.spiderqueen.egg=Spider hatch a new egg. +actors.mobs.spiderqueen.name=Spider queen +actors.mobs.spiderqueen$spideregg.name=spider egg +actors.mobs.spiderqueen$spideregg.desc=spider eggs + +actors.mobs.spiderqueen$spiderworker.name=Spider worker +actors.mobs.spiderqueen$spiderworker.desc=One type spider of spider army. +actors.mobs.spiderqueen$spiderjumper.name=spider jumper +actors.mobs.spiderqueen$spidermind.name=spider minder +actors.mobs.spiderqueen$spidergold.name=spider golder + +actors.mobs.goldcollector.name=Gold Collector +actors.mobs.goldcollector.desc=Why can you collect so many golds. + +actors.mobs.levelchecker.name=Level checker +actors.mobs.levelchecker.desc=This thing shouldn't appare. + +actors.mobs.normalcell.name=Cell mob +actors.mobs.normalcell.desc=The most basic mob in this world. Most of them has already evolve into other monster. + +actors.mobs.hybrid.name=Hybrid +actors.mobs.hybrid.notice=I am Amon's faithful servant. +actors.mobs.hybrid.die=In void... +actors.mobs.hybrid.shield=Amon's power protect me. +actors.mobs.hybrid.desc=An unknown creature mixed b'y alien, beast, undead, and other things. +actors.mobs.hybrid$mixers.name=Hybrid +actors.mobs.hybrid$mixers.desc=An unknown creature mixed b'y alian, beast, undead, and other things. + +actors.mobs.elderavatar.name=Elder avatar +actors.mobs.elderavatar.notice=obey or die! +actors.mobs.elderavatar.disarm=elder disarm your armor. +actors.mobs.elderavatar.die=I am just one of them.... +actors.mobs.elderavatar.shield=Obelisk continuing my life... +actors.mobs.elderavatar.desc=He is one of alien's leader. He is trying to find a way to make him immortality. +actors.mobs.elderavatar$obelisk.name=Obelisk +actors.mobs.elderavatar$obelisk.impossible=Damage reduce. +actors.mobs.elderavatar$obelisk.desc=Some kind of protect device. +actors.mobs.elderavatar$thehunter.name=The Hunter +actors.mobs.elderavatar$thehunter.desc=The alien Hunter +actors.mobs.elderavatar$thewarlock.name=The Warlock +actors.mobs.elderavatar$thewarlock.desc=The alien Warlock +actors.mobs.elderavatar$themonk.name=The Monk +actors.mobs.elderavatar$themonk.desc=The alien Monk +actors.mobs.elderavatar$themech.name=The Mech +actors.mobs.elderavatar$themech.desc=The alien Mech + +actors.mobs.npcs.mtree.name=little tree +actors.mobs.npcs.mtree.desc=A normal tree. + +actors.mobs.lichdancer.name=Lich dancer +actors.mobs.lichdancer.desc=He was a dancer, but now he is a lich. +actors.mobs.lichdancer.notice=In my acting life, I have learned a truth: as human beings, our actors have limits. So... I can fly!!! +actors.mobs.lichdancer$batterytomb.name=Necro Battery +actors.mobs.lichdancer$batterytomb.desc=A battery full with necro energy. +actors.mobs.lichdancer$linkbomb.name=Bomb +actors.mobs.lichdancer$linkbomb.desc=Watch out ,it will explode! + +actors.mobs.firerabbit.name=Lucifer +actors.mobs.firerabbit.desc=A rabbit demi-human, use fire as it's weapon, bring death to undead. +actors.mobs.firerabbit.yell=ko~ko~da~yo + +actors.mobs.manyskeleton.name=Huge Skull +actors.mobs.manyskeleton.desc=A huge skull made by lots of skeletons. + +actors.mobs.yearbeast.name=Year the beast +actors.mobs.yearbeast.disarm=Year hit down your equipment +actors.mobs.yearbeast.desc=A hearsays mobs. +actors.mobs.yearbeast.notice=I AM FREE!!! +actors.mobs.yearbeast.die=You win... Take this... +actors.mobs.yearbeast.escape=Not time now... Escape... +actors.mobs.yearbeast2.name=Year in town +actors.mobs.yearbeast2.disarm=year disarm you! +actors.mobs.yearbeast2.desc=Another year beast. +actors.mobs.yearbeast2.notice=Who is in there?! +actors.mobs.yearbeast2.die=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!!! +actors.mobs.bombbug.name=stone bug +actors.mobs.bombbug.desc=a bug live with ice stone. +###pets +actors.mobs.pets.bluedragon.desc=Blue dragon is good at ice magic. +actors.mobs.pets.bluedragon.name=Blue dragon +actors.mobs.pets.bluedragon.ready=Ice nova ready to use. +actors.mobs.pets.bunny.desc=As Easter Traditions, Easter bunnies and eggs were once famous all over the world. +actors.mobs.pets.bunny.name=Bunny of Easter egg +actors.mobs.pets.bunny.ready=Wild bite ready to use. +actors.mobs.pets.cococat.desc=Just someone who can help you survival in first few days. It might leave soon. +actors.mobs.pets.cococat.name=Bomb cat +actors.mobs.pets.cococat.ready=Super explode ready to use. +actors.mobs.pets.cococat.thanks=Well, I have finish my job. Good luck. +actors.mobs.pets.lightdragon.desc=It is a light dragon. +actors.mobs.pets.lightdragon.name=Light dragon +actors.mobs.pets.lightdragon.ready=Light shoot is ready. +actors.mobs.pets.fly.desc=This fly buzzes with enthusiastic ambition, dreaming to one day become a beautiful butterfly. +actors.mobs.pets.fly.name=Fly +actors.mobs.pets.gentlecrab.desc=It is a gentleman. Also a crab. +actors.mobs.pets.gentlecrab.name=gentle crab +actors.mobs.pets.golddragon.desc=Missing. NO +actors.mobs.pets.golddragon.name=Gold Dragon +actors.mobs.pets.golddragon.ready=Deadly breath ready to use. +actors.mobs.pets.greendragon.desc=Green dragon is good at electricity magic. +actors.mobs.pets.greendragon.name=Green dragon +actors.mobs.pets.greendragon.ready=EMP ready to use. +actors.mobs.pets.leryfire.desc=A Chaos elemental. I think it is powerful. +actors.mobs.pets.leryfire.name=Chaos elemental +actors.mobs.pets.leryfire.ready=Unknow blast ready to use. Are you cool? +actors.mobs.pets.monkey.desc=A klik entirely made of spider silk. It's oddly fluffy. It seems to enjoy food and cloth items. +actors.mobs.pets.monkey.name=spidersilk klik +actors.mobs.pets.pet.levelup=Your pet grow stronger. +actors.mobs.pets.pet.pet_died=Your pet has died... +actors.mobs.pets.reddragon.desc=Red dragon is good at fire magic. +actors.mobs.pets.reddragon.name=Red dragon +actors.mobs.pets.reddragon.ready=Flame breath ready to use. +actors.mobs.pets.ribbonrat.desc=This cute little rate wears only a ribbon that it cherishes highly, but for unknown reasons. It looks ready to show you its pride at just about any moment. +actors.mobs.pets.ribbonrat.name=ribbon rat +actors.mobs.pets.scorpion.desc=A super sized blood thirsty scorpion. Its tail is tipped with a dangerous stinger. +actors.mobs.pets.scorpion.name=Blood Scorpion +actors.mobs.pets.scorpion.ready=Caustic finale ready to use. +actors.mobs.pets.shadowdragon.desc=Dark dragon bring shadow, born in light. +actors.mobs.pets.shadowdragon.name=Shadow dragon +actors.mobs.pets.shadowdragon.ready=Shadow wave ready to use. +actors.mobs.pets.snake.desc=This snake used to enjoy its days under the soft glow of moonshine with its brother, before it decided to follow its wanderlust into the great unknown. +actors.mobs.pets.snake.name=Snake +actors.mobs.pets.spider.desc=A small, fuzzy spider seems to like trying to hide under your armor. However, despite its clingy shyness, it looks ready to help just like any good pet. +actors.mobs.pets.spider.name=Web Spider +actors.mobs.pets.spider.ready=Web is ready for use. +actors.mobs.pets.stone.desc=A freshly hatched metal klik grew from the proximity of stuff in your backpack. Such a cute ball! Might try to eat your gear... +actors.mobs.pets.stone.name=metal klik +actors.mobs.pets.bugdragon.desc=?????? +actors.mobs.pets.bugdragon.name=B u G d r A g O N +actors.mobs.pets.bugdragon.ready=??? is ready +actors.mobs.pets.velocirooster.desc=The Velocirooster is a vicious cousin of the domesticated rooster. It races through the dungeon and attacks with razor sharp talons and a vicious beak. This one has a collar with a tag. It reads, 'To Sprouted from Unleashed. Please enjoy this Velocirooster.' +actors.mobs.pets.velocirooster.name=velocirooster +actors.mobs.pets.velocirooster.ready=Claw ready to use. Cock-a-doodle-roar! +actors.mobs.pets.violetdragon.desc=Violet dragon is good at earth magic. +actors.mobs.pets.violetdragon.name=Violet dragon +actors.mobs.pets.violetdragon.ready=Poison touch ready to use. +actors.mobs.pets.yearpet.desc=a baby year. +actors.mobs.pets.yearpet.name=Baby year +##npc +actors.mobs.npcs.alivefish.desc=A fish man. +actors.mobs.npcs.alivefish.name=alive fish +actors.mobs.npcs.alivefish.yell1=bubble... +actors.mobs.npcs.alivefish.yell2=Blub blub blub... +actors.mobs.npcs.bilboldev.desc=This is a developer who build Skillfull Pixel Dungeon. He is a good person. +actors.mobs.npcs.bilboldev.name=Bilboldev +actors.mobs.npcs.bilboldev.yell1=LOL, you're gonna have to be patient with Skillful Pixel Dungeon updates. xD +actors.mobs.npcs.bilboldev.yell2=Well what's unique about SPD is the skill system and the campaign I plan on picking up soon. +actors.mobs.npcs.bilboldev.yell3=Hatsune's sacrifice will not be forgotten! + +actors.mobs.npcs.blacksmith.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...\nOk, 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. +actors.mobs.npcs.blacksmith.blood_2=I said I need bat blood on the pickaxe. Chop chop! +actors.mobs.npcs.blacksmith.cant_reforge=I can't reforge these items! +actors.mobs.npcs.blacksmith.completed=Oh, you have returned... Better late dan never. +actors.mobs.npcs.blacksmith.cursed=I don't work with cursed items! +actors.mobs.npcs.blacksmith.degraded=It's junk, the quality is too poor! +actors.mobs.npcs.blacksmith.desc=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. +actors.mobs.npcs.blacksmith.get_lost=I'm busy. Get lost! +actors.mobs.npcs.blacksmith.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...\nOk, 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. +actors.mobs.npcs.blacksmith.gold_2=Dark gold ore. 15 pieces. Seriously, is it dat hard? +actors.mobs.npcs.blacksmith.keeppickaxe=Take this pick axe. It will be use full. +actors.mobs.npcs.blacksmith.lost_pick=Are you kiddin' me? Where is my pickaxe?! +actors.mobs.npcs.blacksmith.name=troll blacksmith +actors.mobs.npcs.blacksmith.need_reinforced=Sorry, dis item is too weak to handle so many upgrades. +actors.mobs.npcs.blacksmith.same_item=Select 2 different items, not the same item twice! +actors.mobs.npcs.blacksmith.triforce=So, you find those three force? Ok, I will try to fuse them. +actors.mobs.npcs.blacksmith.shadoweater= +actors.mobs.npcs.blacksmith.un_ided=I need to know what I'm working with, identify them first! + +actors.mobs.npcs.blacksmith2.adamantite=Oh, you've already found Adamant, I can weld this thing with other item to make sure that item can handle any upgrade as you want. It will spend _50 dark gold_. +actors.mobs.npcs.blacksmith2.already_reforge=I can't weld another Adamant into this item... +actors.mobs.npcs.blacksmith2.cant_reforge=I can't weld Adamant into un-upgread item... +actors.mobs.npcs.blacksmith2.cant_work=I can't find Adamant... +actors.mobs.npcs.blacksmith2.cursed=I can't weld cursed item... +actors.mobs.npcs.blacksmith2.degraded=I can't weld degraded item... +actors.mobs.npcs.blacksmith2.desc=This troll welder looks like all trolls look: he is tall and lean, and his skin resembles stone in both color and texture. The troll welder is tinkering with unproportionally small tools. +actors.mobs.npcs.blacksmith2.himself=As you can see, I'm the little brother of that blacksmith. Although my brother thinks that only the traditional blacksmith technology can help trolls, I think science and technology can also be just as beneficial. Well, seems you don't have any _Adamant_ or 50 pieces of dark gold ore. I can't do anything unless I have both to work with. +actors.mobs.npcs.blacksmith2.name=Troll welder +actors.mobs.npcs.blacksmith2.same_item=I can't weld same item... +actors.mobs.npcs.blacksmith2.un_ided=I can't weld unknow item... +actors.mobs.npcs.coconut.desc=A cute orange cat with goggles and shoulder bag. Seems like there are lots of bombs in his bag. +actors.mobs.npcs.coconut.name=coconut +actors.mobs.npcs.coconut.yell1=Ah, you found me! Welcome to my secret shop. Mew! +actors.mobs.npcs.coconut.yell2=I have lots of bombs for sale. Mew! +actors.mobs.npcs.coconut.yell3=Did you know? Hmdzl001 is training bosses right now. Isn't it exciting? Mew! +actors.mobs.npcs.consideredhamster.desc=While this looks like the developer that build YAPD, this is not him. Rather, it is his pet. +actors.mobs.npcs.consideredhamster.name=ConsideredHamster's Mimic +actors.mobs.npcs.consideredhamster.yell1=I'm so hungry... I only need $1, could you feed me please...? +actors.mobs.npcs.consideredhamster.yell2=Pineapples! +actors.mobs.npcs.dachhack.desc=This is a developer who build Sprouted Pixel Dungeon. He is still in work, right? +actors.mobs.npcs.dachhack.name=Dachhack +actors.mobs.npcs.dachhack.yell1=I'm Dachhack. Sorry about those bugs in Sprouted Pixel Dungeon that caused it to crash. +actors.mobs.npcs.dachhack.yell2=This halo...it is means Deistic Pixel Dungeon,a mod baseed by sprouted, I guess. +actors.mobs.npcs.dachhack.yell3=New sprouted is in the test, just waiting for that. +actors.mobs.npcs.evan.desc=This is a sign of Shattered Pixel Dungeon,the most successful mod of pixel dungeon. +actors.mobs.npcs.evan.name=Shattered Pixel Dungeon +actors.mobs.npcs.evan.yell1=I'm made by 00-Evan. Welcome here! +actors.mobs.npcs.evan.yell2=Evan is trying to fix something that's broken(me, perhaps).He is so obsessively that he don't know what should he say. +actors.mobs.npcs.evan.yell3=I will try my best to make shattered more funny, more reasonable, and more challeng. +actors.mobs.npcs.fruitcat.desc=He is a merchant. +actors.mobs.npcs.fruitcat.name=fruit cat +actors.mobs.npcs.fruitcat.yell1=After coconut leave, I buy this shop and sell bombs. For now this shop is belong to Union. +actors.mobs.npcs.fruitcat.yell2=Believe it or not, Coconut had a bunch of Ankhs just lying around here before he left. He didn't even take any with him, he just left them in a pile to collect dust! Anyways, you'll probably need them more than I do. +actors.mobs.npcs.g2159687.desc=This is a developer who build ESPD. +actors.mobs.npcs.g2159687.name=G2159687 +actors.mobs.npcs.g2159687.yell1=I'm G2159687, do you love my ESPD? +actors.mobs.npcs.g2159687.yell2=I fix some bug in Sprouted and make it easier.I also build other verison like EVPD,you know,easier. +actors.mobs.npcs.ghost.crab_1=Hello %s... Once I was like you - strong and confident... But I was slain by an ancient creature... I can't leave this place... Not until I have my revenge... Slay the _great crab,_ that has taken my life...\n\nIt is unnaturally old... With a massive single claw and a thick shell... _Beware its claw, you must surprise the crab or it will block with it..._ +actors.mobs.npcs.ghost.crab_2=Please... Help me... Slay the Crustacean...\n\n_It will always block... When it sees you coming..._ +actors.mobs.npcs.ghost.def_verb=evaded +actors.mobs.npcs.ghost.desc=The ghost is barely visible. It looks like a shapeless spot of faint light with a sorrowful face. +actors.mobs.npcs.ghost.find_me=Thank you... come find me... +actors.mobs.npcs.ghost.gnoll_1=Hello %s... Once I was like you - strong and confident... But I was slain by a devious foe... I can't leave this place... Not until I have my revenge... Slay the _gnoll trickster,_ that has taken my life...\n\nIt is not like the other gnolls... It hides and uses thrown weapons... _Beware its poisonous and incendiary darts, don't attack from a distance..._ +actors.mobs.npcs.ghost.gnoll_2=Please... Help me... Slay the trickster...\n\n_Don't let it hit you... Get near to it..._ +actors.mobs.npcs.ghost.name=sad ghost +actors.mobs.npcs.ghost.rat_1=Hello %s... Once I was like you - strong and confident... But I was slain by a foul beast... I can't leave this place... Not until I have my revenge... Slay the _fetid rat,_ that has taken my life...\n\nIt stalks this floor... Spreading filth everywhere... _Beware its cloud of stink and corrosive bite, the acid dissolves in water..._ +actors.mobs.npcs.ghost.rat_2=Please... Help me... Slay the abomination...\n\n_Fight it near water... Avoid the stench..._ +actors.mobs.npcs.hatesokoban.desc=He is one tester from another world. Maybe is from pony town. +actors.mobs.npcs.hatesokoban.name=hate sokoban +actors.mobs.npcs.hatesokoban.yell1=You know, this is just a game. I came here to test it, isn't that fun? +actors.mobs.npcs.hatesokoban.yell2=If you suck in any sokoban level, try to use wand of flock. If you want summon fairy, use wand of flock shout that soul. +actors.mobs.npcs.hbb.desc=He is Chairman of the Union +actors.mobs.npcs.hbb.name=Rawberry - Chairman of the Union +actors.mobs.npcs.hbb.yell1="The world's still the same, there's just...less in it." +actors.mobs.npcs.hbb.yell2="Friendship is magic!" +actors.mobs.npcs.hbb.yell3="I am a magical princess from another dimension." +actors.mobs.npcs.hexa.desc=This is developer of UNIST pixel dungeon... I never hear about that mod... +actors.mobs.npcs.hexa.name=UNIST HeXA +actors.mobs.npcs.hexa.yell1=I'm HeXA,the developer of UNIST Pixel Dungeon.I think you never hear about that before. +actors.mobs.npcs.hexa.yell2=It only can be download in South Korea,but you can find the code in github. + +actors.mobs.npcs.imp.cya=See you, %s! +actors.mobs.npcs.imp.def_verb=evaded +actors.mobs.npcs.imp.desc=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. +actors.mobs.npcs.imp.golems_1=Are you an adventurer? I love adventurers! You can always rely on them if something needs to be killed. Am I right? For a bounty of course ;)\nIn 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. +actors.mobs.npcs.imp.golems_2=How is your golem safari going? Have you killed _6 of them_ yet? +actors.mobs.npcs.imp.hey=Psst, %s! + +actors.mobs.npcs.imp.monks_1=Are you an adventurer? I love adventurers! You can always rely on them if something needs to be killed. Am I right? For a bounty of course ;)\nIn 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. +actors.mobs.npcs.imp.monks_2=Oh, you are still alive! I knew that your kung-fu is stronger ;) Just don't forget to grab these monks' tokens, specifically _8 of them_. +actors.mobs.npcs.imp.name=ambitious imp +actors.mobs.npcs.impshopkeeper.desc=Imps are lesser demons. They are notable for neither their strength nor their magic talent. But they are quite smart and sociable, and many of imps prefer to live and do business among non-demons. +actors.mobs.npcs.impshopkeeper.greeting2=So... You didn't find anything useful there... Well, look at those three trial, I can sell them to you with low price. +actors.mobs.npcs.impshopkeeper.greeting=Greeting %s! Choose one you want and I will sell it to you. Except those three trials, I spend lots of time to find them. +actors.mobs.npcs.impshopkeeper.name=ambitious imp +actors.mobs.npcs.jinkeloid.desc=It is union president, some kind of ice element. +actors.mobs.npcs.jinkeloid.name=jinkeloid - union president +actors.mobs.npcs.jinkeloid.yell1=Now the union is just a tourist spots. Welcome here. +actors.mobs.npcs.jinkeloid.yell2=In this place, freezing by ice will taken more damage. +actors.mobs.npcs.juh9870.desc=Developer of the Moonshine Pixel Dungeon. +actors.mobs.npcs.juh9870.name=Juh9870 +actors.mobs.npcs.juh9870.yell1=Dreams are forbidden, said my grandpa, also he brewed good moonshine +actors.mobs.npcs.juh9870.yell2=So... Well, I hope I can find more things in here. +actors.mobs.npcs.laji.desc=He is a priest, also he is only repairman in this town. +actors.mobs.npcs.laji.name=Maintainer S.O.F.S +actors.mobs.npcs.laji.yell1=This guest, may I delay you for a moment to talk about our heavenly father, Kesulu? +actors.mobs.npcs.laji.yell2=Many things that the dreamer and the day know are often forgotten by the dreamer at night. +actors.mobs.npcs.laji.yell3=Well, there lots of things I need fix. I am tried about this... +actors.mobs.npcs.lery.desc=It is another element of this union. He is good at training pets. +actors.mobs.npcs.lery.name=Pet dealer Lery +actors.mobs.npcs.lery.yell1=Are you cool? +actors.mobs.npcs.lery.yell2=I sell eggs here... +actors.mobs.npcs.locastan.desc=This is a developer who build Goblins Pixel Dungeon.Goblins Pixel Dungeon is base by Unleashed Pixel Dungeon. +actors.mobs.npcs.locastan.name=Locastan +actors.mobs.npcs.locastan.yell1=This is a locked door,may be I can open it. +actors.mobs.npcs.locastan.yell2=It's not a piece of crap, it's a sophisticated adventuring tool. +actors.mobs.npcs.locastan.yell3=Huh, this lamp? Well you see, this is actually Unleashed Pixel Dungeon. If you don't mind, I need it in my adventure. +actors.mobs.npcs.lyn.desc=He is a demon hunter, as you see. +actors.mobs.npcs.lyn.name=Curse ankh +actors.mobs.npcs.lyn.yell1=Burn! Purify! For Sargeras'great expedition! +actors.mobs.npcs.lyn.yell2=Need some drink? Or some pet food? Just a kidding. +actors.mobs.npcs.lynn.desc=An excellent Rune scholar. +actors.mobs.npcs.lynn.name=Rune Scholar Lynn +actors.mobs.npcs.lynn.yell1=I have fixed that altar. You can use it now. +actors.mobs.npcs.lynn.yell2=What should I do next? + +actors.mobs.npcs.memoryofsand.desc=A tester from other world. He is a cooker now. +actors.mobs.npcs.memoryofsand.name=Cooker M.O.S +actors.mobs.npcs.memoryofsand.yell1=Need some food? Choose what you want. +actors.mobs.npcs.memoryofsand.yell2=Before I play this game, I was an adventurer. +actors.mobs.npcs.mirrorimage.desc=This illusion bears a close resemblance to you, but it's paler and twitches a little. +actors.mobs.npcs.mirrorimage.name=mirror image +actors.mobs.npcs.nyrds.desc=This is a developer who build Pixel Dungeon Remix. He is a ittle red mascot. +actors.mobs.npcs.nyrds.name=Nyrdie +actors.mobs.npcs.nyrds.yell1=Hey folks! Nyrdie here. +actors.mobs.npcs.nyrds.yell2=Advice of the day: don't forget to brush your teeth! +actors.mobs.npcs.oldnewstwist.desc=A gnoll traveler, he is almost naked. +actors.mobs.npcs.oldnewstwist.desc_gnollmission=Now that he has the warmth of good clothing, he can comfortably begin some trading of his own. +actors.mobs.npcs.oldnewstwist.name=Oldnewstwist +actors.mobs.npcs.oldnewstwist.yell1=Ah! Please don't hurt me! I'm not like the other Gnoll you will find throughout the dungeon! +actors.mobs.npcs.oldnewstwist.yell2=Unlike the feral Gnoll you've encountered before, I'm from a clan of civilized, nomadic Gnoll. We travel from settlement to settlement in an attempt to spread our ways of peace and our tribal knowledge. I ended up here after being dragged away, from my group, by those rabid thugs that I am ashamed to call brethren. +actors.mobs.npcs.oldnewstwist.yell3=Brr.. It is cold. Why did those goons have to rip up my clothes..? +actors.mobs.npcs.oldnewstwist.yell4=I heard you defeated the evil Gnoll King! That's great! He won't be terrorizing us anymore! Hey, did he have any clothes? +actors.mobs.npcs.oldnewstwist.yell5=These fine fibers will keep me very warm! Thank you for the clothes, and thank you again for defeating the evil Gnoll King. +actors.mobs.npcs.oldnewstwist.yell6=By the way, I'm selling out-of-season holiday weapons now. +actors.mobs.npcs.otilukenpc.desc=Otiluke, a great wizard from Dolye. You can ask him for reword. +actors.mobs.npcs.otilukenpc.name=Otiluke +actors.mobs.npcs.otilukenpc.yell1=Finally, after so many time, I saw my hometown again. +actors.mobs.npcs.otilukenpc.yell2=I will help you enter Tower if you want. +actors.mobs.npcs.otilukenpc.yell3=Oh, right, I know what you want. Here, take this counterfeit Amulet. I had to give the real one to the Tower, but don't worry. This works the same way, and I have more if you need them. +actors.mobs.npcs.raintrainer.desc=A trainer who are ready to battle. +actors.mobs.npcs.raintrainer.name=trainer rain +actors.mobs.npcs.raintrainer.yell1=Want to training youeself? +actors.mobs.npcs.raintrainer.yell2=Check your DPS on that scarecrow. +actors.mobs.npcs.ratking.desc=This rat is a little bigger than a regular marsupial rat and it's wearing a tiny crown on its head. +actors.mobs.npcs.ratking.desc_festive=This rat is a little bigger than a regular marsupial rat. It's wearing a tiny festive hat instead of its usual crown. Happy Holidays! +actors.mobs.npcs.ratking.havefun=You did it, Wish you a pleasant journey. +actors.mobs.npcs.ratking.name=rat king +actors.mobs.npcs.ratking.not_sleeping=I'm not sleeping! +actors.mobs.npcs.ratking.not_takeing=Away from my treasure!!! +actors.mobs.npcs.ratking.thanks=Well, as a reward for your loyalty, I allow you to kill a thief, he stole one of my Fork, and I think he is hidding close to the exit of the prison. If you did that, I will give you that fork as a reward. +actors.mobs.npcs.ratking.what_is_it=What is it? I have no time for this nonsense. My kingdom won't rule itself! +actors.mobs.npcs.ratking.why=They're all worthless things. I don't care about that. +actors.mobs.npcs.ratkingden.desc=This rat is a little bigger than a regular marsupial rat and it's wearing a tiny crown on its head. +actors.mobs.npcs.ratkingden.desc_festive=This rat is a little bigger than a regular marsupial rat. It's wearing a tiny festive hat instead of its usual crown. Happy Holidays! +actors.mobs.npcs.ratkingden.name=rat king +actors.mobs.npcs.ratkingden.not_sleeping=Oh, you are here. +actors.mobs.npcs.ratkingden.what_is_it=You did great, take those treasure. + +actors.mobs.npcs.rennpc.desc=He is one developer in China. He loves East Project so he mix that into his shattered mod. He is hard-working. +actors.mobs.npcs.rennpc.name=REN +actors.mobs.npcs.rennpc.yell1=What does Usami-Renko mean? +actors.mobs.npcs.rennpc.yell2=If I have time I will tell you a story about the best place in my world. +actors.mobs.npcs.rennpc.yell4=Well, I like teas, no matter what tea it was. +actors.mobs.npcs.rennpc.yell5=You find all secret in each challenge?! Take this, a weapon from my touhou project pixel dungeon. Well it only have Chinese language. +actors.mobs.npcs.rennpc.yell3=Nice to see you, I'm REN. You find my message on that challenge picture, right? Take this Challenge book, it can help you. + +actors.mobs.npcs.rustyblade.desc=He is battle master in this union, and he has his own legend story. +actors.mobs.npcs.rustyblade.name=rustyblade - battle master +actors.mobs.npcs.rustyblade.yell1=I am a master. +actors.mobs.npcs.rustyblade.yell2=Def up, def down, atk up, atk down, those things are basic buffs. +actors.mobs.npcs.sadsaltan.desc=The draftsman of the moonshine dungeon. The name of the name "Moonshine" is hung on his clothes. +actors.mobs.npcs.sadsaltan.name=SadSaltan +actors.mobs.npcs.sadsaltan.yell1=Oh. New wanderer in this dungeon? People are not often shown here. Here all become either rich or dead. When a man has got money in his pocket, he begins to appreciate peace. +actors.mobs.npcs.sadsaltan.yell2=By the way, if you'll pass by the city - visit my saloon! It's easy to find saloon, just say "Moonshine Dungeon" and the local will show you the way. +actors.mobs.npcs.sadsaltan.yell3=Take my business card, maybe I can ask you to have a drink in my bar. +actors.mobs.npcs.seekingbombnpc.desc=Explode while attacking. +actors.mobs.npcs.seekingbombnpc.name=seeking bomb +actors.mobs.npcs.seekingclusterbombnpc.desc=Explode while attacking. +actors.mobs.npcs.seekingclusterbombnpc.name=seeking cluster bomb +actors.mobs.npcs.sfb.desc=He is a fire mage. +actors.mobs.npcs.sfb.hello=Me! +actors.mobs.npcs.sfb.name=Shattered Flame Blast - union fire mage +actors.mobs.npcs.sfb.yell1=I want burning something! +actors.mobs.npcs.sfb.yell2=If a target be burning, it will move fast. +actors.mobs.npcs.sheep.baa!=Baa! +actors.mobs.npcs.sheep.baa...=Baa... +actors.mobs.npcs.sheep.baa.=Baa. +actors.mobs.npcs.sheep.baa?=Baa? +actors.mobs.npcs.sheep.desc=This is a magic sheep. What's so magical about it? You can't kill it. It will stand there until it magically fades away, all the while chewing cud with a blank stare. +actors.mobs.npcs.sheep.name=sheep +actors.mobs.npcs.sheepsokoban.desc=Push this box. This box can be moved like Rook. +actors.mobs.npcs.sheepsokoban.name=Rook Box +actors.mobs.npcs.sheepsokobanblack.desc=After you touch this box, it will destroy one trap. +actors.mobs.npcs.sheepsokobanblack.name=Explode Box +actors.mobs.npcs.sheepsokobancorner.desc=Push this box. This box can be moved like Queen. +actors.mobs.npcs.sheepsokobancorner.name=Queen Box +actors.mobs.npcs.sheepsokobanstop.baa!=baa! +actors.mobs.npcs.sheepsokobanstop.baa...=baa... +actors.mobs.npcs.sheepsokobanstop.baa.=baa. +actors.mobs.npcs.sheepsokobanstop.baa?=baa? +actors.mobs.npcs.sheepsokobanstop.desc=It can't move... +actors.mobs.npcs.sheepsokobanstop.name=Sheep Box +actors.mobs.npcs.sheepsokobanswitch.desc=You can exchange places with this box. +actors.mobs.npcs.sheepsokobanswitch.name=Swap Box +actors.mobs.npcs.shopkeeper.desc=This stout guy looks more appropriate for a trade district in some large city than for a dungeon. His prices explain why he prefers to do business here. +actors.mobs.npcs.shopkeeper.name=shopkeeper +actors.mobs.npcs.shopkeeper.sell=Select an item to sell +actors.mobs.npcs.sp931.desc=This is one of translators who helped translate Shattered into Chinese... +actors.mobs.npcs.sp931.name=931451545 +actors.mobs.npcs.sp931.yell1=I'm 931451545. +actors.mobs.npcs.sp931.yell2=I was king of that union. +actors.mobs.npcs.stormandrain.desc=A tester from other world. He is a demon eye. +actors.mobs.npcs.stormandrain.name=Treasure hunter S.M.R +actors.mobs.npcs.stormandrain.yell1=Hi, need some treasure? +actors.mobs.npcs.stormandrain.yell2=I am not human. But I am a treasure hunter. +actors.mobs.npcs.tempest102.desc=He is a translater and a musician. +actors.mobs.npcs.tempest102.name=tempest102 +actors.mobs.npcs.tempest102.yell1=I only had a tent at past, but now I have my own shop. +actors.mobs.npcs.tempest102.yell2=Welcome to my instrument studio. Do you want to buy anything? +actors.mobs.npcs.tinkerer1.desc=He seems to be waiting for something. +actors.mobs.npcs.tinkerer1.name=Dew developer +actors.mobs.npcs.tinkerer1.tell1=Find anything interest? +actors.mobs.npcs.tinkerer1.tell2=It is a great place. +actors.mobs.npcs.tinkerer2.desc=A scholar lived in Dolyahaven. He know lots of knowledge of magic stone. +actors.mobs.npcs.tinkerer2.name=Rune scholar Lynn +actors.mobs.npcs.tinkerer2.tell1=I think there must be a connection between different kinds of magic... Maybe something can help me. +actors.mobs.npcs.tinkerer3.desc=It looks like he is still waiting for something. +actors.mobs.npcs.tinkerer3.name=Dew developer +actors.mobs.npcs.tinkerer3.tell1=Find anything interest? +actors.mobs.npcs.tinkerer3.tell2=It is a great place. +actors.mobs.npcs.tinkerer4.desc=He is the mayor in this town. He wrote a book about the chancel. +actors.mobs.npcs.tinkerer4.name=The mayor Noodlemire +actors.mobs.npcs.tinkerer4.tell1=Welcome to Dolya town, I am the mayor. +actors.mobs.npcs.tinkerer4.tell2=Here was a great town, but because of the environmental pollution, lots of people leave. +actors.mobs.npcs.tinkerer5.desc=A geological surveyor named Xavier251998. +actors.mobs.npcs.tinkerer5.name=Geological surveyor Xavier251998 +actors.mobs.npcs.tinkerer5.tell1=I was doing a project, relationship between crustal movement and man-made mining. Unfortunately, there was a dragon in the mine site, and then I couldn't get into the mine cave. +actors.mobs.npcs.tinkerer5.tell2=It's said that the town had had a glorious time, a lot of magic ore exports, and bring considerable income to the town. But all this was over before Otiluke was ready to go +actors.mobs.npcs.tinkerer5.tell3=Take this meat, my friend. +actors.mobs.npcs.typedscroll.desc=This is a developer who build LCPD. He looks like a error. +actors.mobs.npcs.typedscroll.name=TypedScroll +actors.mobs.npcs.typedscroll.yell1=I'm TypedScroll, I don't know what should I say now. +actors.mobs.npcs.typedscroll.yell2=Give more confidence to my LCPD. +actors.mobs.npcs.udawos.desc=This is a developer who build Pioneer. Seems like he is doing his job now. +actors.mobs.npcs.udawos.name=Udawos +actors.mobs.npcs.udawos.yell1=I'm Udawos, have you ever played my Pioneer before? My new game is chernog : FOMTMA. You can download it in google play store. +actors.mobs.npcs.udawos.yell2=In fact, Pioneer is not a Roguelike game. Rather, it is an RPG. +actors.mobs.npcs.wandmaker.berry_1=Oh, what a pleasant surprise to meet a decent person in such place! I came here for a rare ingredient - a _Rotberry seed_. Being a magic user, I'm quite able to defend myself against local monsters, but I'm getting lost in no time, it's very embarrassing. Probably you could help me? I would be happy to pay for your service with one of my best wands. +actors.mobs.npcs.wandmaker.berry_2=Any luck with a Rotberry seed, %s? No? Don't worry, I'm not in a hurry. +actors.mobs.npcs.wandmaker.desc=This old but hale gentleman wears a slightly confused expression. He is protected by a magic shield. +actors.mobs.npcs.wandmaker.dust_1=Oh, what a pleasant surprise to meet a decent person in such place! I came here for a rare ingredient - _corpse dust_. It can be gathered from skeletal remains and there is an ample number of them in the dungeon. Being a magic user, I'm quite able to defend myself against local monsters, but I'm getting lost in no time, it's very embarrassing. Probably you could help me? I would be happy to pay for your service with one of my best wands. +actors.mobs.npcs.wandmaker.dust_2=Any luck with corpse dust, %s? Bone piles are the most obvious places to look. +actors.mobs.npcs.wandmaker.name=old wandmaker +actors.mobs.npcs.watabou.desc=This is a developer who build the original Pixel Dungeon from the ground up...\nAmazing... +actors.mobs.npcs.watabou.name=Watabou +actors.mobs.npcs.watabou.yell1=I'm Watabou, still here in spirit even if I haven't updated Pixel Dungeon in about three years. +actors.mobs.npcs.watabou.yell2=Pixel Dungeon isn't my only game. You should try the other ones I made, like Patient Rogue. + +actors.mobs.npcs.kostis12345.name=Secretary kostis12345 +actors.mobs.npcs.kostis12345.desc=She is secretary in this town, she works very hard. +actors.mobs.npcs.kostis12345.yell1=Did you see our mayor? We still have lots of things to do. +actors.mobs.npcs.kostis12345.yell2=If you have questions about the game, go to pixeldungeon.wikia.com and search for Specia Surprise Pixel Dungeon. Come on Teletubby,teleport us to Mars. + +actors.mobs.npcs.hmdzl001.name=hmdzl001 +actors.mobs.npcs.hmdzl001.desc=He is a player, not a developer. He will try to fix some error in this world. +actors.mobs.npcs.hmdzl001.yell1=Welcome. This town is used on celebrate Chinese Spring Festival. +actors.mobs.npcs.hmdzl001.yell2=Do you see my cat, coconut? It is cute, and it is made by metal. +actors.mobs.npcs.hmdzl001.yell3=I know we have different cultures and histories, but here is just one part of this game. Have fun in here. + +actors.mobs.npcs.coconut2.name=Coconut +actors.mobs.npcs.coconut2.desc=A metal cat... maybe... +actors.mobs.npcs.coconut2.yell1=It spend lots of time to build this place. +actors.mobs.npcs.coconut2.yell2=I still have a shop in here. +actors.mobs.npcs.coconut2.yell3=Maybe I will summon some new hero on other world, or not, I don't know. + +actors.mobs.npcs.newplayer.name=You +actors.mobs.npcs.newplayer.desc=??? +actors.mobs.npcs.newplayer.yell1=It is you. +actors.mobs.npcs.newplayer.yell2=It is just you. + +actors.mobs.npcs.thanklist.name=Thank list +actors.mobs.npcs.thanklist.yell1=And everyone who play this game. +actors.mobs.npcs.thanklist.desc=A normal thank list. + +actors.mobs.npcs.arealman.name=ARealMan +actors.mobs.npcs.arealman.desc=He loves alchemy and collect Independent Game. He is still in Union. + +actors.mobs.npcs.whiteghost.name=White ghost +actors.mobs.npcs.whiteghost.yell1=Still... you remember me... +actors.mobs.npcs.whiteghost.desc=She was one of mage in Union, but she disappear in one tower's test. + +actors.mobs.npcs.uncles.name=Uncle S +actors.mobs.npcs.uncles.yell1=Want any training? +actors.mobs.npcs.uncles.desc=He is one strong man in Union. + +actors.mobs.npcs.apostle.name=apostle +actors.mobs.npcs.apostle.yell1=ONLY MAGIC CAN DEFEAT MAGIC. +actors.mobs.npcs.apostle.yell2=sadhidlsijkanduiowhaodiwjqa +actors.mobs.npcs.apostle.yell3=You complate this test. talk to other tester and they will tell you another things. +actors.mobs.npcs.apostle.desc=A sparkling cube, mechanical and magnetic in sound, may be it is one tester from other world. + +actors.mobs.npcs.shower.name=shower +actors.mobs.npcs.shower.yell1=Nice to see you, I am shower. You also can call me mumu. +actors.mobs.npcs.shower.yell2=See the pond on the East side? +actors.mobs.npcs.shower.yell3=Here is a beautiful town, with lots of people. I think I'll spend some time in here. +actors.mobs.npcs.shower.desc=One tester with knuckle. + +actors.mobs.npcs.saidbysun.name=Said by sun +actors.mobs.npcs.saidbysun.yell1=Next step... wait, I did a mistake... +actors.mobs.npcs.saidbysun.yell2=They asked me to help with the test, and I came here.... Oh, I didn't say anything... +actors.mobs.npcs.saidbysun.desc=A cat, also a alchemy tester. + +actors.mobs.npcs.honeypoooot.name=honey poooot +actors.mobs.npcs.honeypoooot.yell1=See that black cat? He is my leader. +actors.mobs.npcs.honeypoooot.yell2=This is honey cap, not a robe. +actors.mobs.npcs.honeypoooot.desc=A sophisticated adventurer, assistant to the trade union chairman, is responsible for helping with various trade union tasks, including the testing of various new items. + +actors.mobs.npcs.millilitre.name=millilitre isaac +actors.mobs.npcs.millilitre.yell1=Leave me alone... +actors.mobs.npcs.millilitre.yell2=I want go home... +actors.mobs.npcs.millilitre.desc=He is one tester, he is frightened. + +actors.mobs.npcs.goblinplayer.name=Shield Goblin +actors.mobs.npcs.goblinplayer.yell1=It's a good world, but it's still too simple for Goblins. +actors.mobs.npcs.goblinplayer.yell2=See this shield? It is full with chaos energy. +actors.mobs.npcs.goblinplayer.desc=A tester goblin, He hold a shield, an artifact from Unleashed Pixel Dungeon. + +actors.mobs.npcs.dreamplayer.name=Dream player +actors.mobs.npcs.dreamplayer.yell1=funny? +actors.mobs.npcs.dreamplayer.yell2=funny! +actors.mobs.npcs.dreamplayer.desc=A tester, a element, and colourful. + +actors.mobs.npcs.nutpainter.name=Nut painter +actors.mobs.npcs.nutpainter.yell1=Nut is best! +actors.mobs.npcs.nutpainter.yell2=Nut forever! +actors.mobs.npcs.nutpainter.desc=A tester, he love nuts. + +actors.mobs.npcs.xixizero.name=XiXi0.12 +actors.mobs.npcs.xixizero.yell1=Mew, I'm developer of darkest pixel dungeon, you can call me Egoal. +actors.mobs.npcs.xixizero.desc=A cat who build darkest pixel dungeon. + +actors.mobs.npcs.afly.name=Alfred, Abbey and Abeys +actors.mobs.npcs.afly.yell1=Hello, I am Alfred, they are Abbey and Abeys. +actors.mobs.npcs.afly.desc=Developer of Fushigi-no Pixel Dungeon + +actors.mobs.npcs.omicronrg9.name=Ømicrónrg9 +actors.mobs.npcs.omicronrg9.yell1=Hey! Out of my way, I have no time for this nonsense. My mod tree won't be made by itself! +actors.mobs.npcs.omicronrg9.yell2=Be cautious with the piranhas. They are dangerous when unarmored. +actors.mobs.npcs.omicronrg9.yell3=There are 24 Pixel Dungeon mods which start with "P". This is not a joking! +actors.mobs.npcs.omicronrg9.yell4=My left eye got burnt because excessive time at computer, searching for new mods. It was a needed sacrifice. +actors.mobs.npcs.omicronrg9.yell5=Hope is still an illusion! +actors.mobs.npcs.omicronrg9.yell6=This world takes stuff from around 9 different worlds! Isn't that amazing? +actors.mobs.npcs.omicronrg9.desc=This long-haired human seems to be a crusader of the old times, but It is actually a Scholar who restlessly researches for different worlds in this big universe. He's here because Honey brought him, and he is collecting data about this world and sharing information about other worlds. He has not slept well so He may be aggresive. + +actors.mobs.npcs.ice13.name=Mercenary -- Thirteen the Frozen Mist +actors.mobs.npcs.ice13.yell1=Greeting,my name is Thirteen. I'm just a normal mercenary.By the way, It's not the first time we meet, right? +actors.mobs.npcs.ice13.yell2=My colours are strange? Bro, they are just RGB. +actors.mobs.npcs.ice13.yell3=Remember, the past is never dead, it's not even past. +actors.mobs.npcs.ice13.yell4=Se Neh Gep Dyus! Uo Sh Yuh! Nat Sh Yuh! +actors.mobs.npcs.ice13.yell5=It's not the elements, but their controllers make them evil. +actors.mobs.npcs.ice13.yell6=There are still some glitches in this world. At least it won't create a black beast. +actors.mobs.npcs.ice13.desc=A warlock who seems a little mad. He came here because of a broken map of Dolya town and the lead of Honey Poooot. In his words, he stays here to create more chaos. + +actors.mobs.npcs.Sharku2011.desc=He is one developer of Girls-Frontline Pixel Dungeon. +actors.mobs.npcs.Sharku2011.name=Sharku2011 +actors.mobs.npcs.Sharku2011.yell1=This treasure is mine! +actors.mobs.npcs.Sharku2011.yell2=no one can touch my treasure! + diff --git a/resources/com/hmdzl/spspd/messages/actors/actors_zh.properties b/resources/com/hmdzl/spspd/messages/actors/actors_zh.properties new file mode 100644 index 00000000..8db3f689 --- /dev/null +++ b/resources/com/hmdzl/spspd/messages/actors/actors_zh.properties @@ -0,0 +1,1352 @@ +###blobs +actors.blobs.confusiongas.desc=这里盘绕着一片眩晕彩雾,眩晕彩雾会使其中的生物失去辨别方向的能力,导致其无法正确的向目标方向移动,并丧失远程攻击能力。 +actors.blobs.corruptgas.desc=这里盘绕着一片恶魔血雾。恶魔血雾即使稍微被接触到就可以导致生物血流不止,甚至失去控制。 +actors.blobs.darkgas.desc=这里盘绕着一片黑色浓烟。黑色浓烟会侵入处于烟雾中生物的眼睛,造成短暂的失明。 +actors.blobs.electrishock.desc=大量的电火花在这片电场中流窜。 +actors.blobs.fire.desc=一团火焰正在这里肆虐。火焰可以用于简单烹饪食物,或者点燃站在火上的单位并对其造成伤害。 +actors.blobs.foliage.desc=光柱刺破了地下花园中的黑暗。 +actors.blobs.frostgas.desc=这里盘绕着一片极寒雪雾。 +actors.blobs.goowarn.desc=黑暗能量正在这里涌动! +actors.blobs.heallight.desc=生命的光芒在这里闪耀! 生命之光能给予其中的生物恢复生命。 +actors.blobs.memoryfire.desc=一团蓝色的火焰正在这里燃烧。 +actors.blobs.paralyticgas.desc=这里盘绕着一片麻痹黄雾。麻痹黄雾能够麻痹生物的神经系统,使进入其中的生物立刻失去知觉。 +actors.blobs.regrowth.desc=营养物质从这儿的地下流窜,给植物施肥,加速其成长,使其成熟,以便立即收获。 +actors.blobs.shockweb.desc=这里所有东西都被杂乱的电网覆盖着。 +actors.blobs.stenchgas.desc=这里盘绕着一片腐毒酸雾。腐毒酸雾会不断地在被酸雾触及的所有东西上凝结出墨绿色的粘稠液体。 +actors.blobs.targas.desc=这里盘绕着一片粘稠油雾。粘稠油雾会不断地在被油雾触及的地方凝结出棕黄色的焦油。 +actors.blobs.toxicgas.desc=这里盘绕着一片鲜绿毒雾。毒雾会伤害所有吸入它的生物。 +actors.blobs.venomgas.desc=这里盘绕着一片鲜彩毒雾。鲜彩毒雾具有强烈的腐蚀性,会不断地侵蚀处于毒雾中的生物。 +actors.blobs.waterofawareness.desc=知识的力量正在从这口井的水里涌出。\n饮下井中的水以揭示所有已装备物品的秘密。 +actors.blobs.waterofawareness.procced=在你小酌一口时,你感觉到知识涌入了你的头脑。现在你对你的物品有了更深入的了解。同时,你掌握了这一层的秘密。 +actors.blobs.waterofhealth.desc=生命的力量正在从这口井的水里涌出。\n饮下井中的水以治疗你的伤口并填满你的肚子。 +actors.blobs.waterofhealth.procced=就在你小酌一口时,你感到你的伤口完全愈合了。 +actors.blobs.wateroftransmutation.desc=变化的力量正在从这口井的水里涌出。\n扔进一个物品以将其转化为其他物品。 +actors.blobs.weather.weatherofdead.desc=这里怨念很重。小心有鬼! +actors.blobs.weather.weatherofquite.desc=这里很安静。安静使人更加专注。 +actors.blobs.weather.weatherofrain.desc=这里下着小雨,降低了生物的命中和闪避。 +actors.blobs.weather.weatherofsand.desc=这里飞扬着沙子。降低了周围生物的攻击。 +actors.blobs.weather.weatherofsnow.desc=这里降着小雪。降低了周围生物的移动速度。 +actors.blobs.weather.weatherofsun.desc=这里阳光普照。提升了周围生物受到的伤害。 +actors.blobs.web.desc=这里所有东西都被厚厚的蜘蛛网覆盖着。 + +###buffs +actors.buffs.amok.desc=狂乱导致状态下的生物进入一种极度愤怒和混乱的状态。 \n\n狂乱的生物会不分敌我地攻击任何靠近它们的人。\n\n剩余的狂乱效果时长:%s回合 +actors.buffs.amok.name=狂乱 +actors.buffs.arcane.desc=魔力流遍了你的全身,增加了10点法强,以提升你的法杖伤害。\n奥术灌注持续时间: %s。 +actors.buffs.arcane.name=奥术灌注 +actors.buffs.armorbreak.desc=持续%s回合,增加%s%%受到的伤害。 +actors.buffs.armorbreak.name=破甲 +actors.buffs.attackdown.desc=持续%s回合,减少%s%%攻击力。 +actors.buffs.attackdown.name=乏力 +actors.buffs.attackup.desc=持续%s回合,增加%s%%攻击力。 +actors.buffs.attackup.name=攻击提升 +actors.buffs.awareness.desc=宝物探查可以允许你看到这片地方的所有宝物以及它们周围的情况。 \n\n剩余的探查效果时长:%s回合 +actors.buffs.awareness.name=宝物探查 +actors.buffs.barkskin.desc=你的皮肤硬化了,摸起来如同树皮一样既粗糙且坚固。 \n\n硬化的皮肤增强了你的实际护甲,使你能更好地抵御物理攻击。这种额外的护甲数值会以每回合一半的速度降低,直到它彻底失去作用。\n\n增加的护甲值:%d +actors.buffs.barkskin.name=树肤 +actors.buffs.berryregeneration.desc=生命恢复将为你提供额外的生命恢复速率,并随着游戏的深入而提供更长的持续时间。 \n\n剩余的恢复效果:%d +actors.buffs.berryregeneration.name=生命恢复 +actors.buffs.bleeding.desc=伤口正在令人不安地涌出大量血液。 \n\n流血每回合都会造成伤害。每回合这个伤害数值都会随机减少,直到出血最终停止。 \n\n当前流血伤害:%d +actors.buffs.bleeding.heromsg=你正在流血! +actors.buffs.bleeding.name=流血 +actors.buffs.bless.desc=你的注意力大大集中了,有人说这是神赐的礼物。 \n\n祝福状态能够显著提高自身的能力,使其在战斗中非常有效。 \n\n剩余的祝福效果时长:%s回合 +actors.buffs.bless.name=祝福 +actors.buffs.blindness.desc=失明使周遭的一切陷入黑暗。 \n\n失明时,角色不能看到周身一格以外的环境、致使远程攻击变得毫无作用、同时也很容易丢失正在追踪的敌人的动向。此外,失明的英雄也无法读书或使用卷轴。 \n\n剩余的失明效果时长:%s回合 +actors.buffs.blindness.heromsg=你失明了! +actors.buffs.blindness.name=失明 + +actors.buffs.burning.burnsup=%s被烧毁了! +actors.buffs.burning.desc=没什么比被火焰吞没更痛苦了。 \n\n火焰会每回合都会造成伤害直到它被液体扑灭或者自行消散。火会在你进入水中时熄灭,打碎药瓶产生的水花也具有同样的效果。 \n\n此外,火焰还会点燃所有接触到的可燃地形(以及可燃地形上的可燃物)。 \n\n剩余的燃烧效果时长:%s回合 +actors.buffs.burning.heromsg=你着火了! +actors.buffs.burning.name=燃烧 +actors.buffs.charm.desc=魅惑是一种能让敌人们暂时彼此爱慕的控制类魔法。 \n\n受魅惑的角色无法直接攻击魅惑它的那个生物,不过仍然可以攻击其他目标。\n\n剩余的魅惑效果时长:%s回合 +actors.buffs.charm.heromsg=你被魅惑了! +actors.buffs.charm.name=魅惑 +actors.buffs.chill.desc=还没有完全冻住,不过已经非常寒冷。\n\n冻伤的目标所有行动都会更加缓慢,减速程度决定于剩余的冻伤效果时间。最严重的冻伤情况等同于迟缓效果。 \n\n剩余的冻伤效果时长:%s回合\n当前减少的速度:%s%% +actors.buffs.chill.freezes=%s 冻住了! +actors.buffs.chill.name=冻伤 +actors.buffs.cold.desc=寒冷使你移动减缓。 \n\n剩余的效果时长:%s回合 +actors.buffs.cold.name=寒冷 +actors.buffs.combo.bonusdmg=\n\n当前连击伤害加成:%f%% +actors.buffs.combo.combo=%d连击! +actors.buffs.combo.desc=通过积累能量,角斗士能造成额外的伤害。\n\n你的连击数会在没有失误的不间断攻击下增加。你的连击数越高,你的攻击速度越快。失败或间断的攻击会重置连击数。 +actors.buffs.combo.name=连击 +actors.buffs.combo.notenough=\n\n你的连击还没有达到能造成额外伤害的程度。 +actors.buffs.countdown.desc=你的生命岌岌可危,再过一小段时间你就会受到大量的伤害。 \n\n剩余时间:%d +actors.buffs.countdown.name=延迟爆破 +actors.buffs.cripple.desc=你很确定自己的腿不该折成那样。 \n\n残废会减半移动速度,移动一格会消耗二回合而不是正常情况下的一回合。 \n\n剩余的残废效果时长:%s回合 +actors.buffs.cripple.heromsg=你残废了! +actors.buffs.cripple.name=残废 +actors.buffs.deadraise.desc=你感觉你身边充满了强烈的怨念,仿佛有什么东西即将出现。 \n\n剩余的效果时长:%s回合 +actors.buffs.deadraise.name=怨念环绕 +actors.buffs.defenceup.desc=持续%s回合,增加%s%%防御力 +actors.buffs.defenceup.name=防御提升 +actors.buffs.dewcharge.desc=当你击杀任何目标时,在它周围生成任意数量的露珠。 \n\n剩余的露珠爆破效果时长:%s回合 +actors.buffs.dewcharge.name=露珠爆炸 +actors.buffs.disarm.desc=无形的麻绳锁住了你的双手,使你无法进行近战攻击,持续%s回合 +actors.buffs.disarm.name=缴械 +actors.buffs.drowsy.desc=一股魔法力量使目标很难保持清醒。 \n\n英雄可以通过受到伤害或保持完整生命值来维持清醒。\n\n几个回合之后,目标将会陷入魔法睡眠。 +actors.buffs.drowsy.name=催眠 +actors.buffs.dry.desc=干燥使你变得心烦意乱,无法专心于战斗,降低了你的攻击力。 \n\n剩余的效果时长:%s回合 +actors.buffs.dry.name=干燥 + +actors.buffs.exitfind.name=出口侦测 + +actors.buffs.earthimbue.desc=你被灌注了大地的力量! \n\n直到该效果结束前你所有的物理攻击都会时敌人被缠绕在原地无法动弹。\n\n剩余大地之力效果时长:%s回合 +actors.buffs.earthimbue.name=大地之力 + +actors.buffs.fireimbue.desc=你被灌注了火焰的力量!\n\n所有物理攻击都有机会使敌人燃烧。与此同时你对火焰完全免疫。\n\n剩余火焰之力效果时长:%s回合 +actors.buffs.fireimbue.name=火焰之力 + +actors.buffs.frostimbue.desc=你被灌注了寒冰的力量!\n\n所有物理攻击都有机会使敌人冻结。与此同时你对冰冻完全免疫。\n\n剩余寒冰之力效果时长:%s回合 +actors.buffs.frostimbue.name=寒冰之力 + +actors.buffs.toxicimbue.desc=你体内被灌注了毒性能量! \n\n在你移动时毒气会从你的身体中翻腾而出,伤害你的敌人。持续时间内免疫毒气和中毒效果。 \n\n剩余的毒性之力时长:%s回合 +actors.buffs.toxicimbue.name=毒性之力 + +actors.buffs.bloodimbue.desc=鲜血之力将为你提供大量的效果免疫并且强化你的攻击。\n\n剩余的灌注效果时长:%s回合 +actors.buffs.bloodimbue.name=鲜血之力 + +actors.buffs.frost.desc=不要认为被冻得很结实了,这种温和的冻结只是把目标包裹在冰里。 \n\n冻结效果类似于麻痹,使目标不能行动。与麻痹不同的是,冻结效果会在目标受到伤害时立即消失,因为冰会碎。\n\n剩余的冻结效果时长:%s回合 +actors.buffs.frost.freezes=%s 冻住了! +actors.buffs.frost.name=冰冻 +actors.buffs.fullmoonstrength.desc=你变得非常强大,获得2.5倍的伤害加成。 +actors.buffs.fullmoonstrength.heromsg=你变强了! +actors.buffs.fullmoonstrength.name=满月之力 +actors.buffs.fury.desc=你非常暴怒,很明显敌人并不喜欢这样的你。\n\n一股猛烈的怒火在你体内燃烧,增加你25%%的物理攻击伤害,并降低25%你受到的伤害。\n\n只要你的生命还低于上限的60%,该效果就会存在。 +actors.buffs.fury.heromsg=你陷入了暴怒之中! +actors.buffs.fury.name=狂暴 +actors.buffs.gasesimmunity.desc=一种奇特的力量正在过滤你周边的空气,它并不会对你造成任何伤害,但它阻挡了所有空气意外的事物,以至于你什么气味都闻不到了!\n\n当该效果存在时你对所有气体效果免疫。\n\n剩余气体免疫效果时长:%s回合 +actors.buffs.gasesimmunity.name=气体免疫 +actors.buffs.glassshield.desc=来自玻璃之神的祝福。当你受到大于10点的伤害时,将伤害改为10。剩余保护次数:%s次。 +actors.buffs.glassshield.name=玻璃保护 +actors.buffs.growseed.desc=通常来讲这种种子专门吸取你的生命,并用于治疗周围的单位。 \n\n剩余的寄生种子效果时长:%s回合 +actors.buffs.growseed.heromsg=奇怪的种子在你的身上生长。 +actors.buffs.growseed.name=寄生种子 +actors.buffs.haste.desc=你的行动速度大幅度提升,持续%s回合。 +actors.buffs.haste.name=极速 +actors.buffs.hot.desc=炎热使你得血脉流动加快,一点小伤口也能带来大量的伤害。 \n\n剩余的效果时长:%s回合 +actors.buffs.hot.name=炎热 +actors.buffs.hunger.cursedhorn=就在你吃东西的时候被诅咒的号角偷走了一部分食物的能量。 +actors.buffs.hunger.desc=\n\n饥饿会在你在地牢里花费时间的同时缓慢累计,直到你饿得难以忍受。在你极度饥饿时生命值会停止回复并且开始缓慢减少 。\n\n合理利用食物非常重要!如果你有足够的生命值来维持饥饿,你就该等到一会儿食物更多的时候再吃。正确的配给可以让食物更有效地发挥作用! +actors.buffs.hunger.desc_intro_hungry=你能感受到自己的肚子在不断寻求食物,这降低了你的攻击力,不过还不算那么严重。 +actors.buffs.hunger.desc_intro_overfed=饱腹使你充满了决心,并提升了你的攻击力。 +actors.buffs.hunger.desc_intro_starving=你的饥饿程度已经危及生命了,这进一步降低了你的攻击力。 +actors.buffs.hunger.hungry=饥饿 +actors.buffs.hunger.onhungry=你有点饿了。 +actors.buffs.hunger.onoverfed=你吃饱了 +actors.buffs.hunger.onstarving=你已经饥肠辘辘! +actors.buffs.hunger.overfed=饱腹 +actors.buffs.hunger.starving=极度饥饿 +actors.buffs.invisibility.desc=你和周围的地形完全融为一体,使你不可能被看到。 \n\n当你在隐形时敌人无法追踪或攻击你。大部分物理攻击和魔法(比如卷轴和法杖)会立即解除隐形效果。 \n\n剩余的隐形效果时长:%s回合 +actors.buffs.invisibility.name=隐形 +actors.buffs.levitation.desc=一股魔力把你从地面托起,让你觉得自己身轻如燕。 \n\n在漂浮时你会无视所有以地面为基础的效果。陷阱不会被触发、火焰不会被水扑灭、植物不会被踩踏、根系无法缠绕你、并且能够跨越深渊。当心,在效果结束的那一刻上述效果都会失效!\n\n剩余的漂浮效果时长:%s回合 +actors.buffs.levitation.name=漂浮 +actors.buffs.light.desc=即使是在最黑暗的地牢中,身边有一个稳定的光源也总是令人欣慰。 \n\n光照能驱散黑暗,使你能够无视周遭的黑暗环境并拥有一个合理的视野范围。 \n\n剩余的发光效果时长:%s回合 +actors.buffs.light.name=发光 +actors.buffs.highlight.desc=即使是在最黑暗的地牢中,身边有一个稳定的光源也总是令人欣慰。 \n\n光照能驱散黑暗,使你能够无视周遭的黑暗环境并拥有一个超大的视野范围。 \n\n剩余的发光效果时长:%s回合 +actors.buffs.highlight.name=高亮 +actors.buffs.locked.desc=一把无形的锁锁死了你的背包,是你无法使用消耗类道具,持续%s回合。 +actors.buffs.locked.name=锁闭 +actors.buffs.lokispoison.desc=毒素传遍全身,缓慢地损伤着各个脏器。 \n\n毒素每回合造成的伤害与其剩余的回合数成正比。 \n\n剩余的中毒效果时长:%s回合 +actors.buffs.lokispoison.heromsg=你中毒了! +actors.buffs.lokispoison.name=猛毒 +actors.buffs.magicalsleep.desc=目标已深深陷入了魔法睡眠,不会自然醒来。\n\n魔法睡眠与一般的睡眠基本一样,但只有受伤会致使目标醒来。\n\n对于英雄,魔法睡眠有一些恢复性的效果,使他们能够在睡眠中迅速愈合伤口。 +actors.buffs.magicalsleep.fallasleep=你深深地陷入了魔法睡眠。 +actors.buffs.magicalsleep.name=魔法睡眠 +actors.buffs.magicalsleep.toohealthy=你十分健康,因此抵抗住了强烈的嗜睡感。 +actors.buffs.magicalsleep.wakeup=你醒来后,感觉浑身清爽并且十分健康。 +actors.buffs.magicimmunity.desc=奥术护盾可以为目标提供一定抗性。\n\n剩余的护盾效果时长:%s回合 +actors.buffs.magicimmunity.name=奥术护盾 +actors.buffs.mindvision.desc=你可以在脑海中以某种方式看到这一层的所有生物。这种感觉非常奇异。\n\n只要灵视效果依然存在,这层的所有生物都会在你的视野当中。通过灵视看到的生物同样算作视野中的目标,可以被很多魔法效果影响。\n\n剩余的灵视效果时长:%s回合 +actors.buffs.mindvision.name=灵视 +actors.buffs.muscle.desc=你感觉你的肌肉更加结实了,获得2点力量,持续%s回合。 +actors.buffs.muscle.name=活动肌肉 +actors.buffs.ooze.desc=这种粘稠的酸性淤泥正在紧贴你的骨肉,并缓慢地将它们腐蚀融化。\n\n淤泥会一直造成稳定伤害直至被水冲洗。\n\n淤泥本身不会自然消失,必须在水中才能洗掉。 +actors.buffs.ooze.heromsg=污泥在腐蚀你的身体。洗掉它! +actors.buffs.ooze.name=腐酸 +actors.buffs.paralysis.desc=通常最坏的事就是什么事都做不出来。\n\n麻痹会停止目标的一切动作,使目标保持原状直到效果消失。受伤导致的疼痛也能帮助目标脱离麻痹。 \n\n剩余的麻痹效果时长:%s回合 +actors.buffs.paralysis.heromsg=你被麻痹了! +actors.buffs.paralysis.name=麻痹 +actors.buffs.poison.desc=毒素传遍全身,缓慢地损伤着各个脏器。 \n\n毒素每回合造成的伤害与其剩余的回合数成正比。 \n\n剩余的中毒效果时长:%s回合 +actors.buffs.poison.heromsg=你中毒了! +actors.buffs.poison.name=中毒 +actors.buffs.recharging.desc=魔力在你体内奔腾而过,提高你的魔杖和法杖的充能速率。 \n\n每回合这个效果都将给你的法杖/魔杖增加四分之一点充能,这个效果的充能不同于正常充能并且能与之叠加。\n\n剩余的充能效果时长:%s回合 +actors.buffs.recharging.name=充能 +actors.buffs.rhythm.desc=你沉浸在你的节奏当中,大幅度提升你的命中和闪避,持续%s回合。 +actors.buffs.rhythm.name=节奏 +actors.buffs.rhythm2.desc=回响使你更加沉浸在你的节奏当中,小幅度提升你的速度,攻击和防御。持续%s回合。 +actors.buffs.rhythm2.name=回响 +actors.buffs.roots.desc=根系(不论是自然或魔法产生)缠到了脚上,将它们牢牢拴在地面。 \n\n根系会让目标被困在当前区域,使其不能移动,但不会干扰其他行为。 \n\n剩余的缠绕效果持续时长:%s回合 +actors.buffs.roots.heromsg=你不能动了! +actors.buffs.roots.name=缠绕 +actors.buffs.shadows.desc=你和周围的阴影融为一体,使你隐形并减缓你的新陈代谢。\n\n当你在隐形时敌人无法追踪或攻击你。大部分物理攻击和魔法(比如卷轴和法杖)会立即解除隐形效果。此外,当你处于暗影融合状态下时,饥饿值增加的速率会降低。\n\n暗影融合状态会一直持续直到你离开阴影或与敌人直接接触。 +actors.buffs.shadows.name=暗影融合 +actors.buffs.shield.desc=超高的护盾 +actors.buffs.shield.name=满月护盾 +actors.buffs.shieldblock.desc=无法驱散的超强控制效果。\n\n剩余的效果时长:%s回合 +actors.buffs.shieldblock.name=护盾打击 +actors.buffs.shocked.desc=当处于该状态的单位进行攻击时,它就会受到少量伤害并被缴械。持续时间: %s 回合。 +actors.buffs.shocked.name=静电乱流 +actors.buffs.silent.desc=沉默使人安静,并且让他无法诵读卷轴或释放咒语。持续%s回合。 +actors.buffs.silent.name=沉默 +actors.buffs.slow.desc=减速魔法影响了目标的时间流速,在目标眼中所有的事物都移动得飞快。 \n\n迟缓下的角色执行所有行动花费的时间是其执行相同行动的两倍。\n\n剩余的迟缓效果持续时长:%s回合 +actors.buffs.slow.name=迟缓 +actors.buffs.snipersmark.desc=狙击手将注意力集中到了附近的一个目标上,获得对目标远程攻击时的攻速加成和破甲效果。\n\n狙击手将不会停止专注直到她切换目标、停止攻击或目标死亡。 +actors.buffs.snipersmark.name=狙击标记 +actors.buffs.soulmark.desc=术士已经击穿了目标的灵魂。他将会在对其造成物理伤害时回复生命并填补饥饿感。 \n\n剩余灵魂印记持续时长:%s回合 +actors.buffs.soulmark.name=灵魂标记 +actors.buffs.speed.desc=移动速度增加 +actors.buffs.speed.name=加速 +actors.buffs.strength.desc=你感觉奇妙的力量充斥着你的身体,使你下次攻击得到极大的增强。 +actors.buffs.strength.name=强力 +actors.buffs.tar.desc=粘稠的油脂覆盖了你的全身,降低了你的行动速度,并且使你身上的火焰无法熄灭。 +actors.buffs.tar.heromsg=你身上覆盖满了粘稠的油脂。 +actors.buffs.tar.name=迟缓焦油 + +actors.buffs.terror.desc=恐惧是使敌人陷入不可控制的恐慌的操纵性魔法。 \n\n恐惧中的角色会远离自己的敌人,试图和敌人隔开尽可能多的门或墙。然而疼痛的冲击足以打破这种影响。\n\n剩余的恐惧效果持续时长:%s +actors.buffs.terror.name=恐惧 + +actors.buffs.venom.desc=剧毒是一种非常可怕且危险的毒素。 \n\n不像一般中毒的危害性随着时间的推移降低,猛毒在目标身上滞留的时间越长伤害越高。\n\n剩余的剧毒效果时长:%s回合\n当前剧毒伤害:%d +actors.buffs.venom.name=剧毒 +actors.buffs.vertigo.desc=如果整个世界都在旋转的话,想走直线会变得十分困难。 \n\n眩晕效果持续时,目标的移动将会向一个随机区域进行,而不是目标原本想到达的地方。\n\n剩余的眩晕效果时长:%s回合 +actors.buffs.vertigo.name=眩晕 +actors.buffs.weakness.desc=你感觉自己的装备突然变得沉重起来。 \n\n你正在被虚弱魔法影响,并减少2点力量。\n\n剩余的虚弱效果时长:%s回合 +actors.buffs.weakness.heromsg=你感到力量正在被抽走! +actors.buffs.weakness.name=虚弱 +actors.buffs.wet.desc=潮湿使你的身体变得笨重,降低了你的命中和闪避能力。 \n\n剩余的效果时长:%s回合 +actors.buffs.wet.name=潮湿 + +actors.buffs.shieldarmor.name=护盾 +actors.buffs.shieldarmor.desc=一种能量护甲正在保护你。\n\n这种护甲能够吸收你受到的100%%伤害,直到其耗尽耐久而瓦解。\n\n护盾量剩余:%d点。 + +actors.buffs.feed.name=狂宴 +actors.buffs.feed.desc=号角的力量流入了你的身体,使你能在击杀后获得生命上限提升。\n\n剩余的效果时长:%s回合。 + +actors.buffs.bloodangry.name=血怒 +actors.buffs.bloodangry.desc=圣杯里的血液和你交融,降低了你当前的生命上限,但大幅度提升了你的速度和伤害。\n\n剩余的效果时长:%s回合。 + +actors.buffs.soulbless.name=魂佑 +actors.buffs.soulbless.desc=玫瑰上的幽灵在保护着你。当你受到致命伤害时,它会阻止这个伤害并大幅度提升你的基础属性。 + +actors.buffs.goldtouch.name=点金 +actors.buffs.goldtouch.desc=臂章里的金币把你的手臂覆盖,使你在攻击时能获得金币。\n\n剩余的效果时长:%s回合。 + +actors.buffs.needling.name=荆棘 +actors.buffs.needling.desc=披风上针刺将你保护起来,使你在攻击的同时扎伤敌人。\n\n剩余的效果时长:%s回合。 + +actors.buffs.forevershadow.name=永影 +actors.buffs.forevershadow.desc=斗篷将它与你结合,短时间内使你无法被任何人察觉,即使你做出惊动他人的动作。\n\n剩余的效果时长:%s回合。 + +actors.buffs.notice.name=敏锐 +actors.buffs.notice.desc=护符提高了你的直觉,使你能够立刻发现各类隐藏事物。\n\n剩余的效果时长:%s回合。 + +actors.buffs.wargroove.name=战律 +actors.buffs.wargroove.desc=战斗的旋律提升了你的注意力,使你下一次攻击时所造成的伤害增加。 + +actors.buffs.targetshoot.name=精准射击 +actors.buffs.targetshoot.desc=投掷等级+10。\n\n剩余的效果时长:%s回合。 + +actors.buffs.mecharmor.name=机甲驾驶 +actors.buffs.mecharmor.desc=你现在在机甲里面。\n\n机甲剩余血量:%s。 + +actors.buffs.spattack.name=奇袭 +actors.buffs.spattack.desc=对满血和残血单位造成额外的伤害。\n\n持续时间:%s。 + +actors.buffs.highattack.name=攀墙伏击 +actors.buffs.highattack.desc=通过攀爬墙壁来蓄力,获得少量闪避提升和下次伤害加成。攀爬时间越久,伤害加成越高。离开墙壁周围会失去这个效果。\n\n下次伤害加成倍率:%s。 + +actors.buffs.paryattack.name=祈祷 +actors.buffs.paryattack.desc=通过站在原地来蓄力,获得伤害减免和伤害加成。祈祷时间越久,伤害加成和伤害减免越高。移动会失去这个效果。\n\n伤害加成倍率:%s。 + + +actors.buffs.highvoice.name=被声援 +actors.buffs.highvoice.desc=你听到了来自外界粉丝的助威,这使你充满了决心。\n\n持续时间:%s。 +actors.buffs.highvoice.atkup=%s你是最棒的! +actors.buffs.highvoice.heal=%s我要给你生猴子! +actors.buffs.highvoice.speed=加油啊%s! +actors.buffs.highvoice.save=守护最好的%s! + +actors.buffs.mirrorshield.name=智慧反射 +actors.buffs.mirrorshield.desc=智慧护盾将你保护起来,使你可以完全反弹接下来所受到的伤害。\n\n持续时间:%s。 + +actors.buffs.boxstar.name=无敌星 +actors.buffs.boxstar.desc=你无敌了。\n\n持续时间:%s。 + +actors.buffs.breakout.name=爆发 +actors.buffs.breakout.desc=你决定全力攻击,造成和受到的伤害同时提升100%。\n\n持续时间:%s。 + +actors.buffs.aflybless.name=不思议智慧 +actors.buffs.aflybless.desc=不思议的智慧带给你启发,少量的提升了你的当前力量和幸运。\n\n持续时间:%s。 + +actors.buffs.taunt.name=可疑标记 +actors.buffs.taunt.desc=??? + +actors.buffs.damageup.name=反击 +actors.buffs.damageup.desc=你抵挡了所受到的伤害,并提升了下一次攻击所造成的伤害。\n\n伤害提升值:%s。 + +actors.buffs.newcombo.name=隆拳连击 +actors.buffs.newcombo.combo=%d连! +actors.buffs.newcombo.bad_target=你的目标必须是攻击距离以内的敌人。 +actors.buffs.newcombo.clobber_prompt=选择一个要击垮的目标\n使其退后并晕向 +actors.buffs.newcombo.clobber_desc=_击垮_技能目前可用。这一招能_击退一个敌人并使其晕向_,但攻击伤害会有所降低。暴打敌人能够让你在苦战中喘一口气。 +actors.buffs.newcombo.cleave_prompt=选择一个要劈斩的目标\n如果劈斩击杀了敌人,连击数将被保留 +actors.buffs.newcombo.cleave_desc=_劈斩_技能目前可用。这次攻击造成更高伤害,_若成功以劈斩杀敌,连击计数将会保留而不是被重置。_在面对大量敌人时可有效积累连击数。 +actors.buffs.newcombo.slam_prompt=选择一个要重击的目标\n根据你的护甲决定造成的伤害与添加的护盾 +actors.buffs.newcombo.slam_desc=_重击_技能目前可用。这次攻击造成更高伤害,并_根据你的护甲造成伤害并提供护盾_。该技能非常适合用来结束战斗,能让你将额外的持久力带到下一场战斗中。 +actors.buffs.newcombo.crush_prompt=选择一个要粉碎的目标\n造成巨额伤害 +actors.buffs.newcombo.crush_desc=_粉碎_技能目前可用。这种毁灭性的打击_能够造成稳定的巨额伤害。_在对抗强力敌人时拥有奇效! +actors.buffs.newcombo.desc=你在成功打击敌人时能够积累能量。每次打击都会提高一次连击数,但长时间不进行攻击或是多于一次攻击失败都会将连击数归零。\n\n积累连击数会激活特殊的处决技能:无法被躲避的强力攻击!在连击数到达2,4,6,8时会提供不同的处决攻击,使用处决攻击会重置你的连击数。 + +actors.buffs.corruption.name=腐化 +actors.buffs.corruption.desc=腐化已渗透到了生命的本质,将其意志扭曲到愿意对抗自己的盟友、同族乃至至亲。\n\n腐化的生物会攻击和激怒他们的盟友,并使其忽略它们共同的敌人。腐化效果同时也会伤害其本身,导致目标缓慢走向死亡。\n\n腐化是永久性的,它只会在死亡后终结。 + +actors.buffs.faithbuff.mechfaith.name=信仰-机械派系 +actors.buffs.faithbuff.mechfaith.desc=对机械的信仰降低了来自机械的伤害,并提升对自然生物的伤害。 + +actors.buffs.faithbuff.lifefaith.name=信仰-自然派系 +actors.buffs.faithbuff.lifefaith.desc=对自然的信仰降低了来自自然生物的伤害,并提升对机械的伤害。 + +actors.buffs.faithbuff.demonfaith.name=信仰-恶魔派系 +actors.buffs.faithbuff.demonfaith.desc=对恶魔的信仰降低了来自恶魔的伤害,并提升对神圣生物的伤害。 + +actors.buffs.faithbuff.humanfaith.name=信仰-神圣派系 +actors.buffs.faithbuff.humanfaith.desc=对神圣的信仰降低了来自神圣生物的伤害,并提升对恶魔的伤害。 + +actors.buffs.faithbuff.balancefaith.name=信仰-平衡派系 +actors.buffs.faithbuff.balancefaith.desc=对平衡的信仰降低了来自强大生物的伤害,并提升对其的伤害。 + +actors.buffs.stoneice.name=源石霜冻 +actors.buffs.stoneice.desc=这种附带放射性的霜冻粒子会减缓目标的移动速度,并使其在移动过程中受到大量的伤害。但同时,这种粒子会提升目标的伤害输出。\n\n持续时间:%s。 + +###hero +actors.char.def_verb=闪避 +actors.char.out_of_paralysis=疼痛使%s从麻痹中解脱出来。 + +actors.hero.hero.auto_potion=你的药水自助器为你灌了一瓶药水! +actors.hero.hero.auto_potion_no=你的药水自助器空了! +actors.hero.hero.dewvial=它和你在其他世界里看到的露珠瓶完全不一样。 +actors.hero.hero.leave=从没有人愿意这么轻易地离开像素地牢。 +actors.hero.hero.level_up=升级 +actors.hero.hero.locked_chest=箱子锁着而你没有对应的钥匙 +actors.hero.hero.locked_door=你没有对应的钥匙。 +actors.hero.hero.name=你 +actors.hero.hero.new_level=恭喜升到%d级!你现在变得更加健康且专注。命中敌人和躲避敌人攻击都变得更加简单。 +actors.hero.hero.noticed_smth=你注意到了些什么。 +actors.hero.hero.pain_resist=疼痛是你从睡梦中惊醒。 +actors.hero.hero.revive=复活十字架爆发出生命的能量 +actors.hero.hero.search=搜索 +actors.hero.hero.search_distracted=你没办法集中精力,搜索花了好一阵时间。 +actors.hero.hero.something_else=这里还有其他东西。 +actors.hero.hero.wait=... +actors.hero.hero.you_now_have=你得到了%s。 + +actors.hero.heroclass.huntress=女猎手 +actors.hero.heroclass.huntress_desc_item=女猎手持有_指虎_和_EMP套索_。\n\n_回旋镖_是猎手的特殊道具 +actors.hero.heroclass.huntress_desc_loadout=女猎手使用投掷武器命中目标后会立刻对其造成一次攻击伤害。\n\n女猎手可以察觉到附近躲在障碍物后的敌人。 +actors.hero.heroclass.huntress_desc_misc=_灵视药水_和_驱散卷轴_在游戏开始就已鉴定。 + +actors.hero.heroclass.mage=法师 +actors.hero.heroclass.mage_desc_item=法师持有_魔法书_,_魔弹法杖_和_解离法杖_。\n\n_奇迹烧瓶_是法师的特殊道具 +actors.hero.heroclass.mage_desc_loadout=法师拥有+3法术强度,并且释放法术速度更快。\n\n法师能更有效的利用露水,并在进食后会获得一个回合的充能效果。 +actors.hero.heroclass.mage_desc_misc=_鉴定卷轴_和_液火药水_在游戏开始就已鉴定。 + +actors.hero.heroclass.performer=演员 +actors.hero.heroclass.performer_desc_item=演员持有_三角铁_,_催眠卷轴_和_炸弹_。\n\n_铁铲_是演员的特殊道具 +actors.hero.heroclass.performer_desc_loadout=演员在击杀或升级后将进入节奏模式,大幅度提升自身的属性。\n\n演员在升级后将获得玻璃祝福,大幅度减少自身受到的伤害。 +actors.hero.heroclass.performer_desc_misc=_催眠卷轴_和_净化药水_在游戏开始就已鉴定。 + +actors.hero.heroclass.rogue=盗贼 +actors.hero.heroclass.rogue_desc_item=盗贼拥有_匕首_和_烟雾手里剑_。\n\n_暗影披风_是盗贼的特殊道具 +actors.hero.heroclass.rogue_desc_loadout=盗贼装备武器时,降低该武器2点力量需求。\n\n盗贼更擅于发现隐藏门和陷阱。 +actors.hero.heroclass.rogue_desc_misc=_探地卷轴_和_隐形药水_在游戏开始就已鉴定。 + +actors.hero.heroclass.warrior=战士 +actors.hero.heroclass.warrior_desc_item=战士持有_短剑_和三枚不同_药丸_。\n\n_盾牌_是战士的特殊道具 +actors.hero.heroclass.warrior_desc_loadout=战士装备防具时,降低该防具2点力量需求。\n\n战士进食后获得更多的生命值。 +actors.hero.heroclass.warrior_desc_misc=_力量药水_和_升级卷轴_在游戏开始就已鉴定。 + +actors.hero.heroclass.soldier=星兵 +actors.hero.heroclass.soldier_desc_item=星兵拥有_投石索_和_逃脱匕首_。\n\n_脉冲手枪_是星兵的特殊道具 +actors.hero.heroclass.soldier_desc_loadout=星兵拥有额外的初始命中,初始闪避和生命成长。\n\n星兵幸运相较其他角色更佳出众,并且可以认出被诅咒的物品。 +actors.hero.heroclass.soldier_desc_misc=_狂怒卷轴_和_恢复药水_在游戏开始就已鉴定。 + +actors.hero.heroclass.follower=信徒 +actors.hero.heroclass.follower_desc_item=信徒拥有_木杖_和_治疗药水_。\n\n_信标盒_是信徒的特殊道具 +actors.hero.heroclass.follower_desc_loadout=信徒使用一件消耗品时,有几率不消耗这件物品。\n\n信徒在商店的开销降低。 +actors.hero.heroclass.follower_desc_misc=_恐惧卷轴_和_治疗药水_在游戏开始就已鉴定。 + +actors.hero.herosubclass.pastor=牧师 +actors.hero.herosubclass.pastor_desc=_牧师_自身的自然恢复和治疗效果翻倍,并且允许自然恢复突破生命上限。此外,攻击命中目标后有几率魅惑目标。 +actors.hero.herosubclass.artisan=工匠 +actors.hero.herosubclass.artisan_desc=_工匠_将降低装备物品的力量需求,并在击败敌人后有几率缴获它的装备。 +actors.hero.herosubclass.agent=特工 +actors.hero.herosubclass.agent_desc=_特工_可以在不装备枪械的情况下使用枪械,而且获得额外的射击速度,装弹速度和潜行能力。 +actors.hero.herosubclass.leader=领袖 +actors.hero.herosubclass.leader_desc=_领袖_能强化召唤物,用气势压制攻击他的敌人,并降低受到的伤害。 +actors.hero.herosubclass.assassin=刺客 +actors.hero.herosubclass.assassin_desc=进行偷袭时,_刺客_能对敌人造成额外伤害。 +actors.hero.herosubclass.battlemage=战斗法师 +actors.hero.herosubclass.battlemage_desc=_战斗法师_拥有更高的法术强度和更快的法术施放速度。 +actors.hero.herosubclass.berserker=狂战士 +actors.hero.herosubclass.berserker_desc=当严重受伤时,_狂战士_会进入狂暴的状态,显著增加伤害输出并减少所受到的伤害。 +actors.hero.herosubclass.freerunner=疾行者 +actors.hero.herosubclass.freerunner_desc=_疾行者_在不负重且不饥饿的情况下跑得更快,如果他处于隐形状态,那么该效果会进一步增强。 +actors.hero.herosubclass.gladiator=角斗士 +actors.hero.herosubclass.gladiator_desc=成功的近战攻击可以令_角斗士_开始连击,连击次数越多造成的伤害越高。 +actors.hero.herosubclass.joker=小丑 +actors.hero.herosubclass.joker_desc=_小丑_及其擅长蛊惑和欺诈,可以在远处攻击敌人的同时,将它们击退。 +actors.hero.herosubclass.sniper=狙击手 +actors.hero.herosubclass.sniper_desc=_狙击手_能够发现敌人的装甲的薄弱点,使用投掷武器的时候有效地无视敌人护甲并增加命中后的攻击速度。 +actors.hero.herosubclass.superstar=巨星 +actors.hero.herosubclass.superstar_desc=_巨星_强大的自信将增幅其本身的节奏,使其更加迅猛。 +actors.hero.herosubclass.warden=守望者 +actors.hero.herosubclass.warden_desc=与自然之力强大的连结允许_守望者_从露珠中获得额外的生命、践踏草地时增加潜行并且能从特殊植物中获得种子和露水。 +actors.hero.herosubclass.warlock=术士 +actors.hero.herosubclass.warlock_desc=_术士_用法杖攻击时会几率标记敌人的灵魂,被标记的敌人受到攻击将回复术士的血量和饥饿值。 + +###really +###this is for save game +actors.hero.heroclass.warrior_name=warrior +actors.hero.heroclass.mage_name=mage +actors.hero.heroclass.rogue_name=rogue +actors.hero.heroclass.huntress_name=huntress +actors.hero.heroclass.performer_name=performer +actors.hero.heroclass.soldier_name=soldier +actors.hero.heroclass.follower_name=follower + +###mobs +actors.mobs.acidic.desc=酸液蝎子较普通蝎子更强,也更加危险。它体内的酸液会在遇到危险时释放,从而保护自己免受天敌的袭击。 +actors.mobs.acidic.name=酸液蝎子 +actors.mobs.adultdragonviolet.atk=离这远点!入侵者! +actors.mobs.adultdragonviolet.desc=守卫巨龙通常是被召唤而来,但是对普通人来说它和野生巨龙没什么两样。 +actors.mobs.adultdragonviolet.die=为了...Otiluke大人!! +actors.mobs.adultdragonviolet.name=守卫巨龙 +actors.mobs.albino.desc=这是一只稀有品种的白色的老鼠,它有一身纯白色的皮毛和锯齿状的牙齿。邪恶污染使它周围布满了血雾。 +actors.mobs.albino.name=白化老鼠 +actors.mobs.albinopiranha.desc=在这种地方生活的肉食鱼经过上百年的演变,它们的视觉早已退化。不过它们的其他感官异常灵敏,可以感受到周围水流的变化,也异常凶猛。 +actors.mobs.albinopiranha.name=原生肉食鱼 +actors.mobs.assassin.def_verb=闪避 +actors.mobs.assassin.desc=由天狗所训练出来的忍者之一,极其擅长远程攻击。 +actors.mobs.assassin.name=暗杀者 +actors.mobs.bandit.desc=较普通绿衣小贼而言,紫衣大盗在偷窃同时,会狠狠伤害被偷窃者,以方便自己逃跑。 +actors.mobs.bandit.name=紫衣大盗 +actors.mobs.banditking.desc=传言,盗贼中有一群另类,他们对金银珠宝没有兴趣,倒是对生物的生命情有独钟。并且,他们可以在神不知鬼不觉的情况下偷走敌人的生命。他们也接受各种委托,但代价一般都是...生命。 +actors.mobs.banditking.die=算了,这次先放过你。 +actors.mobs.banditking.dis=蓝衣神偷消失了。 +actors.mobs.banditking.name=蓝衣神偷 +actors.mobs.banditking.spork=啊!我偷到的叉勺呢! +actors.mobs.bat.def_verb=闪避 +actors.mobs.bat.desc=这些敏捷且坚韧的洞穴穹顶生物能够通过每一次成功的攻击来恢复自己的生命,从而打败比它们大得多的对手。 +actors.mobs.bat.name=吸血蝙蝠 + +actors.mobs.bluecat.name=布鲁凯特 +actors.mobs.bluewraith.def_verb=闪避 +actors.mobs.bluewraith.desc=相较其他怨灵而言,怨灵战士更喜欢近距离作战而不是远程打击。它们的行动速度也比其他怨灵快。 +actors.mobs.bluewraith.name=怨灵战士 +actors.mobs.brokenrobot.broken=系统...关闭... +actors.mobs.brokenrobot.desc=虽然这个机器人的程序没有老化,但它的身躯抵抗不住时间的侵蚀。 +actors.mobs.brokenrobot.explode=自毁启动! +actors.mobs.brokenrobot.name=破损机械 +actors.mobs.brownbat.def_verb=闪避 +actors.mobs.brownbat.desc=小蝙蝠呈棕色,是一种没什么威胁的生物。当然如果你杀死了它的话,它有几率发出很大的响声。 +actors.mobs.brownbat.die=凄惨的叫声惊醒了附近的敌人! +actors.mobs.brownbat.name=小蝙蝠 +actors.mobs.brute.desc=暴徒是豺狼人中体型最庞大,力量最强壮且生命力最顽强的精英。严重受伤时,他们会陷入疯狂之中,对敌人造成更高的伤害。 +actors.mobs.brute.enraged=豺狼暴徒被激怒了! +actors.mobs.brute.name=豺狼暴徒 +actors.mobs.crab.def_verb=格挡 +actors.mobs.crab.desc=这些巨型的螃蟹位居下水道食物链的顶端。它们行动极其迅速且其厚重的甲壳能承受沉重的打击。 +actors.mobs.crab.name=巨蟹 +actors.mobs.crabking.desc=远古巨蟹收集保护类魔法和物品以便保护它的子民免受黑暗或贪婪者的袭击。它的壳本身是件不错的强化道具。 +actors.mobs.crabking.die=抱歉...我的子民... +actors.mobs.crabking.heal=远古巨蟹从高压电壳中吸取了能量! +actors.mobs.crabking.name=远古巨蟹 +actors.mobs.crabking.notice=请离开这,否则我就对你不客气了。 +actors.mobs.demongoo.desc=恶魔goo通常由各种物质组成,如熔岩、黏液、暗能量、恶意;然而,大部分都是黑暗。小心别让它自己分裂,因为即使最弱的部分,只要加入一点熔岩,也能再次变得坚固。 +actors.mobs.demongoo.divide=暗黑黏咕分裂了! +actors.mobs.demongoo.name=暗黑黏咕 + + +actors.mobs.dm300.desc=数个世纪前矮人们制造了这个机器。但此后,矮人们开始使用魔像、元素生物甚至是恶魔来替换机器,最终导致其文明的衰败。DM-300及类似的机器通常用于建设和挖掘,某些情况下,也可以用于城防。 +actors.mobs.dm300.die=任务失败。系统关闭。 +actors.mobs.dm300.heal=DM-300修复了它自己! +actors.mobs.dm300.name=DM-300 +actors.mobs.dm300.notice=检测到未经授权的人员。 +actors.mobs.dm300$tower.alert=生产线遭受攻击!应急保护措施启动! +actors.mobs.dm300$tower.desc=很多年前矮人就建立起一套完整的流水生产线,但他们对魔法的研究使这种流水生产线失于维护。目前这些生产器已经十分老旧了。 +actors.mobs.dm300$tower.name=老旧的生产器 +actors.mobs.dm300$tower.robots=自动防御...自动防御... + + +actors.mobs.dragonking.desc=一只普通的巨龙。它身上的魔法十分不稳定,击败它后可能打开世界通道。 +actors.mobs.dragonking.name=异界龙王 +actors.mobs.dustelement.blind=灰尘阻碍了你的视线。 +actors.mobs.dustelement.desc=年久失修的下水道里面的尘埃和向外扩散的黑暗力量融合,生成了这一种羸弱的元素。 +actors.mobs.dustelement.name=尘埃元素 + +actors.mobs.dwarflich.desc=与矮人国王一同进行不朽实验的矮人。他们虽然没有保留外貌,但是他们获得了极强的灵能。 +actors.mobs.dwarflich.name=不朽矮人 +actors.mobs.eye.desc=这种恶魔还有一个名字叫做“憎恶之球”,因为它在看到敌人时会毫无顾忌地使用它的死亡射线,而根本不顾及队友的存在。 +actors.mobs.eye.name=邪恶之眼 +actors.mobs.fetidrat.desc=很明显这只老鼠身上有着问题。其油腻的黑毛和腐烂的皮肤与你以前见过的健康老鼠很不同。浅绿色的眼睛让它显得更具威胁。\n\n这只老鼠周围围绕着一片可怕恶臭,其恶臭在近距离接触时尤其浓烈。\n\n黑色的淤泥从它的嘴中流出。淤泥腐蚀掉了地板,但其似乎能在水中溶解开来。 +actors.mobs.fetidrat.name=腐臭老鼠 +actors.mobs.fiend.desc=邪魔本身由暗影能量组成...但它的斗篷是哪来的? +actors.mobs.fiend.name=邪魔 +actors.mobs.fireelemental.desc==这些游荡的火元素是在召唤某种更强大存在时产生的副产品。其特性太过紊乱,以至于最强大的恶魔学者都没有办法驱使。 +actors.mobs.fireelemental.name=火元素 +actors.mobs.fishprotector.desc=这类守卫长相相似,但名称不同。这只守卫是守护这片洞穴的。 +actors.mobs.fishprotector.name=洞穴守卫 +actors.mobs.flyingprotector.desc=智慧试炼的守护者。 +actors.mobs.flyingprotector.name=智慧守卫 +actors.mobs.forestprotector.desc=这类守卫长相相似,但名称不同。这只守卫是守护这片森林的。 +actors.mobs.forestprotector.name=森林守卫 +actors.mobs.gnoll.desc=豺狼是鬣狗状的类人生物。它们在下水道和地牢里游荡,不时向上行动试图向地表发起进攻。豺狼巡查是它们种群里最普通的一员,它们既没有豺狼暴徒强壮,也赶不上萨满聪明。 +actors.mobs.gnoll.name=豺狼巡查 +actors.mobs.gnollarcher.desc=这个豺狼隐藏在树叶后。你在这儿让他很烦躁。 +actors.mobs.gnollarcher.name=豺狼弓箭手 +actors.mobs.gnollking$gnollkeeper.desc=豺狼王的亲卫队。它们绝大部分时候都是看守宝库的。 +actors.mobs.gnollking$gnollkeeper.name=豺狼卫士 +actors.mobs.gnollking$gnollkeeper.safe=放弃抵抗! +actors.mobs.gnollking.angry=你惹火我了! +actors.mobs.gnollking.desc=豺狼人霍格是豺狼人中的猛男,11级的杀手。哦,这是哈格啊...哈格是豺狼人的头领。 +actors.mobs.gnollking.die=我的...财宝... +actors.mobs.gnollking.name=哈格 +actors.mobs.gnollking.notice=嗯?谁敢擅闯我的宝库?! +actors.mobs.gnollshaman.desc=那些最具有智慧的豺狼可以掌握萨满魔法,豺狼萨满由于缺少力量所以更喜欢使用战斗法术。任何敢于质疑它们在部落里地位的人都会被萨满用法术毫不留情地消灭。 +actors.mobs.gnollshaman.name=豺狼萨满 +actors.mobs.gnolltrickster.desc=即使以豺狼人的标准来看,这个生物也非常的诡异。它鬼鬼祟祟地弯着腰向前移动,脸上挂着咧着嘴的邪恶笑容,肩上挂着的挎包鼓得同摇篮一般。它的瞳孔中诡异地混合着恐惧与兴奋。\n\n它的挎包里有一大批粗制滥造的飞镖,它们似乎包含着各种有害物质。 +actors.mobs.gnolltrickster.name=豺狼猎手 +actors.mobs.goldorc.def_verb=格挡 +actors.mobs.goldorc.desc=黑暗能量腐蚀了猪人,使纯洁的猪人变得邪恶。 +actors.mobs.goldorc.name=金眼猪人 +actors.mobs.goldthief.desc=不像其他类型的小偷,他们只关心一件特定的事情:闪闪发光的金钱。小心别让他们从你那里偷东西,因为从这些志同道合的小偷的潮汐中找回丢失的金子相当困难。 +actors.mobs.goldthief.name=黄金小盗 +actors.mobs.goldthief.stole=黄金小盗从你那里偷走了%s个金币! +actors.mobs.golem.def_verb=格挡 +actors.mobs.golem.desc=矮人们尝试将他们关于机械的知识与新发现的元素力量结合起来。土地之灵作为公认的最容易掌控的元素之灵,被用来当作机械的"灵魂"。尽管如此,仪式中最细微的失误都会造成严重的爆炸。 +actors.mobs.golem.name=魔像 + +actors.mobs.goo.atk=粘咕正在不断地抽动! +actors.mobs.goo.desc=我们对粘咕所知甚少。它甚至很有可能不是一个生物,而是下水道表面聚集的邪恶物质得到基本智能而产生的实体。不管怎样,很明显是黑暗魔法造就了这个生物。\n\n其凝胶性质让它吸收了很多黑暗能量,你光是靠近就感受到了一股寒意。如果粘咕使用这种能量对你进行攻击那你肯定支撑不了多久。 +actors.mobs.goo.die=咕……咕…… +actors.mobs.goo.name=黏咕 +actors.mobs.goo.notice=咕-咕! +actors.mobs.goo$poisongoo.create=粘咕分裂出了一些迷你粘咕! +actors.mobs.goo$poisongoo.desc=我们对粘咕所知甚少。它甚至很有可能不是一个生物,而是下水道表面聚集的邪恶物质得到基本智能而产生的实体。不管怎样,很明显是黑暗魔法造就了这个生物。\n\n其凝胶性质让它吸收了很多黑暗能量,你光是靠近就感受到了一股寒意。如果粘咕使用这种能量对你进行攻击那你肯定支撑不了多久。 +actors.mobs.goo$poisongoo.divide=毒性粘咕分裂了! +actors.mobs.goo$poisongoo.name=毒性粘咕 +actors.mobs.goo$poisongoo.squeeze=粘咕正在不断地抽动! + + +actors.mobs.graveprotector.desc=这类守卫长相相似,但名称不同。这只守卫是守护这片监狱的。 +actors.mobs.graveprotector.name=监狱守卫 +actors.mobs.greatcrab.noticed=这只螃蟹留意到了你的进攻并用它的巨大钳子格挡了这次攻击。 +actors.mobs.greatcrab.blocked=格挡 +actors.mobs.greatcrab.def_verb=格挡 +actors.mobs.greatcrab.desc=就算是和其他的下水道螃蟹相比较,这只螃蟹也是如此巨大。它的蓝色甲壳上有着一条条裂缝和几只藤壶,证明其经历的无数岁月。它缓慢地在周围爬行,用它那只巨大的钳子勉强保持平衡。\n\n尽管这螃蟹只有一只蟹钳,但钳子的大小完全补偿了这一不足。螃蟹只要发现危险就会把爪子举在自己身前,让自己获得坚不可摧的甲壳防护。 +actors.mobs.greatcrab.name=巨钳螃蟹 +actors.mobs.greyrat.desc=灰毛鼠是棕毛鼠的变种,它可以免疫大量的负面状态。 +actors.mobs.greyrat.name=灰毛鼠 +actors.mobs.guard.def_verb=格挡 +actors.mobs.guard.desc=作为曾经监狱的管理者,这些守卫和那些罪犯已经没什么区别了。它们蹒跚的步伐如同僵尸一般,毫无思绪地四处寻找不属于这片区域的生物,比如你!\n\n它的铁链缠在自己的胯部,也许可以用来将敌人拉扯到非常近的距离。 +actors.mobs.guard.name=监狱守卫 +actors.mobs.guard.scorpion=给我过来! +actors.mobs.hermitcrab.absorb=寄居蟹将攻击的能量吸收进了它的贝壳。 +actors.mobs.hermitcrab.charge=高压电壳充能了%s点。 +actors.mobs.hermitcrab.desc=传奇巨蟹的随从,这些坚韧的螃蟹能用它们的壳吸收除了最弱的攻击之外所有的攻击。吸收的攻击会被用来对闪电贝壳充能。 +actors.mobs.hermitcrab.name=寄居蟹 + + +actors.mobs.king$undead.def_verb=格挡 +actors.mobs.king$undead.desc=由矮人国王的意志唤醒的矮人亡灵,曾经的王国议会成员。除了长着厚实的胡须以外,和正常的骷髅外观上并没有区别。 +actors.mobs.king$undead.name=矮人亡灵 +actors.mobs.king.arise=以我之名,复苏吧!奴隶们! +actors.mobs.king.cannot=我还没有输! +actors.mobs.king.def_verb=格挡 +actors.mobs.king.desc=这位最后的矮人国王以对生死机制的透彻理解而闻名。他说服王国的议会成员参加了一场本应让他们所有人获得永生的仪式。最终成功的仅他一人——以及一支死灵军队。 +actors.mobs.king.die=你无法杀死我,%s... 我是...永恒的... +actors.mobs.king.liches=巫师们,起来吧! +actors.mobs.king.meeting=何人来此喧哗?! +actors.mobs.king.name=矮人国王 +actors.mobs.king.notice=你敢! +actors.mobs.king$dwarfkingtomb.desc=这东西是由各种奇怪的材料制成的,看起来它和矮人王联系密切。 +actors.mobs.king$dwarfkingtomb.impossible=那毫无作用。 +actors.mobs.king$dwarfkingtomb.name=永恒之墓 + +actors.mobs.littower.desc=Otiluke用他的石像代替他来守护核心。石像是无敌的,但是切断魔力来源可以使他停止。你的旅程即将到达尾声,保持你的决心! +actors.mobs.littower.name=Otiluke守护石像 +actors.mobs.littower.zap=远离核心,这不是你该来的地方! +actors.mobs.livemoss.desc=由于黑暗力量的侵蚀,下水道诡异的生物逐渐增多。这个生物就是其中的一种:扭曲的植物占据了死去的老鼠躯体,并向外抛洒寄生孢子。 +actors.mobs.livemoss.name=寄生苔藓 +actors.mobs.magiceye.desc=这种邪眼似乎完全是由能量构成,在释放完全部的能量后就会自行死亡。 +actors.mobs.magiceye.name=青色邪眼 +actors.mobs.mimic.desc=宝箱怪是一种能随意改变外形的生物。在地牢里它们几乎一直以宝箱形态出现,因为它们明白怎么去吸引冒险者。 +actors.mobs.mimic.name=宝箱怪 +actors.mobs.minesentinel.desc=钢铁守卫和普通活化石像的区别就是...材质不同。它手上握着_%s_,看起来非常危险。 +actors.mobs.minesentinel.name=钢铁守卫 +actors.mobs.mob$fleeing.status=这个%s正在逃跑 +actors.mobs.mob$hunting.status=这个%s正在追猎 +actors.mobs.mob$passive.status=这个%s是无害的 +actors.mobs.mob$sleeping.status=这个%s正在睡觉 +actors.mobs.mob$wandering.status=这个%s正在游荡 +actors.mobs.mob.clear1=你成功在目标之前%s步清空本层。 +actors.mobs.mob.clear2=你成功在目标之前1步清空本层。 +actors.mobs.mob.clear3=你花费的时间太长了,下层加油哦。 +actors.mobs.mob.died=你依稀听到有什么东西在远处消亡了。 +actors.mobs.mob.exp=%+d经验值 +actors.mobs.mob.killcount=击杀计数:%s +actors.mobs.mob.rage=\#$%^ +actors.mobs.mob.rankings_desc=死于:%s +actors.mobs.monk.def_verb=招架 +actors.mobs.monk.desc=这些僧侣皆是狂热的信徒,倾其所能从一切异族手中保护他们城市的秘密。他们既不披甲亦不执械,仅仅依靠他们的徒手格斗技巧退敌。 +actors.mobs.monk.disarm=武僧将你手中的武器击飞了! +actors.mobs.monk.name=矮人武僧 +actors.mobs.mossyskeleton.def_verb=格挡 +actors.mobs.mossyskeleton.desc=青苔覆盖了一具骷髅骨架,并由此支配骷髅的行动。 +actors.mobs.mossyskeleton.name=青苔骷髅 + +actors.mobs.musketeer.desc=与矮人国王的想法不同,矮人将军认为火器才是正确的研究方向。于是矮人射手就加入矮人王国的巡逻队。 +actors.mobs.musketeer.name=矮人射手 +actors.mobs.orbofzotmob.desc=你启动了zot牌能源球。它在攻击附近的怪物! +actors.mobs.orbofzotmob.die=机体过热,关闭... +actors.mobs.orbofzotmob.name=zot牌能源球 +actors.mobs.orc.def_verb=格挡 +actors.mobs.orc.desc=力量试炼里的锻炼你的力量的生物。它们纯洁善良,但是下手没有轻重... +actors.mobs.orc.name=猪人 +actors.mobs.otiluke.desc=Otiluke的镜像,但是已经被zot腐化。看起来它在为石像提供能源。 +actors.mobs.otiluke.name=被腐化的Otiluke的镜像 +actors.mobs.otiluke.summon=守卫们,保护核心! +actors.mobs.piranha.desc=这些肉食性鱼类不是地下水池中的天然生物。它们被专门培育用来保护被水淹没的储藏室。 +actors.mobs.piranha.name=巨型肉食鱼 + +actors.mobs.plaguedoctor.crazy=瘟疫医生的信念正在经受考验......狂乱! +actors.mobs.plaguedoctor.desc=这是一个不被人认可的研究者。在他被带到这个世界后,他就疯了。 +actors.mobs.plaguedoctor.name=瘟疫医生 +actors.mobs.plaguedoctor.notice=所以...你是来帮我做研究的吗... +actors.mobs.plaguedoctor.yell2=老鼠...他们到处都是...我们完了... +actors.mobs.plaguedoctor.yell=放心,这不会痛的...我会证明给你看... +actors.mobs.plaguedoctor$shadowrat.desc=一种奇怪的影子。它长得和老鼠差不多。 +actors.mobs.plaguedoctor$shadowrat.name=瘟疫之影 + +actors.mobs.prisonwander$seekbombp.name=追猎炸弹 +actors.mobs.prisonwander$seekbombp.desc=追猎炸弹 +actors.mobs.prisonwander.desc=监狱的最高管理者。结实而强大 +actors.mobs.prisonwander.die=I-will-be-back! +actors.mobs.prisonwander.name=典狱长 +actors.mobs.prisonwander.notice=我看到你了! +actors.mobs.prisonwander.scorpion=没人能从我手上逃离!!! + +actors.mobs.rat.desc=虽说棕毛鼠们具有攻击性,可它们依旧是下水道居民里的弱者。它们成群结队非常烦人,但只有一只时对你够不上什么威胁。 +actors.mobs.rat.name=棕毛鼠 +actors.mobs.ratboss.desc=领头鼠是鼠群的头领。虽然它不像鼠王一样有威信,但它依然可以叫来鼠群。 +actors.mobs.ratboss.name=领头鼠 +actors.mobs.ratboss.spawn=这里出现了一群老鼠! +actors.mobs.redwraith.def_verb=躲避 +actors.mobs.redwraith.desc=相较于普通幽灵而言,混沌幽灵蕴含更强的能量。这也是这种幽灵呈红色的原因。相传有些戒指的魔力来源于它,不知道是不是真的。 +actors.mobs.redwraith.name=混沌幽灵 +actors.mobs.scorpio.desc=这些巨大的节肢类生物会尽可能避免一切近距离接触,并且会在远处射出能够致残的尖刺。 +actors.mobs.scorpio.name=巨型蝎子 +actors.mobs.seekinbomb.desc=只是个追猎炸弹而已。 + + +actors.mobs.senior.desc=相较普通武僧而言,武僧大师变秃了,也变强了! +actors.mobs.senior.name=武僧大师 + +actors.mobs.sentinel.desc=你以为这只是地牢里的另一个丑陋雕像,但它发出红光的眼睛让你放弃了刚才的想法。 尽管雕像本身是用钢铁做的,但它手上握着_%s_,看起来像是真的。 +actors.mobs.sentinel.name=活化钢像 + +actors.mobs.sewerheart.atk=这只植物好像在准备什么! +actors.mobs.sewerheart.blink=这个东西逃走了! +actors.mobs.sewerheart.desc=监狱的典狱长曾经养过许多种奇怪的植物,其中一种就是这个莓果。很明显,在监狱崩溃后这只莓果逃了出来,并在这里自由的生长。 +actors.mobs.sewerheart.name=下水道之心 +actors.mobs.sewerheart$sewerlasher.desc=这东西应该属于茎,反正很危险就是了。 +actors.mobs.sewerheart$sewerlasher.name=藤鞭 + +actors.mobs.shadowyog.blink=Yog之影转移了! +actors.mobs.shadowyog.desc=Yog之影是Yog在另一世界的投影。击败它没准就可以知晓穿越世界的秘密。 +actors.mobs.shadowyog.die=... +actors.mobs.shadowyog.illusion=光明已逝,暗影降临... +actors.mobs.shadowyog.name=Yog-Dzewa之影 + +actors.mobs.shell.desc=没人知道为什么高压电壳带有高压,因为知道的人没一个活了下来。 +actors.mobs.shell.name=高压电壳 + +actors.mobs.shielded.def_verb=格挡 +actors.mobs.shielded.desc=这个豺狼人带着一块盾牌。说真的它还是带把大剑强点。 +actors.mobs.shielded.name=持盾豺狼 +actors.mobs.skeleton.def_verb=格挡 +actors.mobs.skeleton.desc=骷髅是从那些悲惨的冒险者及地牢原住民尸骨的聚合物产生的,来自下层地牢的邪恶力量将它们从死亡中唤起。在吸收了足够的伤害之后,它们就会在骨头的爆炸中消解。 +actors.mobs.skeleton.name=骷髅 +actors.mobs.skeletonhand1.desc=骷髅王的右手,王者的右手 +actors.mobs.skeletonhand1.name=王之右手 +actors.mobs.skeletonhand2.desc=骷髅王的左手,亡者的左手 +actors.mobs.skeletonhand2.name=亡之左手 +actors.mobs.skeletonking.desc=骷髅王是一个十分强大的存在。 +actors.mobs.skeletonking.die=魔法不够了... +actors.mobs.skeletonking.name=奥瑞克莱 +actors.mobs.skeletonking.notice=你会被亡灵的怒火吞没,%s! +actors.mobs.sommonskeleton.name=被召唤的亡灵 +actors.mobs.sommonskeleton.desc=这不过是一个被召唤的亡灵而已。 +actors.mobs.sokobansentinel.desc=一种幻影,没有思维,行动缓慢,手持幻影_%s_,只会对面前的生物发动攻击。 +actors.mobs.sokobansentinel.name=推箱关守卫 +actors.mobs.spinner.desc=绿色而多毛的洞穴蜘蛛们会试着去躲避直接的战斗,它们更喜欢在远处等待其猎物卷入蜘网,在毒素中慢慢死去。 +actors.mobs.spinner.name=矿洞蜘蛛 +actors.mobs.statue.desc=你以为这只是地牢里的另一个丑陋雕像,但它发出红光的眼睛让你放弃了刚才的想法。 尽管雕像本身是用石头做的,但它手上握着_%s_,看起来像是真的。 +actors.mobs.statue.name=活化石像 +actors.mobs.succubus.desc=魅魔是外表诱人(稍有某种哥特风格)的女性恶魔。通过使用魔法,魅魔可以魅惑英雄,使英雄在魅惑消退前无法攻击它。 +actors.mobs.succubus.name=魅魔 +actors.mobs.swarm.def_verb=躲避 +actors.mobs.swarm.desc=致命的飞蝇群愤怒地发出嗡嗡声。每次非魔法攻击都会把它分割成两群更小但同样危险的飞蝇群。 +actors.mobs.swarm.name=蝇群 +actors.mobs.tengu.desc=天狗是远古时期的暗杀组成员。这些刺客以十分善于使用手里剑和陷阱著称。 +actors.mobs.tengu.die=混蛋,走着瞧! +actors.mobs.tengu.name=天狗 +actors.mobs.tengu.notice=嘿,这是我的地盘,%s! +actors.mobs.tenguden.die=诅咒你永世不得好死。 +actors.mobs.tenguden.name=匿藏的天狗 +actors.mobs.tenguden.notice=你是怎么找到我的! +actors.mobs.tenguden.desc=逃跑了的天狗。 +actors.mobs.testmob.desc=试试看,你能打多少伤害。 +actors.mobs.testmob.name=稻草人 +actors.mobs.testmob2.desc=这个稻草人很危险,千万不要触动它。 +actors.mobs.testmob2.name=发条稻草人 +actors.mobs.thief.desc=虽然这些囚犯逃出了他们的牢房,但这个地方仍然是关押着他们的监狱。随着时间的推移,这个地方摧毁了他们的心智以及对自由的希望。在很久以前,这些疯狂的小偷和强盗就已经忘记了它们是谁以及它们在为什么而活。 +actors.mobs.thief.name=绿衣毛贼 +actors.mobs.thiefimp.carries=\n\n这个小鬼携带着一个_%s_。明显是偷来的。 +actors.mobs.thiefimp.desc=小鬼是地狱当中最底层的居民。它们没有固定的收入来源,所以它们经常去其他地方偷窃。 +actors.mobs.thiefimp.name=强盗小鬼 +actors.mobs.thiefimp.stole=小鬼偷走了%s! +actors.mobs.thiefking.desc=传说中最神秘的盗贼。同时也是这个城市的领主。 +actors.mobs.thiefking.die=你的生命,我买不起... +actors.mobs.thiefking.name=金城领主 +actors.mobs.thiefking.notice=你就是让我们组织吃瘪的那个人,%s?那么现在,受死吧。 + +actors.mobs.trollwarrior.angry=你竟敢攻击我!!! +actors.mobs.trollwarrior.desc=巨魔暴躁的脾气和力量,导致他们的犯罪率极高。在监狱沦陷前,监狱里面各种势力都想和巨魔打好关系,即便是守卫也一样。 +actors.mobs.trollwarrior.name=巨魔战士 + +actors.mobs.uamulet.desc=???????????? +actors.mobs.uamulet.name=希望暗影 +actors.mobs.uamulet$darkmirror.name=黑暗镜像 +actors.mobs.uamulet$darkmirror.desc=?????? + +actors.mobs.udm300$seekbomb.name=追猎炸弹 +actors.mobs.udm300.desc=这种机器人是专门为攻城杀人制作的。它内部内置了许多致命的玩意。 +actors.mobs.udm300.name=杀人巨械 + +actors.mobs.ugoo$earthgoo.name=粘土黏咕 +actors.mobs.ugoo$firegoo.name=火焰黏咕 +actors.mobs.ugoo$icegoo.name=冰霜黏咕 +actors.mobs.ugoo$shockgoo.name=雷云黏咕 +actors.mobs.ugoo.desc=虚空的一只黏咕的投影。它可比这个世界的任何一只黏咕都要强。 +actors.mobs.ugoo.name=领主黏咕 + +actors.mobs.uicecorps.name=术士冬痕 +actors.mobs.uicecrops.desc=一只兔人族的术士,向四周散发着寒气 + +actors.mobs.uking.desc=这个家伙是植物的王者。 +actors.mobs.uking.name=植物领主 + +actors.mobs.utengu.desc=年轻时的天狗,既擅长远程攻击也擅长近战攻击。 +actors.mobs.utengu.name=年轻的天狗 + +actors.mobs.uyog.desc=一只叫始祖的眼睛...它看上去很眼熟。 +actors.mobs.uyog.name=始祖之眼 + +actors.mobs.vaultprotector.desc=这类守卫长相相似,但名称不同。这只守卫是这个城市的城管。 +actors.mobs.vaultprotector.name=金城守卫 +actors.mobs.warlock.desc=当矮人的兴趣从工程建设转向奥秘学术时,术士们开始在城市中掌权。它们从元素魔法起步,但很快就开始研究恶魔学和死灵术。 +actors.mobs.warlock.name=矮人术士 +actors.mobs.wraith.def_verb=躲避 +actors.mobs.wraith.desc=怨灵是来自于墓穴中渴望复仇的罪人之魂。作为飘渺的非实体很难被正常武器击中。 +actors.mobs.wraith.name=怨灵 + +actors.mobs.yog$burningfist.name=火焰之拳 +actors.mobs.yog$burningfist.desc=火焰之拳 +actors.mobs.yog$infectingfist.name=酸蚀之拳 +actors.mobs.yog$infectingfist.desc=酸蚀之拳 +actors.mobs.yog$larva.name=古神幼虫 +actors.mobs.yog$larva.desc=古神幼虫 +actors.mobs.yog$pinningfist.name=剧毒之拳 +actors.mobs.yog$pinningfist.desc=剧毒之拳 +actors.mobs.yog$rottingfist.name=大地之拳 +actors.mobs.yog$rottingfist.desc=大地之拳 +actors.mobs.yog.blink=Yog消失了! +actors.mobs.yog.desc=Yog-Dzewa是一位上古之神,来自混沌的强大存在。一个世纪前,古代矮人在与恶魔军队的战争中惨胜,却无法将古神杀死。于是他们把它封印在城市下的大堂里,认为过于虚弱的它永远都不会复苏。 +actors.mobs.yog.die=我...永生... +actors.mobs.yog.name=Yog-Dzewa + +actors.mobs.yog.notice=希望的存在只是一种幻觉… +actors.mobs.zot.desc=Zot是虚空中强大的领主之一。它可以自由操控黑暗和邪能。如果不是Otiluke将它拉到这个位面,你可能根本伤不到他。 +actors.mobs.zot.die=... +actors.mobs.zot.name=Zot +actors.mobs.zot.notice=你这是自寻死路! +actors.mobs.zot.pain=感受这被囚禁的愤怒吧! +actors.mobs.zotphase.desc=Zot的虚像,看上去是真的。 +actors.mobs.zotphase.name=Zot的虚像 + +actors.mobs.virus.desc=梦魇病毒 +actors.mobs.virus.name=---!!!数据删除!!!--- + +actors.mobs.zombie.desc=一种没有思维行动缓慢的不死生物...等下,这不是这种丧尸,这是感染者。 +actors.mobs.zombie.name=丧尸 +actors.mobs.patroluav.desc=一种高科技的无人机,被用于清理下水道垃圾。 +actors.mobs.patroluav.name=巡逻无人机 +actors.mobs.sandmob.desc=一种由沙子组成的怪物,死亡后会分裂。 +actors.mobs.sandmob.name=沙怪 +actors.mobs.sandmob$minisand.name=迷你沙怪 +actors.mobs.sandmob$minisand.desc=迷你沙怪 +actors.mobs.spiderbot.desc=矮人利用实验室废料所制作的机械宠物。它们和普通蜘蛛一样可以织网,并且喷出油脂来攻击。 +actors.mobs.spiderbot.name=机械蜘蛛 + +actors.mobs.demonflower.desc=在地狱中生长的花,它不仅能够移动,还能打出3连爆发并削弱目标的护甲。 +actors.mobs.demonflower.debuff=恶魔花施放了虚弱孢子。 +actors.mobs.demonflower.name=恶魔花 + +actors.mobs.sufferer.desc=这些过于高估自己的术士,尝试控制高等恶魔失败,然后被恶魔奴役,留在了这里。 +actors.mobs.sufferer.name=受难者 + +actors.mobs.tank.desc=一般来说不死族给人的印象都是迟缓,脆弱和源源不断。但是这只不死生物的体型,速度,力量都超过正常亡灵的水平。 +actors.mobs.tank.notice=啊啊啊啊啊嗷嗷嗷嗷嗷嗷!!! +actors.mobs.tank.die=啊啊啊啊啊嗷嗷嗷嗷嗷嗷...... +actors.mobs.tank.rock=TANK丢出了巨石! +actors.mobs.tank.name=TANK + +actors.mobs.spiderqueen.desc=蜘蛛们一般会选择聚在一起来建立一个巢穴。当巢穴的等级到达3级时,蜘蛛们就会推选出一只女王来扩张它们的地盘。 +actors.mobs.spiderqueen.notice=谁在撕扯我的网?! +actors.mobs.spiderqueen.die=我...输了... +actors.mobs.spiderqueen.egg=蛛后孵化了新的巢穴。 +actors.mobs.spiderqueen.name=蜘蛛皇后 +actors.mobs.spiderqueen$spideregg.name=巢穴 +actors.mobs.spiderqueen$spideregg.desc=根据孵化时间的不同,产出的蜘蛛种类也不同。 + +actors.mobs.spiderqueen$spiderworker.name=蜘蛛工人 +actors.mobs.spiderqueen$spiderworker.desc=蜘蛛大军的一种 +actors.mobs.spiderqueen$spiderjumper.name=跳蛛卫士 +actors.mobs.spiderqueen$spidermind.name=灵能蜘蛛 +actors.mobs.spiderqueen$spidergold.name=禁卫金蛛 + +actors.mobs.goldcollector.name=税收官 +actors.mobs.goldcollector.desc=这个是一个普通的税收官。 + +actors.mobs.levelchecker.name=裁决者 +actors.mobs.levelchecker.desc=这个是一个普通的裁决者。 + +actors.mobs.normalcell.name=细胞怪 +actors.mobs.normalcell.desc=天哪,细胞成精啦! + +actors.mobs.hybrid.name=混源体 +actors.mobs.hybrid.notice=我是埃蒙忠实的仆从。 +actors.mobs.hybrid.die=为了...虚空... +actors.mobs.hybrid.shield=埃蒙的力量保护着我。 +actors.mobs.hybrid.desc=由异能者,虫群,亡灵等的基因混合而成的未知生物。 +actors.mobs.hybrid$mixers.name=混源体 +actors.mobs.hybrid$mixers.desc=由异能者,虫群,亡灵等的基因混合而成的未知生物。 + +actors.mobs.elderavatar.name=长老化身 +actors.mobs.elderavatar.notice=效忠于我,或者死去。 +actors.mobs.elderavatar.disarm=长老剥离了你的护甲。 +actors.mobs.elderavatar.die=就算我死了,也有其他人接替我的位置... +actors.mobs.elderavatar.shield=尖碑给予我生命的力量。 +actors.mobs.elderavatar.desc=异能者的领袖,指挥者。他正四处寻找可以延续自身寿命的基因组。 +actors.mobs.elderavatar$obelisk.name=三角尖碑 +actors.mobs.elderavatar$obelisk.impossible=检测到长老生命信号,伤害吸收。 +actors.mobs.elderavatar$obelisk.desc=一种生命储存装置。 +actors.mobs.elderavatar$thehunter.name=猎手 +actors.mobs.elderavatar$thehunter.desc=异能者的尖锐猎手。 +actors.mobs.elderavatar$thewarlock.name=术士 +actors.mobs.elderavatar$thewarlock.desc=异能者的尖锐术士。 +actors.mobs.elderavatar$themonk.name=圣堂 +actors.mobs.elderavatar$themonk.desc=异能者的尖锐圣堂武士。 +actors.mobs.elderavatar$themech.name=裁决 +actors.mobs.elderavatar$themech.desc=异能者的尖锐裁决者。 + +actors.mobs.npcs.mtree.name=树苗 +actors.mobs.npcs.mtree.desc=普通的小树苗 + +actors.mobs.lichdancer.name=巫妖舞者 +actors.mobs.lichdancer.desc=舞者,24岁,是个艺人。自愿接受亡灵的交易,成为了一个巫妖。 +actors.mobs.lichdancer.notice=在我表演的一生中,我明白一个道理:作为人类而言,我们演员是有极限的。所以...我不做人啦! +actors.mobs.lichdancer$batterytomb.name=死灵电池 +actors.mobs.lichdancer$batterytomb.desc=一个奇怪的电池,不断释放着死灵能量。 +actors.mobs.lichdancer$linkbomb.name=炸弹 +actors.mobs.lichdancer$linkbomb.desc=小心,它要炸了! + +actors.mobs.firerabbit.name=堕天使 +actors.mobs.firerabbit.desc=兔人火焰兵,训练方便造价低廉,被派遣至此清剿亡灵。 +actors.mobs.firerabbit.yell=ko~ko~da~yo + +actors.mobs.manyskeleton.name=骷髅球 +actors.mobs.manyskeleton.desc=一大堆骷髅组成的球,打一下就有骷髅掉出来。 + +actors.mobs.yearbeast.name=年兽 +actors.mobs.yearbeast.disarm=年兽解除了你的武装! +actors.mobs.yearbeast.desc=传说中的生物,有着人类的智慧,虎的敏捷,熊的力量,凤的魅力。当然,这一切都是传说而已。 +actors.mobs.yearbeast.notice=我自由啦! +actors.mobs.yearbeast.die=居然能战胜我!这是给你的奖励。 +actors.mobs.yearbeast.escape=现在时候不对,我先溜了。 + +actors.mobs.yearbeast2.name=年兽 +actors.mobs.yearbeast2.disarm=年兽解除了你的武装! +actors.mobs.yearbeast2.desc=传说中的生物,有着人类的智慧,虎的敏捷,熊的力量,凤的魅力。当然,这一切都是传说而已。 +actors.mobs.yearbeast2.notice=谁把我吵醒了?! +actors.mobs.yearbeast2.die=啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊!!! + +actors.mobs.bombbug.name=霜石虫 +actors.mobs.bombbug.desc=包裹着冰石的虫子。 + +###pets +actors.mobs.pets.bluedragon.desc=蓝龙精通冰寒之力,也是原先性价比最高的龙。 +actors.mobs.pets.bluedragon.name=蓝龙 +actors.mobs.pets.bluedragon.ready=冰霜炸裂准备就绪 +actors.mobs.pets.bunny.desc=作为复活节的传统,复活节兔子和彩蛋一度闻名于世界。 +actors.mobs.pets.bunny.name=复活节彩蛋兔 +actors.mobs.pets.bunny.ready=野蛮撕咬准备就绪 +actors.mobs.pets.cococat.desc=椰子所培养的宠物猫。它和椰子一样携带着大量的炸弹。 +actors.mobs.pets.cococat.name=椰子猫 +actors.mobs.pets.cococat.ready=超级炸弹准备就绪 +actors.mobs.pets.cococat.thanks=谢啦,我走了。 +actors.mobs.pets.lightdragon.desc=光龙,顾名思义,是发光的龙 +actors.mobs.pets.lightdragon.name=光龙 +actors.mobs.pets.lightdragon.ready=圣光喷射准备就绪 +actors.mobs.pets.fly.desc=这只苍蝇嗡嗡作响,雄心勃勃,梦想有一天变成一只美丽的蝴蝶。 +actors.mobs.pets.fly.name=飞蝇 +actors.mobs.pets.gentlecrab.desc=为什么这只螃蟹和你那么好,因为对你而言,它很熟。 +actors.mobs.pets.gentlecrab.name=绅士蟹 +actors.mobs.pets.golddragon.desc=图鉴里面并没有这条龙的信息。 +actors.mobs.pets.golddragon.name=黄金龙 +actors.mobs.pets.golddragon.ready=终结吐息准备就绪 +actors.mobs.pets.greendragon.desc=绿龙一般精通闪电的力量。但由于原来没有那么多的闪电来源,所以绿龙十分稀缺。 +actors.mobs.pets.greendragon.name=绿龙 +actors.mobs.pets.greendragon.ready=电磁脉冲准备就绪 +actors.mobs.pets.leryfire.desc=早期破碎翻译组的修齐所制作的元素。它十分不稳定。 +actors.mobs.pets.leryfire.name=修齐元素 +actors.mobs.pets.leryfire.ready=紊乱炸裂准备就绪。你很酷吗? +actors.mobs.pets.monkey.desc=严格意义上它并不是猴子,它只是名字上带猴而已。 +actors.mobs.pets.monkey.name=绿皮猴 +actors.mobs.pets.pet.levelup=你的宠物升级了。 +actors.mobs.pets.pet.pet_died=你的宠物死亡了。 +actors.mobs.pets.reddragon.desc=红龙一般擅长喷射火焰,所以它们非常常见。 +actors.mobs.pets.reddragon.name=红龙 +actors.mobs.pets.reddragon.ready=火焰喷射准备就绪 +actors.mobs.pets.ribbonrat.desc=这个可爱的小老鼠戴着一条它非常珍惜的丝带,但是原因不明。它似乎随时准备向你展示它的骄傲。 +actors.mobs.pets.ribbonrat.name=缎带鼠 +actors.mobs.pets.scorpion.desc=一个大号嗜血的蝎子。它的尾巴镶嵌着一个危险的蜇刺。 +actors.mobs.pets.scorpion.name=血蝎 +actors.mobs.pets.scorpion.ready=腐酸血蛰准备就绪 +actors.mobs.pets.shadowdragon.desc=暗影龙属于黑暗,但需要光明才能将它召唤。 +actors.mobs.pets.shadowdragon.name=暗影龙 +actors.mobs.pets.shadowdragon.ready=暗影能量准备就绪 +actors.mobs.pets.snake.desc=这条蛇过去常常和它的兄弟在月光的柔和光辉下享受它的日子,直到它决定跟随它的流浪欲望进入伟大的未知世界。 +actors.mobs.pets.snake.name=毒蛇 +actors.mobs.pets.spider.desc=一只小小的,毛茸茸的蜘蛛似乎喜欢藏在你的盔甲下。然而,尽管它顽固的害羞,它已经准备好了。 +actors.mobs.pets.spider.name=蜘蛛 +actors.mobs.pets.spider.ready=缠绕之网准备就绪 +actors.mobs.pets.stone.desc=破碎中的一把武器是它的亲戚,但是它的父母来自精灵宝可梦。 +actors.mobs.pets.stone.name=石拳石 +actors.mobs.pets.bugdragon.desc=?????? +actors.mobs.pets.bugdragon.name=BUG龙 +actors.mobs.pets.bugdragon.ready=???准备就绪 +actors.mobs.pets.velocirooster.desc=这只公鸡相对于其他的来说更加凶猛一些。它在地牢中穿行,并用尖锐的爪子和喙来攻击。它的脖子上有一个纸条,写着“从释放到发芽,请享受这只公鸡带来的便利。” +actors.mobs.pets.velocirooster.name=公鸡 +actors.mobs.pets.velocirooster.ready=尖锐爪击准备就绪。Cock-a-doodle-roar! +actors.mobs.pets.violetdragon.desc=紫龙属于地龙的一种,它释放恶臭毒素。 +actors.mobs.pets.violetdragon.name=紫龙 +actors.mobs.pets.violetdragon.ready=剧毒吐息准备就绪 + +actors.mobs.pets.yearpet.desc=一只年兽宝宝,没什么战斗力。 +actors.mobs.pets.yearpet.name=年兽宝宝 + +##npc +actors.mobs.npcs.alivefish.desc=这是一个“淹死”的玩家。 +actors.mobs.npcs.alivefish.name=淹死的食人鱼 +actors.mobs.npcs.alivefish.yell1=(水泡声)(水泡声)(水泡声) +actors.mobs.npcs.alivefish.yell2=涌流法杖...水泡声...水泡声... +actors.mobs.npcs.bilboldev.desc=技巧地牢的制作者。他人非常好,因为据说他曾帮助typedscroll修复bug。 +actors.mobs.npcs.bilboldev.name=Bilboldev +actors.mobs.npcs.bilboldev.yell1=对我的技巧地牢多点耐心,伙计xD。 +actors.mobs.npcs.bilboldev.yell2=我计划未来对技能系统和故事系统做一次巨大的更新。 +actors.mobs.npcs.bilboldev.yell3=Hatsune的牺牲会被人所铭记! + +actors.mobs.npcs.blacksmith.blood_1=嘿,人类!不想当个没用的废物,对吗?拿着那个镐子然后用它_杀只蝙蝠_,我需要镐头上沾着的血。什么?要我如何报答你?真贪心...\n\n好吧,好吧,我没钱付给你,但我可以给你打打铁。想想你运气有多好吧,我可是这附近唯一的铁匠。 +actors.mobs.npcs.blacksmith.blood_2=我说了我需要镐子沾上蝙蝠血。赶紧! +actors.mobs.npcs.blacksmith.cant_reforge=我不能重铸这些物品! +actors.mobs.npcs.blacksmith.completed=噢,你终于回来了… 算了,总比回不来好。 +actors.mobs.npcs.blacksmith.cursed=我可不碰诅咒的东西! +actors.mobs.npcs.blacksmith.degraded=这简直就是个垃圾,质量太差了! +actors.mobs.npcs.blacksmith.desc=这个巨魔铁匠看起来和其他巨魔一样:又高又瘦,皮肤的色泽和纹理都像是石头。这位巨魔铁匠正在拿着一把与其体形极其不符的小锤子不停地修修补补。看起来他是较大的一个。 +actors.mobs.npcs.blacksmith.get_lost=好了,我已经没什么好帮你的了。 +actors.mobs.npcs.blacksmith.gold_1=嘿,人类!不想当个没用的废物,对吗?拿着那个镐子然后给我挖点_暗金矿,15块_就够了。什么?要我如何报答你?真贪心...\n好吧,好吧,我没钱付给你,但我可以给你打打铁。想想你运气有多好吧,我可是这附近唯一的铁匠。 +actors.mobs.npcs.blacksmith.gold_2=_暗金矿_。15块。说真的,有那么难? +actors.mobs.npcs.blacksmith.keeppickaxe=拿好这个镐子。它非常好用。 +actors.mobs.npcs.blacksmith.lost_pick=你在逗我?我的镐子呢?! +actors.mobs.npcs.blacksmith.name=巨魔铁匠 +actors.mobs.npcs.blacksmith.need_reinforced=这件物品无法承受那么高的升级,我想我没法帮你合成。 +actors.mobs.npcs.blacksmith.same_item=选择两个不同的物品,不是两次一样的! +actors.mobs.npcs.blacksmith.triforce=你居然找到这三个碎片!好吧,我想我应该能把它们合在一起。 +actors.mobs.npcs.blacksmith.shadoweater=这仨是啥玩意...我看看...天哪我做了什么?! +actors.mobs.npcs.blacksmith.un_ided=我得知道我在拿什么干活,先鉴定! + +actors.mobs.npcs.blacksmith2.adamantite=哦,你已经找到了这种组件了啊。这东西可以承载任意数量的强化,只要把这个东西和相应的物品相结合,就可以让那件物品承载任意数量的强化。这可是我那顽固的哥哥所做不到的。只要给我_50枚暗金_,我就可以帮你把那两样物品焊接在一起。 +actors.mobs.npcs.blacksmith2.already_reforge=组件已经焊接在上面了啊! +actors.mobs.npcs.blacksmith2.cant_reforge=没法升级的东西我可没法处理啊! +actors.mobs.npcs.blacksmith2.cant_work=东西不对我可没法处理啊,需要组件和道具还要暗金。 +actors.mobs.npcs.blacksmith2.cursed=诅咒的东西我可没法处理啊! +actors.mobs.npcs.blacksmith2.degraded=负等级的东西我可没法处理啊! +actors.mobs.npcs.blacksmith2.desc=这个巨魔焊工看起来和其他巨魔一样:又高又瘦,皮肤的色泽和纹理都像是石头。这位巨魔焊工正在拿着一把与其体形极其不符的电焊枪焊接着什么。看起来他是较小的那个。 +actors.mobs.npcs.blacksmith2.himself=和你看到的一样,我是那个顽固的家伙的弟弟。虽然我哥认为只有拥有传统的铁技才能在巨魔中立足,但是我认为科学技术也能帮我谋生。你目前应该没有见过一些奇怪的组件吧。如果你找到了那种组件,并且给我_50枚暗金_,我想我可以给你一个惊喜。 +actors.mobs.npcs.blacksmith2.name=巨魔焊工 +actors.mobs.npcs.blacksmith2.same_item=同样的东西我可没法处理啊! +actors.mobs.npcs.blacksmith2.un_ided=未知的东西我可没法处理啊! +actors.mobs.npcs.coconut.desc=一只背着单肩包头戴护目镜的橘色猫,看起来他携带有很多炸弹。 +actors.mobs.npcs.coconut.name=椰子 +actors.mobs.npcs.coconut.yell1=欢迎来到我的炸弹商店,我这儿卖各种爆炸物。 +actors.mobs.npcs.coconut.yell2=看起来炸弹翻译器的运行效果不错啊,小心它还可能爆炸哦。 +actors.mobs.npcs.coconut.yell3=你找坚果,那个hmdzl001?他在训练各种boss。短时间内你是找不到他了。 +actors.mobs.npcs.consideredhamster.desc=YAPD的作者的宠物。恕我直言,打不通YAPD简单难度的都是垃圾。 +actors.mobs.npcs.consideredhamster.name=ConsideredHamster的宝箱怪 +actors.mobs.npcs.consideredhamster.yell1=嘿,我现在很饿,能给我喂1美刀吗? +actors.mobs.npcs.consideredhamster.yell2=Pineapples! +actors.mobs.npcs.dachhack.desc=发芽地牢的作者。上面那个光环是代表自然之神地牢。 +actors.mobs.npcs.dachhack.name=Dachhack +actors.mobs.npcs.dachhack.yell1=对发芽地牢的崩溃我表示抱歉,目前我在尝试修复他们。 +actors.mobs.npcs.dachhack.yell2=我不明白为什么hmdzl001这个家伙会把我设计成这样...下面那是什么玩意... +actors.mobs.npcs.dachhack.yell3=最新的发芽你可以在我的谷歌硬盘上找到,虽然还是预览版,但是基本框架我是已经弄好了的。 +actors.mobs.npcs.evan.desc=破碎地牢的制作者。说实在的我无法确定这代表evan还是破碎...他们的图标是一样的。 +actors.mobs.npcs.evan.name=Evan +actors.mobs.npcs.evan.yell1=欢迎,冒险者。这个地牢可不太平呢。-来自00-Evan +actors.mobs.npcs.evan.yell2=我比较低调,所以当我听到hmdzl001和我说要我考虑台词的时候,其实我是拒绝的。 +actors.mobs.npcs.evan.yell3=我需要尽我全力来使破碎地牢更加好玩,更加有趣,更加合理,更加有挑战性。 +actors.mobs.npcs.fruitcat.desc=这是一个很可爱的玩家。 +actors.mobs.npcs.fruitcat.name=工会荣誉商人-菜猫 +actors.mobs.npcs.fruitcat.yell1=自从椰子走后,这家店就由我来管理。放心好了,我可不会涨价。 +actors.mobs.npcs.fruitcat.yell2=信不信由你,在椰子离开之前,他没有带任何东西,只是把它们堆起来让它们吔尘!无论如何,你可能比我更需要它们。 +actors.mobs.npcs.g2159687.desc=简单发芽的作者及汉化者,国人,现在处于弃坑状态。 +actors.mobs.npcs.g2159687.name=G2159687 +actors.mobs.npcs.g2159687.yell1=我是G2159687,喜欢我的简单发芽吗?我可没有其他台词。 +actors.mobs.npcs.g2159687.yell2=我想应该有一些玩家会认为地牢类游戏比较难,所以我弄了几个简单版本。 +actors.mobs.npcs.ghost.crab_1=你好,%s…曾经我像你一样——既强大又自信…但我被一个古老的生物杀死了…我不能离开这个地方……直到我完成我的复仇…杀死_巨钳螃蟹_,就是它夺走了我的生命…\n\n它经历了无数岁月的洗礼…有一个巨大的蟹钳和非常厚重的蟹壳…_小心它的蟹钳,你必须偷袭这只巨蟹否则它会用钳子格挡你的攻击..._ +actors.mobs.npcs.ghost.crab_2=拜托帮助我……杀了那个甲壳类……\n\n_如果它发现你……就会挡住你所有的攻击……_ +actors.mobs.npcs.ghost.def_verb=闪避 +actors.mobs.npcs.ghost.desc=这个幽灵几乎不能被看见。它看起来像是由一片无形的昏暗光斑和一张悲痛的面孔所组成的。 +actors.mobs.npcs.ghost.find_me=悲伤幽灵:谢谢你...来找我吧... +actors.mobs.npcs.ghost.gnoll_1=你好,%s…曾经我像你一样——既强大又自信…但我被一个狡猾的敌人杀死了…我不能离开这个地方……直到我完成我的复仇…杀死_豺狼猎手_,就是它夺走了我的生命…\n\n它与其他豺狼人不同…它会隐藏自己并使用投掷武器… _小心它的毒镖和火镖,尽量靠近它…_ +actors.mobs.npcs.ghost.gnoll_2=请帮助我……杀了那个诡诈的家伙……\n\n_别让它打到你……离它越近越好……_ +actors.mobs.npcs.ghost.name=悲伤幽灵 +actors.mobs.npcs.ghost.rat_1=你好,%s…曾经我像你一样——既强大又自信…但我被一个邪恶的野兽杀死了…我不能离开这个地方……直到我完成我的复仇…杀死_腐臭老鼠_,就是它夺走了我的生命…\n\n它就在这层…四处散播污秽…_小心它的周边的臭云以及带有腐蚀性的撕咬,它产生的粘液可溶于水…_ +actors.mobs.npcs.ghost.rat_2=请帮助我…杀了那个令人憎恶的东西…\n\n_在水附近与它战斗…躲开它的恶臭…_ +actors.mobs.npcs.hatesokoban.desc=这是一个对发芽改有贡献的玩家,同时也是小马的爱好者。 +actors.mobs.npcs.hatesokoban.name=讨厌的羊关 +actors.mobs.npcs.hatesokoban.yell1=你明白这是个游戏对吧,对吧。我需要完整的中文版发芽改,而不是这个半成品。 +actors.mobs.npcs.hatesokoban.yell2=关于招羊法杖,虽然绝大部分时候没什么用,但是它能很好解决推箱关的难题。 +actors.mobs.npcs.hbb.desc=破碎地牢的翻译者之一,同时也是像素地牢吧的吧主,小马的爱好者。 +actors.mobs.npcs.hbb.name=工会主席-巨无霸卡比 +actors.mobs.npcs.hbb.yell1="The-world's-still-the-same, there's-just...less-in-it." +actors.mobs.npcs.hbb.yell2="Friendship-is-magic!" +actors.mobs.npcs.hbb.yell3="I-am-a-magical-princess-from-another-dimension." +actors.mobs.npcs.hexa.desc=UNIST地牢的作者。UNIST地牢还行,只是只有看韩文你才能理解里面的梗。 +actors.mobs.npcs.hexa.name=UNIST HeXA +actors.mobs.npcs.hexa.yell1=我是UNIST地牢的制作者。我觉得你应该没听说过这个mod。 +actors.mobs.npcs.hexa.yell2=目前我只在韩国发布了这个地牢mod。 + +actors.mobs.npcs.imp.cya=再会, %s! +actors.mobs.npcs.imp.def_verb=闪避 +actors.mobs.npcs.imp.desc=小恶魔是一种低等恶魔。它们既没有强大的力量也没有魔法天赋,但他们相当聪明而且善于交际。许多小恶魔都喜欢生活在没有其他恶魔存在的地方。 +actors.mobs.npcs.imp.golems_1=你是个冒险家吗?我爱冒险家!如果有什么东西需要被解决的话,他们永远都能把活干好。我说的对吗?当然是在有赏金的前提下 ;)\n总之,我需要你杀一些_魔像_。你看,我要在这里开始搞点小本生意,但这些愚蠢的傀儡只会毁掉我的生意!跟这些发着光的大个子花岗岩根本没法交流,真是该死!所以请,杀死……我想想,_6个魔像_,然后奖励就是你的了。 +actors.mobs.npcs.imp.golems_2=魔像猎杀得怎么样了?你已经击杀了_6只魔像_了吗? +actors.mobs.npcs.imp.hey=这儿, %s! + +actors.mobs.npcs.imp.monks_1=是个冒险家吗?我爱冒险家!如果有什么东西需要被解决的话,他们永远都能把活干好。我说的对吗?当然是在有赏金的前提下 ;)\n总之,我需要你杀一些_武僧_。你看,我要在这里开始搞点小本生意,但这些疯子不买任何东西还会吓跑顾客。所以请,杀死……我想想,_8个武僧_,然后奖励就是你的了。 +actors.mobs.npcs.imp.monks_2=喔,你还活着!我就知道你得功夫很好;) 只要别忘了拿来那些武僧的标记就好,我需要_8个标记_。 +actors.mobs.npcs.imp.name=野心勃勃的小恶魔 +actors.mobs.npcs.impshopkeeper.desc=小恶魔是一种低等恶魔。它们既没有强大的力量也没有魔法天赋,但他们相当聪明而且善于交际。许多小恶魔都喜欢生活在没有其他恶魔存在的地方。 +actors.mobs.npcs.impshopkeeper.greeting2=所以...你并没有找到Amulet护符,对吧。这样吧,我把那位客人留下的东西给你吧 ,他可能知道些什么。相对的我要收一点小费。 +actors.mobs.npcs.impshopkeeper.greeting=你好, %s!请随便挑选吧。但是其他的那些高价的东西非卖品,是一位客人留下的。 +actors.mobs.npcs.impshopkeeper.name=野心勃勃的小恶魔 +actors.mobs.npcs.jinkeloid.desc=这是mispd作者所创建的镜像。mispd作者同时也是破碎地牢的中文审核者。 +actors.mobs.npcs.jinkeloid.name=公会会长Jinkeloid +actors.mobs.npcs.jinkeloid.yell1=现在工会不对外营业,当然欢迎你们前来参观。 +actors.mobs.npcs.jinkeloid.yell2=你知道冰冻效果吗,它能控制住目标并使其受到更多的伤害。 +actors.mobs.npcs.juh9870.desc=月光地牢的制作者。 +actors.mobs.npcs.juh9870.name=Juh9870 +actors.mobs.npcs.juh9870.yell1=我记得我的祖父曾在月光下对我说过,严禁空想,脚踏实地。 +actors.mobs.npcs.juh9870.yell2=所以...我希望我能在这找到更多有意义的东西。 +actors.mobs.npcs.laji.desc=这是一个祭师,同时也是小镇的维修者。 +actors.mobs.npcs.laji.name=原罪学者-司徒 +actors.mobs.npcs.laji.yell1=这位客人,能不能让我耽误你一点时间讲一讲我们的天父克苏鲁。 +actors.mobs.npcs.laji.yell2=梦与白昼者所知晓之诸多事物常为梦于黑夜者所忘却。 +actors.mobs.npcs.laji.yell3=另外...维护这个小镇很累的...... +actors.mobs.npcs.lery.desc=破碎地牢的翻译者之一,同时也是最早期像素地牢更新日志的翻译者之一。 +actors.mobs.npcs.lery.name=驯兽师-论坛修齐 +actors.mobs.npcs.lery.yell1=你足够冷酷吗? +actors.mobs.npcs.lery.yell2=我这里出售各种蛋。如果你是一个出色的训练家的话,你也可以训练出像我那么强大的怪物的。 +actors.mobs.npcs.locastan.desc=哥布林地牢的制作者。他相当喜欢哥布林这部漫画。神灯是释放地牢的标志。 +actors.mobs.npcs.locastan.name=Locastan +actors.mobs.npcs.locastan.yell1=这个门被锁住了...这个房间肯定不止一个门...没准我可以打开它... +actors.mobs.npcs.locastan.yell2=嘿,这可不是什么废铁,这是一件非常有用的工具。 +actors.mobs.npcs.locastan.yell3=只要我能释放这个神灯的力量,我的世界就会更加精彩纷呈。 +actors.mobs.npcs.lyn.desc=破碎地牢的翻译者之一,是个脚男。 +actors.mobs.npcs.lyn.name=受咒ankh +actors.mobs.npcs.lyn.yell1=燃烧!净化!为了萨格拉斯的伟大远征! +actors.mobs.npcs.lyn.yell2=来杯魔能饮料吗?哦,你想知道宠物吃什么吗?想想它们是什么,是常规生物还是奇幻事物,是素食还是肉食。当然,没有宠物可以拒绝口粮,那是特制的。 +actors.mobs.npcs.lynn.desc=十分出色的符文研究者,对各种派系的魔法都有研究。其中最为出色的研究就是多利亚出产的魔法石。 +actors.mobs.npcs.lynn.name=符文学者-莲恩 +actors.mobs.npcs.lynn.yell1=我已经修好了这个合成台,现在你应该可以使用魔法石合成武器了。 +actors.mobs.npcs.lynn.yell2=我的下一个研究目标应该是什么呢? + +actors.mobs.npcs.memoryofsand.desc=这是一个对发芽改有重大贡献的玩家。 +actors.mobs.npcs.memoryofsand.name=义往尘沙 +actors.mobs.npcs.memoryofsand.yell1=嗨,酒馆现在开放了。随便选个食物尝尝吧。 +actors.mobs.npcs.memoryofsand.yell2=原来我也是个冒险者,直到我试了试发芽改... +actors.mobs.npcs.mirrorimage.desc=这个幻象和你非常相似,但它更加黯淡且在微微震颤。 +actors.mobs.npcs.mirrorimage.name=镜像 +actors.mobs.npcs.nyrds.desc=混合地牢的制作者???一个带墨镜的白牙肌肉块。 +actors.mobs.npcs.nyrds.name=Nyrdie +actors.mobs.npcs.nyrds.yell1=嘿,我是nyrdie +actors.mobs.npcs.nyrds.yell2=美牙建议:不要忘了每天早上刷牙哦! +actors.mobs.npcs.oldnewstwist.desc=一个豺狼流浪者,看来豺狼一族里面也是有纷争的。 +actors.mobs.npcs.oldnewstwist.desc_gnollmission=既然他已经有衣服穿了,他已经可以做一些其他事了。 +actors.mobs.npcs.oldnewstwist.name=Oldnewstwist +actors.mobs.npcs.oldnewstwist.yell1=啊!别伤害我,我和那群邪恶的豺狼人不一样。 +actors.mobs.npcs.oldnewstwist.yell2=我试图在我所在的部落宣扬和平,虽然有些居民支持我,但是掌权者却把我赶出了部落,还剃光了我的体毛。 +actors.mobs.npcs.oldnewstwist.yell3=嗯呐...我感觉有点冷,你能帮我找件衣服吗? +actors.mobs.npcs.oldnewstwist.yell4=我听说你击败了豺狼王,你真的太厉害了!你有没有找到什么东西 可以穿上保暖的那种? +actors.mobs.npcs.oldnewstwist.yell5=我对你非常感谢。你的强大,善良,智慧,令我钦佩。 +actors.mobs.npcs.oldnewstwist.yell6=哦,我这里卖各种特殊武器。它们来自于其他时间。 +actors.mobs.npcs.otilukenpc.desc=Otiluke,一位极具天赋的巫师。 他做了许多事情。其中之一就是带走了Amulet护符。 +actors.mobs.npcs.otilukenpc.name=Otiluke +actors.mobs.npcs.otilukenpc.yell1=我们终于相见了,同时我重新看到了热闹的家乡,就和我小时候一样。 +actors.mobs.npcs.otilukenpc.yell2=我十分感谢你的所作所为。我会把你引荐到高塔的。 +actors.mobs.npcs.otilukenpc.yell3=好吧,我知道你要什么。Amulet护符现在被封印在高塔里面,没法拿出来了。但是我可以给你一个仿制品,它和Amulet护符功能一样。 +actors.mobs.npcs.raintrainer.desc=这是一个早期的计划npc,但是他并没有加入到游戏中。现在,他准备好了。 +actors.mobs.npcs.raintrainer.name=训练家Rain +actors.mobs.npcs.raintrainer.yell1=训练家只要眼神对上了就要战...抱歉说错了。 +actors.mobs.npcs.raintrainer.yell2=你可以用那个稻草人练手,不用担心,它很结实。 +actors.mobs.npcs.ratking.desc=这个老鼠比一般的大一些而且头上带着一个小王冠。 +actors.mobs.npcs.ratking.desc_festive=这个老鼠比一般的大一些。它头上带着一个小圣诞帽而不是通常戴着的王冠。节日快乐! +actors.mobs.npcs.ratking.havefun=干的不错,小子,我家的餐器好不好用啊? +actors.mobs.npcs.ratking.name=鼠王 +actors.mobs.npcs.ratking.not_sleeping=我可没在睡觉! +actors.mobs.npcs.ratking.not_takeing=离我的宝箱远点! +actors.mobs.npcs.ratking.thanks=看来你不是那种贪婪的冒险者啊。那好,我告诉你:近来一些蓝色的家伙频繁过来偷窃。找到并杀死它们,它们偷走的东西就是你的了。 +actors.mobs.npcs.ratking.what_is_it=你这是想干什么?我可没时间管这些破事。我的王国可不会自己运转下去!!! +actors.mobs.npcs.ratking.why=都是些不值钱的东西,你拿去好了 +actors.mobs.npcs.ratkingden.desc=这就是之前你见过的鼠王。 +actors.mobs.npcs.ratkingden.desc_festive=这就是之前你见过的戴圣诞帽的鼠王。节日快乐! +actors.mobs.npcs.ratkingden.name=天狗匿藏处的匿藏鼠王 +actors.mobs.npcs.ratkingden.not_sleeping=哦,差点,我都快睡去了。 +actors.mobs.npcs.ratkingden.what_is_it=你小子干的不错,这里的宝物随便拿吧。 + +actors.mobs.npcs.rennpc.desc=这是東方地下城的作者。虽说原来是基于破碎的材质版本,但他非常勤奋的更新使得東方地下城升级成独特的MOD。 +actors.mobs.npcs.rennpc.name=穿越者REN +actors.mobs.npcs.rennpc.yell1=秘封病...那是什么? +actors.mobs.npcs.rennpc.yell2=沁人心脾的麦芽味,只在九月,一切都如此令人那么地陶醉。 +actors.mobs.npcs.rennpc.yell4=我喜欢酒品:啤酒,白酒,清酒...无论是烈性酒还是低度酒,我仍然都保持着对它们的热衷。 +actors.mobs.npcs.rennpc.yell5=你居然完成了这些挑战里面的隐藏任务,真是了不起。这把东方地牢的特殊武器就送给你了,不要忘了支持我的东方地牢哦。 +actors.mobs.npcs.rennpc.yell3=第一次见面啊...我是REN。你应该看到我给你留下的信息了吧。带上这个,它可以复原并模拟传送道具的魔力。 + +actors.mobs.npcs.rustyblade.desc=混合地牢的翻译者之一,同时也是破碎地牢翻译的协助者。 +actors.mobs.npcs.rustyblade.name=战斗大师-无聊 +actors.mobs.npcs.rustyblade.yell1=嗨,我是无聊,为什么我在这儿。 +actors.mobs.npcs.rustyblade.yell2=攻击提升,攻击下降,防御提升,防御下降,你见过这些buff吗? +actors.mobs.npcs.sadsaltan.desc=月光地牢的绘图者。标识有“月光”的名牌挂在他的胸前。 +actors.mobs.npcs.sadsaltan.name=SadSaltan +actors.mobs.npcs.sadsaltan.yell1=哦,难得一见的新的探险者。人们来这里就是为了寻找财宝的,没有富人会无聊到来这个地方。 +actors.mobs.npcs.sadsaltan.yell2=我在其他地方开设着一个酒吧,我是过来宣传它的。想找到那里十分容易,只要对卫兵说“月光”他就会为你带路。 +actors.mobs.npcs.sadsaltan.yell3=收下我的名片,以后你到那里的时候没准我可以请你喝一杯。 +actors.mobs.npcs.seekingbombnpc.desc=这个东西会在目标面前爆炸 +actors.mobs.npcs.seekingbombnpc.name=追猎炸弹 +actors.mobs.npcs.seekingclusterbombnpc.desc=这个大东西会在目标面前爆炸 +actors.mobs.npcs.seekingclusterbombnpc.name=巨型追猎炸弹 +actors.mobs.npcs.sfb.desc=破碎地牢的翻译者之一。 +actors.mobs.npcs.sfb.hello=看我! +actors.mobs.npcs.sfb.name=流浪法师-破碎暴风火杖 +actors.mobs.npcs.sfb.yell1=打牌吗,跑团吗,带我一个带我一个。 +actors.mobs.npcs.sfb.yell2=火属性是最具有破坏力的属性。它的输出也是最高的 +actors.mobs.npcs.sheep.baa!=咩! +actors.mobs.npcs.sheep.baa...=咩…… +actors.mobs.npcs.sheep.baa.=咩。 +actors.mobs.npcs.sheep.baa?=咩? +actors.mobs.npcs.sheep.desc=这是一只魔法绵羊。为什么叫它魔法绵羊?因为你杀不死它。它只会站在那里直到它消失,它会做的事情只有边反刍边对你翻白眼。 +actors.mobs.npcs.sheep.name=绵羊 +actors.mobs.npcs.sheepsokoban.desc=你可以将这个箱子按车的移动方式推动。 +actors.mobs.npcs.sheepsokoban.name=车行箱 +actors.mobs.npcs.sheepsokobanblack.desc=当你触发这个箱子时,它能覆盖随机的一个破坏陷阱。 +actors.mobs.npcs.sheepsokobanblack.name=爆破箱 +actors.mobs.npcs.sheepsokobancorner.desc=你可以将这个箱子按皇后的移动方式推动。 +actors.mobs.npcs.sheepsokobancorner.name=皇后箱 +actors.mobs.npcs.sheepsokobanstop.baa!=咩! +actors.mobs.npcs.sheepsokobanstop.baa...=咩…… +actors.mobs.npcs.sheepsokobanstop.baa.=咩。 +actors.mobs.npcs.sheepsokobanstop.baa?=咩? +actors.mobs.npcs.sheepsokobanstop.desc=这个箱子已经变成一只羊了。你现在没法推动它了。 +actors.mobs.npcs.sheepsokobanstop.name=羊箱 +actors.mobs.npcs.sheepsokobanswitch.desc=你可以与这个箱子交换位置。 +actors.mobs.npcs.sheepsokobanswitch.name=交换箱 +actors.mobs.npcs.shopkeeper.desc=这家伙会出现在任何可以赚钱的地方。无论那里有多么危险。 +actors.mobs.npcs.shopkeeper.name=黑市商人 +actors.mobs.npcs.shopkeeper.sell=选择一件要出售的物品 +actors.mobs.npcs.sp931.desc=破碎地牢的翻译者之一。虽然我对他了解不多,但是目前他人对他的评价呈两级分化状态。 +actors.mobs.npcs.sp931.name=被放逐者-931451545 +actors.mobs.npcs.sp931.yell1=嘿,还在看空洞无聊的文本贴图吗,来试试我的蓝猫地牢吧。 +actors.mobs.npcs.sp931.yell2=人生如果不装B的话还有什么意思呢? +actors.mobs.npcs.stormandrain.desc=这是一个对发芽改有重大贡献的玩家。 +actors.mobs.npcs.stormandrain.name=雷雨交加 +actors.mobs.npcs.stormandrain.yell1=嗨,需要买些密宝吗。这些可是高级货。 +actors.mobs.npcs.stormandrain.yell2=严格意义上我并不属于人类...但没人规定只有人类才能当财宝猎人。 +actors.mobs.npcs.tempest102.desc=破碎地牢的翻译者之一,同时也是搞音乐的。 +actors.mobs.npcs.tempest102.name=音乐家tempest102 +actors.mobs.npcs.tempest102.yell1=原来我只搭了个帐篷,但现在我有了自己的商店。 +actors.mobs.npcs.tempest102.yell2=欢迎光临我的乐器工作室。想买点什么吗? +actors.mobs.npcs.tinkerer1.desc=一名来自多利亚的研究者。他在等待什么东西上门。 + +actors.mobs.npcs.tinkerer1.name=露珠研究者 +actors.mobs.npcs.tinkerer1.tell1=我想找一个特殊的蘑菇做研究,但是我不敢往下走。 +actors.mobs.npcs.tinkerer1.tell2=我想那东西应该在下一个区域。 + +actors.mobs.npcs.tinkerer2.desc=居住在多利亚的研究者之一,对多利亚的矿石特产有着强烈的兴趣。但是因为矿洞的封锁不得不出门去研究其他事物。 +actors.mobs.npcs.tinkerer2.name=符文学者—莲恩 +actors.mobs.npcs.tinkerer2.tell1=我想不同种类的魔法之间肯定有什么联系...没准某种东西可以帮助我。 +actors.mobs.npcs.tinkerer3.desc=一名来自多利亚的研究者。他还在等待什么东西上门。 +actors.mobs.npcs.tinkerer3.name=露珠研究者 +actors.mobs.npcs.tinkerer3.tell1=找到什么有意思的了吗? +actors.mobs.npcs.tinkerer3.tell2=这里真的是研究露珠的好地方。 +actors.mobs.npcs.tinkerer4.desc=小镇的镇长,著有chancel一书。因为经济萧条所以工作十分轻松。 +actors.mobs.npcs.tinkerer4.name=镇长Noodlemire +actors.mobs.npcs.tinkerer4.tell1=哦,欢迎来到这个小镇。容我介绍一下,我是这个小镇的镇长。这里以前还是一个著名景点,但现在就完全不行了。 +actors.mobs.npcs.tinkerer4.tell2=东边的那幢屋子是一个私人工会,东南方是鱼塘和墓地,西南方是矿洞遗址,西方是武器商店,西北方是杂货店,西方是酒馆,东北方是一间在建旅馆,正中心是教堂。如果你想问居民睡哪里的话,我只能说无可奉告。 +actors.mobs.npcs.tinkerer5.desc=一名勘探小镇地质的家伙,他人很好。 +actors.mobs.npcs.tinkerer5.name=地质勘探员Xavier251998 +actors.mobs.npcs.tinkerer5.tell1=我正在做一个课题,研究地壳变动和人为开矿的关系。可惜的是矿洞遗址里面有条龙再那,我没法进入矿洞查看。 +actors.mobs.npcs.tinkerer5.tell2=据说小镇曾经有过辉煌的时候,大量的魔法矿石出口并给小镇带来可观的收入。但这一切已经结束了。 +actors.mobs.npcs.tinkerer5.tell3=你该不会饿了吧,拿上这块肉,伙计。 +actors.mobs.npcs.typedscroll.desc=LCPD的制作者。虽然他的确有不错的编程能力,但是他的没有仔细考虑程序总会有许多bug。 +actors.mobs.npcs.typedscroll.name=TypedScroll +actors.mobs.npcs.typedscroll.yell1=嘿,为什么我长成这样,为什么和我说话,我不知道该和你说什么。 +actors.mobs.npcs.typedscroll.yell2=LCPD已经上架谷歌商店啦,快去下载吧! +actors.mobs.npcs.udawos.desc=先锋的制作者。先锋是以像素地牢的源代码制作的。 +actors.mobs.npcs.udawos.name=Udawos +actors.mobs.npcs.udawos.yell1=我的新游戏叫做chernog:FOMTMA。你可以在网上下载这个游戏。 +actors.mobs.npcs.udawos.yell2=先锋不同于传统地牢游戏,它是一个rpg游戏,和塞尔达传说1类似。 +actors.mobs.npcs.wandmaker.berry_1=啊,在这种地方遇到一个体面的人是多么惊喜!我来这里是为了寻找一样稀有的材料——一个腐莓种子。作为一个施法者,我可以轻易地对付这里的怪物,但我迷路了,而且魔法盾也在逐渐减弱,好尴尬!也许你能够帮助我?为了报答你的工作,我很愿意给你一把我制作的高质量法杖。 +actors.mobs.npcs.wandmaker.berry_2=腐莓找的怎么样了,%s?没有?不用担心,我不着急。 +actors.mobs.npcs.wandmaker.desc=这位老先生的表情看起来十分困扰。他正在被一个力场盾牌保护着。 +actors.mobs.npcs.wandmaker.dust_1=啊,在这种地方遇到一个体面的人是多么惊喜!我来这里是为了寻找一样稀有的材料——尸骨灰烬。它可以在遗骸中被收集,其中有很强的诅咒。作为一个施法者,我可以轻易地对付这里的怪物,但我迷路了,而且魔法盾也在逐渐减弱,好尴尬!也许你能够帮助我?为了报答你的工作,我很愿意给你一把我制作的高质量法杖。 +actors.mobs.npcs.wandmaker.dust_2=尸骨灰烬找的怎么样了,%s?没有?遗骸应该是最有价值寻找的地方。 +actors.mobs.npcs.wandmaker.name=法杖制作者 +actors.mobs.npcs.watabou.desc=像素地牢的创造者。 +actors.mobs.npcs.watabou.name=Watabou +actors.mobs.npcs.watabou.yell1=为什么不试试我的其他游戏呢? +actors.mobs.npcs.watabou.yell2=像素地牢现在停止更新了...... + +actors.mobs.npcs.kostis12345.name=秘书kostis12345 +actors.mobs.npcs.kostis12345.desc=小镇的秘书,负责小镇宣传以及其他杂物。偶尔高层也会让她出去考察实习。 +actors.mobs.npcs.kostis12345.yell1=你看见过我们的镇长了吗?我们还有许多事情要做。 +actors.mobs.npcs.kostis12345.yell2=如果你对这一切有疑问的话,你可以在pixeldungeon.wikia.com寻找SpeciaSurprisePixelDungeon.还等什么,赶紧上船吧! + +actors.mobs.npcs.hmdzl001.name=hmdzl001 +actors.mobs.npcs.hmdzl001.desc=这个游戏的缔造者,同时也是一位玩家。 +actors.mobs.npcs.hmdzl001.yell1=欢迎,这是为2019春节专门准备的地图,但是现在是2020年啦,我就随便改造一下好了。 +actors.mobs.npcs.hmdzl001.yell2=看到我养的猫了吗,它叫椰子。它很可爱,虽然它并不是一只真猫,你懂的吧...它是机器做的。 +actors.mobs.npcs.hmdzl001.yell3=2020春节快乐。现在就算不是春节这里也会持续开放。 + +actors.mobs.npcs.coconut2.name=椰子 +actors.mobs.npcs.coconut2.desc=由hmdzl所创造的一只生物...大概。 +actors.mobs.npcs.coconut2.yell1=一年过去了...但我的货是不会缩水的。 +actors.mobs.npcs.coconut2.yell2=讲道理啊,人员引进和安排都是由我处理的,也不给我放个假什么的。 +actors.mobs.npcs.coconut2.yell3=之后的计划???谁知道之后会发生什么呢。 + +actors.mobs.npcs.newplayer.name=你 +actors.mobs.npcs.newplayer.desc=??? +actors.mobs.npcs.newplayer.yell1=这是你。 +actors.mobs.npcs.newplayer.yell2=这就是你。 + +actors.mobs.npcs.thanklist.name=感谢名单 +actors.mobs.npcs.thanklist.yell1=以及所有游玩这个游戏的玩家。 +actors.mobs.npcs.thanklist.desc=朴实无华的感谢列表。 + +actors.mobs.npcs.arealman.name=炼金矮人 +actors.mobs.npcs.arealman.desc=工会中的一个奇特的存在,擅长炼金术和收藏独立游戏。 + +actors.mobs.npcs.whiteghost.name=白幽妹 +actors.mobs.npcs.whiteghost.yell1=我很高兴还有人记得我。 +actors.mobs.npcs.whiteghost.desc=由于高塔的实验,她已经失去了原有的形体。 + +actors.mobs.npcs.uncles.name=斯堡罗提德大叔 +actors.mobs.npcs.uncles.yell1=小子,想和我锻炼一下吗 +actors.mobs.npcs.uncles.desc=工会里的力士,是个猛男。 + +actors.mobs.npcs.apostle.name=apostle +actors.mobs.npcs.apostle.yell1=只有,魔法,才能,战胜,魔法。 +actors.mobs.npcs.apostle.yell2=魔法,战胜,才能,魔法,只有。 +actors.mobs.npcs.apostle.yell3=看来你通过了这轮测试。和其他测试者聊聊吧,没准能得到什么。 +actors.mobs.npcs.apostle.desc=一个闪着光芒的立方体,发声机械而又有磁性,可能是其他世界的测试者。 + +actors.mobs.npcs.shower.name=shower +actors.mobs.npcs.shower.yell1=初次见面,我是shower。你也可以叫我沐沐。虽然两个叫法都行,但是叫我沐沐我会更开心的。 +actors.mobs.npcs.shower.yell2=看到东边的池塘了吗?我想你可以在那洗澡...前提在那养鱼之前。 +actors.mobs.npcs.shower.yell3=这是个很棒的小镇,有很多很好的人,我想我会在这玩上一段时间。没准会碰上熟人呢。 +actors.mobs.npcs.shower.desc=指虎教派的成员之一,来这里测试新的指虎武器。 + +actors.mobs.npcs.saidbysun.name=阳说 +actors.mobs.npcs.saidbysun.yell1=我想下一步应该这么做...等等,我搞错了... +actors.mobs.npcs.saidbysun.yell2=他们叫我帮忙测试,我就来这儿了...哦我什么都没说... +actors.mobs.npcs.saidbysun.desc=一只猫,用不安的眼神盯着旁边的炼金设备。没准那里有它讨厌的食物。 + +actors.mobs.npcs.honeypoooot.name=蜜蜂罐罐 +actors.mobs.npcs.honeypoooot.yell1=看见那边的那只黑猫了吗,它是我的头儿。 +actors.mobs.npcs.honeypoooot.yell2=这件蜂蜜袍子很好看?拜托这是兜帽唉。 +actors.mobs.npcs.honeypoooot.desc=一个老练的冒险者,是工会主席的助手,负责帮忙处理各种工会任务,包括各类新道具的测试。 + +actors.mobs.npcs.millilitre.name=millilitre isaac +actors.mobs.npcs.millilitre.yell1=不要管我,让我静静。 +actors.mobs.npcs.millilitre.yell2=这个世界太可怕了...妈妈...我想回家... +actors.mobs.npcs.millilitre.desc=因为意外来到这里的测试者之一,他被吓得不轻。 + +actors.mobs.npcs.goblinplayer.name=神盾哥布林 +actors.mobs.npcs.goblinplayer.yell1=这个世界蛮不错,但比起哥布林族的试炼来说还是太简单了。 +actors.mobs.npcs.goblinplayer.yell2=看见这块盾牌了吗,这是神盾。我们教派的支柱。 +actors.mobs.npcs.goblinplayer.desc=一个参加测试的哥布林,他手里拿着一块炫彩盾牌。 + +actors.mobs.npcs.dreamplayer.name=小萌新大梦想 +actors.mobs.npcs.dreamplayer.yell1=要比比看,谁更滑稽吗? +actors.mobs.npcs.dreamplayer.yell2=圆润地滑稽走。 +actors.mobs.npcs.dreamplayer.desc=一团七彩元素,是一个测试产物。 + +actors.mobs.npcs.nutpainter.name=坚果教教主 +actors.mobs.npcs.nutpainter.yell1=坚果nb!!! +actors.mobs.npcs.nutpainter.yell2=坚果万岁!! +actors.mobs.npcs.nutpainter.desc=一个测试画家,十分喜欢画坚果。 + +actors.mobs.npcs.xixizero.name=西西0.12 +actors.mobs.npcs.xixizero.yell1=你好啊,我是黑暗地牢的制作者。你也可以叫我Egoal。 +actors.mobs.npcs.xixizero.desc=黑暗地牢的制作者。 + +actors.mobs.npcs.afly.name=阿飞,阿比和阿比斯 +actors.mobs.npcs.afly.yell1=你好啊,我是阿飞,旁边两个分别是阿比和阿比斯。 +actors.mobs.npcs.afly.desc=不思议地牢的制作者 + +actors.mobs.npcs.omicronrg9.name=Ømicrónrg9 +actors.mobs.npcs.omicronrg9.yell1=别挡道,伙计!我可没时间弄些杂七杂八的事情,mod表可是不会自己生成的。 +actors.mobs.npcs.omicronrg9.yell2=食人鱼这种这种生物是在是太棒了,它们能轻易撕碎各种动物,特别是没有外壳的。 +actors.mobs.npcs.omicronrg9.yell3=你知道吗,在所有像素地牢的衍生mod中,超过24种是以p字母打头的。 +actors.mobs.npcs.omicronrg9.yell4=为了更好地寻找和收集mod,我把我的一只眼睛换成了钛合金电子眼。这很酷,也很值得。 +actors.mobs.npcs.omicronrg9.yell5=希望这东西...无论在哪,依然是个幻象。 +actors.mobs.npcs.omicronrg9.yell6=这个世界包容了超过9个不同世界的不同产物,真出乎我的意料! +actors.mobs.npcs.omicronrg9.desc=这个看上去像十字军战士的长发男子,是一个研究平行世界的学者。他正在收集这个世界的信息的时候受到了来自高塔的邀请,在蜜蜂罐罐的引导下来的这个世界,并和这个世界的其他人分享关于其他世界的信息。由于看上去有些失眠,所以他可能有攻击性。 + +actors.mobs.npcs.ice13.name=佣兵-寒雾十三 +actors.mobs.npcs.ice13.yell1=你好,我叫寒雾十三,是一位普普通通的佣兵,如果我没记错的话,我们不是第一次见面,对吧? +actors.mobs.npcs.ice13.yell2=我的配色很奇怪吗?呵,这只是三原色而已。 +actors.mobs.npcs.ice13.yell3=记住,拥抱过去,创造未来。 +actors.mobs.npcs.ice13.yell4=为这个世界的造物主——坚果欢呼吧,坚果是至高无上的神! +actors.mobs.npcs.ice13.yell5=元素没有正邪之分,但它的使用者有。 +actors.mobs.npcs.ice13.yell6=这个世界依旧存在一些差错,但它至少不会搞出一只黑色的野兽。 +actors.mobs.npcs.ice13.desc=一个看上去有点神经质的术士,他依靠着一张损坏的多利亚小镇的地图和蜂蜜罐罐的指引来到了这里,他待在这里的目的是为了让这里更加——按他的说法——混乱。 + +actors.mobs.npcs.Sharku2011.desc=吗...一个不愿授权的韩国开发者。 +actors.mobs.npcs.Sharku2011.name=守财奴Sharku2011 +actors.mobs.npcs.Sharku2011.yell1=这些财宝都是我的,给我滚远点! +actors.mobs.npcs.Sharku2011.yell2=没人可以动我的财宝! + diff --git a/resources/com/hmdzl/spspd/messages/items/items.properties b/resources/com/hmdzl/spspd/messages/items/items.properties new file mode 100644 index 00000000..f1d1e7d1 --- /dev/null +++ b/resources/com/hmdzl/spspd/messages/items/items.properties @@ -0,0 +1,2283 @@ +###glyphs +items.armor.glyphs.iceglyph.name=%s of snowhouse +items.armor.glyphs.iceglyph.desc=This glyph is able to store damage dealt to the wearer, dealing it to them slowly rather than all at once. It also can freezes your enemies on hit and make you resistant to frost. +items.armor.glyphs.iceglyph.deferred=deferred %d +items.armor.glyphs.iceglyph$defereddamage.name=Deferred damage +items.armor.glyphs.iceglyph$defereddamage.ondeath=The deferred damage killed you... +items.armor.glyphs.iceglyph$defereddamage.desc=While your armor's glyph has protected you from damage, it seems to be slowly paying you back for it.\n\nDamage is being dealt to you over time instead of immediately. You will take one damage per turn until there is no damage left.\n\nDeferred damage remaining: %d. + +items.armor.glyphs.fireglyph.name=%s of firecover +items.armor.glyphs.fireglyph.desc=This glyph can burn your enemies on hit and decrease damage from fire. It also can improve your damage sometimes. + +items.armor.glyphs.earthglyph.name=%s of breakrock +items.armor.glyphs.earthglyph.desc=This glyph can make you resistant to earth magic, It also can improve your defense an stun your enemies on hit. + +items.armor.glyphs.electricityglyph.name=%s of electricweb +items.armor.glyphs.electricityglyph.desc=This glyph can shock your enemies on hit and give you lightning resistance. It also can giving a small amount of charge to the wearer's wands. + +items.armor.glyphs.lightglyph.name=%s of holyguard +items.armor.glyphs.lightglyph.desc=This glyph can make you resistant to light magic, It also can manipulates the mind of attackers, charming them temporarily. + +items.armor.glyphs.darkglyph.name=%s of shadow +items.armor.glyphs.darkglyph.desc=This glyph can make you resistant to dark magic, It also can harm your enemies on hit and providing a boost of healing to you, + +items.armor.glyphs.revivalglyph.name=%s of revival +items.armor.glyphs.revivalglyph.revival=Revival glyph revival you from death. +items.armor.glyphs.revivalglyph.desc=This glyph may save you from death with a certain chance. + +items.armor.glyphs.changeglyph.name=%s of change +items.armor.glyphs.changeglyph.desc=This glyph have chance to create a mirror from user, and help him away from dangerous. + +items.armor.glyphs.crystalglyph.name=%s of crystal +items.armor.glyphs.crystalglyph.desc=This glyph can give glass shield to user. + +items.armor.glyphs.testglyph.name=%s of testpaint +items.armor.glyphs.testglyph.desc=This glyph have chance to create some dangerous gas for enemy on hit. + +items.armor.glyphs.adaptglyph.name=%s of adapt +items.armor.glyphs.adaptglyph.desc=This glyph can help user survival from battle, based on his environment. + +items.armor.glyphs.recoilglyph.name=%s of recoil +items.armor.glyphs.recoilglyph.desc=This glyph rebounds force against attackers, sending them flying back and causing them to slowly bleed based on the damage they deal. + +###armor +items.armor.normalarmor.normalarmor.stats_known=This _tier-%1$d_ armor blocks _%2$d-%3$d damage_ and requires _%4$d strength_ to use properly. +items.armor.normalarmor.normalarmor.stats_known2=This armor dex is _%1$s_ , stealth is _%2$s_ , energy base is _%3$d_ . +items.armor.normalarmor.normalarmor.stats_unknown=Typically this _tier-%1$d_ armor blocks _%2$d-%3$d damage_ and requires _%4$d strength_ to use properly. +items.armor.normalarmor.normalarmor.too_heavy=Probably this armor is too heavy for you. +items.armor.normalarmor.normalarmor.incompatible=Interaction of different types of magic has erased the glyph on this armor! +items.armor.normalarmor.normalarmor.cursed_worn=Because this armor is cursed, you are powerless to remove it. +items.armor.normalarmor.normalarmor.cursed=You can feel a malevolent magic lurking within this armor. +items.armor.normalarmor.normalarmor.inscribed=It is inscribed, %s +items.armor.normalarmor.normalarmor.stats_desc= + +items.armor.armor$glyph.glyph=glyph + +items.skills.classskill.charge=Cooldown: %d. +items.skills.classskill.name=class skill + +items.skills.mageskill.name=mage robe +items.skills.mageskill.ac_special=MOLTEN EARTH +items.skills.mageskill.ac_special_two=ARCANE BOMBING +items.skills.mageskill.prompt2=choose a target +items.skills.mageskill.ac_special_three=ICE STORM +items.skills.mageskill.ac_special_four=LIGHTNING ARRESTER +items.skills.mageskill.desc=a mage can cast those spell by use his mage robe\n _molten earth_ : All the enemies in his field of view will be set on fire and unable to move at the same time.\n\n_arcane bombing_ : Use arcane bombing a place, destory walls and deal some damage.\n\n_ice storm_ : All the enemies in his field of view will be set on ice and taken lots of damage.\n\n_lightning arrester_ : Recharge wands, and shock near enemies. + +items.skills.huntressskill.name=huntress cloak +items.skills.huntressskill.ac_special=HUNTER INSTINCT +items.skills.huntressskill.ac_special_two=PREPARE HUNTING +items.skills.huntressskill.ac_special_three=FAIRY IN BOTTLE +items.skills.huntressskill.ac_special_four=LIVING ROOT +items.skills.huntressskill.no_space=Can't summon ally in here. +items.skills.huntressskill.desc=a hunter can cast those spell by use her cloak\n _hunter instinct_ : It is easy for her to find treasure, monster, and secret.\n\n_prepare hunting_ : Gain some range skill for now.\n\n_fairy in bottle_ : Summon a fairy.\n\n_living root_ : all the enemies in her field of view will unable to move. If her is powerful, summon some little tree in this place. + +items.skills.rogueskill.name=rogue garb +items.skills.rogueskill.ac_special=SHADOW BLESS +items.skills.rogueskill.ac_special_two=STEAL GOLD +items.skills.rogueskill.ac_special_three=SILENT KILLING +items.skills.rogueskill.ac_special_four=FALLING ATTACK +items.skills.rogueskill.desc=a rogue can cast those spell by use his garb\n _shadow bless_ : Hiding into shadow, and gain some buff.\n\n_steal gold_ : Gain gold in attack.\n\n_silent killing_ : Silence a enemy, until it dead.\n\n_falling attack_ : Near wall, and preapare next attack. + +items.skills.warriorskill.name=warrior suit of armor +items.skills.warriorskill.ac_special=SOURCE POWER +items.skills.warriorskill.ac_special_two=FIGHTING ARENA +items.skills.warriorskill.ac_special_three=SHIELD SPELL +items.skills.warriorskill.ac_special_four=SURPRISE ATTACK +items.skills.warriorskill.desc=a warrior can cast those spell by use his suit of armor \n_source power_ : It will improve his body for a while.\n\n_fighting arena_ : Silence near enemies, and disarm other enemies.\n\n_shield spell_ : Gain shield.\n\n_surprise attack_ : Deal more damage on full health enemy and low health enemy. + +items.skills.performerskill.name=performer jacket +items.skills.performerskill.prompt=Choose a item for change +items.skills.performerskill.ac_special=SPECIAL DANCE +items.skills.performerskill.ac_special_two=CURTAIN CALL +items.skills.performerskill.ac_special_three=MAGIC TRICKS +items.skills.performerskill.ac_special_four=FANS ACCOMPANIMENT +items.skills.performerskill.desc=a performer can cast those spell by use his jacket\n _special dance_ : All the enemies in his field of view will be crazy.\n\n_curtain call_ : Remove all his mucia buff, and deal damage to all the enemies in his field of view.\n\n_magic tricks_ : Transmutation a item.\n\n_fans accompanoment_ : Dancing with your fans and enemies. + +items.skills.soldierskill.name=soldier vest +items.skills.soldierskill.ac_special=MIRROR ARMY +items.skills.soldierskill.ac_special_two=SUMMON MECH +items.skills.soldierskill.ac_special_three=MOVING BOMBS +items.skills.soldierskill.ac_special_four=AIR DROP +items.skills.soldierskill$seekingbomb.name=Bombing robot +items.skills.soldierskill$seekingbomb.desc=Warning: it will expload soon. +items.skills.soldierskill$seekinghugebomb.name=Boooooooooooming robot. +items.skills.soldierskill$seekinghugebomb.desc=Warning: it will exploadddddddddddddd soon. +items.skills.soldierskill.desc=a soldier can cast those spell by use his vest \n_mirror army_ : Create some mirror to help him on battle, and remove some bad buff he have.\n\n_summon mech_ : Gain mech buff.\n\n_moving bombs_ : Summon some bombs.\n\n_air drop_ : Create food and throwning weapon in some where of this place. + +items.skills.followerskill.name=follower overcoat +items.skills.followerskill.ac_special=PRAY +items.skills.followerskill.ac_special_two=FUND RAISING +items.skills.followerskill.ac_special_three=LANGUAGE TRAP +items.skills.followerskill.ac_special_four=BLESS SPELL +items.skills.followerskill.desc=a follower can cast those spell by use his overcoat\n_pary_ : Stand and start pary.\n\n_fund raising_ : collect gold from enemies.\n\n_language trap_ : terror enemy and improve your move speed.\n\n_bless spell_ : Upgrade a item. + +items.armor.normalarmor.clotharmor.name=cloth armor +items.armor.normalarmor.clotharmor.desc=This lightweight armor offers basic protection.\nnormal armor + +items.armor.normalarmor.leatherarmor.name=leather armor +items.armor.normalarmor.leatherarmor.desc=Armor made from tanned monster hide. Not as light as cloth armor but provides better protection.\nnormal armor + +items.armor.normalarmor.mailarmor.name=mail armor +items.armor.normalarmor.mailarmor.desc=Interlocking metal links make for a tough but flexible suit of armor.\nnormal armor +items.armor.normalarmor.platearmor.name=plate armor +items.armor.normalarmor.platearmor.desc=Enormous plates of metal are joined together into a suit that provides unmatched protection to any adventurer strong enough to bear its staggering weight.\nnormal armor + +items.armor.normalarmor.scalearmor.name=scale armor +items.armor.normalarmor.scalearmor.desc=The metal scales sewn onto a leather vest create a flexible, yet protective armor.\nnormal armor + +items.armor.normalarmor.discarmor.name=disc armor +items.armor.normalarmor.discarmor.desc=This armor is made of a metal disc sewn on top of a cloth (hence the name). It's pretty durable, but bulky.\nnormal armor + +items.armor.normalarmor.errorarmor.name=error armor +items.armor.normalarmor.errorarmor.desc=This is a error.\n??? + +items.armor.normalarmor.basearmor.name=base armor +items.armor.normalarmor.basearmor.desc=it is not a armor, but just some kind of body. +items.armor.normalarmor.lifearmor.name=Leaf armor +items.armor.normalarmor.lifearmor.desc=A armor from other world. It is alive. \n special armor +items.armor.normalarmor.woodenarmor.name=Wooden armor +items.armor.normalarmor.woodenarmor.desc=A simple armor made by write birch bark. Because of it, this armor is uncomfortable.\nheavy armor + +items.armor.normalarmor.ceramicsarmor.name=ceramic armor +items.armor.normalarmor.ceramicsarmor.desc=It made by clay and fire.\nheavy armor + +items.armor.normalarmor.stonearmor.name=stone armor +items.armor.normalarmor.stonearmor.desc=This armor is just combine clothes and stone.\nheavy armor + +items.armor.normalarmor.multiplelayerarmor.name=double mail armor +items.armor.normalarmor.multiplelayerarmor.desc=This armor is made by two mail armor.\nheavy armor + +items.armor.normalarmor.bulletarmor.name=bullet armor +items.armor.normalarmor.bulletarmor.desc=A normal fiak jackets.\nheavy armor + +items.armor.normalarmor.machinearmor.name=machine armor +items.armor.normalarmor.machinearmor.desc=It is a machine, not a simple armor.\nheavy armor + +items.armor.normalarmor.vestarmor.name=vest +items.armor.normalarmor.vestarmor.desc=It is a cheap vest.\nlight armor + +items.armor.normalarmor.rubberarmor.name=rubber armor +items.armor.normalarmor.rubberarmor.desc=A cosplay clothes.\nlight armor + +items.armor.normalarmor.cdarmor.name=CD armor +items.armor.normalarmor.cdarmor.desc=It made by scrap CD and DVD. What does it means?\nlight armor + +items.armor.normalarmor.styrofoamarmor.name=PVC armor +items.armor.normalarmor.styrofoamarmor.desc=It is hard to know this armor be made, but you can see PVC in the bottom.\nlight armor + +items.armor.normalarmor.protectiveclothingarmor.name=protective armor +items.armor.normalarmor.protectiveclothingarmor.desc=It is some kind of protective clothing for workers.\nlight armor + +items.armor.normalarmor.phantomarmor.name=phantom armor +items.armor.normalarmor.phantomarmor.desc=Special technology in future.\nlight armor + +###artifacts +items.artifacts.alchemiststoolkit.name=alchemists toolkit +items.artifacts.alchemiststoolkit.ac_brew=BREW +items.artifacts.alchemiststoolkit.ac_create=CREATE +items.artifacts.alchemiststoolkit.prompt=Choose potion for brew +items.artifacts.alchemiststoolkit.waste=None of the potions you used seem to react well. +items.artifacts.alchemiststoolkit.prefect=The mixture you've created seems perfect, you don't think there is any way to improve it! +items.artifacts.alchemiststoolkit.bestbrew=This is your best brew yet! +items.artifacts.alchemiststoolkit.bdorder=potions reacted well, +items.artifacts.alchemiststoolkit.right=potions in right place. +items.artifacts.alchemiststoolkit.desc=This toolkit contains a number of regents and herbs used to improve the process of cooking. The toolkit rests on your hip, the various tools inside make a light jingling sound as you move. \n You can see some message in this toolkit: water, vegetable, special seed. +items.artifacts.alchemiststoolkit.desc_cursed=This toolkit is been curse. It make you waste more seed on cooking potions. +items.artifacts.alchemiststoolkit.level_zero=The toolkit seems to be missing a key tool, a catalyst mixture. You'll have to make your own out of three common potions to get the most out of the toolkit. +items.artifacts.alchemiststoolkit.level_ten=The mixture you have created seems perfect, and the toolkit is working at maximum efficiency. +items.artifacts.alchemiststoolkit.make_from=Your current best mixture is made from: +items.artifacts.alchemiststoolkit.addpotion=You mix the this potion into your current brew. +items.artifacts.alchemiststoolkit.have_add=Your current brew already contains that potion. +items.artifacts.alchemiststoolkit.know_first=You need to identified this potion first. + +items.artifacts.alienbag.name=Alien bag +items.artifacts.alienbag.ac_shield=SHIELD MODE +items.artifacts.alienbag.ac_bomb=BOMB MODE +items.artifacts.alienbag.ac_fly=FLY MODE +items.artifacts.alienbag.ac_etc=ETC MODE +items.artifacts.alienbag.desc=A alien single shoulder bag with many useful function. +items.artifacts.alienbag.no_charge=Need more chargr +items.artifacts.alienbag.full_charge=Full charge +items.artifacts.alienbag$bagrecharge.levelup=Your bag is upgrade. + +items.artifacts.artifact.onlythree=You can only wear three misc items at a time. +items.artifacts.artifact.unequip_title=Unequip one item +items.artifacts.artifact.unequip_message=You can only wear three misc items at a time. +items.artifacts.artifact.cannot_wear_two=You cannot wear two of the same artifact. +items.artifacts.artifact.cursed_worn=The artifact painfully binds itself to you. +items.artifacts.artifact.curse_known=You can feel a malevolent magic lurking within the artifact. +items.artifacts.artifact.need_to_equip=You need to equip your artifact to do that. +items.artifacts.artifact.need_to_change=It has lost its own power. + +items.artifacts.capeofthorns.name=cape of thorns +items.artifacts.capeofthorns.ac_needling=NEEDLING +items.artifacts.capeofthorns.desc=These collapsed sheets of metal from the dwarf's machine have formed together into a rigid cape. It seems to store a deep energy, perhaps it has some of the machine's power? +items.artifacts.capeofthorns.desc_inactive=The cape feels reassuringly heavy on your shoulders, it seems to be gaining energy from the damage you take. +items.artifacts.capeofthorns.desc_active=The cape seems to be releasing stored energy, it is radiating a protective power. +items.artifacts.capeofthorns$thorns.inert=Your Cape becomes inert again. +items.artifacts.capeofthorns$thorns.radiating=Your Cape begins radiating energy, you feel protected! +items.artifacts.capeofthorns$thorns.levelup=Your Cape grows stronger! +items.artifacts.capeofthorns$thorns.name=Thorns +items.artifacts.capeofthorns$thorns.desc=Your cape is radiating energy, surrounding you in a field of deflective force!\n\nAll damage you receive is reduced while the thorns effect is active. Additionally, if the attacker is next to you, the reduced amount is deflected back at the attacker.\n\nTurns of thorns remaining: %s. + +items.artifacts.chaliceofblood.name=chalice of blood +items.artifacts.chaliceofblood.ac_prick=PRICK +items.artifacts.chaliceofblood.ac_bloodangry=BLOODANGRY +items.artifacts.chaliceofblood.yes=Yes, I know what I'm doing +items.artifacts.chaliceofblood.no=No, I changed my mind +items.artifacts.chaliceofblood.prick_warn=Each time you use the chalice it will drain more life energy, if you are not careful this can easily kill you.\n\nAre you sure you want to offer it more life energy? +items.artifacts.chaliceofblood.onprick=You prick yourself, and your life essence drains into the chalice. +items.artifacts.chaliceofblood.ondeath=The Chalice sucks your life essence dry... +items.artifacts.chaliceofblood.desc=This shining silver chalice is oddly adorned with sharp gems at the rim. +items.artifacts.chaliceofblood.desc_cursed=The cursed chalice has bound itself to your hand, and is inhibiting your ability to regenerate health. +items.artifacts.chaliceofblood.desc_1=As you hold the chalice, you feel oddly compelled to prick yourself on the sharp gems. +items.artifacts.chaliceofblood.desc_2=Some of your blood is pooled into the chalice, you can subtly feel the chalice feeding life energy into you. You still want to cut yourself on the chalice, even though you know it will hurt. +items.artifacts.chaliceofblood.desc_3=The chalice is filled to the brim with your life essence. You can feel the chalice pouring life energy back into you. + +items.artifacts.cloakofshadows.name=cloak of shadows +items.artifacts.cloakofshadows.ac_stealth=STEALTH +items.artifacts.cloakofshadows.ac_shadow=SHADOW +items.artifacts.cloakofshadows.cooldown=Your cloak needs %d more rounds to re-energize. +items.artifacts.cloakofshadows.no_charge=Your cloak hasn't recharged enough to be usable yet. +items.artifacts.cloakofshadows.desc=A priceless magical cloak, stolen from the royal armory many years ago by the Rogue. When worn, it can be used to turn completely invisible for a short time.\n\nThe more the cloak is used, the stronger it will become, allowing the Rogue to become invisible more frequently and for longer durations. +items.artifacts.cloakofshadows$cloakstealth.no_charge=Your cloak has run out of energy. +items.artifacts.cloakofshadows$cloakstealth.levelup=Your cloak grows stronger! +items.artifacts.cloakofshadows$cloakstealth.name=Cloaked +items.artifacts.cloakofshadows$cloakstealth.desc=Your cloak of shadows is granting you invisibility while you are shrouded by it.\n\nWhile you are invisible enemies are unable to attack or follow you. Physical attacks and magical effects (such as scrolls and wands) will immediately cancel invisibility.\n\nYou will remain cloaked until it is cancelled or your cloak runs out of charge. + +items.artifacts.driedrose.name=dried rose +items.artifacts.driedrose.ac_summon=SUMMON +items.artifacts.driedrose.ac_outfit=OUTFIT +items.artifacts.driedrose.ac_soulbless=SOULBLESS +items.artifacts.driedrose.spawned=You have already summoned the ghost. +items.artifacts.driedrose.no_charge=Your rose isn't fully charged yet. +items.artifacts.driedrose.cursed=You cannot use a cursed rose. +items.artifacts.driedrose.no_space=There is no free space near you. +items.artifacts.driedrose.charged=Your rose is fully charged! +items.artifacts.driedrose.desc=Is this the rose that the ghost mentioned before disappearing? It seems to hold some spiritual power, perhaps it can be used to channel the energy of that lost warrior. +items.artifacts.driedrose.desc_no_quest=A dried aged rose that is somehow still holding together despite its age.\n\nIt seems to have some spiritual power, but you have no idea how to use it right now. +items.artifacts.driedrose.desc_hint=It seems to be missing some petals. Perhaps reattaching them will strengthen the rose. +items.artifacts.driedrose.desc_cursed=The cursed rose is bound to your hand, it feels eerily cold. +items.artifacts.driedrose$petal.name=dried petal +items.artifacts.driedrose$petal.no_rose=You have no rose to add this petal to. +items.artifacts.driedrose$petal.no_room=There is no room left for this petal, so you discard it. +items.artifacts.driedrose$petal.maxlevel=The rose is completed! +items.artifacts.driedrose$petal.levelup=You add the petal to the rose. +items.artifacts.driedrose$petal.desc=A frail dried up petal, which has somehow survived this far into the dungeon. +items.artifacts.driedrose$ghosthero.name=sad ghost +items.artifacts.driedrose$sghosthero.name=mad ghost +items.artifacts.driedrose$ghosthero.def_verb=evaded +items.artifacts.driedrose$ghosthero.hello=Hello again %s. +items.artifacts.driedrose$ghosthero.introduce=My spirit is bound to this rose, it was very precious to me, a gift from my love whom I left on the surface.\n\nI cannot return to him, but thanks to you I have a second chance to complete my journey. When I am able I will respond to your call and fight with you.\n\nhopefully you may succeed where I failed... +items.artifacts.driedrose$sghosthero.desc=This is still in work. +items.artifacts.driedrose$ghosthero.desc=A frail looking ethereal figure with a humanoid shape. Its power seems tied to the rose you have.\n\nThis ghost may not be much, but it seems to be your only true friend down here. +items.artifacts.driedrose$wndghosthero.title=Ghost's Equipment +items.artifacts.driedrose$wndghosthero.desc=The ghost is weak on their own, but their form is solid enough to be equipped with a weapon and armor. They will be able to use these items just like you do.\n\nThe ghost can currently equip items requiring up to _%d strength._ +items.artifacts.driedrose$wndghosthero.weapon_prompt=Select a weapon +items.artifacts.driedrose$wndghosthero.armor_prompt=Select an armor +items.artifacts.driedrose$wndghosthero.cant_unique=The ghost can't use unique items. +items.artifacts.driedrose$wndghosthero.cant_unidentified=You don't know enough about that item. +items.artifacts.driedrose$wndghosthero.cant_cursed=You can't give the ghost cursed equipment. +items.artifacts.driedrose$wndghosthero.cant_strength=The ghost is not strong enough to use that. + +items.artifacts.etherealchains.name=ethereal chains +items.artifacts.etherealchains.ac_cast=CAST +items.artifacts.etherealchains.ac_locked=LOCKED +items.artifacts.etherealchains.no_charge=Your chains do not have enough charge. +items.artifacts.etherealchains.cursed=You can't use cursed chains. +items.artifacts.etherealchains.does_nothing=That won't do anything. +items.artifacts.etherealchains.cant_pull=Your chains cannot pull that target. +items.artifacts.etherealchains.nothing_to_grab=There is nothing to grab there. +items.artifacts.etherealchains.prompt=Choose a location to target. +items.artifacts.etherealchains.desc=These large yet lightweight chains glow with spiritual energy. They can be used to pull you towards terrain, or pull enemies toward you. The ethereal nature of the chains even allows them to extend through walls! +items.artifacts.etherealchains.desc_cursed=The cursed chains are locked to your side, constantly swinging around, trying to trip or bind you +items.artifacts.etherealchains.desc_equipped=The chains rest around your side, slowly siphoning the spiritual energy of those you defeat. Each charge is a link in the chain, which will extend out exactly one tile. +items.artifacts.etherealchains$chainsrecharge.levelup=Your chains grow stronger! + +items.artifacts.hornofplenty.name=horn of plenty +items.artifacts.hornofplenty.ac_eat=EAT +items.artifacts.hornofplenty.ac_store=STORE +items.artifacts.hornofplenty.ac_feed=FEED +items.artifacts.hornofplenty.eat=You eat from the horn. +items.artifacts.hornofplenty.prompt=Select a piece of food +items.artifacts.hornofplenty.no_food=Your horn has no food in it to eat! +items.artifacts.hornofplenty.full=Your horn is full of food! +items.artifacts.hornofplenty.reject=Your horn rejects the uncooked blandfruit. +items.artifacts.hornofplenty.maxlevel=Your horn has consumed all the food it can! +items.artifacts.hornofplenty.levelup=The horn consumes your food offering and grows in strength! +items.artifacts.hornofplenty.desc=This horn can't be blown into, but instead seems to fill up with food over time when equipped. +items.artifacts.hornofplenty.desc_hint=Perhaps there is a way to increase the horn's power by giving it food energy. +items.artifacts.hornofplenty.desc_cursed=The cursed horn has bound itself to your side, it seems to be eager to take food rather than produce it. + +items.artifacts.masterthievesarmband.name=master armband +items.artifacts.masterthievesarmband.ac_goldtouch=GOLDTOUCH +items.artifacts.masterthievesarmband.desc=This purple velvet armband bears the mark of a master. +items.artifacts.masterthievesarmband.desc_worn=With the armband around your wrist, every piece of gold you find makes you desire other people's property more. Perhaps it wouldn't be too hard to get preferential in pixel mart... + +items.artifacts.pylon.name=Small pylon +items.artifacts.pylon.ac_zap=ZAP +items.artifacts.pylon.ac_set=SET +items.artifacts.pylon.ac_return=RETURN +items.artifacts.pylon.ac_rankup=RANKUP +items.artifacts.pylon.no_charge=Your pylon does not have enough energy right now. +items.artifacts.pylon.tele_fail=The teleportation magic fails. +items.artifacts.pylon.prompt=Choose a location to zap. +items.artifacts.pylon.levelup=Your pylon grows stronger! +items.artifacts.pylon.rankup=Rank Up!!! +items.artifacts.pylon.preventing=Strong magic aura of this place prevents you from using the pylon! +items.artifacts.pylon.creatures=Psychic aura of neighbouring creatures doesn't allow you to use the pylon at this moment. +items.artifacts.pylon.return=The pylon is successfully set at your current location, now you can return here anytime. +items.artifacts.pylon.desc=Pylon is an intricate magical building which grants the user control of teleportation magics. The beacon can be used to return to a set location, but can also expel bursts of random teleportation magic once it has charged from being equipped. This magic can be directed at a target or at the user themselves. +items.artifacts.pylon.desc_set=This pylon was set somewhere on the depth %dof SPS Pixel Dungeon. + + +items.artifacts.sandalsofnature.name=sandals of nature +items.artifacts.sandalsofnature.name_1=shoes of nature +items.artifacts.sandalsofnature.name_2=boots of nature +items.artifacts.sandalsofnature.name_3=greaves of nature +items.artifacts.sandalsofnature.ac_feed=FEED +items.artifacts.sandalsofnature.ac_root=ROOT +items.artifacts.sandalsofnature.ac_sprout=SPROUT +items.artifacts.sandalsofnature.no_charge=They have no energy right now. +items.artifacts.sandalsofnature.prompt=Select a seed +items.artifacts.sandalsofnature.already_fed=Your footwear have already recently gained nutrients from that seed. +items.artifacts.sandalsofnature.levelup=Your footwear surges in size! +items.artifacts.sandalsofnature.absorb_seed=The footwear absorbs the seed, they seem healthier. +items.artifacts.sandalsofnature.desc_1=What initially seem like sandals made of twine are actually two plants! They seem very weak and pale, perhaps they need to be given nutrients? +items.artifacts.sandalsofnature.desc_2=The footwear has grown and now more closely resemble two tailored shoes. Some colour has returned to them, perhaps they can still grow further? +items.artifacts.sandalsofnature.desc_3=The plants have grown again and now resembles a pair of solid boots made from bark. The plants seem to have regained their strength, but perhaps they can still grow further? +items.artifacts.sandalsofnature.desc_4=The plants seem to have reached their maximum size, they resemble a pair of armored greaves. The greaves are a deep brown and resemble a very sturdy tree. +items.artifacts.sandalsofnature.desc_hint=You feel more attuned with nature while wearing this artifact. +items.artifacts.sandalsofnature.desc_cursed=The cursed sandals are blocking any attunement with nature. +items.artifacts.sandalsofnature.desc_ability=The footwear has gained the ability to form up into a sort of immobile natural armour, but will need to charge up for it. +items.artifacts.sandalsofnature.desc_seeds=You have fed the footwear %d seeds. + +items.artifacts.talismanofforesight.name=talisman of foresight +items.artifacts.talismanofforesight.ac_scry=SCRY +items.artifacts.talismanofforesight.ac_notice=NOTICE +items.artifacts.talismanofforesight.no_charge=Your talisman isn't fully charged yet. +items.artifacts.talismanofforesight.scry=The Talisman floods your mind with knowledge about the current floor. +items.artifacts.talismanofforesight.desc=A smooth stone with strange engravings on it. You feel like it's watching everything around you, keeping an eye out for anything unusual. +items.artifacts.talismanofforesight.desc_worn=When you hold the talisman you feel like your senses are heightened. +items.artifacts.talismanofforesight.desc_cursed=The cursed talisman is intently staring into you, making it impossible to concentrate. +items.artifacts.talismanofforesight$foresight.name=Foresight +items.artifacts.talismanofforesight$foresight.levelup=Your Talisman grows stronger! +items.artifacts.talismanofforesight$foresight.full_charge=Your Talisman is fully charged! +items.artifacts.talismanofforesight$foresight.uneasy=You feel uneasy. +items.artifacts.talismanofforesight$foresight.desc=You feel very nervous, as if there is nearby unseen danger. + +items.artifacts.timekeepershourglass.name=timekeeper's hourglass +items.artifacts.timekeepershourglass.ac_activate=ACTIVATE +items.artifacts.timekeepershourglass.ac_restart=RESTART +items.artifacts.timekeepershourglass.in_use=Your hourglass is already in use. +items.artifacts.timekeepershourglass.no_charge=Your hourglass hasn't recharged enough to be usable yet. +items.artifacts.timekeepershourglass.cursed=You cannot use a cursed hourglass. +items.artifacts.timekeepershourglass.onstasis=The world seems to shift around you in an instant. +items.artifacts.timekeepershourglass.onfreeze=Everything around you suddenly freezes. +items.artifacts.timekeepershourglass.stasis=Put myself in stasis +items.artifacts.timekeepershourglass.freeze=Freeze time around me +items.artifacts.timekeepershourglass.prompt=How would you like to use the hourglass's magic?\n\nWhile in stasis, time will move normally while you are frozen and completely invulnerable.\n\nWhen time is frozen, you can move as if your actions take no time. Note that attacking will break this. +items.artifacts.timekeepershourglass.desc=This large ornate hourglass looks fairly unassuming, but you feel a great power in its finely carved frame. As you rotate the hourglass and watch the sand pour you can feel its magic tugging at you, surely using this magic would give you some control over time. +items.artifacts.timekeepershourglass.desc_hint=The hourglass seems to have lost some sand, if only you could find some... +items.artifacts.timekeepershourglass.desc_cursed=The cursed hourglass is locked to your side, you can feel it trying to manipulate your flow of time. +items.artifacts.timekeepershourglass$sandbag.name=bag of magic sand +items.artifacts.timekeepershourglass$sandbag.levelup=You add the sand to your hourglass. +items.artifacts.timekeepershourglass$sandbag.maxlevel=Your hourglass is filled with magical sand! +items.artifacts.timekeepershourglass$sandbag.no_hourglass=You have no hourglass to place this sand into. +items.artifacts.timekeepershourglass$sandbag.desc=This small bag of fine sand should work perfectly with your hourglass.\n\nIt seems odd that the shopkeeper would have this specific item right when you need it... + +items.artifacts.unstablespellbook.name=unstable spellbook +items.artifacts.unstablespellbook.ac_read=READ +items.artifacts.unstablespellbook.ac_add=ADD +items.artifacts.unstablespellbook.ac_song=SONG +items.artifacts.unstablespellbook.blinded=You cannot read from the book while blinded. +items.artifacts.unstablespellbook.no_charge=Your spellbook is out of energy for now. +items.artifacts.unstablespellbook.cursed=You cannot read from a cursed spellbook. +items.artifacts.unstablespellbook.prompt=Select a scroll +items.artifacts.unstablespellbook.infuse_scroll=You infuse the scroll's energy into the book. +items.artifacts.unstablespellbook.unable_scroll=You are unable to add this scroll to the book. +items.artifacts.unstablespellbook.unknown_scroll=You're not sure what type of scroll this is yet. +items.artifacts.unstablespellbook.desc=This Tome is in surprising good condition given its age. It fizzes and crackles as you move the pages, surging with unstable energy. If you read from this book, there's no telling what spell you might cast. +items.artifacts.unstablespellbook.desc_cursed=The cursed book has bound itself to you, it is inhibiting your ability to use most scrolls. +items.artifacts.unstablespellbook.desc_index=It have %s exp. +items.artifacts.unstablespellbook.exp=It have %s exp. + +items.artifacts.eyeofskadi.name=eye of skadi +items.artifacts.eyeofskadi.ac_add=ADD +items.artifacts.eyeofskadi.ac_blast=ICE BLAST +items.artifacts.eyeofskadi.ac_curse=CURSE +items.artifacts.eyeofskadi.no_charge=Use ice of skadi need more charge. +items.artifacts.eyeofskadi.prompt=Add a stone ore +items.artifacts.eyeofskadi.need_charge=It is still need charge. +items.artifacts.eyeofskadi.full_charge=It is full charge. +items.artifacts.eyeofskadi.exp=It have %s exp. +items.artifacts.eyeofskadi.infuse_ore=You add stone ore into this eye. +items.artifacts.eyeofskadi.desc=Extremely rare artifact, guarded by the azure dragons. + +items.artifacts.robotdmt.name=Robot HEART +items.artifacts.robotdmt.ac_heart=SIMULATE +items.artifacts.robotdmt.ac_memory=DETERMINATION +items.artifacts.robotdmt.no_charge=Your robot isn't fully charged yet. +items.artifacts.robotdmt.full_charge=Your robot is fully charged now. +items.artifacts.robotdmt.patience=Try to analysis : patience +items.artifacts.robotdmt.bravery=Try to analysis : branery +items.artifacts.robotdmt.integrity=Try to analysis : integrity +items.artifacts.robotdmt.preseverance=Try to analysis : preseverance +items.artifacts.robotdmt.kindness=Try to analysis : kindness +items.artifacts.robotdmt.justice=Try to analysis : justice +items.artifacts.robotdmt.soul=Try to analysis : soul +items.artifacts.robotdmt.friendship=Try to analysis : friendship +items.artifacts.robotdmt.chaos=Try to analysis : chaos... error +items.artifacts.robotdmt.determination=Try to analysis : determination... error +items.artifacts.robotdmt.desc=A mysterious artifact made by unknown scientist. It will charge itself so only thing you should do is waiting. + +items.artifacts.glasstotem.name=glass totem +items.artifacts.glasstotem.ac_atk=ATTACK BLESS +items.artifacts.glasstotem.ac_def=DEFENSE BLESS +items.artifacts.glasstotem.desc=A strange totem made by glass. Use it may good for your battle. + + +###bags +items.bags.bag.name=backpack +items.bags.potionbandolier.name=potion bandolier +items.bags.potionbandolier.desc=This thick bandolier fits around your chest like a sash, it has many insulated straps on it to hold potion vials.\n\nWhile inside the bandolier, your potions should be protected from the cold. +items.bags.scrollholder.name=scroll holder +items.bags.scrollholder.desc=This tubular container looks like it would hold an astronomer's charts, but your scrolls will fit just as well.\n\nThe holder doesn't look very flammable, so your scrolls should be safe from fire inside it.\n\nYou also can put bombs in here. +items.bags.seedpouch.name=seed pouch +items.bags.seedpouch.desc=This small velvet pouch allows you to store any number of seeds in it. Very convenient. +items.bags.wandholster.name=wand holster +items.bags.wandholster.desc=This slim holster is made from some exotic animal, and is designed to compactly hold many wands. +items.bags.keyring.name=key ring +items.bags.keyring.desc=This keyring can hold your keys and rings. It also can hold other transport items! +items.bags.shoppingcart.name=shopping cart +items.bags.shoppingcart.desc=A modern trolley. You can put food in it. +items.bags.heartofscarecrow.name=portable scarecrow +items.bags.heartofscarecrow.desc=A portable scarecrow which can hold some weapons. + +###food +items.food.fruit.blandfruit.name=blandfruit +items.food.fruit.blandfruit.sunfruit=sunfruit +items.food.fruit.blandfruit.rotfruit=rotfruit +items.food.fruit.blandfruit.earthfruit=earthfruit +items.food.fruit.blandfruit.blindfruit=blindfruit +items.food.fruit.blandfruit.firefruit=firefruit +items.food.fruit.blandfruit.icefruit=icefruit +items.food.fruit.blandfruit.fadefruit=fadefruit +items.food.fruit.blandfruit.sorrowfruit=sorrowfruit +items.food.fruit.blandfruit.stormfruit=stormfruit +items.food.fruit.blandfruit.dreamfruit=dreamfruit +items.food.fruit.blandfruit.starfruit=starfruit +items.food.fruit.blandfruit.powerfruit=powerfruit +items.food.fruit.blandfruit.mightyfruit=mightyfruit +items.food.fruit.blandfruit.heartfruit=heartfruit + +items.food.fruit.blandfruit.raw=You can't bear to eat it raw. +items.food.fruit.blandfruit.ice_msg=The icefruit tastes a bit like Frozen Carpaccio. +items.food.fruit.blandfruit.fire_msg=You feel a great fire burning within you! +items.food.fruit.blandfruit.toxic_msg=You are imbued with vile toxic power! +items.food.fruit.blandfruit.para_msg=You feel the power of the earth coursing through you! +items.food.fruit.blandfruit.desc=So dry and insubstantial, perhaps stewing it with another ingredient would improve it. +items.food.fruit.blandfruit.desc_cooked=The fruit has plumped up from its time soaking in the pot and has even absorbed the properties of the seed it was cooked with.\n\nIt looks ready to be eaten! + +items.food.meatfood.chargrilledmeat.name=chargrilled meat +items.food.meatfood.chargrilledmeat.desc=It looks like a decent steak. + +items.food.food.name=ration of food +items.food.food.ac_eat=EAT +items.food.food.locked=Locked magic prevents you to eat this food. +items.food.food.bosslevel=It is a bad idea to eat this food here... +items.food.food.desc=Nothing fancy here: dried meat, some biscuits - things like that. + +items.food.staplefood.normalration.name=ration of food +items.food.staplefood.normalration.desc=Nothing fancy here: dried meat, some biscuits - things like that. + +items.food.staplefood.pasty.pasty=pasty +items.food.staplefood.pasty.assorted=Spring Festival Food +items.food.staplefood.pasty.pie=pumpkin pie +items.food.staplefood.pasty.egg=Rainbow egg +items.food.staplefood.pasty.book=School work +items.food.staplefood.pasty.cane=candy cane +items.food.staplefood.pasty.turkey=Roast Turkey +items.food.staplefood.pasty.bread=brick bread +items.food.staplefood.pasty.jelly=jelly sword + +items.food.staplefood.pasty.pasty_desc=This is authentic Cornish pasty with traditional filling of beef and potato. +items.food.staplefood.pasty.assorted_desc=The rice cake, the dumpling, and the dumplings are filled with the steamer. As one of the traditional foods of the new spring festival, it can completely eliminate your hunger and make you full of determination. \n\n happy Spring Festival! +items.food.staplefood.pasty.pie_desc=great big slice of pumpkin pie! Its sweet and spicy flavor will fill you up and give you a tiny bit of healing.\n\nHappy Halloween! +items.food.staplefood.pasty.book_desc=This is some kind of school work in summer vacation. Finish it and you will full with knowledge. +items.food.staplefood.pasty.egg_desc=Although this thing looks small, eating it can completely eliminate your hunger and make you energetic. \n\n Happy Easter! +items.food.staplefood.pasty.cane_desc=A huge sugary sweet candy cane! It's big enough to fill you up, and the sugar might give your wands a tiny bit of extra charge too.\n\nHappy Holidays! +items.food.staplefood.pasty.turkey_desc=A roasted turkey. Eating it can restore your hunger and make you faster.\n\nHappy Thanksgiving! +items.food.staplefood.pasty.bread_desc=This bread is build by from flour and butter. It looks like brick.\n\nCelebrating International Workers' Day! +items.food.staplefood.pasty.jelly_desc=a jelly looks like a sword. I think child will love this. \n\n Happy International Children's Day! +items.food.staplefood.pasty.worker=You earn 500 golds. + +items.food.meatfood.frozencarpaccio.name=frozen carpaccio +items.food.meatfood.frozencarpaccio.hard=You feel your skin harden! +items.food.meatfood.frozencarpaccio.refresh=Refreshing! +items.food.meatfood.frozencarpaccio.invisbility=You are blessed by shadow! +items.food.meatfood.frozencarpaccio.better=You feel better! +items.food.meatfood.frozencarpaccio.desc=It's a piece of frozen raw meat. The only way to eat it is by cutting thin slices of it. And this way it's suprisingly good. + +items.food.meatfood.mysterymeat.not_well=You are not feeling well. +items.food.meatfood.mysterymeat.name=mystery meat +items.food.meatfood.mysterymeat.hot=Oh it's hot! +items.food.meatfood.mysterymeat.legs=You can't feel your legs! +items.food.meatfood.mysterymeat.bad=You feel bad. +items.food.meatfood.mysterymeat.stuffed=You are stuffed. +items.food.meatfood.mysterymeat.desc=Eat at your own risk! + +items.food.staplefood.overpricedration.name=overpriced food ration +items.food.staplefood.overpricedration.desc=It looks exactly like a standard ration of food but smaller. + +items.food.fruit.blackberry.name=black berry +items.food.fruit.blackberry.desc=A delectable berry. This berry is full with life energy. + +items.food.fruit.blueberry.name=blue berry +items.food.fruit.blueberry.stop=The magic of this place prevents this type of scrying! +items.food.fruit.blueberry.desc=A mysterious blue berry. It is full of knowledge. + +items.food.fruit.cloudberry.name=cloud berry +items.food.fruit.cloudberry.desc=A delectable and light berry. It is full with wind energy. + +items.food.fruit.fullmoonberry.name=full moon berry +items.food.fruit.fullmoonberry.desc=In the darkest hours of night a full moon berry grows. It was blessed by Selemene. + +items.food.fruit.moonberry.name=moon berry +items.food.fruit.moonberry.desc=A hearty blue-green berry. It is full with power. + +items.food.completefood.goldennut.name=Golden nut bless by developer +items.food.completefood.goldennut.effect1=+1str,+60hp +items.food.completefood.goldennut.effect2=+2str,+30hp +items.food.completefood.goldennut.desc=Super secret nut made by developer hmdzl001. Eat it! + +items.food.meatfood.meat.name=meat +items.food.meatfood.meat.bad=you feel bad... +items.food.meatfood.meat.desc=Just some normal meat selled in market. + +items.food.nut.name=nut +items.food.nut.desc=Common dungeon nut. It can be used on cooking. + +items.food.vegetable.nutvegetable.name=nut vine +items.food.vegetable.nutvegetable.desc=A common vegetable, usually used in cooking. Even with out cooking it tastes delicious. + +items.food.vegetable.healgrass.name=Heal grass +items.food.vegetable.healgrass.desc=A common vegetable cut from sun grass. + +items.food.vegetable.battleflower.name=Star flower +items.food.vegetable.battleflower.desc=A common vegetable cut from star flower. + +items.food.vegetable.dreamleaf.name=Dream leaf +items.food.vegetable.dreamleaf.desc=A common vegetable cut from dream foil. + +items.food.honey.name=Honey +items.food.honey.desc=It is made by Honeypot. + +items.food.completefood.petfood.name=Pet Food +items.food.completefood.petfood.desc=Every pet loves it, that is why it called pet food. + +items.food.completefood.perfectfood.name=perfect food +items.food.completefood.perfectfood.desc=This is perfect food, it is good for worker. + +items.food.completefood.honeymeat.name=honey meat +items.food.completefood.honeymeat.desc=A honey meat. + +items.food.completefood.icecream.name=ice-cream +items.food.completefood.icecream.desc=A honey Icecream. + +items.food.completefood.vegetablesoup.name=vegetable soup +items.food.completefood.vegetablesoup.desc=Vegetable soup is prepared using vegetables and leaf vegetables as main ingredients. Some fruits can also be used, such as tomato, squash, and others. + +items.food.completefood.ediblegrass.name=Edible grass +items.food.completefood.ediblegrass.desc=Some simple vegetable. + +items.food.completefood.garbage.name=garbage +items.food.completefood.garbage.desc=Only garbage in here. + +items.food.completefood.crystalnucleus.name=crystal nucleus +items.food.completefood.crystalnucleus.desc=Sell it, don't eat. + +items.food.completefood.kebab.name=kebab +items.food.completefood.kebab.desc=Just some kind of kebab. + +items.food.completefood.hamburger.name=hamburger +items.food.completefood.hamburger.desc=A huge hamburger. + +items.food.completefood.chickennugget.name=chicken nugget +items.food.completefood.chickennugget.desc=Although it called chicken nugget, there no chicken in this food. + +items.food.completefood.herbmeat.name=herb meat +items.food.completefood.herbmeat.desc=It is made by meat and herb. + +items.food.completefood.porksoup.name=pork soup +items.food.completefood.porksoup.desc=Commercial soup became popular with the invention of canning in the 19th century, and today a great variety of canned and dried soups are on the market. + +items.food.completefood.honeyrice.name=honey rice +items.food.completefood.honeyrice.desc=It made by honey and rice and... bees? + +items.food.completefood.vegetablekebab.name=vegetable kebab +items.food.completefood.vegetablekebab.desc=It is like kebab, without meat. + +items.food.completefood.ricefood.name=rice +items.food.completefood.ricefood.desc=It is rice, yes, rice. + +items.food.completefood.fruitsalad.name=fruit salad +items.food.completefood.fruitsalad.desc=This food is made by fruit and water. In this world it don't need salad. + +items.food.completefood.foamedbeverage.name=foamed beverage +items.food.completefood.foamedbeverage.desc=This drink is like Coca-Cola. + +items.food.completefood.gel.name=gel +items.food.completefood.gel.desc=A simple gel, can be used on burning or cooking. + +items.food.completefood.honeygel.name=honey gel +items.food.completefood.honeygel.desc=Honey and gel combine perfect, + +items.food.completefood.honeywater.name=honey water +items.food.completefood.honeywater.desc=Made by honey and water. + +items.food.completefood.meatroll.name=meat roll +items.food.completefood.meatroll.desc=It made by scroll and meat. Yes, it need scroll. + +items.food.completefood.vegetableroll.name=vegetable roll +items.food.completefood.vegetableroll.desc=It is same as meat roll, but it is full with vegetables. + +items.food.completefood.chocolate.name=chocolate +items.food.completefood.chocolate.desc=pure chocolate, super bitter. + +items.food.completefood.foodfans.name=Silk noodles +items.food.completefood.foodfans.desc=Pay attention to cooking and eating. + +items.food.completefood.frenchfries.name=French fries +items.food.completefood.frenchfries.desc=Excess starch warning. + +items.food.wateritem.name=clean water +items.food.wateritem.desc=clean water made by dew, usually used on cooking. + +items.food.completefood.aflyfood.name=Fushigi-no rice ball +items.food.completefood.aflyfood.desc=a rice ball made by Alfred, have power from another world. + +###medicine +items.medicine.pill.ac_eat=EAT + +items.medicine.powerpill.name=power pill +items.medicine.powerpill.desc=This pill will make your stronger. + +items.medicine.hardpill.name=hard pill +items.medicine.hardpill.desc=This pill will improve your power. + +items.medicine.smashpill.name=smash pill +items.medicine.smashpill.desc=This pill will improve your defense. + +items.medicine.musicpill.name=music pill +items.medicine.musicpill.desc=This pill will improve your skill. + +items.medicine.magicpill.name=magic pill +items.medicine.magicpill.desc=This pill will improve your magic. + +items.medicine.shootpill.name=shoot pill +items.medicine.shootpill.desc=This pill will improve your shoot. + +items.medicine.bluemilk.name=blue milk +items.medicine.bluemilk.desc=This mushroom oozes a milky blue substance.You feel your senses slipping. It can improve your speed, and heal everyone in this place. + +items.medicine.deathcap.name=death cap mushroom +items.medicine.deathcap.desc=A deadly-looking fungus found growing in the dungeon. It is too dangerous. + +items.medicine.earthstar.name=earthstar mushroom +items.medicine.earthstar.desc=A tiny bit of an unknown world grows in this mushroom. It looks like blade. + +items.medicine.goldenjelly.name=golden jelly mushroom +items.medicine.goldenjelly.desc=A gelatinous fungi covered in a sticky ooze. Looks like it might cause some havoc. + +items.medicine.jackolantern.name=jack o lantern mushroom +items.medicine.jackolantern.desc=A strange heat emminates from this mushroom. It is easy to fire. + +items.medicine.pixieparasol.name=pixie parasol mushroom +items.medicine.pixieparasol.desc=These mushrooms seem to spin in front of your eyes. You hear fleeting laughter. + +items.medicine.greenspore.name=green spore mushroom +items.medicine.greenspore.not_time=nothing happend. +items.medicine.greenspore.desc=This is new mushroom, It is full with dew power. + +###journal pages +items.journalpages.journalpage.name=Location +items.journalpages.journalpage.desc=Location +items.journalpages.safespotpage.name=Housing contract +items.journalpages.safespotpage.desc=A title deed of luxury villas with three rooms, two halls, one kitchen, one bathroom and one terrace. +items.journalpages.sokoban1.name=Otiluck's journal -- sokoban1 +items.journalpages.sokoban1.desc=Location of sokoban1\n\nMy hometown, was a beautiful place in 50 years ago. Lost of people come here for magic stone, great waterfall, delicious food, or something wonderful. \n\nBut because of empire's industrial pollution and low-quality visitors, my hometown become worse. So I decide to save my town. +items.journalpages.sokoban2.name=Otiluck's journal -- sokoban2 +items.journalpages.sokoban2.desc=Location of sokoban 2\n\nIt spend lots of time to collect useful information, I finally find this place. I see some huge box, traps and treasure in there.\n\nI'm sure this is some quest, and I know I can solve it. +items.journalpages.sokoban3.name=Otiluck's journal -- sokoban3 +items.journalpages.sokoban3.desc=Location of sokoban 3\n\nI found that island, a castle appare after I use Dust of Appearance.\n\nI know this castle has same builder as that prison. There are same traps, same boxes, same tr... wait, a huge mirror with mirror weapon?! I must reduce my voice.\n\nI will never give up before I find my way to save my hometown. +items.journalpages.sokoban4.name=Otiluck's journal -- sokoban4 +items.journalpages.sokoban4.desc=Location of sokoban 4\n\nThose creatures is fear when I close them, and they will transport me in somewhere else. \n\nIt was 61st time. I find a big stone tablet, and I can see some unknown word in there. If I can understand what is this says, I may communication with that creature. +items.journalpages.town.name=Invitation from town +items.journalpages.town.desc=Location of Dolye town.\n\n_Sorry, no magic stone selled in here now._ +items.journalpages.energycore.name=Otiluck's journal -- about the code +items.journalpages.energycore.desc=The address of the energy core.\n\nDescription: This is an automatic attack creature. It was created by zot and I controlled the creature after I defeated zot. +items.journalpages.vault.name=Spring Festival Land +items.journalpages.vault.desc=A simple location with number 25/1/2020. + +###challenge list +items.challengelists.challengelist.name=Challenges +items.challengelists.challengelist.desc=This paper was lost its magic power. You can see some word at the back of this paper.\n_Hello, my name is Ren, Because someone's time magic, some transport item like this can't work now. Find me in Dolye town and I will help you fix that._ + +items.challengelists.sewerchallenge.name=sewer challenge +items.challengelists.prisonchallenge.name=prison challenge +items.challengelists.cavechallenge.name=cave challenge +items.challengelists.citychallenge.name=city challenge +items.challengelists.couragechallenge.name=Courage Trial +items.challengelists.couragechallenge.desc=This book was lost its magic power. \nIt is courage trial +items.challengelists.powerchallenge.name=Power Trial +items.challengelists.powerchallenge.desc=This book was lost its magic power.\nIt is power trial. +items.challengelists.wisdomchallenge.name=Wisdom Trial +items.challengelists.wisdomchallenge.desc=This book was lost its magic power.\nIt is wisdom trial. + +###keys +items.keys.goldenkey.name=golden key +items.keys.goldenkey.desc=The notches on this golden key are tiny and intricate. Maybe it can open some chest lock? +items.keys.ironkey.name=iron key +items.keys.ironkey.desc=The notches on this ancient iron key are well worn; its leather lanyard is battered by age. What door might it open? +items.keys.skeletonkey.name=skeleton key +items.keys.skeletonkey.desc=This key looks serious: its head is shaped like a skull. Probably it can open some serious door. +items.keys.goldenskeletonkey.name=Crystal key +items.keys.goldenskeletonkey.desc=The notches on this crystal key are tiny and intricate. Maybe it can open some chest lock? +items.keys.ironkey.depth=iron key %d + +###misc +items.misc.autopotion.name=auto potion +items.misc.autopotion.desc=Wearing this charm will automatically use a potion when your life gets low. + +items.misc.miscequippable.2miscs=you can only wear 3 misc items at a time +items.misc.miscequippable.desc=This is a misc item. + +items.misc.spectacles.name=spectacles +items.misc.spectacles.desc=I wonder what these do??? + +###nornstone +items.nornstone.nornstone.name=magic stone +items.nornstone.nornstone.desc=A magic stone from Dolye town. + +items.nornstone.greennornstone.name=green magic stone +items.nornstone.greennornstone.desc=A green magic stone from Dolye town. + +items.nornstone.bluenornstone.name=blue magic stone +items.nornstone.bluenornstone.desc=A blue magic stone from Dolye town. + +items.nornstone.orangenornstone.name=orange magic stone +items.nornstone.orangenornstone.desc=A magic stone from Dolye town. + +items.nornstone.purplenornstone.name=purple magic stone +items.nornstone.purplenornstone.desc=A violet magic stone from Dolye town. + +items.nornstone.yellownornstone.name=yellow magic stone +items.nornstone.yellownornstone.desc=A yellow magic stone from Dolye town. + +###potions +items.potions.potion.ac_drink=DRINK +items.potions.potion.turquoise=turquoise +items.potions.potion.crimson=crimson +items.potions.potion.azure=azure +items.potions.potion.jade=jade +items.potions.potion.golden=golden +items.potions.potion.magenta=magenta +items.potions.potion.charcoal=charcoal +items.potions.potion.ivory=ivory +items.potions.potion.amber=amber +items.potions.potion.bistre=bistre +items.potions.potion.indigo=indigo +items.potions.potion.silver=silver +items.potions.potion.aqua=aqua +items.potions.potion.violet=violet +items.potions.potion.unknown_name=%s potion +items.potions.potion.unknown_desc=This flask contains a swirling %s liquid. Who knows what it will do when drunk or thrown? +items.potions.potion.harmful=Harmful potion! +items.potions.potion.beneficial=Beneficial potion +items.potions.potion.yes=Yes, I know what I'm doing +items.potions.potion.no=No, I changed my mind +items.potions.potion.sure_drink=Are you sure you want to drink it? In most cases you should throw such potions at your enemies. +items.potions.potion.sure_throw=Are you sure you want to throw it? In most cases it makes sense to drink it. +items.potions.potion.shatter=%s has been destory. +items.potions.potion.stop=Strong magic make this potion dispal... +items.potions.potion.locked=Locked magic prevents you to use this potion. + +items.potions.potionofexperience.name=potion of experience +items.potions.potionofexperience.desc=The storied experiences of multitudes of battles reduced to liquid form, this draught will instantly raise your power for some time. +items.potions.potionoffrost.name=potion of frost +items.potions.potionoffrost.desc=Upon exposure to open air this chemical will evaporate into a freezing cloud, causing any creature that contacts it to be frozen in place unable to act and move. The freezing effect is much stronger if the environment is wet. +items.potions.potionofhealing.name=potion of healing +items.potions.potionofhealing.heal=Your wounds heal completely. +items.potions.potionofhealing.desc=An elixir that will instantly return you to full health and cure poison. +items.potions.potionofinvisibility.name=potion of invisibility +items.potions.potionofinvisibility.invisible=You see your hands turn invisible! +items.potions.potionofinvisibility.desc=Drinking this potion will render you temporarily invisible. While invisible, enemies will be unable to see you. Attacking an enemy, as well as using a wand or a scroll before enemy's eyes, will dispel the effect. +items.potions.potionoflevitation.name=potion of levitation +items.potions.potionoflevitation.float=You float into the air! +items.potions.potionoflevitation.desc=Drinking this curious liquid will cause you to hover in the air, able to drift effortlessly over traps and pits. Throwing this potion will create a cloud of unrefined gas, disorienting anything caught in it. +items.potions.potionofliquidflame.name=potion of liquid flame +items.potions.potionofliquidflame.desc=This flask contains an unstable compound which will burst violently into flame upon exposure to open air. +items.potions.potionofmight.name=potion of might +items.potions.potionofmight.msg_1=+15 ht +items.potions.potionofmight.desc=This powerful liquid will course through your muscles, permanently increasing your health by 15 points. +items.potions.potionofmindvision.name=potion of mind vision +items.potions.potionofmindvision.see_mobs=You can somehow feel the presence of other creatures' minds! +items.potions.potionofmindvision.see_none=You can somehow tell that you are alone on this level at the moment. +items.potions.potionofmindvision.desc=After drinking this, your mind will become attuned to the psychic signature of distant creatures, enabling you to sense biological presences through walls. Also this potion will permit you to see through nearby walls and doors. +items.potions.potionofparalyticgas.name=potion of paralytic gas +items.potions.potionofparalyticgas.desc=Upon exposure to open air, the liquid in this flask will vaporize into a numbing yellow haze. Anyone who inhales the cloud will be paralyzed instantly, unable to move for some time after the cloud dissipates. This item can be thrown at distant enemies to catch them within the effect of the gas. +items.potions.potionofpurity.name=potion of purification +items.potions.potionofpurity.freshness=You feel uncommon freshness in the air. +items.potions.potionofpurity.no_smell=You've stopped sensing any smells! +items.potions.potionofpurity.desc=This reagent will quickly neutralize all harmful gases in the area of effect. Drinking it will give you a temporary immunity to such gases. +items.potions.potionofstrength.name=potion of strength +items.potions.potionofstrength.msg_1=+1 str +items.potions.potionofstrength.msg_2=Newfound strength surges through your body. +items.potions.potionofstrength.desc=This powerful liquid will course through your muscles, permanently increasing your strength by one point. +items.potions.potionoftoxicgas.name=potion of toxic gas +items.potions.potionoftoxicgas.desc=Uncorking or shattering this pressurized glass will cause its contents to explode into a deadly cloud of toxic green gas. You might choose to fling this potion at distant enemies instead of uncorking it by hand. +items.potions.potionofhaste.name=potion of haste +items.potions.potionofhaste.effect=You move fast! +items.potions.potionofhaste.desc=After use this you will move fast. +items.potions.potionofmending.name=potion of mending +items.potions.potionofmending.effect=your wound heal fast. +items.potions.potionofmending.desc=Drink it will make you heal fast. +items.potions.potionofoverhealing.name=potion of life +items.potions.potionofoverhealing.effect=You heal completely and fill with a magical inner strength! +items.potions.potionofoverhealing.fill=gain %s ex health. +items.potions.potionofoverhealing.desc=An elixir that will instantly return you to full health, cures ailments, and overfills your health. + +###quest items +items.quest.ceremonialcandle.name=ceremonial candle +items.quest.ceremonialcandle.desc=A set of candles, melted down and fused together through use.\n\nAlone they are worthless, but used with other candles in a pattern, they can focus the energy for a summoning ritual. +items.quest.corpsedust.name=corpse dust +items.quest.corpsedust.desc=The ball of corpse dust doesn't differ outwardly from a regular dust ball. But you can feel a malevolent energy lurking within it.\n\nGetting rid of it as soon as possible would be a good idea. +items.quest.darkgold.name=dark gold ore +items.quest.darkgold.desc=This metal is called dark not because of its color (it doesn't differ from the normal gold), but because it melts under the daylight, making it useless on the surface. +items.quest.dwarftoken.name=dwarf token +items.quest.dwarftoken.desc=Many dwarves and some of their larger creations carry these small pieces of metal of unknown purpose. Maybe they are jewelry or maybe some kind of ID. Dwarves are strange folk. +items.quest.embers.name=elemental embers +items.quest.embers.desc=Special embers which can only be harvested from young fire elementals. They radiate thermal energy. +items.quest.pickaxe.name=pickaxe +items.quest.pickaxe.ac_mine=MINE +items.quest.pickaxe.no_vein=There is no dark gold vein near you to mine. +items.quest.pickaxe.desc=This is a large and sturdy tool for breaking rocks. Probably it can be used as a weapon. +items.quest.ratskull.name=giant rat skull +items.quest.ratskull.desc=A surprisingly large rat skull. It would make a great hunting trophy, if you had a wall to mount it on. +items.quest.mushroom.name=Dew mushroom +items.quest.mushroom.desc=A toadstool mushroom! Growing here in this dank dungeon! Who would have imagined such a thing! +items.quest.gnollclothes.name=Gnoll clothes +items.quest.gnollclothes.desc=A small, delicate windbreaker doesn't seem to be the size of a human being. + +###rings +items.rings.ring.diamond=diamond +items.rings.ring.opal=opal +items.rings.ring.garnet=garnet +items.rings.ring.ruby=ruby +items.rings.ring.amethyst=amethyst +items.rings.ring.topaz=topaz +items.rings.ring.onyx=onyx +items.rings.ring.tourmaline=tourmaline +items.rings.ring.emerald=emerald +items.rings.ring.sapphire=sapphire +items.rings.ring.quartz=quartz +items.rings.ring.agate=agate +items.rings.ring.cursed=The ring tightens around your finger painfully! +items.rings.ring.unknown_name=%s ring +items.rings.ring.unknown_desc=This metal band is adorned with a large %s gem that glitters in the darkness. Who knows what effect it has when worn? +items.rings.ring.known=This is a %s +items.rings.ring.identify=You are now familiar enough with your %s to identify it. It is %s. +items.rings.ring.on_finger=The %s is on your finger. +items.rings.ring.cursed_worn=Because this ring is cursed, you are powerless to remove it. +items.rings.ring.curse_known=You can feel a malevolent magic lurking within the %s. +items.rings.ring.toomany=you can only wear 3 misc items at a time. + +items.rings.ringofaccuracy.name=ring of accuracy +items.rings.ringofaccuracy.stats=ACU improve _ %1$d _ , Attack range improve _%2$d_ . +items.rings.ringofaccuracy.desc=This ring increases your focus, reducing your enemy's ability to dodge your attacks. Also every 10 level it can make player gain one more attack distance. + +items.rings.ringofelements.name=ring of elements +items.rings.ringofelements.stats=Gain element resistance. +items.rings.ringofelements.desc=This ring provides resistance to different elements, such as fire, electricity, gases etc. Also it decreases duration of negative effects. + +items.rings.ringofevasion.name=ring of evasion +items.rings.ringofevasion.stats=Dex improve _%d_ , steath improve _%2$d_ . +items.rings.ringofevasion.desc=This ring obfuscates the true position of the wearer, making them harder to detect and attack. A degraded ring will instead make the user easier to detect and strike. Every 5 level it will give wearer 1 steath, but max steath improve is 6. + +items.rings.ringofforce.name=ring of force +items.rings.ringofforce.stats=Melee damage improve _%1$s%%_ . If you don't have melee weapon, you will deal _ %2$d- %3$d_ base damage in melee attack. +items.rings.ringofforce.desc=This ring enhances the force of the wearer's blows. The max level of this ring is 30. + +items.rings.ringoffuror.name=ring of furor +items.rings.ringoffuror.stats=Melee attack speed improve _%s%%_ . +items.rings.ringoffuror.desc=This ring grants the wearer an inner fury, allowing them to attack more rapidly. The max level of this ring is 30. + +items.rings.ringofhaste.name=ring of haste +items.rings.ringofhaste.stats=Move speed improve _%s%%_ . +items.rings.ringofhaste.desc=This ring reduces the stress of movement on the wearer, allowing them to run at superhuman speeds. The max level of this ring is 30. + +items.rings.ringofmagic.name=ring of magic +items.rings.ringofmagic.stats=MIG improve _%d_ . +items.rings.ringofmagic.desc=Your wands will become more powerful in the arcane field that radiates from this ring. The max level of this ring is 30. + +items.rings.ringofmight.name=ring of might +items.rings.ringofmight.stats=STR improve _%1$d_ , HT improve _%2$d_ . +items.rings.ringofmight.desc=This ring enhances the physical traits of the wearer, granting them greater physical constitution. Every 5 level it will give wearer one strength. + +items.rings.ringofsharpshooting.name=ring of sharpshooting +items.rings.ringofsharpshooting.stats=Range weapon ACU improve _%1$d_ , Range weapon damage improve _%2$s%%_ . +items.rings.ringofsharpshooting.desc=This ring enhances the wearer's precision and aim, which will make all projectile weapons more accurate and durable. + +items.rings.ringoftenacity.name=ring of tenacity +items.rings.ringoftenacity.stats=Damage resistance _%s%%_ . +items.rings.ringoftenacity.desc=This ring will allow the wearer to resist normally mortal strikes. The max level of this ring is 30. + +items.rings.ringofenergy.name=ring of energy +items.rings.ringofenergy.stats=Wand charge speed improve _%s%%_ . +items.rings.ringofenergy.desc=Your wands will recharge more quickly in the arcane field that radiates from this ring. + +###scrolls +items.scrolls.scroll.ac_read=READ +items.scrolls.scroll.kaunan=KAUNAN +items.scrolls.scroll.sowilo=SOWILO +items.scrolls.scroll.laguz=LAGUZ +items.scrolls.scroll.yngvi=YNGVI +items.scrolls.scroll.gyfu=GYFU +items.scrolls.scroll.raido=RAIDO +items.scrolls.scroll.isaz=ISAZ +items.scrolls.scroll.mannaz=MANNAZ +items.scrolls.scroll.naudiz=NAUDIZ +items.scrolls.scroll.berkanan=BERKANAN +items.scrolls.scroll.odal=ODAL +items.scrolls.scroll.tiwaz=TIWAZ +items.scrolls.scroll.ncosrane=NCOSRANE +items.scrolls.scroll.nendil=NENDIL +items.scrolls.scroll.libra=LIBRA +items.scrolls.scroll.unknown_name=scroll "%s" +items.scrolls.scroll.unknown_desc=This parchment is covered with indecipherable writing, and bears a title of rune %s. Who knows what it will do when read aloud? +items.scrolls.scroll.blinded=You can't read a scroll while blinded. +items.scrolls.scroll.locked=You can't read a scroll while locked. +items.scrolls.scroll.silent=You can't read a scroll while be silent. +items.scrolls.scroll.cursed=Your cursed spellbook prevents you from invoking this scroll's magic! A scroll of remove curse might be strong enough to still work though... +items.scrolls.scroll.prevent=Something scrambles the scrying magic! +items.scrolls.scrollofmagicmapping.prevent=Magic mapping can't work in here. +items.scrolls.scrollofmirrorimage.prevent=Magic mirror can't work here. + +items.scrolls.inventoryscroll.warning=Do you really want to cancel this scroll usage? It will be consumed anyway. +items.scrolls.inventoryscroll.yes=Yes, I'm positive +items.scrolls.inventoryscroll.no=No, I changed my mind +items.scrolls.scrollofidentify.name=scroll of identify +items.scrolls.scrollofidentify.inv_title=Select an item to identify +items.scrolls.scrollofidentify.it_is=It is %s +items.scrolls.scrollofidentify.desc=This scroll permanently reveals all of the secrets of a single item. +items.scrolls.scrolloflullaby.name=scroll of lullaby +items.scrolls.scrolloflullaby.sooth=The scroll utters a soothing melody. You feel very sleepy. +items.scrolls.scrolloflullaby.desc=Reading this scroll emits a soothing melody will lull all who hear it into a deep magical sleep. +items.scrolls.scrollofmagicalinfusion.name=scroll of magical infusion +items.scrolls.scrollofmagicalinfusion.inv_title=Select an item to infuse +items.scrolls.scrollofmagicalinfusion.infuse=your %s is infused with arcane energy! +items.scrolls.scrollofmagicalinfusion.desc=This scroll will infuse a weapon or armor with powerful magical energy.\n\nIn addition to being upgraded, A weapon will gain a magical enchantment, or armor will be imbued with a magical glyph.\n\nIf the item already has an enchantment or glyph, it will never be erased by this scroll. +items.scrolls.scrollofmagicmapping.name=scroll of magic mapping +items.scrolls.scrollofmagicmapping.layout=You are now aware of the level layout. +items.scrolls.scrollofmagicmapping.desc=When this scroll is read, an image of crystal clarity will be etched into your memory, alerting you to the precise layout of the level. The locations of items, traps, hidden door and creatures will remain unknown. +items.scrolls.scrollofmirrorimage.name=scroll of mirror image +items.scrolls.scrollofmirrorimage.desc=The incantation on this scroll will create illusionary twins of the reader, which will chase their enemies. +items.scrolls.scrollofpsionicblast.name=scroll of psionic blast +items.scrolls.scrollofpsionicblast.ondeath=The Psionic Blast tears your mind apart... +items.scrolls.scrollofpsionicblast.desc=This scroll contains destructive energy that can be channeled to tear apart the minds of all visible creatures. The power unleashed by the scroll will also temporarily blind, stun, and seriously harm the reader. +items.scrolls.scrollofrage.name=scroll of rage +items.scrolls.scrollofrage.roar=The scroll emits an enraging roar that echoes throughout the dungeon! +items.scrolls.scrollofrage.desc=When read aloud, this scroll will unleash a great roar that draws all enemies to the reader, and enrages nearby ones. +items.scrolls.scrollofrecharging.name=scroll of recharging +items.scrolls.scrollofrecharging.surge=A surge of energy courses through your body, invigorating your wands! +items.scrolls.scrollofrecharging.desc=The raw magical power bound up in this parchment will, when released, charge up all the users wands over time. +items.scrolls.scrollofremovecurse.name=scroll of remove curse +items.scrolls.scrollofremovecurse.cleansed=Your pack glows with a cleansing light, and a malevolent energy disperses. +items.scrolls.scrollofremovecurse.not_cleansed=Your pack glows with a cleansing light, but nothing happens. +items.scrolls.scrollofremovecurse.desc=The incantation on this scroll will instantly strip from the reader's weapon, armor, rings and carried items any evil enchantments that might prevent the wearer from removing them. +items.scrolls.scrollofteleportation.name=scroll of teleportation +items.scrolls.scrollofteleportation.tele=In a blink of an eye you were teleported to another location of the level. +items.scrolls.scrollofteleportation.no_tele=Strong magic aura of this place prevents you from teleporting! +items.scrolls.scrollofteleportation.desc=The spell on this parchment instantly transports the reader to a random location on the dungeon level. It can be used to escape a dangerous situation, but the unlucky reader might find themselves in an even more dangerous place. +items.scrolls.scrollofterror.name=scroll of terror +items.scrolls.scrollofterror.none=The scroll emits a brilliant flash of red light. +items.scrolls.scrollofterror.one=The scroll emits a brilliant flash of red light and the %s flees! +items.scrolls.scrollofterror.many=The scroll emits a brilliant flash of red light and the monsters flee! +items.scrolls.scrollofterror.desc=A flash of red light will overwhelm all creatures in your field of view with terror, and they will turn and flee. Attacking a fleeing enemy will dispel the effect. +items.scrolls.scrollofupgrade.name=scroll of upgrade +items.scrolls.scrollofupgrade.inv_title=Select an item to upgrade +items.scrolls.scrollofupgrade.looks_better=your %s certainly looks better now +items.scrolls.scrollofupgrade.desc=This scroll will upgrade a single item, improving its quality. A wand will increase in power and in number of charges; a weapon will inflict more damage; a suit of armor will better absorb damage; the effect of a ring on its wearer will intensify. Weapons and armor will also require less strength to use, and any curses on the item will be lifted. +items.scrolls.inventoryscroll.title=choose one item + +items.scrolls.scrollofmultiupgrade.better=your %s certainly looks better now +items.scrolls.scrollofmultiupgrade.name=scroll of multi upgrade +items.scrolls.scrollofmultiupgrade.title=Choose one item. +items.scrolls.scrollofmultiupgrade.desc=This scroll will upgrade a single item, improving its quality. A wand will increase in power and in number of charges; a weapon will inflict more damage; a suit of armor will better absorb damage; the effect of a ring on its wearer will intensify. Weapons and armor will also require less strength to use, and any curses on the item will be lifted. +items.scrolls.scrollofregrowth.layout=plants grow in this floor, and you are now aware of the level layout. +items.scrolls.scrollofregrowth.name=scroll of regrowth +items.scrolls.scrollofregrowth.desc=The magic in the scroll feels powerful and inviting. The dungeon cries out for you to read it. +items.scrolls.scrollofsacrifice.name=scroll of sacrifice +items.scrolls.scrollofsacrifice.desc=A scroll that boosts strength at a certain cost. It is harmless at start, the more use, the dangerous you will be. +items.scrolls.scrollofsacrifice.use_1=+5 HT +items.scrolls.scrollofsacrifice.use_2=+1 STR +items.scrolls.scrollofsacrifice.use_lot=You don't feel good. + +###wands +items.wands.wand.ac_zap=ZAP +items.wands.wand.fizzles=Your wand fizzles; it must not have enough charge. +items.wands.wand.self_target=You can't target you self! +items.wands.wand.identify=You know your %s. +items.wands.wand.cursed=This wand is cursed, making its magic chaotic and random. +items.wands.wand.curse_discover=This %s is cursed! +items.wands.wand.prompt=Choose a location to zap +items.wands.wand.silent=Silent magic stop you cast magic. + +items.wands.wandoferror.name=Wand of Error +items.wands.wandoferror.desc=It is a error +items.wands.wandoferror.stats_desc=??? + +items.wands.wandofcharm.name=Wand of Charm +items.wands.wandofcharm.desc=A fairly plainly shaped wand, it stands out due to its magenta hue and pitch black gem at the tip. +items.wands.wandofcharm.stats_desc=This wand will make enemies be charmed. + +items.wands.wandofmeteorite.name=Wand of Meteorite +items.wands.wandofmeteorite.desc=This wand is made of a sort of meteorite, with gold trim and a round black gem at the tip. It feels very weighty in your hand. +items.wands.wandofmeteorite.stats_desc=This wand can create a mark to call the meteor attack at the target position. The power of the explosion will cause _%1$d-%2$d_ damage and is strong enough to stun most enemies. + +items.wands.wandoftcloud.name=Wand of Thundercloud +items.wands.wandoftcloud.desc=This stick is made of a conductive metal, with a tiny black cloud at the top of it. Fortunately, you won't feel uncomfortable holding your hand. +items.wands.wandoftcloud.stats_desc=This wand can create an automatic cloud at the target site. +items.wands.wandoftcloud.more_charge=Your need more charge to sommon thundercloud. +items.wands.wandoftcloud$tcloud.name=Thundercloud +items.wands.wandoftcloud$tcloud.desc=A Thundercloud +items.wands.wandoftcloud$stcloud.name=KEKE +items.wands.wandoftcloud$stcloud.desc=KEKE _IS_ MOVE, MOB _WILL_ DEAD. + +items.wands.wandofblood.name=Wand of Blood +items.wands.wandofblood.desc=This wand radiates dark energy, if that weren't already obvious from the small decorative skull shaped onto its tip. +items.wands.wandofblood.stats_desc=This wand will release a blast of corrupting energy, attempting to bend enemies' soul to your will. It will deals _%1$d-%2$d damage,_ and heal yourself. + +items.wands.wandofdisintegration.name=Wand of Disintegration +items.wands.wandofdisintegration.desc=This wand is made from a solid smooth chunk of obsidian, with a deep purple light running up its side, ending at the tip. It glows with destructive energy, waiting to shoot forward. +items.wands.wandofdisintegration.stats_desc=This wand shoots a beam that pierces any obstacle, and will go farther the more it is upgraded. The beam deals _%1$d-%2$d damage,_ and will also deal bonus damage for each enemy and wall it penetrates. + +items.wands.wandoffirebolt.name=Wand of Firebolt +items.wands.wandoffirebolt.desc=This wand is made from red-lacquered wood with golden leaf used liberally to make it look quite regal. It crackles and hisses at the tip, eager to unleash its powerful magic. +items.wands.wandoffirebolt.stats_desc=This wand produces a blast of fire when used, extending out into a cone shape. It will cause. _%1$d-%2$d damage_ . + +items.wands.wandofflock.name=Wand of Flock +items.wands.wandofflock.desc=This wand looks like an ordinary stick, but the gold ornaments at both ends make it look less ordinary. +items.wands.wandofflock.stats_desc=It can summon flock. +items.wands.wandofflock.guard=Guard appear because of this magic. +items.wands.wandofflock$magicsheep.desc=This is a magic sheep. What's so magical about it? You can't kill it. It will stand there until it magically fades away, all the while chewing cud with a blank stare. +items.wands.wandofflock$magicsheep.name=magic sheep +items.wands.wandofflock$magicbombsheep.desc=LEVEL _TOO_ HARD, BABA _IS_ DONE. BETTER _LOOK_ OUT, BABA _HAS_ GUN. +items.wands.wandofflock$magicbombsheep.name=BABA + + +items.wands.wandoflightning.name=Wand of Lightning +items.wands.wandoflightning.desc=This wand is made out of solid metal, making it surprisingly heavy. Two prongs curve together at the tip, and electricity arcs between them. +items.wands.wandoflightning.stats_desc=This wand sends powerful lightning arcing through whatever it is shot at, dealing _%1$d-%2$d damage._ This electricity can bounce between many nearby foes, spreading damage between them. The lightning and damage spread much more effectively in water. If you're too close, you may get shocked as well! + +items.wands.wandofmagicmissile.name=Wand of Magic missile +items.wands.wandofmagicmissile.desc=This fairly plain wand launches missiles of pure magical energy. While not as strong as other wands, it makes up for it somewhat with more available charges. +items.wands.wandofmagicmissile.stats_desc=Each bolt from this wand deals _%1$d-%2$d damage,_ and has no additional effects. + +items.wands.wandofpoison.name=Wand of Poison +items.wands.wandofpoison.desc=This wand has a purple body which opens to a brilliant green gem. +items.wands.wandofpoison.stats_desc=This wand shoots a bolt which explodes into a cloud of vile venomous gas at a targeted location. Anything caught inside this cloud will take continual damage, increasing with time. + +items.wands.wandoflight.name=Wand of Light +items.wands.wandoflight.desc=This wand is made of a solid piece of translucent crystal, like a long chunk of smooth glass. Small bits of colorful light dance around the tip of the wand, eager to burst forth. +items.wands.wandoflight.stats_desc=This wand shoots rays of light which cut through the darkness of the dungeon. The beam can blind enemies, and deals _%1$d-%2$d damage._ + +items.wands.wandoffreeze.name=Wand of Freeze +items.wands.wandoffreeze.desc=This wand seems to be made out of some kind of magical ice. It grows brighter towards its rounded tip. It feels very cold when held, but somehow your hand stays warm. +items.wands.wandoffreeze.stats_desc=This wand shoots blasts of icy energy toward your foes, dealing _%1$d-%2$d damage_ and chilling, which reduces speed. The effect seems stronger in water. Chilled and frozen enemies take less damage from this wand, as they are already cold. + +items.wands.wandofflow.name=Wand of Flow +items.wands.wandofflow.desc=The wand is shorter than the ordinary wand, but there is a small fountain at the top of this wand. +items.wands.wandofflow.stats_desc=The stick can spray a powerful flow of water into the target site, knocking off the target, deals _%1$d-%2$d damage_ and wetting it. + +items.wands.wandofacid.name=Wand of Acid +items.wands.wandofacid.desc=This wand is made from a thin shaft of expertly carved wood. Somehow it is still alive and vibrant, bright green like a young tree's core. +items.wands.wandofacid.stats_desc=When used, this wand will blast magical acid energy. This magic will deals _%1$d-%2$d damage_ , and add acid into them. + +items.wands.cannonofmage.name=Reno's rainbowr cannon +items.wands.cannonofmage.desc=An ancient relic find in Uldum. +items.wands.cannonofmage.stats_desc=When used, this wand will blast random energy. This magic will deals _%1$d-%2$d damage, and gain more damage from user's magic skill. + +###enchantments +items.weapon.enchantments.enchantmentdark.name=dark %s +items.weapon.enchantments.enchantmentdark.desc=This enchantment strike fear into enemies, causing them to flee from the attacker. It also will dear some dark damage. + +items.weapon.enchantments.enchantmentfire.name=fire %s +items.weapon.enchantments.enchantmentfire.desc=This enchantment causes flames to spit forth from a weapon, burning enemies and terrain alike. It also will dear some fire damage. + +items.weapon.enchantments.enchantmentlight.name=light %s +items.weapon.enchantments.enchantmentlight.desc=This enchantment strike light into enemies, causing much more damage on evil mobs. It also will dear some light damage. + +items.weapon.enchantments.enchantmentenergy.name=energy %s +items.weapon.enchantments.enchantmentenergy.desc=This enchantment has chance to improve user's attack. It also will dear some physics damage. + +items.weapon.enchantments.enchantmentearth.name=earth %s +items.weapon.enchantments.enchantmentearth.desc=This enchantment strike seed into enemies, healing other life near that target. It also will dear some earth damage. + +items.weapon.enchantments.enchantmentshock.name=electric %s +items.weapon.enchantments.enchantmentshock.desc=This enchantment dealing extra damage to all nearby enemies. It also will dear some storm damage. + +items.weapon.enchantments.enchantmentice.name=ice %s +items.weapon.enchantments.enchantmentice.desc=This enchantment slowing enemy's' movement and attacks. It also will dear some ice damage. + +items.weapon.enchantments.enchantmentdark2.name=weakness %s +items.weapon.enchantments.enchantmentdark2.desc=This enchantment can reduce target' melee attack. + +items.weapon.enchantments.enchantmentfire2.name=tar %s +items.weapon.enchantments.enchantmentfire2.desc=This enchantment can add tar to target. + +items.weapon.enchantments.enchantmentlight2.name=shining %s +items.weapon.enchantments.enchantmentlight2.desc=This enchantment can blind target. + +items.weapon.enchantments.enchantmentenergy2.name=dance %s +items.weapon.enchantments.enchantmentenergy2.desc=This enchantment can improve user's defense. + +items.weapon.enchantments.enchantmentearth2.name=acid %s +items.weapon.enchantments.enchantmentearth2.desc=This enchantment can add ooze to target. + +items.weapon.enchantments.enchantmentshock2.name=shock %s +items.weapon.enchantments.enchantmentshock2.desc=This enchantment can add static electricity to target. + +items.weapon.enchantments.enchantmentice2.name=coldwave %s +items.weapon.enchantments.enchantmentice2.desc=This enchantment can add cold and wet to target. + +items.weapon.enchantments.aresleech.name=drawing %s +items.weapon.enchantments.aresleech.desc=heal you slowly. +items.weapon.enchantments.aresleech.effect=It drawing %s energy from other mobs. +items.weapon.enchantments.aresleech$healdamage.name=extract +items.weapon.enchantments.aresleech$healdamage.desc=While your weapon's enchantment heal you slowly.\n\nYou will heal one health per turn until there is no healing left.\n\nHeal remaining: %d. + +items.weapon.enchantments.buzzsaw.name=overload%s +items.weapon.enchantments.buzzsaw.desc=use dews to deal more damage. +items.weapon.enchantments.buzzsaw.fuel=low power +items.weapon.enchantments.buzzsaw.off=overload off + +items.weapon.enchantments.cromluck.name=lucky%s +items.weapon.enchantments.cromluck.desc=deal another damage. + +items.weapon.enchantments.jupitershorror.name=horror%s +items.weapon.enchantments.jupitershorror.desc=horror will threaten the target + +items.weapon.enchantments.lokispoison.name=lokispoison%s +items.weapon.enchantments.lokispoison.desc=prison targrt. + +items.weapon.enchantments.neptuneshock.name=neptuneshock%s +items.weapon.enchantments.neptuneshock.desc=neptune will deal damage to many target. + +###relic +items.weapon.melee.relic.aressword.name=extract long sword +items.weapon.melee.relic.aressword.desc=This sword's long razor-sharp steel blade shines reassuringly, though its size does make it quite heavy. -- 00-EVAN\nWith the power of violet magic stone, this weapon can extract life energy from others. --Lynn +items.weapon.melee.relic.aressword.ac_regen=HEAL +items.weapon.melee.relic.cromcruachaxe.name=mince great axe +items.weapon.melee.relic.cromcruachaxe.desc=Meant to be wielded over the shoulder, this titanic axe is as powerful as it is heavy. -- 00-EVAN\nWith the power of orange magic stone, this weapon can crate shield to defence magic attack --Lynn +items.weapon.melee.relic.cromcruachaxe.ac_dispel=SHIELD +items.weapon.melee.relic.lokisflail.name=shadow flail +items.weapon.melee.relic.lokisflail.desc=A spiked ball attached to a handle by a length of chain. Very unwieldy, but devastating if it lands a solid hit. --00-EVAN\nWith the power of green magic stone, this weapon can hidden user in shadow. --Lynn +items.weapon.melee.relic.lokisflail.ac_stealth=SHADOW +items.weapon.melee.relic.neptunustrident.name=water trident +items.weapon.melee.relic.neptunustrident.desc=A Trident is a three-pronged spear. It is used for spear fishing and historically as a polearm. --Wiki\nWith the power of blue magic stone, it can change ground into water. -- Lynn +items.weapon.melee.relic.neptunustrident.ac_flood=RAIN +items.weapon.melee.relic.jupiterswraith.name=rock chakram +items.weapon.melee.relic.jupiterswraith.ac_explode=ROCK +items.weapon.melee.relic.jupiterswraith.desc=This razor-edged missile is made in such curious way that skilled user returns to the hands of the thrower on successful hit. --Consideredhamster\nWith the power of yellow magic stone, this weapon can crate rock fallen in target place. --Lynn + +###melee weapons + +items.weapon.melee.assassinsblade.name=assassins blade +items.weapon.melee.assassinsblade.desc=A small wavy blade made of obsidian, difficult to use despite being lightweight, but deadly if it finds the right mark.--00-Evan \n Puncture + +items.weapon.melee.battleaxe.name=battle axe +items.weapon.melee.battleaxe.desc=The enormous steel head of this battle axe puts considerable heft behind each stroke. --Watabou \n Rupture + +items.weapon.melee.club.name=club +items.weapon.melee.club.desc=A simple heavy wooden weapon. --Snof33 \n Blunt + +items.weapon.melee.dagger.name=dagger +items.weapon.melee.dagger.desc=A simple iron dagger with a well worn wooden handle. --Watabou \n Puncture + +items.weapon.melee.dualknive.name=Dual sword +items.weapon.melee.dualknive.desc=Two razor sharp blades for more damage.--Bilboldev \n Puncture + +items.weapon.melee.special.errorw.name=Error weapon +items.weapon.melee.special.errorw.desc=It is a error... \n Error + +items.weapon.melee.fightgloves.name=fight gloves +items.weapon.melee.fightgloves.desc=Such a weapon was formed by simple leather and metal tips. --Juh9870 \n Blunt + +items.weapon.melee.glaive.name=glaive +items.weapon.melee.glaive.desc=A polearm consisting of a sword blade on the end of a pole. --Watabou \n Cripple + +items.weapon.melee.gsword.name=greatsword +items.weapon.melee.gsword.desc=This towering blade inflicts heavy damage by investing its heft into every swing.--00-Evan \n Rupture + +items.weapon.melee.halberd.name=halberd +items.weapon.melee.halberd.desc=Some day, someone had a brilliant idea about combining reach of the spear with brutality of an axe.--Consideredhamster \n Cripple + +items.weapon.melee.handaxe.name=hand axe +items.weapon.melee.handaxe.desc=A light axe, most commonly used for felling trees. The wide blade works well against foes as well.--00-Evan \n Rupture + +items.weapon.melee.special.handcannon.name=handcannon +items.weapon.melee.special.handcannon.ac_on=ON +items.weapon.melee.special.handcannon.ac_off=OFF +items.weapon.melee.special.handcannon.power_on=Overload on! +items.weapon.melee.special.handcannon.power_off=Overload off! +items.weapon.melee.special.handcannon.desc=While initially flintlock weapons were a human invention, dwarves quickly adapted and improved the concept. Handcannons are heavy and require lots of gunpowder to use, but they are far more deadly than any other firearm.--Consideredhamster\nOverload + +items.weapon.melee.knuckles.name=knuckleduster +items.weapon.melee.knuckles.desc=A piece of iron shaped to fit around the knuckles. --Watabou \n Cripple + +items.weapon.melee.lance.name=lance +items.weapon.melee.lance.desc=The stout iron bars are connected to the huge cones, forming such a weapon. --Hmdzl001 \n Puncture + +items.weapon.melee.magebook.name=magic book +items.weapon.melee.magebook.desc=A magic book from tower. It is hard to read. --Coconut \n Blunt + +items.weapon.melee.nunchakus.name=nunchakus +items.weapon.melee.nunchakus.desc=The nunchakus are characterized in that the nunchakus also include a connection section connected with the connection rope.-- Hmdzl001 \n Blunt+ + +items.weapon.melee.rapier.name=rapier +items.weapon.melee.rapier.desc=A thin, long and sharp weapon. --Snof33 \n Puncture+ + +items.weapon.melee.special.runicblade.name=runic blade +items.weapon.melee.special.runicblade.ac_reforge=REFORGE +items.weapon.melee.special.runicblade.choose=Select an item to upgrade +items.weapon.melee.special.runicblade.reforged=You use runicblade to upgrade your weapon. +items.weapon.melee.special.runicblade.desc=A mysterious weapon from a distant land, with a bright blue blade. --00-Evan \n Refining + +items.weapon.melee.scimitar.name=scimitar +items.weapon.melee.scimitar.desc=A thick curved blade. Its shape allows for faster, yet less powerful attacks.--00-Evan \n Rupture+ + +items.weapon.melee.shortsword.name=short sword +items.weapon.melee.shortsword.desc=It is indeed quite short, just a few inches longer, than a dagger. --Watabou \n Rupture + +items.weapon.melee.spear.name=spear +items.weapon.melee.spear.desc=A slender wooden rod tipped with sharpened iron. --Watabou \n Cripple + +items.weapon.melee.special.spork.name=spork +items.weapon.melee.special.spork.desc=Is it a spoon? Is it a fork? It is neither and it is both. Mobs better respect! --Dachhack \n Binge + +items.weapon.melee.special.tekkokagi.name=tekkokagi +items.weapon.melee.special.tekkokagi.desc= A ninja weapon looks like the claws from wolverine. --Typedscroll \nDeadly + +items.weapon.melee.warhammer.name=war hammer +items.weapon.melee.warhammer.desc=Few creatures can withstand the crushing blow of this towering mass of lead and steel, but only the strongest of adventurers can use it effectively. --Watabou \n Blunt + +items.weapon.melee.whip.name=whip +items.weapon.melee.whip.desc=While the barbed length of rope at the end of this weapon deals poor damage, its reach cannot be matched. --00-Evan \n Cripple+ + +items.weapon.melee.special.wraithbreath.name=Wraith breath +items.weapon.melee.special.wraithbreath.desc=..............-- . \n.... + +items.weapon.melee.special.pumpkin.name=pumpkin lamp +items.weapon.melee.special.pumpkin.desc=Happy Halloween! \nIgnition, Lighting, Intimidation, Dessert + +items.weapon.melee.special.tree.name=christmas tree +items.weapon.melee.special.tree.desc=Merry Christmas! \n Sputter, Weak, Gift + +items.weapon.melee.special.firecracker.name=firecrackers +items.weapon.melee.special.firecracker.desc=The traditional 800 sounded firecrackers. Happy 2018 Spring Festival! \n Blowout, Ignition, Noisy, Intimidating + +items.weapon.melee.special.hookham.name=hook & ham +items.weapon.melee.special.hookham.desc=It is time to have fun. Let's cosplay pirates. Happy 2018 summer vacation! \n Gifts, Recovery, Rupture + +items.weapon.melee.triangolo.name=triangolo +items.weapon.melee.triangolo.desc=A percussion instrument made of thin steel bars bent into a triangle. A crisp and melodious sound is produced when struck with a metal bar. --?? \n Resonance + +items.weapon.melee.flute.name=flute +items.weapon.melee.flute.desc=The flute is a family of musical instruments in the woodwind group. --wiki\nResonance + +items.weapon.melee.wardurm.name=war durm +items.weapon.melee.wardurm.desc=The drum is a member of the percussion group of musical instruments. --wiki\nResonance+ + +items.weapon.melee.trumpet.name=trumpet +items.weapon.melee.trumpet.desc=A trumpet is a brass instrument commonly used in classical and jazz ensembles. --wiki\n Resonance + +items.weapon.melee.harp.name=harp +items.weapon.melee.harp.desc=The harp is a stringed musical instrument that has a number of individual strings running at an angle to its soundboard; the strings are plucked with the fingers. --wiki \n Resonance + +items.weapon.melee.woodenstaff.name=Wooden staff +items.weapon.melee.woodenstaff.desc=A staff carved from special wood that can be enchanted.--dachhack \nAccumulate + +items.weapon.melee.mace.name=mace +items.weapon.melee.mace.desc=The iron head of this weapon inflicts substantial damage. --Watabou\nAccumulate + +items.weapon.melee.holywater.name=holy water +items.weapon.melee.holywater.desc=A potion of bless water. --???\nAccumulate+ + +items.weapon.melee.prayerwheel.name=prayer wheel +items.weapon.melee.prayerwheel.desc=A simple paryer wheel --???\nAccumulate + +items.weapon.melee.stonecross.name=stone cross +items.weapon.melee.stonecross.desc=A huge cross made by stone. --Coconut\nAccumulate + +items.weapon.melee.special.goei.name=Reimus Goei +items.weapon.melee.special.goei.desc=A new goei.You can with it eorcism. --REN \nEvil Killer, Accumulate + +items.weapon.melee.special.brick.name=brick +items.weapon.melee.special.brick.desc=A common brick made of clay. Celebrating International Workers' Day!\nBlunt+, Fragile-Reward + +items.weapon.melee.special.lollipop.name=Lollipop +items.weapon.melee.special.lollipop.desc=This is a weapon, not a food. Happy Children Day! \n Sticky, Charming, Fragile-Lost + +items.weapon.melee.special.sjrbmusic.name=Song, Jump, Rap. Basketball, and play music +items.weapon.melee.special.sjrbmusic.desc=A famous jocker's clothes in China in 2019. Happy 2019 summer!\nResonance, Puncture+, Charm, Noise +items.weapon.melee.special.sjrbmusic.rap=Because your beaut!!! +items.weapon.melee.special.keyweapon.name=key message +items.weapon.melee.special.keyweapon.desc=Stay at home, keep distance with strangers,and make sure you are healthy. A message from former epidemic area. \n Blunt, Puncture, Puncture, Warn +items.weapon.melee.zero.woodenhammer.name=Example Wooden hammer +items.weapon.melee.zero.woodenhammer.desc=A simple wooden hammer. -- Luigi.\nBlunt, Fragile - Critical + +items.weapon.melee.zero.emptypotion.name=empty bottle +items.weapon.melee.zero.emptypotion.desc=A empty bottle. -- ???\nResonance, Fragile - Critical + +items.weapon.melee.special.linksword.name=Legend of Hyrule +items.weapon.melee.special.linksword.desc=Legend weapons in Hyrule.\nLegend +items.weapon.melee.special.linksword.ac_wisdom=WISDOM PROTECT +items.weapon.melee.special.linksword.ac_power=POWER IMBUE +items.weapon.melee.special.linksword.ac_courage=COURAGE BOOMERANG +items.weapon.melee.special.linksword.power=This weapon looks better now. +items.weapon.melee.special.linksword.charge=charge: %d / %d +items.weapon.melee.special.linksword.no=No charge now. + +items.weapon.melee.special.diamondpickaxe.name=Steve's diamond pickaxe +items.weapon.melee.special.diamondpickaxe.desc=A diamond pickaxe.\nLooting, Unbreaking, Efficiency, Sharpness, Silk Touch, Smite +items.weapon.melee.special.diamondpickaxe.ac_mine=Mine +items.weapon.melee.special.diamondpickaxe.no_thing=No thing in here. +items.weapon.melee.special.diamondpickaxe.noise=Mine alerted nearby mobs. +items.weapon.melee.special.shadoweater.name=Shadow Eater +items.weapon.melee.special.shadoweater.desc=A curse weapon build by all testers. Uncurse will remove its power. \n Asleep-Cost, Whisper +items.weapon.melee.special.shadoweater.charge=shadow: %d / 20 +items.weapon.melee.special.shadoweater.ac_awake=AWAKE +items.weapon.melee.special.shadoweater.ac_uncurse=UNCURSE +items.weapon.melee.special.shadoweater.awake=BLOOD... +items.weapon.melee.special.shadoweater.bleeding=GIVE ME YOUR BLOOD... +items.weapon.melee.special.shadoweater.silent=GIVE ME YOUR MOUTH... +items.weapon.melee.special.shadoweater.locked=GIVE ME YOUR HAND... +items.weapon.melee.special.shadoweater.stand=GIVE ME YOU LEG... +items.weapon.melee.block.goblinshield.name=Goblin Shield +items.weapon.melee.block.goblinshield.desc=A shield from goblin. \n Block, Wonder +items.weapon.melee.block.goblinshield.charge=charge: %d / 10 +items.weapon.melee.block.tengusword.name=Tengu Katana +items.weapon.melee.block.tengusword.desc=Tengu's katana. \n Rupture, Block +items.weapon.melee.block.spknuckles.name=Special knuckles +items.weapon.melee.block.spknuckles.desc=A powerful knuckles blesssed by knuckles sect. \n Blunt, Block +###items.weapon.melee..name= +###items.weapon.melee..desc= + +items.weapon.melee.meleeweapon.stats_known=This _tier-%1$d_ melee weapon deals _%2$d-%3$d damage_ and requires _%4$d strength_ to use properly. +items.weapon.melee.meleeweapon.stats_known2=This weapon acu is _%1$s_ , attack DLY is _%2$s_ , attack range is _%3$d_ . +items.weapon.melee.meleeweapon.stats_unknown=Typically this _tier-%1$d_ melee weapon deals _%2$d-%3$d damage_ and requires _%4$d strength_ to use properly. +items.weapon.melee.meleeweapon.too_heavy=this weapon is too heavy for you. +items.weapon.melee.meleeweapon.probably_too_heavy=It is probably too heavy to you. +items.weapon.melee.meleeweapon.excess_str=Because of your excess strength, you will deal up to _%d bonus damage_ with this weapon. +items.weapon.melee.meleeweapon.identify=You are now familiar enough with your weapon to identify it. +items.weapon.melee.meleeweapon.incompatible=Interaction of different types of magic has negated the enchantment on this weapon! +items.weapon.melee.meleeweapon.cursed_worn=Because this weapon is cursed, you are powerless to remove it. +items.weapon.melee.meleeweapon.cursed=You can feel a malevolent magic lurking within this weapon. +items.weapon.melee.meleeweapon.enchanted=It is enchanted, %s + +items.weapon.melee.meleeweapon.stats_desc=...\n + +items.weapon.weapon.identify=You are now familiar enough with your %s to identify it. It is %s. +items.weapon.weapon.avg_dmg=This missile weapon deals _%1$d-%2$d damage_ . +items.weapon.weapon.too_heavy=Because of your inadequate strength this weapon will hinder your attack speed, accuracy. +items.weapon.weapon.incompatible=Interaction of different types of magic has negated the enchantment on this weapon! + +items.weapon.weapon.charge=charge: %d / %d + +###test Guns +items.weapon.guns.toygun.name=Toy Gun +items.weapon.guns.toygun.desc=A simple toy. Happy 2019 new year and spring festival. +items.weapon.guns.toygun.ac_shoot=SHOOT +items.weapon.guns.toygun.ac_reload=RELOAD +items.weapon.guns.toygun.reloading=reloading... +items.weapon.guns.toygun.need_to_equip=You need equip this weapon first. +items.weapon.guns.toygun.full=full ammo +items.weapon.guns.toygun.empty=ammo is empty +items.weapon.guns.toygun.prompt=choose a target +items.weapon.guns.toygun.stats_known=This _tier-%1$d_ weapon deals _%2$d-%3$d damage_ and requires _%4$d strength_ to use properly. + +items.weapon.guns.toygun.stats_desc=...\n + +items.weapon.guns.toygun.charge=ammo: %d/%d + +items.weapon.guns.gunweapon.ac_shoot=SHOOT +items.weapon.guns.gunweapon.ac_reload=RELOAD +items.weapon.guns.gunweapon.ac_ammo=CHANGE AMMO +items.weapon.guns.gunweapon.reloading=reloading... +items.weapon.guns.gunweapon.stats_desc=...\n +items.weapon.guns.gunweapon.need_to_equip=You need equip this weapon first. +items.weapon.guns.gunweapon.prompt2=Choose special ammo. +items.weapon.guns.gunweapon.full=full ammo +items.weapon.guns.gunweapon.empty=ammo is empty +items.weapon.guns.gunweapon.imbue=You reload %d. +items.weapon.guns.gunweapon.ammo_add=Special ammo it have now: +items.weapon.guns.gunweapon.warning=Are you sure you want to add your ammo into this weapon? The old ammo will be lost. +items.weapon.guns.gunweapon.yes=Yes +items.weapon.guns.gunweapon.no=No + +items.weapon.guns.guna.name=Type A - Gunslinger Pistol +items.weapon.guns.guna.desc=An improvised firearm made of spare parts left from other guns. Mostly used by farmers and petty criminals. The only good things about it are its low price and light weight. --Juh9870\nIn fact, this weapon is made base on this introduce. Tower test it on sewer. + +items.weapon.guns.gunb.name=Type B - Pistol +items.weapon.guns.gunb.desc=A well-known short-barreled firearm. One of the most popular guns in the Kingdom and beyond due to its reliability, double barrel, and relatively decent price. --Juh9870\nIn fact, this weapon is made base on this introduce. Tower test it on prison. + +items.weapon.guns.gunc.name=Type C - Blunderbuss +items.weapon.guns.gunc.desc=Originally from the Southern Gulf, these firearms use shot. This is what makes them perfect for sea battles?or small spaces. --Juh9870\nIn fact, this weapon is made base on this introduce. Tower test it on cave. + +items.weapon.guns.gund.name=Type D - Fusil +items.weapon.guns.gund.desc=A smoothbore weapon straight from the royal manufactories. Its high accuracy makes up for the fair amount of time it takes to recharge as well as for its rarity. Pride of the soldiers! --Juh9870\nIn fact, this weapon is made base on this introduce. Tower test it on city. + +items.weapon.guns.gune.name=Type E - Mortair +items.weapon.guns.gune.desc=.Mortar deals huge damage and push enemies back, but also takes very long to reload. --Juh9870\nIn fact, this weapon is made base on this introduce. Tower test it on hell. + +items.weapon.guns.sling.name=Sling +items.weapon.guns.sling.desc=A simple sling, made out of a several leather straps. With it, simple lead bullets can be turned into much deadlier projectiles. --Consideredhamster + +items.weapon.spammo.heavyammo.name=Heavy ammo +items.weapon.spammo.heavyammo.desc=Add more damage on gun. Made by double stone. + +items.weapon.spammo.fireammo.name=Fire ammo +items.weapon.spammo.fireammo.desc=Add fire on gun. Made by stone and firebloom seed. + +items.weapon.spammo.iceammo.name=Ice ammo +items.weapon.spammo.iceammo.desc=Add ice on gun. Made by stone and icecap seed. + +items.weapon.spammo.stormammo.name=Storm ammo +items.weapon.spammo.stormammo.desc=Add storm on gun. Made by stone and stormvine. + +items.weapon.spammo.mossammo.name=Moss ammo +items.weapon.spammo.mossammo.desc=Add poison on gun. Made by stone and sorrowmoss seed. + +items.weapon.spammo.blindammo.name=Blind ammo +items.weapon.spammo.blindammo.desc=Add blind on gun. Made by stone and blindweed. + +items.weapon.spammo.starammo.name=Star ammo +items.weapon.spammo.starammo.desc=Add star damage on gun. Made by stone and starflower seed + +items.weapon.spammo.dreamammo.name=Dream ammo +items.weapon.spammo.dreamammo.desc=Add dream on gun. Made by stone and dreamfoil seed. + +items.weapon.spammo.dewammo.name=Dew ammo +items.weapon.spammo.dewammo.desc=Add dew damage on gun. Made by stone and dewcatcher seed. + +items.weapon.spammo.sunammo.name=Sun ammo +items.weapon.spammo.sunammo.desc=Add grow seed on gun. Made by stone and sungrass seed. + +items.weapon.spammo.sandammo.name=Sand ammo +items.weapon.spammo.sandammo.desc=Add sand on gun. Made by stone and fadeleaf seed. + +items.weapon.spammo.goldammo.name=Gold ammo +items.weapon.spammo.goldammo.desc=Add gold on gun. Made by stone and seedpod seed. It will cost golds. + +items.weapon.spammo.emptyammo.name=Empty ammo +items.weapon.spammo.emptyammo.desc=How dose this ammo work? Made by stone and blandfruit seed. + +items.weapon.spammo.rotammo.name=Rot ammo +items.weapon.spammo.rotammo.desc=Add rot on gun. Made by stone and rotberry seed. + +items.weapon.spammo.evolveammo.name=Evolve ammo +items.weapon.spammo.evolveammo.desc=Add DNA on gun. It will change target to another mob. Made by stone and phaseshift seed. + +items.weapon.spammo.thornammo.name=Thorn ammo +items.weapon.spammo.thornammo.desc=Add bleeding on gun. Made by stone and earthroot seed. + +items.weapon.spammo.battleammo.name=Battle ammo +items.weapon.spammo.battleammo.desc=Add suona on gun. It will improve your body on battle. Made by stone and flytrap seed. + +items.weapon.spammo.woodenammo.name=Wooden ammo +items.weapon.spammo.woodenammo.desc=Add wooden on gun. Made by stone and nut. + +###missile weapons +items.weapon.missiles.empbola.name=EMP bola +items.weapon.missiles.empbola.desc=Bolas are mostly used for hunting and they usually don't do much damage but they can ensnare the target leaving it helpless and motionless for some time. + +items.weapon.missiles.boomerang.name=boomerang +items.weapon.missiles.boomerang.ac_ammo=ADD AMMO +items.weapon.missiles.boomerang.prompt=Choose special ammo +items.weapon.missiles.boomerang.desc=Thrown to the enemy this flat curved wooden missile will return to the hands of its thrower. + +items.weapon.missiles.manyknive.name=Lzayoi's thousand knives +items.weapon.missiles.manyknive.ac_shoot=SHOOT +items.weapon.missiles.manyknive.ac_ammo=ADD AMMO +items.weapon.missiles.manyknive.prompt=Choose special ammo +items.weapon.missiles.manyknive.desc=It made by lots of throw knife. Can use special ammo. +items.weapon.missiles.manyknive.damage=This weapon can deal _ %d - %d damage _ ,and spend less time on attack. + +items.weapon.missiles.taurcenbow.name=Centaur Bow +items.weapon.missiles.taurcenbow.ac_shoot=SHOOT +items.weapon.missiles.taurcenbow.ac_break=ARMOR BREAK ARROW +items.weapon.missiles.taurcenbow.ac_fire=FIRE ARROW +items.weapon.missiles.taurcenbow.ac_ice=ICE ARROW +items.weapon.missiles.taurcenbow.ac_posion=POSION ARROW +items.weapon.missiles.taurcenbow.ac_ele=EMP ARROW +items.weapon.missiles.taurcenbow.desc=A centaur bow used by taurcen. +items.weapon.missiles.taurcenbow.damage=This weapon can deal _ %d - %d damage _ ,and auto use special arrow attack after attack some number of times. +items.weapon.missiles.taurcenbow.charge=charge: %d / %d + +items.weapon.missiles.forestdart.name=Lucky throwing knives +items.weapon.missiles.forestdart.desc=These simple metal blades are weighted to fly true and sting their prey with a flick of the wrist. + +items.weapon.missiles.incendiarydart.name=incendiary dart +items.weapon.missiles.incendiarydart.desc=The spike on each of these darts is designed to pin it to its target while the unstable compounds strapped to its length burst into brilliant flames. + +items.weapon.missiles.hugeshuriken.name=Huge shuriken +items.weapon.missiles.hugeshuriken.desc=Huge star-shaped pieces of metal with razor-sharp blades do significant damage when they hit a target. + +items.weapon.missiles.escapeknive.name=Escape knife +items.weapon.missiles.escapeknive.desc=These simple metal blades are weighted to fly true and sting their prey with a flick of the wrist. + +items.weapon.missiles.normalbomb.name=Empty bomb +items.weapon.missiles.normalbomb.desc=How did this work? + +items.weapon.missiles.poisondart.name=poison dart +items.weapon.missiles.poisondart.desc=These little evil darts don't do much damage but they can paralyze the target leaving it helpless and motionless for some time. + +items.weapon.missiles.riceball.name=rice ball +items.weapon.missiles.riceball.desc=It is some kind of pet food. + +items.weapon.missiles.smoke.name=Smoke +items.weapon.missiles.smoke.desc=Star-shaped pieces of metal with razor-sharp blades share smoke when they hit a target. + +items.weapon.missiles.skull.name=skull +items.weapon.missiles.skull.desc=It is a evil weapon. + +items.weapon.missiles.tamahawk.name=tomahawk +items.weapon.missiles.tamahawk.desc=This throwing axe is not that heavy, but it still requires significant strength to be used effectively. + +items.weapon.missiles.wave.name=wave +items.weapon.missiles.wave.desc=It is a wave weapon. + +items.weapon.missiles.shatteredammo.name=shattered ammo +items.weapon.missiles.shatteredammo.desc=It is small but dangerous. + +items.weapon.missiles.errorammo.name=error ammo +items.weapon.missiles.errorammo.desc=this is a error + +items.weapon.missiles.minimoai.name=Mini Moai +items.weapon.missiles.minimoai.desc=A easter egg from easter land for easter day. + +items.weapon.missiles.pocketball.name=lantern of soul collect +items.weapon.missiles.pocketball.desc=A empty lantern which can collect your pet. +items.weapon.missiles.pocketball.get_pet=You catch this pet. + +items.weapon.missiles.moneypack.name=red packet +items.weapon.missiles.moneypack.desc=You can use gold to solve many problems in Spring Festival. Happy 2020 Spring Festival!!! + +##mc block +items.weapon.missiles.buildblock.wallblock.name=Wall block +items.weapon.missiles.buildblock.wallblock.desc=Wall block + +items.weapon.missiles.buildblock.doorblock.name=Door block +items.weapon.missiles.buildblock.doorblock.desc=Door block + +items.weapon.missiles.buildblock.stoneblock.name=Statue block +items.weapon.missiles.buildblock.stoneblock.desc=Statue block + +items.weapon.missiles.buildblock.bookblock.name=Bookshelf block +items.weapon.missiles.buildblock.bookblock.desc=Bookshelf block + +items.weapon.missiles.buildblock.woodenblock.name=Wooden block +items.weapon.missiles.buildblock.woodenblock.desc=Wooden block + +items.weapon.missiles.buildblock.waterblock.name=Water block +items.weapon.missiles.buildblock.waterblock.desc=Water block + +items.wateritem2.name=Water block +items.wateritem2.pour=USE +items.wateritem2.desc=Water block + +##eggs +items.eggs.egg.prevent=This is not the best place to summon it. +items.eggs.egg.notready=You already have one pet. +items.eggs.egg.yolk=Some of the energy is four diaspora. +items.eggs.egg.name=Soul of mobs +items.eggs.egg.hatch=You get new pet. +items.eggs.egg.scratch=You hear some whisper. +items.eggs.egg.slithers=You hear some word. +items.eggs.egg.kick=You hear big noise. +items.eggs.egg.slosh=You can't hear anything. +items.eggs.egg.zap=Huge sound wave hurt your body. +items.eggs.egg.ac_break=SUMMON +items.eggs.egg.ac_shake=LISTEN +items.eggs.egg.warmhome=This soul absorbs energy in your warm backpack. +items.eggs.egg.onlyone=Only one soul can absorb energy in the backpack. +items.eggs.egg.desc=It is egg in sprouted, but in here it called soul. Just try to get one pet on it. You can feed your pet to make it stronger. +items.eggs.egg.moves=Energy:%d +items.eggs.egg.burns=Fire:%d +items.eggs.egg.freezes=Ice:%d +items.eggs.egg.poisons=Earth:%d +items.eggs.egg.lits=Electy:%d +items.eggs.egg.summons=Dark:%d +items.eggs.egg.light=Light:%d + +items.eggs.easteregg.name=Soul of rabbit +items.eggs.easteregg.desc=Soul of easter egg. + +items.eggs.cococategg.name=Soul of cat +items.eggs.cococategg.desc=Soul of bombs + +items.eggs.randomegg.name=Random soul +items.eggs.randomegg.desc=Summon a random basic pet. + +items.eggs.shadowdragonegg.name=Soul of shadow dargeon +items.eggs.shadowdragonegg.desc=Soul of shadow. + +items.eggs.leryfireegg.name=Soul of chaos +items.eggs.leryfireegg.desc=Soul of chaos. + +items.eggs.bluedragonegg.name=Soul of blue dargeon +items.eggs.bluedragonegg.desc=Soul of ice dargeon + +items.eggs.lightdragonegg.name=Soul of white dargeon +items.eggs.lightdragonegg.desc=Soul of light. + +items.eggs.greendragonegg.name=Soul of green dargeon +items.eggs.greendragonegg.desc=Soul of lightning + +items.eggs.reddragonegg.name=Soul of red dargeon +items.eggs.reddragonegg.desc=Soul of fire. + +items.eggs.scorpionegg.name=Soul of scorpion +items.eggs.scorpionegg.desc=.Soul of scorpion + +items.eggs.spideregg.name=Soul of web +items.eggs.spideregg.desc=Soul of web. + +items.eggs.velociroosteregg.name=Soul of velocirooster +items.eggs.velociroosteregg.desc=Soul of velocirooster, the kiing of unleashed. + +items.eggs.violetdragonegg.name=Soul of violet dargeon +items.eggs.violetdragonegg.desc=Soul of earth. + +items.eggs.golddragonegg.name=Soul of gold dargeon +items.eggs.golddragonegg.desc=soul of missing No. +items.eggs.yearpetegg.name=Soul Of Year +items.eggs.yearpetegg.desc=Soul of year. +##Bombs +items.bombs.bomb.name=bomb +items.bombs.bomb.ac_lightthrow=LIGHT & THROW +items.bombs.bomb.snuff_fuse=You quickly snuff the bomb's fuse. +items.bombs.bomb.desc=A fairly hefty black powder bomb. An explosion from this would certainly do damage to anything nearby.\n\nIt looks like the fuse will take a couple rounds to burn down once it is lit. +items.bombs.bomb.desc_burning=A fairly hefty black powder bomb. An explosion from this would certainly do damage to anything nearby.\n\nThe bomb's fuse is burning away, keep your distance or put it out! + +items.bombs.firebomb.name=Fire bomb +items.bombs.firebomb.desc=It will cause fire explode. + +items.bombs.icebomb.name=Ice bomb +items.bombs.icebomb.desc=It will cause ice explode. + +items.bombs.earthbomb.name=Acid bomb +items.bombs.earthbomb.desc=It will cause acid and regrow explode. + +items.bombs.fishingbomb.name=fishing bomb +items.bombs.fishingbomb.no_tp=Can't find dry place. +items.bombs.fishingbomb.tp=Something away. +items.bombs.fishingbomb.desc=It can send mob into dry place. + +items.bombs.stormbomb.name=Storm bomb +items.bombs.stormbomb.desc=It will cause storm explode. + +items.bombs.darkbomb.name=Dark bomb +items.bombs.darkbomb.desc=It will cause dark explode, and it is harmful to life. + +items.bombs.hugebomb.name=Huge bomb +items.bombs.hugebomb.desc=It will cause huge explode, and it will destroy walls. + +items.bombs.lightbomb.name=Holy bomb +items.bombs.lightbomb.desc=It will cause light explode, and it is harmful to.abiotic. + +items.bombs.dungeonbomb.name=Bomb +items.bombs.dungeonbomb.desc=A fairly hefty black powder bomb. An explosion from this would certainly do damage to anything nearby and destroy walls .\n\nIt looks like the fuse will take a couple rounds to burn down once it is lit. +items.bombs.dungeonbomb$doublebomb.name=two bombs +items.bombs.dungeonbomb$doublebomb.desc=A stack of two hefty black powder bombs, looks like you get one free! + +items.bombs.buildbomb.name=Build bomb +items.bombs.buildbomb.desc=A normal bomb made by human. It can be used to create other special bomb. + +items.bombs.minibomb.name=Mini bomb +items.bombs.minibomb.desc=It can deal damage. + +###tp items +items.tengukey.name=tengu! +items.tengukey.ac_port=PORT +items.tengukey.desc=A strange paper, it says: Tengu, 10000 gold. +items.potkey.name=POOOOT KEY +items.potkey.ac_port=use +items.potkey.desc=A teleport item from POOOOT. +items.treasuremap.name=treasure map +items.treasuremap.ac_port=PORT +items.treasuremap.desc=This map radiates an eerie power. Reading the inscription will take you to the Gnoll King. + +items.bone.ac_port=PORT +items.bone.name=bone +items.bone.desc=This bone radiates an eerie power. Reading the inscription will open the portal to the Skeleton King. + +items.conchshell.name=conch shell +items.conchshell.ac_port=PORT +items.conchshell.desc=This shell radiates an eerie power. Blow through it to take you to the Crab King. + +items.ancientcoin.ac_port=PORT +items.ancientcoin.name=ancient coin +items.ancientcoin.desc=This coin radiates an eerie power. Reading the inscription will take you to the Bandit King. + +items.triforce.ac_port=PORT +items.triforce.name=triforce +items.triforce.desc=The puzzle is complete. The force will open a portal to the final boss. You will be immediately transported when the portal is opened. + +items.bossrush.name=Boss Rush +items.bossrush.ac_read=PORT +items.bossrush.desc=This is a uncompleted bossrush. You can try to fight with those new boss. + +items.palantir.name=palantir +items.palantir.ac_port=PORT +items.palantir.desc=The ancient powerful scrying device. Zot is trapped inside. + +###reward +items.reward.sewerreward.name=sewer reward bag +items.reward.sewerreward.ac_use=USE +items.reward.sewerreward.desc=reward of sewer challenge + +items.reward.prisonreward.name=prison reward bag +items.reward.prisonreward.ac_use=USE +items.reward.prisonreward.desc=reward of prison challenge + +items.reward.cavereward.name=cave reward bag +items.reward.cavereward.ac_use=USE +items.reward.cavereward.desc=reward of cave challenge + +items.reward.cityreward.name=city reward bag +items.reward.cityreward.ac_use=USE +items.reward.cityreward.desc=reward of city challenge + +##summon item +items.summon.honeypot.name=honeypot +items.summon.honeypot.ac_shatter=SHATTER +items.summon.honeypot.desc=This large honeypot is only really lined with honey, instead it houses a giant bee! These sorts of massive bees usually stay in their hives, perhaps the pot is some sort of specialized trapper's cage? The bee seems pretty content inside the pot with its honey, and buzzes at you warily when you look at it. +items.summon.honeypot$shatteredpot.name=shattered honeypot +items.summon.honeypot$shatteredpot.desc=The pot has been shattered, only the sticky honey that lines its walls is holding it together, and it is slowly coming apart.\n\nDespite its broken state, the bee still seems to want to protect the pot. +items.summon.honeypot$bee.name=Golden bee +items.summon.honeypot$bee.desc=Despite their small size, golden bees tend to protect their home fiercely. This one is very mad, better keep your distance. +items.summon.honeypot$steelbee.name=Steel bee +items.summon.honeypot$steelbee.desc=This bee is upgrade by power of leader. It is stronger and loyal. + +items.summon.activemrdestructo.name=mr.destructo +items.summon.activemrdestructo.ac_active=USE +items.summon.activemrdestructo.desc=It reads, MR DESTRUCTO. An odd contraption. What does it do? +items.summon.activemrdestructo$mrdestructo.name=mr destructo +items.summon.activemrdestructo$mrdestructo.desc=You use this thing and it is attacking mobs. +items.summon.activemrdestructo$mrdestructo2dot0.name=mr destructo 2.0 +items.summon.activemrdestructo$mrdestructo2dot0.desc=You use this thing and it is attacking mobs. It was upgrade by power of leader. + +items.summon.callcoconut.name=Summon key +items.summon.callcoconut.ac_active=USE +items.summon.callcoconut.desc=It can summon coconut. +items.summon.callcoconut$scococat.name=coconut +items.summon.callcoconut$scococat.desc=Let's start! +items.summon.callcoconut$excococat.name=EX coconut +items.summon.callcoconut$excococat.desc=Let's start again! + +items.summon.mobile.name=control mobile +items.summon.mobile.ac_active=USE +items.summon.mobile.desc=It will summon a mobile satellite. +items.summon.mobile$mobilesatellite.name=mobile satellite +items.summon.mobile$mobilesatellite.desc=mobile satellite +items.summon.mobile$exmobilesatellite.name=ex mobile satellite +items.summon.mobile$exmobilesatellite.desc=ex mobile satellite + +items.summon.fairycard.name=fairy card +items.summon.fairycard.ac_active=USE +items.summon.fairycard.desc=Draw a card, and summon a fairy. +items.summon.fairycard$fairy.name=Fairy +items.summon.fairycard$fairy.desc=Fairy can heal your wound. +items.summon.fairycard$sugarplumfairy.name=Warlock Fairy +items.summon.fairycard$sugarplumfairy.desc=Warlock fairy can heal your wound and harm your enemy. + +###misc items +items.dwarfhammer.prevent=This is not the right floor to use this item. +items.dwarfhammer.unseal=You unseal the entrance to the next level. +items.dwarfhammer.ac_break=BREAK +items.dwarfhammer.name=magic breaker +items.dwarfhammer.desc=Too fragile to use as a weapon, this magic hammer was used to seal the demons in this level. Perhaps there is just enough magic left to unseal the next level... + +items.amulet.name=amulet of yendor +items.amulet.ac_end=END THE GAME +items.amulet.desc=The Amulet of Yendor is the most powerful known artifact of unknown origin. It is said that the amulet is able to fulfil any wish if its owner's will-power is strong enough to "persuade" it to do it. + +items.ankh.name=ankh +items.ankh.ac_bless=BLESS +items.ankh.bless=You bless the ankh with clean water. +items.ankh.desc=This ancient symbol of immortality grants the ability to return to life after death. Upon resurrection all non-equipped items are lost. Using a full dew vial, the ankh can be blessed with extra strength. +items.ankh.desc_blessed=This ancient symbol of immortality grants the ability to return to life after death. The ankh has been blessed and is now much stronger. The Ankh will sacrifice itself to save you in a moment of deadly peril. +items.ankh.revive=The ankh explodes with life-giving energy! + +items.armorkit.name=skill kit +items.armorkit.ac_apply=APPLY +items.armorkit.desc=Using this kit of small will give user a special ability depending on his class. No need skills in tailoring or leatherworking. + +items.dewdrop.name=dewdrop +items.dewdrop.value=%+dHP +items.dewdrop.already_full=You already have full health. +items.dewdrop.desc=A crystal clear dewdrop.\n\nDue to the magic of this place, pure water has minor restorative properties. + +items.equipableitem.unequip_cursed=You can't remove a cursed item! +items.equipableitem.ac_equip=EQUIP +items.equipableitem.ac_unequip=UNEQUIP + +items.gold.name=gold +items.gold.desc=A pile of gold coins. Collect gold coins to spend them later in a shop. + +items.heap.mimic=This is a mimic! +items.heap.chest=chest +items.heap.chest_desc=Open too see what in it. +items.heap.locked_chest=locked chest +items.heap.locked_chest_desc=Open it with a gold key to see what is in there. +items.heap.crystal_chest=crystal chest +items.heap.crystal_chest_desc=You can see %s in there, but you need a gold key to open it. +items.heap.artifact=artifact +items.heap.wand=wand +items.heap.ring=ring +items.heap.tomb=tomb +items.heap.tomb_desc=This ancient tomb may contain something useful, but its owner will most certainly object to checking. +items.heap.skeleton=remain +items.heap.skeleton_desc=This is all that's left of some unfortunate adventurer. Maybe it's worth checking for any valuables. +items.heap.remains=hero remain +items.heap.remains_desc=This is all that's left from one of your predecessors. Maybe it's worth checking for any valuables. + +items.item.pack_full=Your pack is too full for the %s. +items.item.prompt=Choose direction of throw +items.item.ac_drop=DROP +items.item.ac_throw=THROW +items.item.not_here=This is not the right floor to use this item. +items.item.boss_first=You should kill boss first. +items.item.item_first=You need to stand on a platform with key props first and hold high key props to use this prop to leave. +items.item.reinforced=Adamant have been weld. + +items.kindofmisc.unequip_title=unequip one equipment +items.kindofmisc.unequip_message=You can only wear three misc items at a time. + +items.kindofweapon.cursed=you wince as your grip involuntarily tightens around your %s + +items.kindofarmor.cursed=The armor constricts around you painfully. + +items.kindofweapon.destory=Your weapon destroy. +items.kindofweapon.almost_destory=Your weapon is almost broken. + +items.merchantsbeacon.name=merchant's beacon +items.merchantsbeacon.ac_use=USE +items.merchantsbeacon.desc=This odd piece of dwarven technology allows you to communicate from great distances.\n\nAfter being activated, this beacon will let you sell items to Pixel Mart from anywhere in the dungeon.\n\nHowever, the magic within the beacon will only last for one session, so use it wisely. + +items.stylus.name=arcane stylus +items.stylus.ac_inscribe=INSCRIBE +items.stylus.prompt=Select an armor to inscribe +items.stylus.inscribed=You inscribed your armor with the stylus +items.stylus.desc=This arcane stylus is made of some dark, very hard stone. Using it you can inscribe a magical glyph on your armor, but you have no power over choosing what glyph it will be, the stylus will decide it for you. + +items.torch.name=torch +items.torch.ac_light=LIGHT +items.torch.desc=An adventuring staple, when a dungeon goes dark, a torch can help lead the way. + +items.weightstone.name=weightstone +items.weightstone.ac_apply=APPLY +items.weightstone.select=Select a weapon to enchant +items.weightstone.apply=You apply your weapon with the weightstone +items.weightstone.desc=Using a weightstone, you can enchant your melee weapon. + +items.adamantarmor.name=adamant armor +items.adamantarmor.desc=It is adamant armor. +items.adamantring.name=adamant ring +items.adamantring.desc=It is adamant ring. +items.adamantwand.name=adamant wand +items.adamantwand.desc=It is adamant wand. +items.adamantweapon.name=adamant weapon +items.adamantweapon.desc=It is adamant weapon. + +items.dewvial.name=dew vial +items.dewvial.ac_drink=DRINK +items.dewvial.value=%+dHP +items.dewvial.collected=You collected the dew into dew vial +items.dewvial.full=Your dew vial is full! +items.dewvial.empty=Your dew vial is empty! +items.dewvial.ac_water=PLANT +items.dewvial.ac_splash=SPEED +items.dewvial.ac_bless=UPGRADE +items.dewvial.ac_light=LIGHT +items.dewvial.ac_pour=CLEAN +items.dewvial.ac_peek=PEEK +items.dewvial.ac_refine=REFINE +items.dewvial.watered=Plant grow around you. +items.dewvial.blessed=Mistery power upgread your item. +items.dewvial.remove_curse=Curse has been remove. +items.dewvial.curse=Nothing happend. +items.dewvial.select=Choose one item to upgread +items.dewvial.fly=You float into air. +items.dewvial.light=You are surrounded by dark lights and hiding you into shadows. +items.dewvial.fast=You move fast! +items.dewvial.pour=You clear you body by water. +items.dewvial.desc=An old and mysterious magic vial used on collect dews.\nThose dews can be used for various functions.\nBasic: healing, light, refine. +items.dewvial.desc_v1=lv 1 : upgrade, plant. +items.dewvial.desc_v2=lv 2 : clean, speed. +items.dewvial.desc_v3=lv 3 : dew vial become bigger, and flying when use speed. + +items.orbofzot.name=orbofzot +items.orbofzot.ac_activatethrow=USE +items.orbofzot.ac_break=BREAK +items.orbofzot.desc=The Orb of Zot is source of unlimited power created by the lord Zot. Apparently, Yog was harnessing its power to infest the dungeon. +items.orbofzot.charge=charge: %d /%d + +items.dolyaslate.prevent=Unknow location, error +items.dolyaslate.ac_return=RETURN +items.dolyaslate.ac_add=ADD +items.dolyaslate.ac_read=USE +items.dolyaslate.ac_set=SET +items.dolyaslate.ac_back=BACK +items.dolyaslate.prompt=Choose location +items.dolyaslate.name=Dolya slate +items.dolyaslate.desc=A transport item made in Dolye town.\nYou can add some location in to this magic stone and you can go there by use this thing. +items.dolyaslate.charge=Charge: %d / %d +items.dolyaslate.add_page=Location load successfully. + +items.challengebook.prevent=It is useless. +items.challengebook.ac_return=RETURN +items.challengebook.ac_add=ADD +items.challengebook.ac_read=USE +items.challengebook.ac_back=BACK +items.challengebook.prompt=Add a Challenge +items.challengebook.name=Challenge book +items.challengebook.desc=A simple note book with some aline magic\n\n_So here is some tutorial for you. Add that challenge paper into this book and you will free to come and go there place.\n\nI also want write some other things but I can't understand your language.\nThere some secret reword in each challenge. If you find all of them I will give you a weapon from my east project pixel dungeon._ +items.challengebook.add_page=Add challenge successful + +items.puddingcup.name=chocolate pudding cup +items.puddingcup.ac_save=SAVE +items.puddingcup.desc=Its good smell will make you remember what have happened. + +items.reddewdrop.name=red dew drop +items.reddewdrop.value=%+d hp +items.reddewdrop.desc=red dew drop + +items.violetdewdrop.name=violet dew drop +items.violetdewdrop.value=%+d hp +items.violetdewdrop.desc=violet dew drop + +items.yellowdewdrop.name=yellow dew drop +items.yellowdewdrop.value=%+d hp +items.yellowdewdrop.desc=yellow dew drop + +items.triforceofcourage.name=triforce of courage +items.triforceofcourage.desc=Courage part of triforce. +items.triforceofpower.name=triforce of power +items.triforceofpower.desc=Power part of triforce. +items.triforceofwisdom.name=triforce of wisdom +items.triforceofwisdom.desc=Wisdom part of triforce. + +items.stoneore.name=stone ore +items.stoneore.desc=Simple stone can be used on cooking or sell for money. + +items.expore.name=EXP ore +items.expore.ac_use=USE +items.expore.desc=Level up. + +items.tomeofmastery.name=Tome of Mastery +items.tomeofmastery.ac_read=READ +items.tomeofmastery.blind=You can't read while blinded. +items.tomeofmastery.way=You have chosen the way of the %s! +items.tomeofmastery.desc=This worn leather book is not that thick, but you feel somehow, that you can gather a lot from it. Remember though that reading this tome may require some time. + +items.towel.prevent=You don't need use this towel. +items.towel.apply=You use that towel. +items.towel.end=This towel is broken. +items.towel.ac_towel=USE +items.towel.ac_towel_pet=USE TO PET +items.towel.name=towel +items.towel.desc=Don't forget your towel! + +items.upgradeblobred.ac_inscribe=USE +items.upgradeblobred.name=red upgrade item +items.upgradeblobred.desc=This blob of red goo holds a powerful magic. It can upgrade your gear when applied. +items.upgradeblobviolet.name=violet upgrade item +items.upgradeblobviolet.ac_inscribe=USE +items.upgradeblobviolet.desc=This blob of violet goo holds a powerful magic. It can upgrade your gear when applied. +items.upgradeblobyellow.name=yellow upgrade item +items.upgradeblobyellow.ac_inscribe=USE +items.upgradeblobyellow.desc=This blob of yellow goo holds a powerful magic. It can upgrade your gear when applied. + +items.whistle.ac_call=USE +items.whistle.name=Book of soul +items.whistle.message=need writing... +items.whistle$wndwhistle.title=Book of soul +items.whistle$wndwhistle.desc=need writing... +items.whistle.desc=Book of soul + +### new stuff +items.misc.ankhshield.name=ankh shield +items.misc.ankhshield.charge=charge: %d /%d +items.misc.ankhshield.ac_defence=SHIELD BLAST +items.misc.ankhshield.rest=need more charge +items.misc.ankhshield.desc=A powerful item work like bomb in STG game. It was create by developer. + +items.misc.jumph.name=jump shoes of huntress +items.misc.jumph.ac_jump=JUMP +items.misc.jumph.desc=With the guide from nature, hunter can attack some mob when jump. + +items.misc.jumpm.name=jump shoes of mage +items.misc.jumpm.ac_jump=JUMP +items.misc.jumpm.desc=Mage was study in tower, so he can use blink instead of jump, and improve his magic power in sometime. + +items.misc.jumpr.name=jump shoes of rogue +items.misc.jumpr.ac_jump=JUMP +items.misc.jumpr.desc=Without training, rogue can't jump far away, but he can hidden his body in jump and hover in air. + +items.misc.jumpshoes.name=jump shoes +items.misc.jumpshoes.charge=Charge: %d / %d +items.misc.jumpshoes.ac_jump=JUMP +items.misc.jumpshoes.prompt=Choose one place to jump to +items.misc.jumpshoes.rest=You need rest +items.misc.jumpshoes.desc=Jumping action from other action games, used to skip all kinds of pits. The additional effects are different depending on the profession. + +items.misc.jumpw.name=jump shoes of warrior +items.misc.jumpw.ac_jump=JUMP +items.misc.jumpw.desc=Warrior can use charge to stun enemy he touch and close target quickly. + +items.misc.jumpp.name=jump shoes of performer +items.misc.jumpp.ac_jump=JUMP +items.misc.jumpp.desc=For become a idol, performer spend lots of time in training dance. It allowed he immerse in his own rhythm, and have little change reduce next damage he taken. + +items.misc.jumps.name=jump shoe of soldier +items.misc.jumps.ac_jump=JUMP +items.misc.jumps.desc=As a survivor from chaos war, soldier can reload when jumping, and have little chance to prepare for his next range attack. + +items.misc.jumpf.name=jump shoes of follower +items.misc.jumpf.ac_jump=JUMP +items.misc.jumpf.desc=In order to facilitate business between villages of different races and faiths, Follower can prepare a hidden place to redecorate themselves immediately. He also has a chance to find some special plants after landing. + +items.misc.attackshoes.name=plumber's shoes +items.misc.attackshoes.ac_jump=JUMP +items.misc.attackshoes.desc=This shoes don't need charge to use, but it spend more time on landing, and deal damage to nearby enemies. + +items.misc.shovel.name=shovel +items.misc.shovel.ac_use=BREAK WALL +items.misc.shovel.ac_build=BUILD WALL +items.misc.shovel.not_wall=There no wall around you. +items.misc.shovel.break=No charge now +items.misc.shovel.charge=charge: %d /%d +items.misc.shovel.desc=Shovel can used on break wall.\nIt will cost some charge. + +items.misc.bshovel.name=Vtuber's effect button +items.misc.bshovel.ac_use=USE +items.misc.bshovel.break=Need more chargr +items.misc.bshovel.charge=charge: %d /%d +items.misc.bshovel.desc=This button can remove nearby walls. It also will give random effect. + +items.misc.bshovel.mob=Accurate attack +items.misc.bshovel.haste=Fast move +items.misc.bshovel.item=Item search +items.misc.bshovel.gold=Gold fallen +items.misc.bshovel.heal=Health protect +items.misc.bshovel.mech=Mech around + +items.misc.potionofmage.name=wonder flask +items.misc.potionofmage.ac_use=USE +items.misc.potionofmage.ac_drink=DRINK +items.misc.potionofmage.ac_shattered=SHATTERED +items.misc.potionofmage.prompt=Choose a place to use it. +items.misc.potionofmage.break=There are nothing in flask now. +items.misc.potionofmage.not_mob=That is too far away. +items.misc.potionofmage.charge=Charge : %d / %d . +items.misc.potionofmage.desc=Use it on enemy or empty space. It will help you on battle. + +items.misc.gunofsoldier.name=pulse pistol +items.misc.gunofsoldier.ac_use=SHOOT +items.misc.gunofsoldier.prompt=Choose a location to target. +items.misc.gunofsoldier.not_mob=There are no enemy in there. +items.misc.gunofsoldier.break=Low power. +items.misc.gunofsoldier.not=You can't choose that target. +items.misc.gunofsoldier.charge=Charge: %d / %d +items.misc.gunofsoldier.desc=It will harm target based on how much damage it already taken. + +items.misc.mkbox.name=Mushroom kingdom's ? box +items.misc.mkbox.ac_use=HIT + +items.misc.mkbox.star=STAR +items.misc.mkbox.flowerf=Fire flower +items.misc.mkbox.floweri=Ice flower +items.misc.mkbox.mushroom=Mushroom +items.misc.mkbox.coin=50 coins +items.misc.mkbox.1up=1-up +items.misc.mkbox.hammer=Hammer +items.misc.mkbox.mbox=Trap + +items.misc.mkbox.need_gold=You need 100 gold to use it. +items.misc.mkbox.charge=%d +items.misc.mkbox.desc=A box with different stuff. It need 100 gold to use. + +items.misc.missileshield.name=Wooden shield +items.misc.missileshield.ac_cast=CAST +items.misc.missileshield.ac_shield=DEFENSE +items.misc.missileshield.rest=You need more charge to use this skill. +items.misc.missileshield.prompt=Choose target +items.misc.missileshield.not=You can't hit that target +items.misc.missileshield.not_mob=No target in there +items.misc.missileshield.desc=A simple wooden shield.\nCan be thrown.\nCan use to reduce damage. +items.misc.missileshield.damage=This shield can deal _ %d - %d damage _ ,and deal more damage on bosses. +items.misc.missileshield.charge=charge: %d / %d + +items.misc.attackshield.name=Ryu’s hadoken +items.misc.attackshield.ac_cast=DOWN RIGHT ATTACK +items.misc.attackshield.ac_blast=BREAK OUT +items.misc.attackshield.rest=Need more charge +items.misc.attackshield.prompt=Choose a place to use it. +items.misc.attackshield.not=You can't hit that target +items.misc.attackshield.not_mob=No target in there +items.misc.attackshield.desc=This is not a simple hadoken, it will deal more damage on full health enemy, and charge by melee attack. After use BREAK OUT, if you don't have melee weapon, you will have new power from fighter. +items.misc.attackshield.damage=This item can deal _ %d - %d damage _ . +items.misc.attackshield.charge=charge: %d / %d + +items.misc.copyball.name=Slime +items.misc.copyball.ac_use=CAST +items.misc.copyball.prompt=choose a target +items.misc.copyball.break=Need more charge. +items.misc.copyball.charge=Charge: %d/%d. +items.misc.copyball.desc=Slime can dominate or confusion enemy.\nIt may cause slow, said by system. + +items.misc.gnollmark.name=Shaman Mask +items.misc.gnollmark.ac_light=LIGHT RITE +items.misc.gnollmark.ac_dark=DARK RITE +items.misc.gnollmark.ac_earth=NATURAL RITE +items.misc.gnollmark.break=Need more charge. +items.misc.gnollmark.charge=Charge: %d/%d. +items.misc.gnollmark.desc=A shaman mask, charged by use wand.\nLight rite will improve user's physical power, but the magic power will be reduce. Dark rite is opposite.r\nNatural rite will improve user's resistance ability. + +items.misc.mechpocket.name=Four dimensional space bag +items.misc.mechpocket.ac_use=SEARCH +items.misc.mechpocket.desc=A future item, but only can use once. It will pour out every item it have.\nIt need to be sorted out. - Nobita + +items.misc.skillofatk.name=Learn how to attack +items.misc.skillofatk.ac_read=READ +items.misc.skillofatk.desc=A simple scroll which writen some attack skill in there. +items.misc.skillofatk.skillup=attack skill + + +items.misc.skillofdef.name=Learn how to dodge +items.misc.skillofdef.ac_read=READ +items.misc.skillofdef.desc=A simple scroll which writen some dodge skill in there. +items.misc.skillofdef.skillup=dodge skill + + +items.misc.skillofmig.name=Learn how to use magic +items.misc.skillofmig.ac_read=READ +items.misc.skillofmig.desc=A simple scroll which writen some magic skill in there. +items.misc.skillofmig.skillup=magic skill + + +items.misc.demoscroll.name=Demon contract +items.misc.demoscroll.ac_read=ACCEPT +items.misc.demoscroll.desc=Use your HT to make you stronger. \nEvery level you can use it once. +items.misc.demoscroll.hitup=Your ACU improve. +items.misc.demoscroll.evaup=Your DEX improve. +items.misc.demoscroll.migup=Your MIG improve. +items.misc.demoscroll.strup=Your STR imoprove. +items.misc.demoscroll.htdown=You lose some health limit. + +items.misc.undeadbook.name=Undead Bible +items.misc.undeadbook.ac_read=READ +items.misc.undeadbook.ac_bless=PARY +items.misc.undeadbook.desc=A Bible write with undead language... Why?\nRead this bible will reduce reader's health limit, and gain dew bless for some time.\nPary this bible will find an ankh, but only can pary once in one level. +items.misc.undeadbook.bless=You blessed by dew, but also lose some health limit. +items.misc.undeadbook.1up=Bible give your an ankh. + +items.misc.luckybadge.name=Lucky badge +items.misc.luckybadge.desc=A badge left by shop keeper. It is full with luck and It can be upgrade. + +items.misc.fourclover.name=Four-leaf Mint Necklace +items.misc.fourclover.desc=This four-leaf clover necklace can give wearer something when he level up, and increasing enchanted equipment's chances to be activated. + +items.misc.faithsign.name=Sign box +items.misc.faithsign.ac_demon=Faith-DEMON +items.misc.faithsign.ac_human=Faith-HOLY +items.misc.faithsign.ac_mech=Faith-MECH +items.misc.faithsign.ac_life=Faith-NATURAL +items.misc.faithsign.ac_balance=Faith-BALANCE +items.misc.faithsign.desc=A box full of different faith's signs. Based on 5 different types, those signs can be used on solve faith problem. + +items.misc.savagehelmet.name=Savage helmet +items.misc.savagehelmet.desc=A helmet for year hunting. It has chance to reduce damage and improve next melee attack. When be equip, this chance will become 100%. + +items.misc.healbag.name=Medical box +items.misc.healbag.ac_heal=MASS HEAL +items.misc.healbag.ac_cook=RANDOM COOKING +items.misc.healbag.needcharge=need charge +items.misc.healbag.desc=A medical box for year hunting. It can heal health, or cook a random potion, pill or food. + +items.misc.rangebag.name=Throwing weapon bag +items.misc.rangebag.ac_buy=BUY +items.misc.rangebag.need_gold=You need gold to buy throwing weapon. +items.misc.rangebag.desc=A bag for year hunting. It can find throwing weapon by use gold. When be equip, it has chance to find throwing weapon after kill mobs. + +items.misc.horsetotem.name=Horse Totem +items.misc.horsetotem.desc=A totem for year hunting. It has chance to improve damage and improve speed. When be equip, this chance will become 100%.\nIt called Red Hare. + +items.misc.dancelion.name=Learn lion dance +items.misc.dancelion.ac_spin=SPIN +items.misc.dancelion.ac_stand=STAND +items.misc.dancelion.ac_back=BACK +items.misc.dancelion.ac_rush=DASH +items.misc.dancelion.ac_jump=JUMP +items.misc.dancelion.desc=A book for year hunting. Reader can learn lion dance on it. + +items.playericon.name=player icon +items.playericon.thank4play=Thanks for playing. +items.playericon.desc=Reword of bossrush. +items.weapon.melee.special.testweapon.name=test weapon +items.weapon.melee.special.testweapon.desc=test weapon + +items.elevator.name=ghost elevator +items.elevator.desc=A ghost is attached to this suit, which can bring you up and down the floor freely.\nBut it only can work on floor 2 - 25. +items.elevator.ac_up=UP +items.elevator.ac_down=DOWN + +items.soulcollect.name=soul collect stone +items.soulcollect.desc=Otiluke is been trapped in here. Break it and save his life. +items.soulcollect.ac_break=BREAK +items.soulcollect.win=Thank you for your help. See you in town. + +items.pocketballfull.name=Lantern with some soul +items.pocketballfull.desc=A soul is lives in here. You can use it or sell it. +items.pocketballfull.ac_use=USE + +items.powerhand.name=Power Hand +items.powerhand.desc=?????????? +items.powerhand.desc_stones=%dstones have now. +items.powerhand.prompt=Choose a stone +items.powerhand.ac_add=ADD STONE +items.powerhand.ac_use=USE +items.powerhand.nothing=Nothing happen +items.powerhand.already_fed=This stone type is already on there. +items.powerhand.absorb_stone=You add this stone in this hand. + +items.saveyourlife.name=Emergency Offline Device +items.saveyourlife.desc=Emergency Offline Device +items.saveyourlife.ac_save=OFFLINE + +items.transmutationball.name=Transmutation item +items.transmutationball.prompt=choose a target +items.transmutationball.desc=Transmutation a item +items.transmutationball.ac_use=USE + +items.upgradeeatball.name=Upgrade eater +items.upgradeeatball.prompt=choose a target +items.upgradeeatball.desc=Upgrade eater +items.upgradeeatball.ac_use=USE + +items.flag.name=Flag +items.flag.desc=The 70th Anniversary of the Founding of The People's Republic of China. + + diff --git a/resources/com/hmdzl/spspd/messages/items/items_zh.properties b/resources/com/hmdzl/spspd/messages/items/items_zh.properties new file mode 100644 index 00000000..e5395388 --- /dev/null +++ b/resources/com/hmdzl/spspd/messages/items/items_zh.properties @@ -0,0 +1,2310 @@ + ###glyphs +items.armor.glyphs.iceglyph.name=雪屋%s +items.armor.glyphs.iceglyph.desc=雪屋刻印可以增加使用者的冰冻抗性,并有几率在冰冻敌人的同时延缓使用者所受到的物理伤害。 +items.armor.glyphs.iceglyph.deferred=延缓%d点伤害 +items.armor.glyphs.iceglyph$defereddamage.name=延缓伤害 +items.armor.glyphs.iceglyph$defereddamage.ondeath=被延迟的伤害还是杀掉了你…… +items.armor.glyphs.iceglyph$defereddamage.desc=虽然你的护甲符文保护你免受损伤,但它似乎在让你慢慢偿还代价。\n\n损伤会被转化为持续伤害,而非直接扣除。你将每回合受到1点伤害直到伤害被全额返还。 \n\n剩余的延迟伤害:%d点 + +items.armor.glyphs.fireglyph.name=火罩%s +items.armor.glyphs.fireglyph.desc=火罩刻印可以增加使用者的火焰抗性,并有几率在点燃敌人的同时提升使用者的攻击力。 + +items.armor.glyphs.earthglyph.name=残岩%s +items.armor.glyphs.earthglyph.desc=残岩刻印可以增加使用者的地面抗性,并有几率在眩晕敌人的同时提升使用者的防御力。 + +items.armor.glyphs.electricityglyph.name=电网%s +items.armor.glyphs.electricityglyph.desc=电网刻印可以增加使用者的雷电抗性,并有几率在电击敌人的同时提升使用者的充能效率。 + +items.armor.glyphs.lightglyph.name=神圣%s +items.armor.glyphs.lightglyph.desc=神圣刻印可以增加使用者的光照抗性,并有几率在魅惑敌人的同时将其狂乱。 + +items.armor.glyphs.darkglyph.name=暗契%s +items.armor.glyphs.darkglyph.desc=暗契刻印可以增加使用者的黑暗抗性,并有几率在对敌人造成伤害的同时恢复使用者的生命。 + +items.armor.glyphs.revivalglyph.name=复生%s +items.armor.glyphs.revivalglyph.revival=护甲的附魔为你抵挡了致命伤害。 +items.armor.glyphs.revivalglyph.desc=复生刻印有几率为使用者抵挡致命的物理攻击,并恢复使用者大量的生命。 + +items.armor.glyphs.changeglyph.name=变幻%s +items.armor.glyphs.changeglyph.desc=变幻刻印有几率为使用者创造一个镜像,并使使用者远离危险。 + +items.armor.glyphs.crystalglyph.name=晶化%s +items.armor.glyphs.crystalglyph.desc=晶化刻印有几率为使用者提供玻璃保护效果。 + +items.armor.glyphs.testglyph.name=试验%s +items.armor.glyphs.testglyph.desc=试验刻印有几率为使用者创造一个对敌人危险的气体。 + +items.armor.glyphs.adaptglyph.name=适应%s +items.armor.glyphs.adaptglyph.desc=适应刻印有几率根据使用者当前所在的环境给与不同的增益效果。 + +items.armor.glyphs.recoilglyph.name=反冲%s +items.armor.glyphs.recoilglyph.desc=反冲刻印有几率击退攻击者,并对其造成流血效果。 + +###armor +items.armor.normalarmor.normalarmor.stats_known=这件_%1$d阶_防具可以抵挡_%2$d~%3$d点伤害_,并且需要_%4$d点力量_来正常装备。 +items.armor.normalarmor.normalarmor.stats_known2=这件防具的闪避为_%1$s_,潜行为_%2$s_,能量计数为_%3$d_。 +items.armor.normalarmor.normalarmor.stats_unknown=一般而言这件_%1$d阶_防具可以抵挡_%2$d~%3$d点伤害_,并且需要_%4$d点力量_来正常装备。 +items.armor.normalarmor.normalarmor.too_heavy=你的力量不足以完美使用它。 +items.armor.normalarmor.normalarmor.incompatible=不同属性的魔法相冲突,消除了防具上的附魔! +items.armor.normalarmor.normalarmor.cursed_worn=由于这件防具被诅咒,你无法将其卸下。 +items.armor.normalarmor.normalarmor.cursed=你能感觉到这件武器里潜伏着一股充满恶意的魔力。 +items.armor.normalarmor.normalarmor.inscribed=这件防具已经有刻印了,%s +items.armor.normalarmor.normalarmor.stats_desc= + +items.armor.armor$glyph.glyph=刻印 + +items.skills.classskill.charge=冷却:%d。 +items.skills.classskill.name=职业技能 + +items.skills.mageskill.name=法师长袍 +items.skills.mageskill.ac_special=熔岩之怒 +items.skills.mageskill.ac_special_two=奥术轰炸 +items.skills.mageskill.prompt2=选择施放的地点。 +items.skills.mageskill.ac_special_three=暴风雪 +items.skills.mageskill.ac_special_four=引雷 +items.skills.mageskill.desc=法师技能 \n熔岩之怒:缠绕并腐蚀所有范围内的敌人。\n\n奥术轰炸:利用轰击一处地点并造成伤害。\n\n暴风雪:伤害并冻结所有范围内的敌人。\n\n引雷:获得充能,并静电周围的单位。 + +items.skills.huntressskill.name=猎手披风 +items.skills.huntressskill.ac_special=猎手本能 +items.skills.huntressskill.ac_special_two=狩猎准备 +items.skills.huntressskill.ac_special_three=自然之助 +items.skills.huntressskill.ac_special_four=活体根须 +items.skills.huntressskill.no_space=没有召唤物所能待的地方。 +items.skills.huntressskill.desc=女猎手技能 \n猎手本能:获得自然系增益。\n\n狩猎准备:投掷武器增益,并破甲目标。\n\n自然之助:吸引一只生命精灵。\n\n活体根须:寄生敌人,或召唤树苗。 + +items.skills.rogueskill.name=盗贼风衣 +items.skills.rogueskill.ac_special=暗影祝福 +items.skills.rogueskill.ac_special_two=探云手 +items.skills.rogueskill.ac_special_three=无需遗言 +items.skills.rogueskill.ac_special_four=信仰之跃 +items.skills.rogueskill.desc=盗贼技能 \n暗影祝福:隐身,获得伤害系增益 \n\n探云手:我,盗贼,打钱。\n\n无需遗言:沉默一个单位,直至它死亡。\n\n信仰之跃:在障碍物旁蓄力,并造成惊人的伤害。 + +items.skills.warriorskill.name=战士重甲 +items.skills.warriorskill.ac_special=原始力量 +items.skills.warriorskill.ac_special_two=决斗 +items.skills.warriorskill.ac_special_three=圣盾术 +items.skills.warriorskill.ac_special_four=奇袭战术 +items.skills.warriorskill.desc=战士技能 \n原始力量:B-K-B。\n\n决斗:伤害减免,缴械并沉默其他非决斗目标。\n\n圣盾术:抵挡伤害,并伤害其他单位。\n\n奇袭战术:对满血的单位和残血的单位的攻击造成额外的伤害。 + +items.skills.performerskill.name=演员夹克 +items.skills.performerskill.prompt=选择要变换的道具 +items.skills.performerskill.ac_special=奇异舞步 +items.skills.performerskill.ac_special_two=谢幕礼花 +items.skills.performerskill.ac_special_three=魔术手法 +items.skills.performerskill.ac_special_four=粉丝狂热 +items.skills.performerskill.desc=演员技能 \n奇异舞步:狂乱视野范围内所有敌人。\n\n谢幕礼花:致盲视野范围内所有敌人。\n\n魔术手法:转换一样装备。\n\n粉丝狂热:召唤一个狂热的粉丝为你打call。 + +items.skills.soldierskill.name=星兵背心 +items.skills.soldierskill.ac_special=幻影之军 +items.skills.soldierskill.ac_special_two=召唤机甲 +items.skills.soldierskill.ac_special_three=自爆假人 +items.skills.soldierskill.ac_special_four=空投补给 +items.skills.soldierskill$seekingbomb.name=砰砰机器人 +items.skills.soldierskill$seekingbomb.desc=警告:该机器人随时可能爆炸。 +items.skills.soldierskill$seekinghugebomb.name=砰砰砰砰机器人 +items.skills.soldierskill$seekinghugebomb.desc=警告:该机器人随时可能爆爆爆爆炸。 +items.skills.soldierskill.desc=星兵技能 \n幻影之军:生成多个幻想,弱驱散。\n\n召唤机甲:召唤并乘坐一个机甲。\n\n自爆假人:召唤多个会自爆的机器人。\n\n空投补给:提供食物和其他道具。 + +items.skills.followerskill.name=信徒外套 +items.skills.followerskill.ac_special=祈祷 +items.skills.followerskill.ac_special_two=资金募集 +items.skills.followerskill.ac_special_three=巧嘴滑舌 +items.skills.followerskill.ac_special_four=祝福术 +items.skills.followerskill.desc=信徒技能 \n祈祷:蓄力,获得伤害加成和伤害减免。\n\n资金募集:根据视野中单位的数量获得金币。\n\n巧嘴滑舌:恐惧敌人,并使你跑得飞快。\n\n祝福术:强化并驱散一件装备。 + +items.armor.normalarmor.clotharmor.name=布甲 +items.armor.normalarmor.clotharmor.desc=这件轻便的护甲能提供最基本的防御。\n常规护甲 + +items.armor.normalarmor.leatherarmor.name=皮甲 +items.armor.normalarmor.leatherarmor.desc=用鞣制的兽皮制成的护甲。没有布甲轻,但提供更好的防御。\n常规护甲 + +items.armor.normalarmor.mailarmor.name=链甲 +items.armor.normalarmor.mailarmor.desc=由金属链环环相扣制成的一套结实又不失灵活的护甲。\n常规护甲 +items.armor.normalarmor.platearmor.name=板甲 +items.armor.normalarmor.platearmor.desc=厚重的金属板拼接到一起,为能承受其骇人重量的冒险者提供无与伦比的防御。\n常规护甲 + +items.armor.normalarmor.scalearmor.name=鳞甲 +items.armor.normalarmor.scalearmor.desc=在厚实的皮背心中缝入金属鳞片,形成了灵活而高防御的护甲。\n常规护甲 + +items.armor.normalarmor.discarmor.name=碟甲 +items.armor.normalarmor.discarmor.desc=这种盔甲只是将金属片缝在布料上(它因此而得名)。它虽然耐用,但有着很大的体积。\n常规护甲 + +items.armor.normalarmor.errorarmor.name=错误护甲 +items.armor.normalarmor.errorarmor.desc=这是个错误。\n ??? + +items.armor.normalarmor.basearmor.name=基础护甲 +items.armor.normalarmor.basearmor.desc=这并不是一件护甲,但是为了美观,这件物品被装备在该角色身上。\n 非护甲 + +items.armor.normalarmor.lifearmor.name=活性护甲 +items.armor.normalarmor.lifearmor.desc=一株活着的植物,会根据受到的伤害调整它的厚度。当处于安全状态时,它会将多余的部分转换为营养物质。\n 特殊护甲 + +items.armor.normalarmor.woodenarmor.name=木甲 +items.armor.normalarmor.woodenarmor.desc=精选上等白桦树皮所制,坚固耐用,但及不舒适。\n重型护甲 + +items.armor.normalarmor.ceramicsarmor.name=陶甲 +items.armor.normalarmor.ceramicsarmor.desc=粘土火中烧,结实又可靠。\n重型护甲 + +items.armor.normalarmor.stonearmor.name=石甲 +items.armor.normalarmor.stonearmor.desc=利用大地的魔法制作而成的护甲,坚硬而沉重。\n重型护甲 + +items.armor.normalarmor.multiplelayerarmor.name=复层甲 +items.armor.normalarmor.multiplelayerarmor.desc=这种护甲有内外两层,以敏捷为代价换取防御。\n重型护甲 + +items.armor.normalarmor.bulletarmor.name=防弹衣 +items.armor.normalarmor.bulletarmor.desc=基本上就是常规的防弹衣。\n重型护甲 + +items.armor.normalarmor.machinearmor.name=机械甲 +items.armor.normalarmor.machinearmor.desc=常规的板甲配备核心电源,外设四只机械臂,就是会发出巨大噪音。\n重型护甲 + +items.armor.normalarmor.vestarmor.name=背心 +items.armor.normalarmor.vestarmor.desc=一件工厂生产的普通商品,虽然没法抵御伤害,但是十分适合运动。\n轻型护甲 + +items.armor.normalarmor.rubberarmor.name=橡胶衣 +items.armor.normalarmor.rubberarmor.desc=一种可以紧贴全身的服装,一般用于cosplay。\n轻型护甲 + +items.armor.normalarmor.cdarmor.name=光碟甲 +items.armor.normalarmor.cdarmor.desc=一堆废弃光盘串成的护甲。很明显这是某个环保比赛的优秀作品。\n轻型护甲 + +items.armor.normalarmor.styrofoamarmor.name=塑料泡沫甲 +items.armor.normalarmor.styrofoamarmor.desc=用塑料泡沫充当护甲,这能小幅减轻外来的冲击。\n轻型护甲 + +items.armor.normalarmor.protectiveclothingarmor.name=防护服 +items.armor.normalarmor.protectiveclothingarmor.desc=部分有毒有害工厂工人必须穿着的工装,可以有效将有毒有害的环境与自身隔离。\n轻型护甲 + +items.armor.normalarmor.phantomarmor.name=幻影护甲 +items.armor.normalarmor.phantomarmor.desc=先进高科技,外衣上装载着迷你投影仪,可以有效迷惑有眼睛的敌人。\n轻型护甲 + +###artifacts +items.artifacts.alchemiststoolkit.name=炼金工具箱 +items.artifacts.alchemiststoolkit.ac_brew=组合 +items.artifacts.alchemiststoolkit.ac_create=造物 +items.artifacts.alchemiststoolkit.prompt=选择置入的药水 +items.artifacts.alchemiststoolkit.waste=你加入的药水不完全对。 +items.artifacts.alchemiststoolkit.prefect=完美的组合,这正是这个箱子所需要的。 +items.artifacts.alchemiststoolkit.bestbrew=这次组合比之前好。 +items.artifacts.alchemiststoolkit.bdorder=瓶药剂反应成功, +items.artifacts.alchemiststoolkit.right=瓶药剂反应得很正确。 +items.artifacts.alchemiststoolkit.desc=这个工具箱是由一位伟大的炼金术士所制作的。它用于减少炼金的材料消耗,以及提升锅子的容量。你移动时,这个工具包里面的各种工具互相碰撞,在发出轻微的叮当声。 +items.artifacts.alchemiststoolkit.desc_cursed=这个工具箱被诅咒了,极大增加了你合成药水所需的材料。 +items.artifacts.alchemiststoolkit.level_zero=看起来这个工具箱还需要一种混合试剂。你需要找到3瓶不同的药剂并将它们按照正确的顺序来排列,从而合成这种试剂。 +items.artifacts.alchemiststoolkit.level_ten=完美的组合使工具箱的效果已经达到最大。 +items.artifacts.alchemiststoolkit.make_from=目前为止你最好的测试结果是 +items.artifacts.alchemiststoolkit.addpotion=你将药水倒入工具箱中。 +items.artifacts.alchemiststoolkit.have_add=这种药水已经被倒入工具箱中了。 +items.artifacts.alchemiststoolkit.know_first=你需要先鉴定这瓶药水。 + +items.artifacts.alienbag.name=异星肩包 +items.artifacts.alienbag.ac_shield=护盾模式 +items.artifacts.alienbag.ac_bomb=爆破模式 +items.artifacts.alienbag.ac_fly=飞行模式 +items.artifacts.alienbag.ac_etc=隐藏模式 +items.artifacts.alienbag.desc=一个由异星科技所制作出的背包。包含各种功能,并通过吸收残骸来升级。 +items.artifacts.alienbag.no_charge=充能不足 +items.artifacts.alienbag.full_charge=充能完毕 +items.artifacts.alienbag$bagrecharge.levelup=你的肩包升级了。 + +items.artifacts.artifact.onlythree=最多同时装备三件饰品。 +items.artifacts.artifact.unequip_title=拿下一件饰品 +items.artifacts.artifact.unequip_message=你只能同时装备最多两件饰品。 +items.artifacts.artifact.cannot_wear_two=你不能装备两件相同的神器。 +items.artifacts.artifact.cursed_worn=神器紧紧地将其捆绑在你身上。 +items.artifacts.artifact.curse_known=你能感觉到在这个神器上潜伏着一股充满恶意的魔力。 +items.artifacts.artifact.need_to_equip=你需要装备神器才能进行该操作。 +items.artifacts.artifact.need_to_change=这件神器已经失去了它原有的效果。 + +items.artifacts.capeofthorns.name=荆棘斗篷 +items.artifacts.capeofthorns.ac_needling=激发 +items.artifacts.capeofthorns.desc=矮人实验室里的研究反射魔法的副产物之一,这件由奇怪的金属片构成的坚硬斗篷能够从敌人的攻击中摄取能量,并将其反馈给攻击者。 +items.artifacts.capeofthorns.desc_inactive=斗篷压在你的肩上的感觉非常沉重,它似乎能从你受的伤里获得能量。 +items.artifacts.capeofthorns.desc_active=斗篷似乎在释放其存储的能量,并将其辐射出一种防护力场。 +items.artifacts.capeofthorns$thorns.inert=你的斗篷再次失效了。 +items.artifacts.capeofthorns$thorns.radiating=你的斗篷正在释放存储的能量,你感到自己正在被保护着! +items.artifacts.capeofthorns$thorns.levelup=你的斗篷变得更强大了! +items.artifacts.capeofthorns$thorns.name=荆棘 +items.artifacts.capeofthorns$thorns.desc=你的斗篷在你周围辐射能量,产生了一个偏斜力场! \n\n该效果下你受到的所有伤害都会被减少。此外,如果攻击者就在你旁边,被减少的伤害会反弹给攻击者。\n\n荆棘效果持续时间:%s回合 + +items.artifacts.chaliceofblood.name=蓄血圣杯 +items.artifacts.chaliceofblood.ac_prick=血祭 +items.artifacts.chaliceofblood.ac_bloodangry=血怒 +items.artifacts.chaliceofblood.yes=是的,我知道我在做什么 +items.artifacts.chaliceofblood.no=不,我改主意了 +items.artifacts.chaliceofblood.prick_warn=每次使用圣杯都会消耗更多的生命能量,要是不够小心,这种行为可以轻易地杀死你。\n\n你确定要给它更多的生命能量吗? +items.artifacts.chaliceofblood.onprick=你刺破了自己的手指,使你的生命精华流入了圣杯。 +items.artifacts.chaliceofblood.ondeath=圣杯将你的生命精华吸噬殆尽了… +items.artifacts.chaliceofblood.desc=这个闪闪发光的银质酒杯在边沿突兀地装饰着几颗造型尖锐的宝石。 +items.artifacts.chaliceofblood.desc_cursed=被诅咒的圣杯将自己固定在你手上,抑制着你回复生命的能力。 +items.artifacts.chaliceofblood.desc_1=握住圣杯的那一刻,你涌起一股想在那些尖锐宝石上刺伤自己的奇特冲动。 +items.artifacts.chaliceofblood.desc_2=你的一些血液汇集到圣杯里,你可以隐约感受到杯子在为你送来生命能量。你还想用圣杯继续割伤自己,即便你知道那很疼。 +items.artifacts.chaliceofblood.desc_3=圣杯已经被你的生命精华填满。你可以感觉到圣杯正将生命能量倾泻般回馈给你。 + +items.artifacts.cloakofshadows.name=暗影斗篷 +items.artifacts.cloakofshadows.ac_stealth=潜行 +items.artifacts.cloakofshadows.ac_shadow=永影 +items.artifacts.cloakofshadows.cooldown=你的披风还需要%d回合来重新激活。 +items.artifacts.cloakofshadows.no_charge=你的斗篷充能不足无法使用。 +items.artifacts.cloakofshadows.desc=这是盗贼多年前从皇家军械库窃取的一件无价的魔法披风。穿上时,能够使你在短时间内完全隐身。\n\n被使用得越频繁,披风就会变得越强,使盗贼更频繁地隐身,持续时间也更长。 +items.artifacts.cloakofshadows$cloakstealth.no_charge=你的披风耗尽了能量。 +items.artifacts.cloakofshadows$cloakstealth.levelup=你的披风变得更强大了! +items.artifacts.cloakofshadows$cloakstealth.name=披风之下 +items.artifacts.cloakofshadows$cloakstealth.desc=你身上的暗影披风正给予你隐形效果。\n\n当你在隐形时敌人无法追踪或攻击你。大部分物理攻击和魔法(比如卷轴和法杖)会不可避免地消除隐形效果。\n\n你会一直拥有该状态,直到你自行取消或披风耗尽能量。 + +items.artifacts.driedrose.name=干枯玫瑰 +items.artifacts.driedrose.ac_summon=召唤 +items.artifacts.driedrose.ac_outfit=军备 +items.artifacts.driedrose.ac_soulbless=超度 +items.artifacts.driedrose.spawned=你已经召唤出幽灵了。 +items.artifacts.driedrose.no_charge=你的玫瑰尚未充能完毕。 +items.artifacts.driedrose.cursed=你不能使用受诅咒的玫瑰。 +items.artifacts.driedrose.no_space=你附近没有可用于召唤的空地。 +items.artifacts.driedrose.charged=你的玫瑰已经充能完毕! +items.artifacts.driedrose.desc=这就是那朵在幽灵消失前被提及的玫瑰吗?它似乎拥有某种精神力量,也许能以此为媒介触及这位陨落战士的能量。 +items.artifacts.driedrose.desc_no_quest=一株因岁月而干枯但仍然没有完全凋零的玫瑰。\n\n看起来它上面依然残留了一些力量,只是你不知道如何使用它。 +items.artifacts.driedrose.desc_hint=它似乎缺少了一些花瓣。也许把花瓣拼回来可以增强玫瑰。 +items.artifacts.driedrose.desc_cursed=受诅咒的玫瑰将自己绑在了你的手上,你感觉到它出奇的冷。 +items.artifacts.driedrose$petal.name=干枯的花瓣 +items.artifacts.driedrose$petal.no_rose=你没有玫瑰来添加这片花瓣。 +items.artifacts.driedrose$petal.no_room=你的玫瑰已经放不下这片花瓣了,所以你无视了它。 +items.artifacts.driedrose$petal.maxlevel=玫瑰再一次完整了! +items.artifacts.driedrose$petal.levelup=你将花瓣放在了玫瑰上。 +items.artifacts.driedrose$petal.desc=一片干枯脆弱的花瓣,它居然能够在这么深的地牢之中幸存下来。 +items.artifacts.driedrose$ghosthero.name=悲伤幽灵 +items.artifacts.driedrose$sghosthero.name=暴躁幽灵 +items.artifacts.driedrose$ghosthero.def_verb=躲避 +items.artifacts.driedrose$ghosthero.hello=再次向你问好,%s。 +items.artifacts.driedrose$ghosthero.introduce=我的灵魂与这朵玫瑰相连,对我来说它非常珍贵,是我爱人在我离开地面前送给我的礼物。\n\n我无法回去见他了,但感谢你让我有第二次机会来完成我的旅程。当我准备好后,我会回应你的呼唤与你并肩作战。\n\n希望你能在我倒下的地方继续走下去…… +items.artifacts.driedrose$sghosthero.desc=强化后的悲伤幽灵,速度更快,并会在死亡时复活。 +items.artifacts.driedrose$ghosthero.desc=这是一个拥有人类外形的脆弱幻影。它的力量似乎与我手上的玫瑰联系在了一起。\n\n这个幽灵可能无法逗留太久,但它应该是我在这里唯一的挚友了。 +items.artifacts.driedrose$wndghosthero.title=幽灵的装备 +items.artifacts.driedrose$wndghosthero.desc=幽灵本身十分脆弱,但她的形体已经完整到足以装备一件武器和防具。她可以和你一样自如使用这些装备。\n\n幽灵目前可装备_力量需求上限低于%d_的物品。 +items.artifacts.driedrose$wndghosthero.weapon_prompt=选择一件武器 +items.artifacts.driedrose$wndghosthero.armor_prompt=选择一件护甲 +items.artifacts.driedrose$wndghosthero.cant_unique=幽灵无法使用特殊装备。 +items.artifacts.driedrose$wndghosthero.cant_unidentified=你对于那个道具并不是十分了解。 +items.artifacts.driedrose$wndghosthero.cant_cursed=你不能让幽灵使用有诅咒的物品。 +items.artifacts.driedrose$wndghosthero.cant_strength=幽灵的形体还不够强大,无法装备此物品。 + +items.artifacts.etherealchains.name=虚空锁链 +items.artifacts.etherealchains.ac_cast=施放 +items.artifacts.etherealchains.ac_locked=封印 +items.artifacts.etherealchains.no_charge=你的锁链充能不足。 +items.artifacts.etherealchains.cursed=你不能使用受诅咒的锁链。 +items.artifacts.etherealchains.does_nothing=这样并没有用。 +items.artifacts.etherealchains.cant_pull=你的锁链不能拉动那个目标。 +items.artifacts.etherealchains.nothing_to_grab=目标区域没有可供抓取的物件。 +items.artifacts.etherealchains.prompt=选择要瞄准的地方 +items.artifacts.etherealchains.desc=这些巨大但轻盈的锁链散发着灵魂能量。它们可以用来把你拉向一些地形,或将敌人拉向你。无实体的天然特质甚至可以允许其穿透墙壁! +items.artifacts.etherealchains.desc_cursed=被诅咒的锁链将自己锁在了你的身边,不断地在周围晃动,试图绊倒或绑住你。 +items.artifacts.etherealchains.desc_equipped=锁链围绕在你的身边,缓慢地收集被你击败者的精神能量。每一发充能都是锁链中的一环,每一个环节都能正好延长一格。 +items.artifacts.etherealchains$chainsrecharge.levelup=你的锁链变得更强大了! + +items.artifacts.hornofplenty.name=丰饶之角 +items.artifacts.hornofplenty.ac_eat=食用 +items.artifacts.hornofplenty.ac_store=贮存 +items.artifacts.hornofplenty.ac_feed=盛宴 +items.artifacts.hornofplenty.eat=你吃光了号角中的食物。 +items.artifacts.hornofplenty.prompt=选择一个食物 +items.artifacts.hornofplenty.no_food=你的号角里没有食物可供食用! +items.artifacts.hornofplenty.full=你的号角装满了食物! +items.artifacts.hornofplenty.reject=你的号角并不接受未经烹煮的无味果。 +items.artifacts.hornofplenty.maxlevel=你的号角已经吞噬了尽可能多的食物! +items.artifacts.hornofplenty.levelup=号角吞噬了你提供的食物,变得更加强大了。 +items.artifacts.hornofplenty.desc=这个号角不能被用来吹奏,不过装备时它似乎会随时间流逝逐渐填充食物。 +items.artifacts.hornofplenty.desc_hint=也许可以通过给予它食物的能量来增加号角的力量。 +items.artifacts.hornofplenty.desc_cursed=被诅咒的号角把自己绑在了你的身边,它似乎在渴望得到食物而不是制造食物。 + +items.artifacts.masterthievesarmband.name=会员袖章 +items.artifacts.masterthievesarmband.ac_goldtouch=点金 +items.artifacts.masterthievesarmband.desc=这个紫色的天鹅绒袖标是大会员的标志。不知道是谁把他丢在这的。 +items.artifacts.masterthievesarmband.desc_worn=让它戴在你的手腕上,你找到的每块金币都让商店为你减价。大会员你懂的。 + +items.artifacts.pylon.name=便携式水晶塔 +items.artifacts.pylon.ac_zap=释放 +items.artifacts.pylon.ac_set=设置 +items.artifacts.pylon.ac_return=返回 +items.artifacts.pylon.ac_rankup=升阶 +items.artifacts.pylon.no_charge=你的水晶塔现在并没有足够的能量支撑发射传送魔法。 +items.artifacts.pylon.tele_fail=传送魔法失败了。 +items.artifacts.pylon.prompt=选择要释放魔法的位置 +items.artifacts.pylon.levelup=你的水晶变得更强大了! +items.artifacts.pylon.rankup=晋升!!! +items.artifacts.pylon.preventing=这里强大的魔力流使你无法使用时空道标! +items.artifacts.pylon.creatures=邻近生物的心灵信号正在干扰你的时空道标并使其无法被使用。 +items.artifacts.pylon.return=水晶被成功设置在了你的当前位置,现在你可以随时折跃到这里。 +items.artifacts.pylon.desc=水晶塔是一个具有控制空间能力的复杂建筑。该水晶塔可以用来折跃至预定地点,但其在装备时的能量也可以用来对指定目标发射随机传送魔法。这个魔法可以针对某个目标或使用者自身。 +items.artifacts.pylon.desc_set=水晶被设置在了像素地牢第%d层的某处。 + + +items.artifacts.sandalsofnature.name=自然之履 +items.artifacts.sandalsofnature.name_1=自然之鞋 +items.artifacts.sandalsofnature.name_2=自然之靴 +items.artifacts.sandalsofnature.name_3=自然护腿 +items.artifacts.sandalsofnature.ac_feed=喂食 +items.artifacts.sandalsofnature.ac_root=扎根 +items.artifacts.sandalsofnature.ac_sprout=发芽 +items.artifacts.sandalsofnature.no_charge=它们现在还没有能量。 +items.artifacts.sandalsofnature.prompt=选择一个种子 +items.artifacts.sandalsofnature.already_fed=你的鞋子已经从这种种子里中获取过营养了。 +items.artifacts.sandalsofnature.levelup=你的鞋子尺寸变大了! +items.artifacts.sandalsofnature.absorb_seed=鞋子吸收了种子,看起来更健康了。 +items.artifacts.sandalsofnature.desc_1=初看像是用麻绳编成的凉鞋实际上是两株植物!它们看上去既虚弱又苍白,也许它们需要一点营养? +items.artifacts.sandalsofnature.desc_2=这双鞋子已经长大了,现在更像是一双合脚的鞋。它们已经没那么苍白了,也许还可以进一步成长? +items.artifacts.sandalsofnature.desc_3=这两株植物又长大了。像是一双树皮制成的厚靴子。植物似乎已经恢复了它们的力量,但也许仍能进一步成长? +items.artifacts.sandalsofnature.desc_4=植物们似乎已长到最大,就像是一对装甲护胫。这对深棕色护腿看上去仿如一棵非常坚毅的树。 +items.artifacts.sandalsofnature.desc_hint=穿上这件神器时你感到更加亲近自然了。 +items.artifacts.sandalsofnature.desc_cursed=被诅咒的鞋子切断了一切你与自然的联系。 +items.artifacts.sandalsofnature.desc_ability=这双鞋已经获得了形成一种固定的天然装甲的能力,但它们需要充能。 +items.artifacts.sandalsofnature.desc_seeds=你已经给鞋子喂过了%d种种子。 + +items.artifacts.talismanofforesight.name=先见护符 +items.artifacts.talismanofforesight.ac_scry=探查 +items.artifacts.talismanofforesight.ac_notice=预知 +items.artifacts.talismanofforesight.no_charge=你的护符尚未被完全充能。 +items.artifacts.talismanofforesight.scry=护符将关于本层的知识填满了你的脑海。 +items.artifacts.talismanofforesight.desc=一块奇怪的有着光滑雕刻的石头。你觉得它在关注着你周围的一切,留意任何不寻常的东西。 +items.artifacts.talismanofforesight.desc_worn=当你拿着护符时你感觉你的感知力提高了。 +items.artifacts.talismanofforesight.desc_cursed=被诅咒的护符目不转睛地瞪着你,使你无法集中精力。 +items.artifacts.talismanofforesight$foresight.name=先见 +items.artifacts.talismanofforesight$foresight.levelup=你的护符变得更强大了!你似乎预见到了某些危险。 +items.artifacts.talismanofforesight$foresight.full_charge=你的护符充能满了! +items.artifacts.talismanofforesight$foresight.uneasy=你感到很不安。 +items.artifacts.talismanofforesight$foresight.desc=你感到非常焦虑,仿佛周遭有未被发现的危险。 + +items.artifacts.timekeepershourglass.name=时光沙漏 +items.artifacts.timekeepershourglass.ac_activate=激活 +items.artifacts.timekeepershourglass.ac_restart=重置 +items.artifacts.timekeepershourglass.in_use=你的沙漏正在使用中。 +items.artifacts.timekeepershourglass.no_charge=你的沙漏充能还不足以用来激活。 +items.artifacts.timekeepershourglass.cursed=你不能使用受诅咒的沙漏。 +items.artifacts.timekeepershourglass.onstasis=你周遭的世界似乎就在这一瞬间变化了。 +items.artifacts.timekeepershourglass.onfreeze=你周围的一切突然都彻底静止下来。 +items.artifacts.timekeepershourglass.stasis=使我彻底静止 +items.artifacts.timekeepershourglass.freeze=冻结周围时间 +items.artifacts.timekeepershourglass.prompt=你想怎样使用沙漏的魔法?\n\n当你被静止,周围的时间会正常流动,而你则会冻结并变得无敌。\n\n当时间被冻结,你的行动仿佛不需要任何时间。注意,进行攻击将打破该效果。 +items.artifacts.timekeepershourglass.desc=这只大型的华贵沙漏看起来却并不怎么起眼,但你仍觉得它精雕细刻的框架内蕴含着某种强大的力量。在翻转沙漏、在看着沙子流下的同时,你能感受到一种魔法正在拉扯着你,使用这种魔法肯定能给你一些控制时间的方法。 +items.artifacts.timekeepershourglass.desc_hint=沙漏似乎失去了一些沙子,如果你能再找到一些…… +items.artifacts.timekeepershourglass.desc_cursed=被诅咒的沙漏把它自己锁在了你的身边,你可以感觉它试图操纵你的时间流动。 +items.artifacts.timekeepershourglass$sandbag.name=一包魔力流沙 +items.artifacts.timekeepershourglass$sandbag.levelup=你将沙子填入到你的沙漏中。 +items.artifacts.timekeepershourglass$sandbag.maxlevel=你的沙漏填满了魔法沙子! +items.artifacts.timekeepershourglass$sandbag.no_hourglass=你没有沙漏来存放这些沙子。 +items.artifacts.timekeepershourglass$sandbag.desc=这一小袋细砂应该能够在你的沙漏上完美使用。\n\n每次当你需要这种东西时,店主都会摆出来一些,看起来很奇怪…… + +items.artifacts.unstablespellbook.name=无序魔典 +items.artifacts.unstablespellbook.ac_read=阅读 +items.artifacts.unstablespellbook.ac_add=加入 +items.artifacts.unstablespellbook.ac_song=圣歌 +items.artifacts.unstablespellbook.blinded=你不能在失明的时候阅读书籍。 +items.artifacts.unstablespellbook.no_charge=你的咒语书耗尽了能量。 +items.artifacts.unstablespellbook.cursed=受诅咒的咒语书锁死了书页,你无法阅读它。 +items.artifacts.unstablespellbook.prompt=选择一个卷轴 +items.artifacts.unstablespellbook.infuse_scroll=你将卷轴的能量注入了书中。 +items.artifacts.unstablespellbook.unable_scroll=你无法将这个物品添加到书中。 +items.artifacts.unstablespellbook.unknown_scroll=你仍然不清楚这个卷轴的类型。 +items.artifacts.unstablespellbook.desc=令人惊讶的是这本古老的法典被保养得很好。当你翻动页面时它不断地噼啪作响并发出嘶嘶声,涌动着不稳定的能量。一旦诵读这本书,没人能笃定你会释放出什么咒语。 +items.artifacts.unstablespellbook.desc_cursed=被诅咒的书本将自己绑在了你身上,并在抑制你使用大部分卷轴的能力。 +items.artifacts.unstablespellbook.desc_index=目前该物品所有的经验为%s。 +items.artifacts.unstablespellbook.exp=目前该物品所有的经验为%s。 + +items.artifacts.eyeofskadi.name=斯嘉蒂之眼 +items.artifacts.eyeofskadi.ac_add=献祭 +items.artifacts.eyeofskadi.ac_blast=冰暴 +items.artifacts.eyeofskadi.ac_curse=诅咒 +items.artifacts.eyeofskadi.no_charge=冰眼尚未充能完毕。 +items.artifacts.eyeofskadi.prompt=选择原石作为献祭素材 +items.artifacts.eyeofskadi.need_charge=冰眼还没有准备好。 +items.artifacts.eyeofskadi.full_charge=冰眼已经准备完毕。 +items.artifacts.eyeofskadi.exp=目前能量%s。 +items.artifacts.eyeofskadi.infuse_ore=冰眼熔化了原石。 +items.artifacts.eyeofskadi.desc=极度罕见的古物,原由苍空之龙看管,因时空乱流流落至此。这只眼睛仿佛有生命一般,散发出可怕的气息。 + +items.artifacts.robotdmt.name=机械核心 +items.artifacts.robotdmt.ac_heart=使用 +items.artifacts.robotdmt.ac_memory=决心 +items.artifacts.robotdmt.no_charge=机械核心尚未充能完毕。 +items.artifacts.robotdmt.full_charge=机械核心已完全充能。 +items.artifacts.robotdmt.patience=尝试解析:耐心 +items.artifacts.robotdmt.bravery=尝试解析:勇气 +items.artifacts.robotdmt.integrity=尝试解析:诚实 +items.artifacts.robotdmt.preseverance=尝试解析:坚毅 +items.artifacts.robotdmt.kindness=尝试解析:慷慨 +items.artifacts.robotdmt.justice=尝试解析:公正 +items.artifacts.robotdmt.soul=尝试解析:灵魂 +items.artifacts.robotdmt.friendship=尝试解析:友谊 +items.artifacts.robotdmt.chaos=尝试解析:混沌...解析失败 +items.artifacts.robotdmt.determination=尝试解析:决心...解析失败 +items.artifacts.robotdmt.desc=一位疯狂的科学家为了研究人类的毅力所制造的机器。它不需要任何能源来驱动,并且能够每隔一段时间返回解析结果。 + +items.artifacts.glasstotem.name=玻璃图腾 +items.artifacts.glasstotem.ac_atk=进攻祝福 +items.artifacts.glasstotem.ac_def=保护祝福 +items.artifacts.glasstotem.desc=由玻璃女神的信徒所制作的一件...图腾?可以用它来和玻璃女神沟通并乞求她的祝福。 + + +###bags +items.bags.bag.name=背包 +items.bags.potionbandolier.name=药剂挎带 +items.bags.potionbandolier.desc=这副厚实的挎带能像肩带一样缠在身上,上面有许多用来放药瓶的隔热革带。 \n\n挎带能为存放其中的药瓶抵御寒冷。 +items.bags.scrollholder.name=卷轴筒 +items.bags.scrollholder.desc=这个管状的容器看起来可以装下一整份天文学家的手书,不过你的卷轴也刚好能放在里面。\n\n这个容器看起来并不是很可燃,所以你的卷轴在里面一定很安全。\n\n其中还有一个存放炸弹和其他爆炸物的小隔间。 +items.bags.seedpouch.name=种子包 +items.bags.seedpouch.desc=这个丝绒制作的小袋子能让你储存任意数量的种子或者类似大小的东西。 +items.bags.wandholster.name=法杖套 +items.bags.wandholster.desc=这个修长的皮套看起来是由某种异域动物的毛皮制成,这个皮套的设计允许它紧密地持有多个法杖。 +items.bags.keyring.name=钥匙环 +items.bags.keyring.desc=这个钥匙环能容纳你的钥匙和戒指。一些神奇的力量使它可以容纳各种传送道具。 +items.bags.shoppingcart.name=购物车 +items.bags.shoppingcart.desc=一个现代的小推车。你可以把食物放在里面。 +items.bags.heartofscarecrow.name=草靶子 +items.bags.heartofscarecrow.desc=可以承载各类武器靶子。 + +###food +items.food.fruit.blandfruit.name=无味果 +items.food.fruit.blandfruit.sunfruit=阳光果 +items.food.fruit.blandfruit.rotfruit=腐朽果 +items.food.fruit.blandfruit.earthfruit=大地果 +items.food.fruit.blandfruit.blindfruit=目盲果 +items.food.fruit.blandfruit.firefruit=火焰果 +items.food.fruit.blandfruit.icefruit=冰霜果 +items.food.fruit.blandfruit.fadefruit=渐隐果 +items.food.fruit.blandfruit.sorrowfruit=忧伤果 +items.food.fruit.blandfruit.stormfruit=暴风果 +items.food.fruit.blandfruit.dreamfruit=梦乡果 +items.food.fruit.blandfruit.starfruit=星陨果 +items.food.fruit.blandfruit.powerfruit=强化果 +items.food.fruit.blandfruit.mightyfruit=决心果 +items.food.fruit.blandfruit.heartfruit=生命果 + +items.food.fruit.blandfruit.raw=这玩意没法生吃。 +items.food.fruit.blandfruit.ice_msg=这个冰霜果尝起来有点冰冻生肉片的感觉。 +items.food.fruit.blandfruit.fire_msg=你感觉到体内有一股烈焰在熊熊燃烧! +items.food.fruit.blandfruit.toxic_msg=你被灌注了强大的毒素力量! +items.food.fruit.blandfruit.para_msg=你感到大地的力量在体内奔腾! +items.food.fruit.blandfruit.desc=干燥且脆弱,或许加点其他材料再煮能够增强它的效果。 +items.food.fruit.blandfruit.desc_cooked=这个果实已经因为吸收锅中的汤而鼓胀,并且吸收了其中种子的属性。\n\n看起来已经可以吃了! + +items.food.meatfood.chargrilledmeat.name=烤肉排 +items.food.meatfood.chargrilledmeat.desc=烧烤是最基础的处理食材的方式。这种方式处理的食物虽然味道不是很好,但是却能提供更多的能量以及更长的保质时间。 + +items.food.food.name=干粮包 +items.food.food.ac_eat=食用 +items.food.food.locked=锁闭魔法阻止了你进食。 +items.food.food.bosslevel=这里不适合吃这种食物。 +items.food.food.desc=里面没什么有意思的东西:肉干和一些饼干——这之类的东西。 + +items.food.staplefood.normalration.name=干粮包 +items.food.staplefood.normalration.desc=里面没什么有意思的东西:肉干和一些饼干——这之类的东西。 + +items.food.staplefood.pasty.pasty=肉馅饼 +items.food.staplefood.pasty.assorted=春什锦 +items.food.staplefood.pasty.pie=南瓜派 +items.food.staplefood.pasty.egg=七彩蛋 +items.food.staplefood.pasty.book=暑假作业 +items.food.staplefood.pasty.cane=拐杖糖 +items.food.staplefood.pasty.turkey=烤火鸡 +items.food.staplefood.pasty.bread=砖头糕 +items.food.staplefood.pasty.jelly=软糖剑 + +items.food.staplefood.pasty.pasty_desc=这是份正宗康郡肉烘饼,内含土豆加牛肉的传统馅料。 +items.food.staplefood.pasty.assorted_desc=年糕、汤圆,饺子什么的塞满了这个蒸笼。作为新春佳节的传统食物之一,它能完全消除你的饥饿感并让你充满决心。\n\n春节快乐! +items.food.staplefood.pasty.pie_desc=好大的一块南瓜派!甘甜又微辣,它会填饱你的肚子并让你恢复少量生命。\n\n万圣节快乐! +items.food.staplefood.pasty.book_desc=这是一份暑假作业,注意劳逸结合。\n\n暑假快乐! +items.food.staplefood.pasty.egg_desc=虽然这个东西看起来不大,但吃下它能够完全消除你的饥饿感,并让你精神抖擞。\n\n复活节快乐! +items.food.staplefood.pasty.cane_desc=甜度爆表的巨型拐杖糖!大到够你一次吃饱,其中的糖分或许还能让你的法杖获得一点点额外充能。\n\n节日快乐! +items.food.staplefood.pasty.turkey_desc=刚烤好的一只感恩节火鸡。吃下它可以恢复你的饥饿值并加快你的速度。\n\n感恩节快乐! +items.food.staplefood.pasty.bread_desc=由面粉和奶油烧制成的砖头形状的糕点。没准里面有金子呢。\n\n劳动节快乐! +items.food.staplefood.pasty.jelly_desc=一个做成剑形状的软糖,估计只有小孩才喜欢这种味道。\n\n儿童节快乐! +items.food.staplefood.pasty.worker=辛苦了,这是500块的报酬。 + +items.food.meatfood.frozencarpaccio.name=冻肉片 +items.food.meatfood.frozencarpaccio.hard=你感到皮肤变硬了! +items.food.meatfood.frozencarpaccio.refresh=神清气爽! +items.food.meatfood.frozencarpaccio.invisbility=你被暗影祝福了! +items.food.meatfood.frozencarpaccio.better=你感觉好多了! +items.food.meatfood.frozencarpaccio.desc=冰冻也是处理食物的方式之一。这种方式处理的食物味道会比其他食物好点,但本身不能提供太多能量。由于神秘的魔法在地牢里面萦绕,制作冻肉的同时可能把这种魔法凝聚到冻肉内部,使它提供更多的增益效果。 + +items.food.meatfood.mysterymeat.not_well=你感觉……不太好 +items.food.meatfood.mysterymeat.name=怪物肉 +items.food.meatfood.mysterymeat.hot=嗷!好烫! +items.food.meatfood.mysterymeat.legs=你的腿没有知觉了! +items.food.meatfood.mysterymeat.bad=你感觉很难受。 +items.food.meatfood.mysterymeat.stuffed=你的神经麻痹了。 +items.food.meatfood.mysterymeat.desc=这种肉和市场上卖的不同,看起来十分危险。如果不处理而食用它可能带来不可预知的后果。 + +items.food.staplefood.overpricedration.name=干粮小包 +items.food.staplefood.overpricedration.desc=容量较食物包小的食物小包,很受年轻女性冒险者的欢迎。 + +items.food.fruit.blackberry.name=粉色浆果 +items.food.fruit.blackberry.desc=野生浆果的一种,富含大量维生素和矿物质,食用后可以大幅度提升机体的恢复速度。同时还有几率开发你的灵能,使你发现隐藏在地牢里的其他生物。 + +items.food.fruit.blueberry.name=蓝色浆果 +items.food.fruit.blueberry.stop=这里的魔法阻止了你使用这种方法来探查地牢! +items.food.fruit.blueberry.desc=野生浆果的一种,富含大量维生素和矿物质,食用后你将获得这一层的全部信息。 + +items.food.fruit.cloudberry.name=红色浆果 +items.food.fruit.cloudberry.desc=野生浆果的一种,富含大量维生素和矿物质,食用后可以使人行动更为敏捷。 + +items.food.fruit.fullmoonberry.name=满月浆果 +items.food.fruit.fullmoonberry.desc=野生浆果的一种,富含大量维生素和矿物质,这种浆果由于受到了月亮女神的祝福,食用后将给你提供十分强大的效果。 + +items.food.fruit.moonberry.name=青色浆果 +items.food.fruit.moonberry.desc=野生浆果的一种,富含大量维生素和矿物质,食用后可以使人身强力壮,充满活力。 + +items.food.completefood.goldennut.name=受hmdzl001祝福的坚果 +items.food.completefood.goldennut.effect1=+1力量,+60血量上限 +items.food.completefood.goldennut.effect2=+2力量,+30血量上限 +items.food.completefood.goldennut.desc=由hmdzl001亲自种植的坚果。它...我...算了... + +items.food.meatfood.meat.name=生肉 +items.food.meatfood.meat.bad=你感觉……不太好 +items.food.meatfood.meat.desc=和普通集市上卖的肉一样。最好加工后再吃它。 + +items.food.nut.name=生坚果 +items.food.nut.desc=坚果类食物富含各种蛋白质和脂肪,是消遣时光的好伴侣。一般来说熟的味道会好点。 + +items.food.vegetable.nutvegetable.name=坚果藤 +items.food.vegetable.nutvegetable.desc=一种常见的蔬菜,通常用于烹饪。即使是生食也十分美味。 + +items.food.vegetable.healgrass.name=治疗草 +items.food.vegetable.healgrass.desc=阳春草的一部分,可以用于食用。 + +items.food.vegetable.battleflower.name=星花瓣 +items.food.vegetable.battleflower.desc=星陨花的一部分,可以用于食用。 + +items.food.vegetable.dreamleaf.name=好梦叶 +items.food.vegetable.dreamleaf.desc=夜梦草的一部分,可以用于食用。 + +items.food.honey.name=蜂皇浆 +items.food.honey.desc=一种有很高的营养价值的食物。深受中老年人的喜爱。 + +items.food.completefood.petfood.name=宠物口粮 +items.food.completefood.petfood.desc=为宠物专门设计的食物。 + +items.food.completefood.perfectfood.name=完美便当 +items.food.completefood.perfectfood.desc=这是烹饪的最高杰作,完美便当。 + +items.food.completefood.honeymeat.name=蜜汁肉排 +items.food.completefood.honeymeat.desc=把蜂蜜浇在肉排上...很甜。 + +items.food.completefood.icecream.name=冰雪盛宴 +items.food.completefood.icecream.desc=一个超大的冰淇凌。吃了肯定很爽。 + +items.food.completefood.vegetablesoup.name=菜汤 +items.food.completefood.vegetablesoup.desc=把杂七杂八的蔬菜放到一起煮出来的汤。 + +items.food.completefood.ediblegrass.name=可食用草 +items.food.completefood.ediblegrass.desc=吃什么草,有种吃土。 + +items.food.completefood.garbage.name=垃圾 +items.food.completefood.garbage.desc=这玩意完全不能吃。 + +items.food.completefood.crystalnucleus.name=闪耀晶核 +items.food.completefood.crystalnucleus.desc=这种晶核的味道并不好,但是它能卖钱。 + +items.food.completefood.kebab.name=大肉串 +items.food.completefood.kebab.desc=就是大肉串。 + +items.food.completefood.hamburger.name=巨无霸汉堡 +items.food.completefood.hamburger.desc=啊!好大! + +items.food.completefood.chickennugget.name=椒盐鸡块 +items.food.completefood.chickennugget.desc=想吃我的香香鸡吗? + +items.food.completefood.herbmeat.name=药草酱肉 +items.food.completefood.herbmeat.desc=沾草后口味更佳 + +items.food.completefood.porksoup.name=排骨汤 +items.food.completefood.porksoup.desc=你可以看到浮在上面的油水 + +items.food.completefood.honeyrice.name=蜂蜜拌饭 +items.food.completefood.honeyrice.desc=天哪,我嘴里塞满了蜜蜂! + +items.food.completefood.vegetablekebab.name=大菜串 +items.food.completefood.vegetablekebab.desc=素食主义者最喜欢的。 + +items.food.completefood.ricefood.name=精制米饭 +items.food.completefood.ricefood.desc=有些时候精制米饭味道更好。 + +items.food.completefood.fruitsalad.name=水果沙拉 +items.food.completefood.fruitsalad.desc=事实上制作这种食物并不需要沙拉。 + +items.food.completefood.foamedbeverage.name=发泡饮料 +items.food.completefood.foamedbeverage.desc=一起哈啤! + +items.food.completefood.gel.name=凝胶 +items.food.completefood.gel.desc=一团凝胶 + +items.food.completefood.honeygel.name=蜂蜜布丁 +items.food.completefood.honeygel.desc=蜂蜜布满了凝胶 + +items.food.completefood.honeywater.name=蜂糖水 +items.food.completefood.honeywater.desc=稀释后的蜂蜜 + +items.food.completefood.meatroll.name=肉卷 +items.food.completefood.meatroll.desc=这意味着可以吃书了 + +items.food.completefood.vegetableroll.name=菜卷 +items.food.completefood.vegetableroll.desc=肉卷的兄弟 + +items.food.completefood.chocolate.name=巧克力 +items.food.completefood.chocolate.desc=超纯的巧克力,超苦的。 + +items.food.completefood.foodfans.name=粉丝 +items.food.completefood.foodfans.desc=注意煮熟后食用。 + +items.food.completefood.frenchfries.name=薯条 +items.food.completefood.frenchfries.desc=过量淀粉警告。 + +items.food.wateritem.name=水 +items.food.wateritem.desc=通过露珠瓶净化后的水,可以用于烹饪。 + +items.food.completefood.aflyfood.name=不思议饭团 +items.food.completefood.aflyfood.desc=阿飞特制的不思议饭团,拥有另一个世界的力量。 + +###medicine +items.medicine.pill.ac_eat=食用 + +items.medicine.powerpill.name=力量药丸 +items.medicine.powerpill.desc=在一段时间内提升力量。 + +items.medicine.hardpill.name=硬化药丸 +items.medicine.hardpill.desc=在一段时间内提升防御。 + +items.medicine.smashpill.name=增幅药丸 +items.medicine.smashpill.desc=在一段时间内提升伤害。 + +items.medicine.musicpill.name=节奏药丸 +items.medicine.musicpill.desc=在一段时间内提升自信。 + +items.medicine.magicpill.name=奥术药丸 +items.medicine.magicpill.desc=在一段时间内提升法强。 + +items.medicine.shootpill.name=神射药丸 +items.medicine.shootpill.desc=在一段时间内提升射击力。 + +items.medicine.bluemilk.name=蓝奶伞 +items.medicine.bluemilk.desc=这种蘑菇像浆果一样鲜嫩多汁,食用它可以大幅度加快你的行动速度和恢复速度。只是...它对其他生物也有相同的效果。 + +items.medicine.deathcap.name=致死帽 +items.medicine.deathcap.desc=这种头上布满白斑的红色菌类肯定是具有致命效果的东西。希望它也会对其他生物有效。 + +items.medicine.earthstar.name=地裂星 +items.medicine.earthstar.desc=这种菌类并不属于地球。它可能来自虚空...或死星什么的...反正不会是小马国。食用它可能会撕裂这片区域所有人的身体。 + +items.medicine.goldenjelly.name=凝胶团 +items.medicine.goldenjelly.desc=与其说这是一种菌类,倒不如说这是一袋种子。它是这种菌类的繁殖的表现:受到挤压后,大量的孢子飞向四周,减缓生物的移动的同时致幻目标。 + +items.medicine.jackolantern.name=灯笼球 +items.medicine.jackolantern.desc=这种菌类含有大量的磷。当它受到外界挤压时它会将会把体内的磷成分以白磷的形式释放,从而引起大火。 + +items.medicine.pixieparasol.name=单色块 +items.medicine.pixieparasol.desc=一种有强烈致幻作用的菌类,食用后会使人的伤口恢复,同时使其他生物陷入睡眠状态。 + +items.medicine.greenspore.name=绿菌孢 +items.medicine.greenspore.not_time=奇怪的能量流入了你的背包,但是什么也没发生。 +items.medicine.greenspore.desc=露珠研究者培育出来的新品种蘑菇,相比其他蘑菇这个完全没有副作用,并且可以让露珠产出更加频繁。 + +###journal pages +items.journalpages.journalpage.name=坐标 +items.journalpages.journalpage.desc=Location +items.journalpages.safespotpage.name=房契 +items.journalpages.safespotpage.desc=一套三室两厅一厨一卫一露台的豪华别墅的地址。 +items.journalpages.sokoban1.name=Otiluck的旅行日志之推箱教程 +items.journalpages.sokoban1.desc=推箱教程的地址。\n\n说起我的故乡,多利亚小镇,想必大家不会陌生。优美的环境,舒适的气候,丰富的矿产资源,一度让其成为最适宜居住的城镇之一。当然那已经是我成年前的事了。\n\n肆意开采矿产外加乱排乱放垃圾使得小镇一天天衰败。我想我应该去做些什么。 +items.journalpages.sokoban2.name=Otiluck的旅行日志之奇异城堡 +items.journalpages.sokoban2.desc=奇异城堡的地址。\n\n撬开知情人士的嘴花了我不少时间,最后还是让我确定了这个地点。一个看上去像是废弃监狱的地方。巨大的箱子和致命的陷阱胡乱的摆放在哪儿,宝箱在那些东西中间若隐若现。\n\n经过一段时间的分析,我确定这是个谜题,并且可以尝试解开。 +items.journalpages.sokoban3.name=Otiluck的旅行日志之传送迷阵 +items.journalpages.sokoban3.desc=传送迷阵的地址。\n\n那个坐标指引我到了一块荒凉的地方。撒上驱魔粉尘后,一座城堡拔地而起。\n\n进入城堡后,我确认这里和之前废弃监狱一样出自同一个人之手。类似的箱子,类似的陷阱,还有类似的...等一下,一个幻影巨人,看样子它并不欢迎我。\n\n无论如何我也得要继续下去,因为我知道这里肯定有什么巨大的秘密。 +items.journalpages.sokoban4.name=Otiluck的旅行日志之终极挑战 +items.journalpages.sokoban4.desc=终极挑战的地址。\n\n似乎这些生物十分害怕我。我该说这里民风淳朴呢还是我长得太危险了呢?当我尝试靠近它们时,它们就会把我传送到另一个位置。好在这里还有一些可食用的食物,否则我肯定会饿死在这里。\n\n当我第61次被传送走时,我看到了一块巨大的石碑。令我吃惊的是,它似乎是在讲述一段历史。只要我能读懂这段历史,我就能知晓它们的语言... +items.journalpages.town.name=多利亚小镇 +items.journalpages.town.desc=多利亚小镇的地址。\n\n_我们非常抱歉:目前我们已经不再生产及销售多利亚石板。但是如果你不相信的话,欢迎来我们小镇看看。 +items.journalpages.energycore.name=Otiluck的旅行日志之能源核心 +items.journalpages.energycore.desc=能源核心的地址。\n\n说明:这是一个自动攻击的生物。它由zot创造,在我打败zot后我控制了这个生物。 +items.journalpages.vault.name=宝地坐标 +items.journalpages.vault.desc=一个字迹潦草的地点坐标,旁边有2020.1.25的字样。 + +###challenge list +items.challengelists.challengelist.name=挑战 +items.challengelists.challengelist.desc=原先的传送道具,但已经丧失了它原有的魔力。底下还有一行小字。 \n _你好,我叫ren,我因为一场意外穿越到这里,受此影响原先的部分传送道具失去了魔力,变成了现在这个样子。来多利亚小镇找我,我会帮你修复这些。_ + +items.challengelists.sewerchallenge.name=下水道挑战 +items.challengelists.prisonchallenge.name=监狱挑战 +items.challengelists.cavechallenge.name=洞窟挑战 +items.challengelists.citychallenge.name=城市挑战 +items.challengelists.couragechallenge.name=勇气试炼 +items.challengelists.couragechallenge.desc=原先的传送道具,但已经丧失了它原有的魔力。\n三大试炼之一。这个试炼将带你前往漆黑之地,让你直面你原始的恐惧 +items.challengelists.powerchallenge.name=力量试炼 +items.challengelists.powerchallenge.desc=原先的传送道具,但已经丧失了它原有的魔力。\n三大试炼之一。这个试炼将测试你的力量。在源源不断的猪人大军中存活下来。 +items.challengelists.wisdomchallenge.name=智慧试炼 +items.challengelists.wisdomchallenge.desc=原先的传送道具,但已经丧失了它原有的魔力。\n三大试炼之一。这个试炼被建立在天空当中。稍有差池就会失去一切。 + +###keys +items.keys.goldenkey.name=金钥匙 +items.keys.goldenkey.desc=这个金色钥匙的凹刻精妙而复杂。或许它能用来打开某种宝箱锁? +items.keys.ironkey.name=铁钥匙 +items.keys.ironkey.desc=这个铁钥匙的匙齿已经严重磨损;皮制系带也久经年岁摧残。它对应的是哪扇门呢? +items.keys.skeletonkey.name=骷髅钥匙 +items.keys.skeletonkey.desc=这个钥匙看起来不能等闲视之:其顶端被制成头骨的形状。或许它能打开什么不得了的大门。 +items.keys.goldenskeletonkey.name=水晶钥匙 +items.keys.goldenskeletonkey.desc=这个水晶钥匙上的凹刻在不断地变换和移动,仿佛活的一样。或许它能用来打开某种宝箱锁? +items.keys.ironkey.depth=%d层铁钥匙 + +###misc +items.misc.autopotion.name=自助药水器 +items.misc.autopotion.desc=装备这件饰品能在你的生命值降低时自动使用治疗药水。 + +items.misc.miscequippable.2miscs=你只能同时装备3样饰品。 +items.misc.miscequippable.desc=这是一个饰品。 + +items.misc.spectacles.name=眼镜 +items.misc.spectacles.desc=十分普通的眼镜,但是能够强化使用者的灵能。 + +###nornstone +items.nornstone.nornstone.name=魔法矿石 +items.nornstone.nornstone.desc=多利亚哈芬的特产,富有能量的魔法矿石。 + +items.nornstone.greennornstone.name=绿色魔法矿石 +items.nornstone.greennornstone.desc=多利亚哈芬的特产,富有能量的魔法矿石。绿色对应着_猛毒重型链枷_。 + +items.nornstone.bluenornstone.name=蓝色魔法矿石 +items.nornstone.bluenornstone.desc=多利亚哈芬的特产,富有能量的魔法矿石。蓝色对应着_休克三叉水戟_。 + +items.nornstone.orangenornstone.name=橙色魔法矿石 +items.nornstone.orangenornstone.desc=多利亚哈芬的特产,富有能量的魔法矿石。橙色对应着_碎骨锯肉巨斧_。 + +items.nornstone.purplenornstone.name=紫色魔法矿石 +items.nornstone.purplenornstone.desc=多利亚哈芬的特产,富有能量的魔法矿石。紫色对应着_抽灵萃魂长剑_。 + +items.nornstone.yellownornstone.name=黄色魔法矿石 +items.nornstone.yellownornstone.desc=多利亚哈芬的特产,富有能量的魔法矿石。黄色对应着_威慑落岩圆刃_。 + +###potions +items.potions.potion.ac_drink=饮用 +items.potions.potion.turquoise=青绿 +items.potions.potion.crimson=猩红 +items.potions.potion.azure=湛青 +items.potions.potion.jade=翡翠 +items.potions.potion.golden=金黄 +items.potions.potion.magenta=品红 +items.potions.potion.charcoal=煤黑 +items.potions.potion.ivory=乳白 +items.potions.potion.amber=琥珀 +items.potions.potion.bistre=深褐 +items.potions.potion.indigo=靛蓝 +items.potions.potion.silver=银灰 +items.potions.potion.aqua=藏青 +items.potions.potion.violet=紫靛 +items.potions.potion.unknown_name=%s药水 +items.potions.potion.unknown_desc=这瓶里装着些不断打旋的%s色液体,谁知道投掷或饮用它们时会有什么效果呢? +items.potions.potion.harmful=有害药水! +items.potions.potion.beneficial=有益药水 +items.potions.potion.yes=是的,我知道我在做什么 +items.potions.potion.no=不,我改变主意了 +items.potions.potion.sure_drink=你确定要饮用它吗? 大多数情况下你该把它扔向敌人的。 +items.potions.potion.sure_throw=你确定要投掷它吗? 大多数情况下把它喝下去会更有用。 +items.potions.potion.shatter=药瓶碎裂开来,%s色液体无害地溅出了。 +items.potions.potion.stop=禁魔结界阻止了这瓶药水生效。 +items.potions.potion.locked=锁闭魔法阻止了你使用这瓶药水。 + +items.potions.potionofexperience.name=经验药水 +items.potions.potionofexperience.desc=大量的战斗经验被浓缩为液态,这种药水能够瞬间提升你的战斗力。 +items.potions.potionoffrost.name=冰霜药水 +items.potions.potionoffrost.desc=一旦暴露在空气里,该化学品会气化成一片冰冷的气雾,将任何接触它的生物冻结并无法行动。其冷冻效果在潮湿环境下会大幅提升。 +items.potions.potionofhealing.name=治疗药水 +items.potions.potionofhealing.heal=你的伤口愈合了很多。 +items.potions.potionofhealing.desc=一支让你瞬间回复大量生命值并清除毒素的万能药水。 +items.potions.potionofinvisibility.name=隐形药水 +items.potions.potionofinvisibility.invisible=你看到你的手隐形了! +items.potions.potionofinvisibility.desc=饮用这种药水会使你暂时隐形。隐身期间,敌人将无法看见你。攻击敌人,或在敌人面前使用法杖和卷轴,会让药水效果立即消失。 +items.potions.potionoflevitation.name=浮空药水 +items.potions.potionoflevitation.float=你漂浮到了空中! +items.potions.potionoflevitation.desc=饮用这种古怪的药水能让你漂浮到空中,从而轻易地越过陷阱和裂隙。扔出它会产生一片未知气体,让其中的所有生物迷失方向。 +items.potions.potionofliquidflame.name=液火药水 +items.potions.potionofliquidflame.desc=该药瓶里装着一种不稳定的化合物,一旦暴露在空气中就会猛烈地燃烧起来。 +items.potions.potionofmight.name=根骨药水 +items.potions.potionofmight.msg_1=+15生命上限 +items.potions.potionofmight.desc=饮用这瓶药水,你可以永久性获得15点生命上限。 +items.potions.potionofmindvision.name=灵视药水 +items.potions.potionofmindvision.see_mobs=你可以感受到其他生物的存在! +items.potions.potionofmindvision.see_none=你能判定现在本层内就只有你一个人。 +items.potions.potionofmindvision.desc=喝下这个,你的心智将与大范围内的生物精神同调,让你能感受到围墙背后的生体所在。该药水还能够让你的视野无视身边门墙的阻挡。 +items.potions.potionofparalyticgas.name=麻痹药水 +items.potions.potionofparalyticgas.desc=暴露于空气时,烧瓶里的液体会气化成一片令人失去知觉的黄色云雾。任何吸入气雾的生物都可能立即麻痹,直到云雾消散后一段时间才能行动。可以把该物件扔到远处的敌群中,让气体覆盖影响它们。 +items.potions.potionofpurity.name=净化药水 +items.potions.potionofpurity.freshness=你闻到了空气中不寻常的清新气息。 +items.potions.potionofpurity.no_smell=你什么都闻不到了! +items.potions.potionofpurity.desc=这种试剂能迅速中和掉作用区域内的一切有害气体。饮用它将使你暂时免疫这些气体。 +items.potions.potionofstrength.name=力量药水 +items.potions.potionofstrength.msg_1=+1力量 +items.potions.potionofstrength.msg_2=新生的力量在你的体内喷薄而出。 +items.potions.potionofstrength.desc=这种强力的液体会洗刷你的肌肉,永久性增加1点力量值。 +items.potions.potionoftoxicgas.name=毒气药水 +items.potions.potionoftoxicgas.desc=打开或摔碎这个密封的药瓶将导致内容物爆发成一团剧毒的绿色烟雾。你应该选择从远处将这瓶药水扔向敌人,而不是手动开封。 +items.potions.potionofhaste.name=疾速药水 +items.potions.potionofhaste.effect=你的移动速度快多了! +items.potions.potionofhaste.desc=喝下这瓶药水可以暂时提升你的行动速度。 +items.potions.potionofmending.name=恢复药水 +items.potions.potionofmending.effect=你的伤口正在快速愈合。 +items.potions.potionofmending.desc=一瓶使你恢复加快的药水。 +items.potions.potionofoverhealing.name=生命药水 +items.potions.potionofoverhealing.effect=你的伤口完全愈合了,同时一股魔法力量注入了你的身体! +items.potions.potionofoverhealing.fill=血量溢出%s点! +items.potions.potionofoverhealing.desc=一支让你瞬间回复甚至溢出生命值并清除毒素的万能药水。 + +###quest items +items.quest.ceremonialcandle.name=仪祭蜡烛 +items.quest.ceremonialcandle.desc=配套的蜡烛,在使用中融化在了一起。\n\n单独看来它们毫无价值,但与其它蜡烛按特定排布共用时却能为召唤仪式聚集能量。 +items.quest.corpsedust.name=尸尘 +items.quest.corpsedust.desc=在外观上这团尸尘和普通灰尘差不多。而你却能够感受到其中潜伏着一股充满恶意的魔力。\n\n尽快脱手为好。 +items.quest.darkgold.name=暗金矿 +items.quest.darkgold.desc=这种金属名中的暗并非源于其色泽(它看起来和普通金子一样),而是因为它会在阳光下熔化,令其在地表上毫无用处。 +items.quest.dwarftoken.name=矮人徽记 +items.quest.dwarftoken.desc=很多矮人和他们的造物都携带着这种小块金属,理由不详。兴许它是装饰品或什么身份识别牌。 矮人都挺奇怪的。 +items.quest.embers.name=元素余烬 +items.quest.embers.desc=只能从新生火元素身上采集到的特殊余烬.。它们散发着温暖的能量。 +items.quest.pickaxe.name=镐子 +items.quest.pickaxe.ac_mine=采掘 +items.quest.pickaxe.no_vein=附近没有可供采掘的暗金矿脉。 +items.quest.pickaxe.desc=这是一件巨大且耐用的凿岩工具。也许能当武器用。 +items.quest.ratskull.name=巨鼠头骨 +items.quest.ratskull.desc=一颗大得吓人的老鼠头骨。如果你能找到一面合适的墙来挂,它会是件不错的狩猎纪念品。 +items.quest.mushroom.name=露珠菌孢 +items.quest.mushroom.desc=这东西对于我们来说并没有什么用,但对于一些学者而言这东西大有研究价值。 +items.quest.gnollclothes.name=豺狼风衣 +items.quest.gnollclothes.desc=一件短小精致的风衣,看起来不像是人类应该有的尺寸。 + +###rings +items.rings.ring.diamond=钻石 +items.rings.ring.opal=蛋白石 +items.rings.ring.garnet=石榴石 +items.rings.ring.ruby=红宝石 +items.rings.ring.amethyst=紫水晶 +items.rings.ring.topaz=黄玉 +items.rings.ring.onyx=缟玛瑙 +items.rings.ring.tourmaline=碧玺 +items.rings.ring.emerald=祖母绿 +items.rings.ring.sapphire=蓝宝石 +items.rings.ring.quartz=石英 +items.rings.ring.agate=玛瑙 +items.rings.ring.cursed=这枚戒指紧紧箍住了你的手指! +items.rings.ring.unknown_name=%s戒指 +items.rings.ring.unknown_desc=这枚金属环镶嵌着一大颗%s,在黑暗中闪烁发光。谁知道戴上后会有什么效果? +items.rings.ring.known=这是个%s。 +items.rings.ring.identify=你已经对%s足够熟悉了。它是%s。 +items.rings.ring.on_finger=这个%s正在你的手指头上。 +items.rings.ring.cursed_worn=由于这个戒指被诅咒,你无力将其除下。 +items.rings.ring.curse_known=你能感觉到在%s上潜伏着一股充满恶意的魔力。 +items.rings.ring.toomany=你最多同时装备3样饰品。 + +items.rings.ringofaccuracy.name=精准戒指 +items.rings.ringofaccuracy.stats=佩戴这枚戒指时,你的精准度会增加_%1$d_点,攻击距离会增加_%2$d_格。 +items.rings.ringofaccuracy.desc=这枚戒指提高了你的专注力,使敌人难以躲闪你的攻击。该戒指每10级提供1格额外的攻击距离。 + +items.rings.ringofelements.name=元素戒指 +items.rings.ringofelements.stats=当佩戴这枚戒指时,你会获得元素抗性。 +items.rings.ringofelements.desc=这枚戒指能为你提供多种元素抗性,譬如火焰,雷电,气体等;它还能降低负面效果的持续时间。 + +items.rings.ringofevasion.name=闪避戒指 +items.rings.ringofevasion.stats=佩戴这枚戒指时,你的闪避值会增加_%d_点,潜行会增加_%2$d_点。 +items.rings.ringofevasion.desc=这枚戒指会混淆配戴者的真实位置,令其更难被敌人击中。该戒指每5级提供1点额外的潜行,但最多提供6点潜行。 + +items.rings.ringofforce.name=武力戒指 +items.rings.ringofforce.stats=佩戴这枚戒指时能额外能够造成_%1$s%%_的伤害。如果你未装备近战武器,你基础攻击将造成_%2$d~%3$d伤害_。 +items.rings.ringofforce.desc=这枚戒指能够增强配戴者的打击力度。在30级时这枚戒指的打击加成效果达到最强。 + +items.rings.ringoffuror.name=狂怒戒指 +items.rings.ringoffuror.stats=佩戴这枚戒指时,你的武器的攻击速度会提升_%s%%_。 +items.rings.ringoffuror.desc=这枚戒指会激发配戴者内心的怒火,使其能够更迅猛地攻击。在30级时这枚戒指效果达到最强。 + +items.rings.ringofhaste.name=疾速戒指 +items.rings.ringofhaste.stats=佩戴这枚戒指时,你的移动速度会提升_%s%%_。 +items.rings.ringofhaste.desc=这枚戒指减轻了配戴者在移动时的负担,使其能够飞速奔跑。在30级时这枚戒指效果达到最强。 + +items.rings.ringofmagic.name=奥术戒指 +items.rings.ringofmagic.stats=佩戴这枚戒指时,你的法强值会提升_%d_点。 +items.rings.ringofmagic.desc=你的法杖在这枚戒指散布的奥术力场中会变得更加强大。在30级时这枚戒指效果达到最强。 + +items.rings.ringofmight.name=根骨戒指 +items.rings.ringofmight.stats=佩戴这枚戒指时,你的力量值会提升_%1$d_点,生命上限会提升_%2$d_点。 +items.rings.ringofmight.desc=这枚戒指会增强配戴者的体质,使其拥有更强的体格。该戒指每5级提供1点额外力量。 + +items.rings.ringofsharpshooting.name=神射戒指 +items.rings.ringofsharpshooting.stats=佩戴这枚戒指时,你的投掷武器的命中值会提升_%1$d_,伤害值会提升_%2$s%%_。 +items.rings.ringofsharpshooting.desc=这枚戒指加强了配戴者的精度和瞄准,使得远程武器能够造成更高的伤害。 + +items.rings.ringoftenacity.name=韧性戒指 +items.rings.ringoftenacity.stats=佩戴这枚戒指时,你承受的伤害降低_%s%%_。 +items.rings.ringoftenacity.desc=这枚戒指使配戴者能够抵御受到的伤害。在30级时这枚戒指效果达到最强。 + +items.rings.ringofenergy.name=能量戒指 +items.rings.ringofenergy.stats=佩戴这枚戒指时,你的法杖充能速度会提升_%s%%_。 +items.rings.ringofenergy.desc=在戒指的奥术领域笼罩下你的所有法杖充能速度都会因此提升。在30级时这枚戒指效果达到最强。 + +###scrolls +items.scrolls.scroll.ac_read=阅读 +items.scrolls.scroll.kaunan=KAUNAN +items.scrolls.scroll.sowilo=SOWILO +items.scrolls.scroll.laguz=LAGUZ +items.scrolls.scroll.yngvi=YNGVI +items.scrolls.scroll.gyfu=GYFU +items.scrolls.scroll.raido=RAIDO +items.scrolls.scroll.isaz=ISAZ +items.scrolls.scroll.mannaz=MANNAZ +items.scrolls.scroll.naudiz=NAUDIZ +items.scrolls.scroll.berkanan=BERKANAN +items.scrolls.scroll.odal=ODAL +items.scrolls.scroll.tiwaz=TIWAZ +items.scrolls.scroll.ncosrane=NCOSRANE +items.scrolls.scroll.nendil=NENDIL +items.scrolls.scroll.libra=LIBRA +items.scrolls.scroll.unknown_name="%s"卷轴 +items.scrolls.scroll.unknown_desc=这张羊皮纸上写满了难以破译的文字,以%s符文作为代号。大声念出来会发生什么? +items.scrolls.scroll.blinded=你不能在失明时阅读卷轴。 +items.scrolls.scroll.locked=你不能在被锁闭时阅读卷轴。 +items.scrolls.scroll.silent=你不能在被沉默时阅读卷轴。 +items.scrolls.scroll.cursed=被诅咒的法典抑制了卷轴中法术的启动!也许祛邪卷轴足够强大还能被使用... +items.scrolls.scroll.prevent=魔法乱流阻止了这张卷轴的生效。 +items.scrolls.scrollofmagicmapping.prevent=探测魔法被阻断了! +items.scrolls.scrollofmirrorimage.prevent=镜像的创建被阻断了! + +items.scrolls.inventoryscroll.warning=你真的想终止这张卷轴的施放?它仍旧会被消耗掉。 +items.scrolls.inventoryscroll.yes=是的,我确定 +items.scrolls.inventoryscroll.no=不,我改主意了 +items.scrolls.scrollofidentify.name=鉴定卷轴 +items.scrolls.scrollofidentify.inv_title=选择一样要鉴定的物品 +items.scrolls.scrollofidentify.it_is=这是%s。 +items.scrolls.scrollofidentify.desc=该卷轴能永久揭示一件物品的所有秘密。 +items.scrolls.scrolloflullaby.name=催眠卷轴 +items.scrolls.scrolloflullaby.sooth=卷轴发出了某种舒缓的旋律。你觉得非常困倦。 +items.scrolls.scrolloflullaby.desc=阅读这张卷轴会释放出一段舒缓的旋律,让所有听到它的人陷入魔法沉眠。 +items.scrolls.scrollofmagicalinfusion.name=注魔卷轴 +items.scrolls.scrollofmagicalinfusion.inv_title=选择一件要注魔的物品 +items.scrolls.scrollofmagicalinfusion.infuse=你的%s被注入了奥术之力! +items.scrolls.scrollofmagicalinfusion.desc=这张卷轴将为你的武器或护甲注入强大的魔力。\n\n除了升级以外,武器还会被附魔,而护甲则会获得魔法刻印。\n\n如果升级物品上已经存在附魔和刻印,卷轴将会将其抹去并替换成新的附魔。 +items.scrolls.scrollofmagicmapping.name=探地卷轴 +items.scrolls.scrollofmagicmapping.layout=你熟悉了这层的地形。 +items.scrolls.scrollofmagicmapping.desc=阅读这张卷轴时,一副明晰的景象会刻入你的记忆中,告知你整个楼层的精确布局并揭开所有隐藏的秘密。不过道具位置和生物分布依旧是未知状态。 +items.scrolls.scrollofmirrorimage.name=镜像卷轴 +items.scrolls.scrollofmirrorimage.desc=卷轴上的咒文会创造数个阅读者的镜像来追击敌人。 +items.scrolls.scrollofpsionicblast.name=灵能震爆卷轴 +items.scrolls.scrollofpsionicblast.ondeath=灵能震爆撕碎了你的意识…… +items.scrolls.scrollofpsionicblast.desc=这张卷轴蕴含着毁灭性的能量,一旦引导出来将撕裂视野内所有生物的心灵。这股力量的释放也会对阅读者产生严重伤害,并导致暂时性的失明和眩晕。 +items.scrolls.scrollofrage.name=盛怒卷轴 +items.scrolls.scrollofrage.roar=卷轴产生的激怒咆哮在地牢中回荡! +items.scrolls.scrollofrage.desc=大声诵读内容时,卷轴将释放出一声轰响的咆哮,将所有敌人引向你并激怒附近的单位。 +items.scrolls.scrollofrecharging.name=充能卷轴 +items.scrolls.scrollofrecharging.surge=一股能量在体内奔腾而过,使你的法杖力量充沛! +items.scrolls.scrollofrecharging.desc=纯正的魔法能量被禁锢在羊皮纸内,当这股能量被释放时可以瞬间为阅读者的所有法杖充满能量。 +items.scrolls.scrollofremovecurse.name=祛邪卷轴 +items.scrolls.scrollofremovecurse.cleansed=你的背包闪耀着净化的光芒,一股恶毒的能量从中消散。 +items.scrolls.scrollofremovecurse.not_cleansed=你的背包闪耀着净化的光芒,不过什么也没发生。 +items.scrolls.scrollofremovecurse.desc=卷轴上的咒语能够瞬间清除使用者所装备的武器、护甲、戒指和携带物品的诅咒。 +items.scrolls.scrollofteleportation.name=传送卷轴 +items.scrolls.scrollofteleportation.tele=眨眼之间你就被传送到本层的另外一个位置。 +items.scrolls.scrollofteleportation.no_tele=强大的魔力流阻止了你的传送! +items.scrolls.scrollofteleportation.desc=羊皮纸上的咒语能立刻让阅读者传送到本层的随机位置。这能助你脱离险境,而不幸的阅读者则可能会被传送到一个更危险的地方。 +items.scrolls.scrollofterror.name=恐惧卷轴 +items.scrolls.scrollofterror.none=这个卷轴产生了一阵明亮的红色闪光。 +items.scrolls.scrollofterror.one=这个卷轴产生了一阵明亮的红色闪光的同时%s逃跑了! +items.scrolls.scrollofterror.many=这个卷轴产生了一阵明亮的红色闪光的同时怪物们逃跑了! +items.scrolls.scrollofterror.desc=一道红色闪光将以恐惧压垮使用者视觉范围内生物的心智并使它们转身逃跑。攻击正在逃跑的敌人将会打消该效果。 +items.scrolls.scrollofupgrade.name=升级卷轴 +items.scrolls.scrollofupgrade.inv_title=选择一件要升级的物品 +items.scrolls.scrollofupgrade.looks_better=你的%s看起来明显更优质了 +items.scrolls.scrollofupgrade.desc=这份卷轴能升级一件物品,提升其品质:法杖将更强力和拥有更高的总充能数;武器将会造成更多伤害;护甲将能吸收更多伤害;戒指将可产生更强的效果。 +items.scrolls.inventoryscroll.title=选择一个物品 + +items.scrolls.scrollofmultiupgrade.better=你的%s看起来明显更优质了 +items.scrolls.scrollofmultiupgrade.name=多重升级卷轴 +items.scrolls.scrollofmultiupgrade.title=选择一件要升级的物品 +items.scrolls.scrollofmultiupgrade.desc=这份卷轴能升级一件物品五次,提升其品质:法杖将更强力和拥有更高的总充能数;武器将会造成更多伤害;护甲将能吸收更多伤害;戒指将可产生更强的效果。 +items.scrolls.scrollofregrowth.layout=地牢中长出了大量植物,同时你熟悉了这层的地形。 +items.scrolls.scrollofregrowth.name=再生卷轴 +items.scrolls.scrollofregrowth.desc=这份卷轴可以催化种子的生长,并将使你能感知到它们的位置。 +items.scrolls.scrollofsacrifice.name=献祭卷轴 +items.scrolls.scrollofsacrifice.desc=以一种宇宙香料为原材料所制作的卷轴。这种香料能极大的提升食用者的能力,但是过多的使用会带来不可预知的副作用。 +items.scrolls.scrollofsacrifice.use_1=+5生命上限 +items.scrolls.scrollofsacrifice.use_2=+1力量 +items.scrolls.scrollofsacrifice.use_lot=你感觉不太舒服。 + +###wands +items.wands.wand.ac_zap=释放 +items.wands.wand.fizzles=你的法杖滋滋作响;一定是没能量了。 +items.wands.wand.self_target=你不能瞄准你自己! +items.wands.wand.identify=你现在了解了你的%s。 +items.wands.wand.cursed=这根法杖受到了诅咒,导致它的魔法混乱而随机。 +items.wands.wand.curse_discover=这根%s是诅咒的! +items.wands.wand.prompt=选择要释放魔法的位置 +items.wands.wand.silent=沉默魔法阻止你释放法术。 + +items.wands.wandoferror.name=错误法杖 +items.wands.wandoferror.desc=这是个错误 +items.wands.wandoferror.stats_desc=??? + +items.wands.wandofcharm.name=魅惑法杖 +items.wands.wandofcharm.desc=这根光属性法杖形状很普通,是那暗红的色泽和镶在顶端的漆黑宝石让它显眼起来。 +items.wands.wandofcharm.stats_desc=该法杖能导致敌人被暂时魅惑。 + +items.wands.wandofmeteorite.name=陨星法杖 +items.wands.wandofmeteorite.desc=这根火属性法杖由一种陨石制成,嵌有金饰并在顶部镶着一个浑圆的黑陨石。它在你手中的感觉非常沉重。 +items.wands.wandofmeteorite.stats_desc=该法杖能制造一个标记,在目标位置召唤陨石攻击。爆炸的力量会造成_%1$d~%2$d点伤害_并强到足以击晕大多数敌人。 + +items.wands.wandoftcloud.name=雷云法杖 +items.wands.wandoftcloud.desc=这根电属性法杖由一种导电金属制成,法杖顶端有一朵迷你乌云。很庆幸的是握在手上你不会感觉难受。 +items.wands.wandoftcloud.stats_desc=这根法杖能在目标地点创造一些电流。若消耗足够多的充能,则会生成一朵自动攻击的乌云。 +items.wands.wandoftcloud.more_charge=目前充能数无法召唤雷云。 +items.wands.wandoftcloud$tcloud.name=雷云 +items.wands.wandoftcloud$tcloud.desc=一朵噼啪放电的雷云。 +items.wands.wandoftcloud$stcloud.name=KEKE +items.wands.wandoftcloud$stcloud.desc=KEKE_IS_MOVE,MOB_WILL_DEAD. + +items.wands.wandofblood.name=鲜血法杖 +items.wands.wandofblood.desc=这根暗属性法杖能发射黑暗能量,如果法杖头上那小小的装饰用头骨还不够露骨地揭示这点。 +items.wands.wandofblood.stats_desc=该法杖会释放腐坏的能量,能按你意愿抽取敌人的灵魂,造成_%1$d~%2$d点伤害_用于治愈自身。 + +items.wands.wandofdisintegration.name=解离法杖 +items.wands.wandofdisintegration.desc=这根无属性法杖由一整块光滑的黑曜石制成,深紫色的光自其边缘流向法杖顶端。它闪烁着破坏性能量,准备着向前迸射。 +items.wands.wandofdisintegration.stats_desc=这根法杖射出的光束能穿透任何障碍物,造成_%1$d~%2$d点伤害_ ,并将随着法杖等级的提升而射得更远。光束穿透的地形和敌人越多,法杖造成的额外伤害就越大。 + +items.wands.wandoffirebolt.name=火球法杖 +items.wands.wandoffirebolt.desc=这根火属性法杖由红漆木制成,饰以金叶,这使它看起来相当庄严。它的顶端噼啪作响嘶嘶而鸣,渴望着释放其强大的魔法。 +items.wands.wandoffirebolt.stats_desc=该法杖在使用时会产生一股强大的焰浪,焚毁经过的路径,并灼烧目标地点,造成_%1$d~%2$d点伤害_ 。 + +items.wands.wandofflock.name=招羊法杖 +items.wands.wandofflock.desc=这根暗属性法杖看起来就像普通木棍一样,但它两头的金色饰物使它看起来并不那么普通。 +items.wands.wandofflock.stats_desc=使用该法杖将在目标地点召唤一只无害绵羊。由于这种魔法和生成魔法相类似,所以一定程度上可以代替生成魔法。 +items.wands.wandofflock.guard=魔法引起了智慧守卫的注意。 +items.wands.wandofflock$magicsheep.desc=这是一只魔法绵羊。为什么叫它魔法绵羊?因为你杀不死它。它只会站在那里直到它消失,它会做的事情只有边反刍边对你翻白眼。 +items.wands.wandofflock$magicsheep.name=魔法绵羊 +items.wands.wandofflock$magicbombsheep.desc=LEVEL_TOO_HARD,BABA_IS_DONE.BETTER_LOOK_OUT,BABA_HAS_GUN. +items.wands.wandofflock$magicbombsheep.name=BABA + + +items.wands.wandoflightning.name=雷霆法杖 +items.wands.wandoflightning.desc=这根电属性法杖由实心金属制成,这使它惊人地沉重。电弧顶端有两个内弯的叉齿间跳跃。 +items.wands.wandoflightning.stats_desc=这根法杖能向任何目标放出强大的电弧并造成_%1$d~%2$d点伤害_ 。这种电能在附近多个敌人间跳跃,在水里会更强力。要是太接近,你自己同样可能被电到。 + +items.wands.wandofmagicmissile.name=魔弹法杖 +items.wands.wandofmagicmissile.desc=这根无属性法杖能发射纯魔法能量构成的导弹。 +items.wands.wandofmagicmissile.stats_desc=尽管不如其它法杖那么强大,但它的大量充能数弥补了这一点。它能造成_%1$d~%2$d点伤害_ 。 + +items.wands.wandofpoison.name=剧毒法杖 +items.wands.wandofpoison.desc=这根地属性法杖的紫色主干半包住顶端一颗亮绿色宝石。 +items.wands.wandofpoison.stats_desc=该法杖能射出一颗会在目标位置爆炸的毒性法球。被击中的单位将缓慢受到毒性伤害。 + +items.wands.wandoflight.name=强光法杖 +items.wands.wandoflight.desc=这根光属性法杖由一块实心半透明水晶构成,就像一块厚长光滑的玻璃。 +items.wands.wandoflight.stats_desc=该法杖射出的光线能刺破地牢的黑暗,造成_%1$d~%2$d点伤害_并致盲敌人。 + +items.wands.wandoffreeze.name=霜冻法杖 +items.wands.wandoffreeze.desc=这根冰属性法杖似乎由某种魔法冰块制成。它的圆顶闪着亮光。握起来很冰,但不知为何你的手仍保持着温暖。 +items.wands.wandoffreeze.stats_desc=该法杖能向你的敌人射击冰霜能量,造成_%1$d~%2$d点伤害_并冷冻目标,降低其行动速度。在水中的作用似乎更强。正被冻伤和冻结的敌人将受到更少该法杖的伤害,因为他们已经足够冷了。 + +items.wands.wandofflow.name=涌流法杖 +items.wands.wandofflow.desc=这根冰属性法杖比普通法杖来的短,但是这根法杖的顶端的小喷泉使它看起来和普通法杖一样。 +items.wands.wandofflow.stats_desc=该法杖能向目标地点喷射出强劲有力的水流,造成_%1$d~%2$d点伤害_ ,击退目标并将其打湿。 + +items.wands.wandofacid.name=酸蚀法杖 +items.wands.wandofacid.desc=这根地属性法杖由一根细长木枝巧琢而成。不知为何它还活着而且生机盎然,像一株树苗的嫩芽般艳绿。 +items.wands.wandofacid.stats_desc=被使用时,这根法杖会释放出翠绿的强酸,造成_%1$d~%2$d点伤害_并持续伤害被命中的敌人。 + +items.wands.cannonofmage.name=雷诺的七彩大炮 +items.wands.cannonofmage.desc=一件古遗物,它储存着魔法的精华,并可以将它们发射出去。 +items.wands.cannonofmage.stats_desc=被使用时,这根法杖会释放出随机的效果,造成_%1$d~%2$d点伤害_。该法杖受到额外的法强加成。 + +###enchantments +items.weapon.enchantments.enchantmentdark.name=暗影%s +items.weapon.enchantments.enchantmentdark.desc=暗影附魔有几率恐吓目标,并造成额外的暗属性伤害。 + +items.weapon.enchantments.enchantmentfire.name=烈焰%s +items.weapon.enchantments.enchantmentfire.desc=烈焰附魔有几率点燃目标,并造成额外的火属性伤害。 + +items.weapon.enchantments.enchantmentlight.name=圣光%s +items.weapon.enchantments.enchantmentlight.desc=圣光附魔有几率对邪物造成高额的伤害,并造成额外的光属性伤害。 + +items.weapon.enchantments.enchantmentenergy.name=战意%s +items.weapon.enchantments.enchantmentenergy.desc=战意附魔有几率提升使用者的攻击力,并造成额外的物理伤害。 + +items.weapon.enchantments.enchantmentearth.name=自然%s +items.weapon.enchantments.enchantmentearth.desc=自然附魔有几率对目标埋下寄生种子,并造成额外的地属性伤害。 + +items.weapon.enchantments.enchantmentshock.name=乱流%s +items.weapon.enchantments.enchantmentshock.desc=乱流附魔有几率对多个目标造成伤害,并造成额外的雷属性伤害。 + +items.weapon.enchantments.enchantmentice.name=冰霜%s +items.weapon.enchantments.enchantmentice.desc=冰霜附魔有几率冻结目标,并造成额外的冰属性伤害。 + +items.weapon.enchantments.enchantmentdark2.name=弱化%s +items.weapon.enchantments.enchantmentdark2.desc=弱化附魔有几率削弱目标的攻击力。 + +items.weapon.enchantments.enchantmentfire2.name=焦油%s +items.weapon.enchantments.enchantmentfire2.desc=焦油附魔有几率给目标的泼油。 + +items.weapon.enchantments.enchantmentlight2.name=闪耀%s +items.weapon.enchantments.enchantmentlight2.desc=闪耀附魔有几率致盲目标。 + +items.weapon.enchantments.enchantmentenergy2.name=剑舞%s +items.weapon.enchantments.enchantmentenergy2.desc=剑舞附魔有几率提升使用者的防御力。 + +items.weapon.enchantments.enchantmentearth2.name=酸蚀%s +items.weapon.enchantments.enchantmentearth2.desc=酸蚀附魔有几率给目标上腐酸。 + +items.weapon.enchantments.enchantmentshock2.name=电震%s +items.weapon.enchantments.enchantmentshock2.desc=电震附魔有几率给目标上静电效果。 + +items.weapon.enchantments.enchantmentice2.name=寒潮%s +items.weapon.enchantments.enchantmentice2.desc=寒潮有几率给目标上寒冷和潮湿效果。 + +items.weapon.enchantments.aresleech.name=抽灵%s +items.weapon.enchantments.aresleech.desc=抽灵附魔能将造成的伤害转为能量,缓慢的输送回你的身体。 +items.weapon.enchantments.aresleech.effect=从附近的敌人处吸取了%s点能量。 +items.weapon.enchantments.aresleech$healdamage.name=萃取 +items.weapon.enchantments.aresleech$healdamage.desc=你的武器正在缓慢将吸收到的灵魂回馈给你。\n\n灵魂会被转化为生命恢复,而非直接回复。\n\n剩余的生命恢复:%d点 + +items.weapon.enchantments.buzzsaw.name=充能%s +items.weapon.enchantments.buzzsaw.desc=充能附魔能通过消耗露珠,来造成短时间内的大量伤害。 +items.weapon.enchantments.buzzsaw.fuel=低能源警告! +items.weapon.enchantments.buzzsaw.off=过载关闭! + +items.weapon.enchantments.cromluck.name=锯骨%s +items.weapon.enchantments.cromluck.desc=锯骨附魔能够无视防御造成一次额外的伤害。 + +items.weapon.enchantments.jupitershorror.name=威慑%s +items.weapon.enchantments.jupitershorror.desc=威慑附魔能够恐吓目标。 + +items.weapon.enchantments.lokispoison.name=猛毒%s +items.weapon.enchantments.lokispoison.desc=猛毒附魔能给目标下毒。 + +items.weapon.enchantments.neptuneshock.name=休克%s +items.weapon.enchantments.neptuneshock.desc=休克附魔能对多个目标造成伤害。 + +###relic +items.weapon.melee.relic.aressword.name=萃魂长剑 +items.weapon.melee.relic.aressword.desc=这柄剑的厚长利刃闪烁着令人宽心的寒光,不过这长度也确实让它非常沉重。——Watabou\n借由紫色魔法石的能量,这把武器可以吸取周围敌人的生命精华并将其回报至持有者。——Lynn +items.weapon.melee.relic.aressword.ac_regen=灵魂萃取 +items.weapon.melee.relic.cromcruachaxe.name=碎肉巨斧 +items.weapon.melee.relic.cromcruachaxe.desc=这个巨型的战斧无坚不摧,重如泰山,举过肩才有空间挥舞。——00-Evan\n借由橙色魔法石的能量,这把武器可以使持有者周围生成一种类似于龙鳞的外壳,以抵抗外来的魔法攻击。——Lynn +items.weapon.melee.relic.cromcruachaxe.ac_dispel=奥术护盾 +items.weapon.melee.relic.lokisflail.name=重型链枷 +items.weapon.melee.relic.lokisflail.desc=铁链上附着的一个带刺的钢球。笨重难用,能命中的话威力极强。——00-Evan\n借由绿色魔法石的能量,这把武器可以匿藏使用者的身形,使其更加容易对敌人发动袭击。——Lynn +items.weapon.melee.relic.lokisflail.ac_stealth=魔法隐形 +items.weapon.melee.relic.neptunustrident.name=三叉水戟 +items.weapon.melee.relic.neptunustrident.desc=前端装有三根尖刃的长柄武器。——Jinkeloid\n借由蓝色魔法石的能量,这把武器可以在小范围内制造降雨,减缓敌人的移动速度并且将它们脚下的平地转化为水滩。——Lynn +items.weapon.melee.relic.neptunustrident.ac_flood=风暴降雨 +items.weapon.melee.relic.jupiterswraith.name=落岩圆刃 +items.weapon.melee.relic.jupiterswraith.ac_explode=落岩爆裂 +items.weapon.melee.relic.jupiterswraith.desc=只要能熟练使用,它能在击中目标后返回,即便这原理不明。——Consideredhamster \n 借由黄色魔法石的力量,这件武器可以在目标地点制造小范围的落石,将其中的敌人埋入土地以使它们应对接下来的攻击。——Lynn + +###melee weapons + +items.weapon.melee.assassinsblade.name=暗杀之刃 +items.weapon.melee.assassinsblade.desc=黑曜石制的波浪形短刃,虽轻便但不易用,如果能击中要害足以致命。——00-Evan \n穿刺 + +items.weapon.melee.battleaxe.name=战斧 +items.weapon.melee.battleaxe.desc=这把有着硕大钢制头部的战斧能将庞大的力量倾注在每次挥舞之中。——Watabou \n割裂 + +items.weapon.melee.club.name=棒槌 +items.weapon.melee.club.desc=一件简单而沉重的木质武器。——Snof33 \n钝器 + +items.weapon.melee.dagger.name=匕首 +items.weapon.melee.dagger.desc=配以磨损木柄的简单钢匕首。——Watabou \n穿刺 + +items.weapon.melee.dualknive.name=对剑 +items.weapon.melee.dualknive.desc=成对的刀片带来更高的伤害。——Bilboldev \n穿刺 + +items.weapon.melee.special.errorw.name=错误武器 +items.weapon.melee.special.errorw.desc=这是个错误。——??? \n混沌 + +items.weapon.melee.fightgloves.name=战斗拳套 +items.weapon.melee.fightgloves.desc=简单的皮革加上金属尖块形成了这样一件武器。——Juh9870 \n钝器 + +items.weapon.melee.glaive.name=关刀 +items.weapon.melee.glaive.desc=由一支长木杆和末端接上的利刃组成。——Watabou \n致残 + +items.weapon.melee.gsword.name=巨剑 +items.weapon.melee.gsword.desc=这把大剑进行的每次沉重挥舞都能造成大量伤害。——00-Evan \n割裂 + +items.weapon.melee.halberd.name=戟斧 +items.weapon.melee.halberd.desc=长枪和战斧组合而成的武器。——Consideredhamster \n致残 + +items.weapon.melee.handaxe.name=手斧 +items.weapon.melee.handaxe.desc=一把轻斧头,通常用来砍树。当然,它的宽刃对敌人来说同样有效。——00-Evan \n割裂 + +items.weapon.melee.special.handcannon.name=奥能火炮 +items.weapon.melee.special.handcannon.ac_on=启动过载 +items.weapon.melee.special.handcannon.ac_off=关闭过载 +items.weapon.melee.special.handcannon.power_on=过载模式启动! +items.weapon.melee.special.handcannon.power_off=过载模式关闭。 +items.weapon.melee.special.handcannon.desc=人类发明了火器,矮人强化并改进了它。作为这个世界为数不多的火器之一,这件巨炮可以从很远的地方打击目标。——Consideredhamster \n??? + +items.weapon.melee.knuckles.name=指虎 +items.weapon.melee.knuckles.desc=基本上就是带有钢刃的指节套。——Watabou \n致残 + +items.weapon.melee.lance.name=骑士枪 +items.weapon.melee.lance.desc=结实的铁棒连接着巨大圆锥,形成了这么一件武器。——Hmdzl001 \n穿刺 + +items.weapon.melee.magebook.name=魔典 +items.weapon.melee.magebook.desc=一本法师高塔里的厚重魔典。内容十分难懂。——Coconut \n钝器 + +items.weapon.melee.nunchakus.name=双截棍 +items.weapon.melee.nunchakus.desc=两根粗短的木棍被结实的绳索连接,形成了这么一件武器。——Hmdzl001 \n高级钝器 + +items.weapon.melee.rapier.name=刺剑 +items.weapon.melee.rapier.desc=一件又细又长又尖的武器。——Snof33 \n高级穿刺 + +items.weapon.melee.special.runicblade.name=符文之刃 +items.weapon.melee.special.runicblade.ac_reforge=重铸 +items.weapon.melee.special.runicblade.choose=选择要强化的武器 +items.weapon.melee.special.runicblade.reforged=你用符文之刃强化了你的武器。 +items.weapon.melee.special.runicblade.desc=来自失落之地的神秘武器,有着明亮的蓝色刀刃。——00-Evan \n精炼 + +items.weapon.melee.scimitar.name=弯刀 +items.weapon.melee.scimitar.desc=一把厚重的弯刀。它的形状能让它进行更快但不甚强力的攻击。——00-Evan \n高级割裂 + +items.weapon.melee.shortsword.name=短剑 +items.weapon.melee.shortsword.desc=它确实相当短,不比一把匕首长出几英寸。——Watabou \n割裂 + +items.weapon.melee.spear.name=长矛 +items.weapon.melee.spear.desc=这是一根装着锋锐铁刺的细长木杆。——Watabou \n致残 + +items.weapon.melee.special.spork.name=皇室餐具 +items.weapon.melee.special.spork.desc=一把将叉子和勺子结合在一起的餐具。说真的,这是一把武器?——Dachhack \n暴食 + +items.weapon.melee.special.tekkokagi.name=攻击之爪 +items.weapon.melee.special.tekkokagi.desc= 看起来像金刚狼爪子的忍者武器。——Typedscroll \n致死 + +items.weapon.melee.warhammer.name=战锤 +items.weapon.melee.warhammer.desc=很少有生物能抵挡这铅铁巨块的辗压,但也只有最强壮的冒险者才能有效使用它。——Watabou \n钝器 + +items.weapon.melee.whip.name=长鞭 +items.weapon.melee.whip.desc=虽然这把武器另一端带倒刺的绳子伤害不高,但它的攻击范围是数一数二的。——00-Evan \n高级致残 + +items.weapon.melee.special.wraithbreath.name=幽灵之息 +items.weapon.melee.special.wraithbreath.desc=.................——无聊 \n恐吓 + +items.weapon.melee.special.pumpkin.name=南瓜灯 +items.weapon.melee.special.pumpkin.desc=已经被点燃的南瓜灯。万圣节快乐!\n引燃,照明,恐吓,甜食 + +items.weapon.melee.special.tree.name=圣诞树 +items.weapon.melee.special.tree.desc=一个简单的圣诞树装饰物。圣诞节快乐!\n溅射,虚弱,礼物 + +items.weapon.melee.special.firecracker.name=鞭炮 +items.weapon.melee.special.firecracker.desc=传统的800响鞭炮。2018春节快乐!\n爆裂,引燃,喧闹,恐吓 + +items.weapon.melee.special.hookham.name=钩子和火腿 +items.weapon.melee.special.hookham.desc=是时候来cos海盗了。2018暑假快乐!\n礼物,恢复,割裂 + +items.weapon.melee.triangolo.name=三角铁 +items.weapon.melee.triangolo.desc=用细钢条弯制成三角形的打击乐器。用金属棒敲击后就会发出清脆悦耳的声音。\n共振 + +items.weapon.melee.flute.name=长笛 +items.weapon.melee.flute.desc=一根有着许多小孔的空心木棍,吹奏起来会发出尖锐的啸声。\n共振 + +items.weapon.melee.wardurm.name=战鼓 +items.weapon.melee.wardurm.desc=发音较低,但很响亮。被用于鼓舞士气或指挥战斗。 \n高级共振 + +items.weapon.melee.trumpet.name=小号 +items.weapon.melee.trumpet.desc=铜管乐器家族中音域最高的乐器,常负责旋律部分或高吭节奏的演奏。\n共振 + +items.weapon.melee.harp.name=竖琴 +items.weapon.melee.harp.desc=世界上最古老的拨弦乐器之一。 \n共振 + +items.weapon.melee.woodenstaff.name=木杖 +items.weapon.melee.woodenstaff.desc=用特殊木头雕刻而成的棍子。——dachhack \n积蓄 + +items.weapon.melee.mace.name=硬头锤 +items.weapon.melee.mace.desc=这把武器前端的大型铁头能够造成可观的伤害。——Watabou \n积蓄 + +items.weapon.melee.holywater.name=圣水 +items.weapon.melee.holywater.desc=被祝福过的水。——??? \n高级积蓄 + +items.weapon.melee.prayerwheel.name=转经轮 +items.weapon.melee.prayerwheel.desc=就是转经轮。——??? \n积蓄 + +items.weapon.melee.stonecross.name=十碑 +items.weapon.melee.stonecross.desc=一个巨大的石头十字碑。——Coconut \n积蓄 + +items.weapon.melee.special.goei.name=驱魔御币 +items.weapon.melee.special.goei.desc=一把驱魔御币,博丽的巫女常用它来治退妖魔鬼怪。——REN\n除秽,积蓄 + +items.weapon.melee.special.brick.name=砖头 +items.weapon.melee.special.brick.desc=一块由泥土烧成的普通砖头。劳动节辛苦了。\n高级钝器,易碎-报酬 + +items.weapon.melee.special.lollipop.name=棒棒糖 +items.weapon.melee.special.lollipop.desc=很难想象这样的食物是一把武器。儿童节快乐!\n粘滞,迷人,易碎-失落 + +items.weapon.melee.special.sjrbmusic.name=S-J-R-B音乐套装 +items.weapon.melee.special.sjrbmusic.desc=这是一个知名的虚拟表演者的服装。2019暑假快乐!\n共振,高级穿刺,迷人,喧闹 +items.weapon.melee.special.sjrbmusic.rap=鸡你太美!!! + +items.weapon.melee.special.keyweapon.name=天堂之门 +items.weapon.melee.special.keyweapon.desc=奇怪的钥匙武器。共战2020疫情纪念!\n钝器,穿刺,警示 + +items.weapon.melee.zero.woodenhammer.name=简易木槌 +items.weapon.melee.zero.woodenhammer.desc=一把普通的小木槌——路易基。 \n钝器,易碎-暴击 + +items.weapon.melee.zero.emptypotion.name=空瓶 +items.weapon.melee.zero.emptypotion.desc=一个普通的空瓶子——???。 \n共振,易碎-暴击 + +items.weapon.melee.special.linksword.name=海拉鲁传奇 +items.weapon.melee.special.linksword.desc=海拉鲁大陆上颇具传奇色彩的武器组。\n传奇 +items.weapon.melee.special.linksword.ac_wisdom=智慧守护 +items.weapon.melee.special.linksword.ac_power=力量压制 +items.weapon.melee.special.linksword.ac_courage=勇气回旋 +items.weapon.melee.special.linksword.power=这把武器看起来更优质了。 +items.weapon.melee.special.linksword.charge=能量:%d / %d。 +items.weapon.melee.special.linksword.no=没有能量了。 + +items.weapon.melee.special.diamondpickaxe.name=史蒂夫的钻石镐 +items.weapon.melee.special.diamondpickaxe.desc=一把钻石做的镐。\n时运,耐久,效率,锋利,精准,杀手 +items.weapon.melee.special.diamondpickaxe.ac_mine=挖掘 +items.weapon.melee.special.diamondpickaxe.no_thing=这里没东西好挖了。 +items.weapon.melee.special.diamondpickaxe.noise=挖掘惊动了附近的怪物。 + +items.weapon.melee.special.shadoweater.name=暗噬 +items.weapon.melee.special.shadoweater.desc=受诅咒的武器,是由测试者们的合作产生的。\n休眠-双刃,低语 +items.weapon.melee.special.shadoweater.charge=暗影:%d / 20。 +items.weapon.melee.special.shadoweater.ac_awake=唤醒 +items.weapon.melee.special.shadoweater.ac_uncurse=驱逐 +items.weapon.melee.special.shadoweater.awake=血... +items.weapon.melee.special.shadoweater.bleeding=无需血肉... +items.weapon.melee.special.shadoweater.silent=无需言语... +items.weapon.melee.special.shadoweater.locked=无需帮助... +items.weapon.melee.special.shadoweater.stand=无需移动... + +items.weapon.melee.block.goblinshield.name=哥布林神盾 +items.weapon.melee.block.goblinshield.desc=一面来自哥布林部落的萨满盾牌。\n奇迹,招架 +items.weapon.melee.block.goblinshield.charge=能量:%d / 10。 + +items.weapon.melee.block.tengusword.name=天狗太刀 +items.weapon.melee.block.tengusword.desc=天狗所使用的太刀。\n割裂,招架 + +items.weapon.melee.block.spknuckles.name=特制指虎 +items.weapon.melee.block.spknuckles.desc=指虎教徒所崇拜的指虎。\n钝器,招架 + + +###items.weapon.melee..name= +###items.weapon.melee..desc= + +items.weapon.melee.meleeweapon.stats_known=这件_%1$d阶_近战武器可以造成_%2$d~%3$d点伤害_,并且需要_%4$d点力量_来正常使用。 +items.weapon.melee.meleeweapon.stats_known2=这件武器的命中为_%1$s_,攻击延迟为_%2$s_,攻击距离为_%3$d_。 +items.weapon.melee.meleeweapon.stats_unknown=一般而言这件_%1$d阶_近战武器可以造成_%2$d~%3$d点伤害_,并且需要_%4$d点力量_来正常使用。 +items.weapon.melee.meleeweapon.too_heavy=你的力量不足以完美使用它。 +items.weapon.melee.meleeweapon.probably_too_heavy=没准你的力量不足以完美使用它。 +items.weapon.melee.meleeweapon.excess_str=你的额外力量让你在使用这件武器时能够造成_%d点额外伤害_。 +items.weapon.melee.meleeweapon.identify=你对手中的武器已经足够熟悉并将其完全鉴定。 +items.weapon.melee.meleeweapon.incompatible=不同属性的魔法相冲突,消除了武器上的附魔! +items.weapon.melee.meleeweapon.cursed_worn=由于这件武器被诅咒,你无法将其放下。 +items.weapon.melee.meleeweapon.cursed=你能感觉到这件武器里潜伏着一股充满恶意的魔力。 +items.weapon.melee.meleeweapon.enchanted=这件武器已经被附魔了,%s + +items.weapon.melee.meleeweapon.stats_desc=...\n + +items.weapon.weapon.identify=你对%s已经足够熟悉并且可以因此将其完全鉴定。它是%s。 +items.weapon.weapon.avg_dmg=它能造成_%1$d~%2$d点伤害_。 +items.weapon.weapon.too_heavy=因为你的力量不足,使用该武器时的攻速和精准都会减少。 +items.weapon.weapon.incompatible=不同属性的魔法相冲突,消除了武器上的附魔! + +items.weapon.weapon.charge=充能:%d / %d。 + +###test Guns +items.weapon.guns.toygun.name=玩具枪 +items.weapon.guns.toygun.desc=一把简易的玩具枪,2019新年快乐。 +items.weapon.guns.toygun.ac_shoot=射击 +items.weapon.guns.toygun.ac_reload=填弹 +items.weapon.guns.toygun.reloading=填弹中 +items.weapon.guns.toygun.need_to_equip=你需要先装备这件武器才能射击 +items.weapon.guns.toygun.full=弹夹已满 +items.weapon.guns.toygun.empty=弹药不足 +items.weapon.guns.toygun.prompt=选择射击目标 +items.weapon.guns.toygun.stats_known=这件_%1$d阶_武器可以造成_%2$d~%3$d点伤害_,并且需要_%4$d点力量_来正常使用。 + +items.weapon.guns.toygun.stats_desc=...\n + +items.weapon.guns.toygun.charge=弹药:%d / %d。 + +items.weapon.guns.gunweapon.ac_shoot=射击 +items.weapon.guns.gunweapon.ac_reload=填弹 +items.weapon.guns.gunweapon.ac_ammo=切换子弹 +items.weapon.guns.gunweapon.reloading=填弹中 +items.weapon.guns.gunweapon.stats_desc=...\n +items.weapon.guns.gunweapon.need_to_equip=你需要先装备这件武器才能射击 +items.weapon.guns.gunweapon.prompt2=选择加载的强化弹药 +items.weapon.guns.gunweapon.full=弹夹已满 +items.weapon.guns.gunweapon.empty=弹药不足 +items.weapon.guns.gunweapon.imbue=你加载了%d。 +items.weapon.guns.gunweapon.ammo_add=当前强化弹药: +items.weapon.guns.gunweapon.warning=确定加载这种弹药?原先的弹药将被替换 +items.weapon.guns.gunweapon.yes=是的 +items.weapon.guns.gunweapon.no=不要 + +items.weapon.guns.guna.name=枪械A +items.weapon.guns.guna.desc=高塔根据前时间旅行的报告所制作的实验性枪械,被投入到无害的环境中进行测试。 + +items.weapon.guns.gunb.name=枪械B +items.weapon.guns.gunb.desc=高塔基于无害环境下的试验结果制作的枪械,被投入到相对危险的环境中进行测试。 + +items.weapon.guns.gunc.name=枪械C +items.weapon.guns.gunc.desc=高塔基于相对危险的环境下的试验结果制作的枪械,被投入到极其危险的环境中进行压力测试。 + +items.weapon.guns.gund.name=枪械D +items.weapon.guns.gund.desc=高塔基于极其危险的环境下的试验结果制作的枪械,被投入到战争环境中进行测试。 + +items.weapon.guns.gune.name=枪械E +items.weapon.guns.gune.desc=高塔基于战争环境下的试验结果制作的枪械,被投入到地狱中进行测试。 + +items.weapon.guns.sling.name=投石索 +items.weapon.guns.sling.desc=简单而极具伤害的武器原型。 + +items.weapon.spammo.heavyammo.name=重铅弹 +items.weapon.spammo.heavyammo.desc=将两枚原石组合而成的特殊子弹,能使枪械附带更高的伤害。 + +items.weapon.spammo.fireammo.name=燃烧弹 +items.weapon.spammo.fireammo.desc=将原石和火焰种组合而成的特殊子弹,能使枪械附带火焰的伤害。 + +items.weapon.spammo.iceammo.name=寒霜弹 +items.weapon.spammo.iceammo.desc=将原石和寒冰种组合而成的特殊子弹,能使枪械附带寒冰的伤害。 + +items.weapon.spammo.stormammo.name=雷暴弹 +items.weapon.spammo.stormammo.desc=将原石和风暴种组合而成的特殊子弹,能使枪械附带雷电的伤害。 + +items.weapon.spammo.mossammo.name=淬毒弹 +items.weapon.spammo.mossammo.desc=将原石和毒药种组合而成的特殊子弹,能使枪械附带毒液的伤害。 + +items.weapon.spammo.blindammo.name=闪光弹 +items.weapon.spammo.blindammo.desc=将原石和致盲种组合而成的特殊子弹,能使枪械附带致盲效果。 + +items.weapon.spammo.starammo.name=陨星弹 +items.weapon.spammo.starammo.desc=将原石和星陨种组合而成的特殊子弹,能使枪械附带更高的伤害。 + +items.weapon.spammo.dreamammo.name=催眠弹 +items.weapon.spammo.dreamammo.desc=将原石和睡眠种组合而成的特殊子弹,能使枪械附带催眠的效果。 + +items.weapon.spammo.dewammo.name=碎片弹 +items.weapon.spammo.dewammo.desc=将原石和露珠种组合而成的特殊子弹,能使枪械附带多段伤害。 + +items.weapon.spammo.sunammo.name=活性弹 +items.weapon.spammo.sunammo.desc=将原石和恢复种组合而成的特殊子弹,能使枪械附带吸取的效果。 + +items.weapon.spammo.sandammo.name=烟尘弹 +items.weapon.spammo.sandammo.desc=将原石和消逝种组合而成的特殊子弹,能使枪械附带削弱的效果。 + +items.weapon.spammo.goldammo.name=彩票弹 +items.weapon.spammo.goldammo.desc=将原石和种子荚组合而成的特殊子弹,能使枪械附带金币的伤害。 + +items.weapon.spammo.emptyammo.name=空心弹 +items.weapon.spammo.emptyammo.desc=将原石和无味种组合而成的特殊子弹...这有什么用? + +items.weapon.spammo.rotammo.name=腐败弹 +items.weapon.spammo.rotammo.desc=将原石和腐梅种组合而成的特殊子弹,能使枪械附带致死的效果。 + +items.weapon.spammo.evolveammo.name=退化弹 +items.weapon.spammo.evolveammo.desc=将原石和转换种组合而成的特殊子弹,能使枪械附带退化的效果。 + +items.weapon.spammo.thornammo.name=荆棘弹 +items.weapon.spammo.thornammo.desc=将原石和地种组合而成的特殊子弹,能使枪械附带流血的效果。 + +items.weapon.spammo.battleammo.name=战斗弹 +items.weapon.spammo.battleammo.desc=将原石和吞星种组合而成的特殊子弹,能使增加战斗的力量。 + +items.weapon.spammo.woodenammo.name=软木弹 +items.weapon.spammo.woodenammo.desc=将原石和坚果组合而成的特殊子弹,能击晕目标。 + +###missile weapons +items.weapon.missiles.empbola.name=电磁套索 +items.weapon.missiles.empbola.desc=用于抓捕或狩猎的工具之一,能够减缓目标的移动甚至将其麻痹。 + +items.weapon.missiles.boomerang.name=回旋镖 +items.weapon.missiles.boomerang.ac_ammo=涂油 +items.weapon.missiles.boomerang.prompt=选择用于涂抹的强化子弹 +items.weapon.missiles.boomerang.desc=被投向敌人后,这具扁平的曲状木制投掷物能够自动回到投掷者手中。此外这个回旋镖可以使用强化子弹强化。 + +items.weapon.missiles.manyknive.name=十六夜的千支刀 +items.weapon.missiles.manyknive.ac_shoot=投掷 +items.weapon.missiles.manyknive.ac_ammo=涂油 +items.weapon.missiles.manyknive.prompt=选择用于涂抹的强化子弹 +items.weapon.missiles.manyknive.desc=由大量普通飞刀组成的飞刀组。此外这个飞刀组可以使用强化子弹强化。 +items.weapon.missiles.manyknive.damage=这件武器可以造成_%d - %d 点伤害_,拥有较高的攻速。 + +items.weapon.missiles.taurcenbow.name=马人长弓 +items.weapon.missiles.taurcenbow.ac_shoot=射击 +items.weapon.missiles.taurcenbow.ac_break=破甲箭头 +items.weapon.missiles.taurcenbow.ac_fire=燃烧箭头 +items.weapon.missiles.taurcenbow.ac_ice=霜冻箭头 +items.weapon.missiles.taurcenbow.ac_posion=腐蚀箭头 +items.weapon.missiles.taurcenbow.ac_ele=电磁箭头 +items.weapon.missiles.taurcenbow.desc=一把结实的复合弓,在马人族中这种弓就是上等品 +items.weapon.missiles.taurcenbow.damage=这件武器可以造成_%d - %d 点伤害_,并可以在不同类型的箭头间切换。当攻击足够次数后,下一次的攻击会附加特殊箭头。 +items.weapon.missiles.taurcenbow.charge=充能:%d / %d。 + +items.weapon.missiles.forestdart.name=森林飞刀 +items.weapon.missiles.forestdart.desc=受到森林的祝福的飞刀,能造成大量的伤害。 + +items.weapon.missiles.incendiarydart.name=燃烧飞镖 +items.weapon.missiles.incendiarydart.desc=飞镖上的刺能让它钉入目标,而在飞镖上的不稳定物质则会在目标身上燃起烈焰。 + +items.weapon.missiles.hugeshuriken.name=巨型手里剑 +items.weapon.missiles.hugeshuriken.desc=锋锐的星形金属刃片能有效伤害目标,并大幅削弱目标的意志。 + +items.weapon.missiles.escapeknive.name=逃脱小刀 +items.weapon.missiles.escapeknive.desc=简单的金属片,但可以帮你从困境中逃脱。 + +items.weapon.missiles.normalbomb.name=空弹 +items.weapon.missiles.normalbomb.desc=这个炸弹里面没有火药,看起来没有什么特别。 + +items.weapon.missiles.poisondart.name=毒镖 +items.weapon.missiles.poisondart.desc=这种飞镖上覆盖着某种毒素,可以轻松的麻痹目标的神经,使其无法反抗。 + +items.weapon.missiles.riceball.name=糯米团 +items.weapon.missiles.riceball.desc=用于投食的食物,由于其量大份足,任何食用它的有生命的怪物都会去寻找一个安全的地方来美美睡上一觉。 + +items.weapon.missiles.smoke.name=烟雾弹 +items.weapon.missiles.smoke.desc=手里剑形状的烟雾弹,能制造小范围的烟雾。 + +items.weapon.missiles.skull.name=鬼骨镖 +items.weapon.missiles.skull.desc=一种邪恶的东西,能使你吸取目标的生命。 + +items.weapon.missiles.tamahawk.name=致命飞斧 +items.weapon.missiles.tamahawk.desc=这种投掷斧并没有多重,却需要相当的力量才能有效运用它。 + +items.weapon.missiles.wave.name=声波诱饵 +items.weapon.missiles.wave.desc=这个东西能够迷惑被击中的敌人,使它狂乱并被致盲 + +items.weapon.missiles.shatteredammo.name=破片炸弹 +items.weapon.missiles.shatteredammo.desc=虽然看起来非常怪,但是这东西爆炸所造成的伤害非常高 + +items.weapon.missiles.errorammo.name=错误弹丸 +items.weapon.missiles.errorammo.desc=这个是个错误 + +items.weapon.missiles.minimoai.name=迷你复活节岛石雕 +items.weapon.missiles.minimoai.desc=一个旅游纪念品,就当是复活节的彩蛋吧 + +items.weapon.missiles.pocketball.name=引魂灯 +items.weapon.missiles.pocketball.desc=一种空的容器,将其扔向你的宠物可以将它收服,以方便携带或者出售。 +items.weapon.missiles.pocketball.get_pet=你回收了这只宠物的灵魂。 + +items.weapon.missiles.moneypack.name=红包 +items.weapon.missiles.moneypack.desc=只要准备好钱,在春节就能解决好多问题。2020春节快乐!!! + +##mc block +items.weapon.missiles.buildblock.wallblock.name=墙块 +items.weapon.missiles.buildblock.wallblock.desc=一种墙块。 + +items.weapon.missiles.buildblock.doorblock.name=门块 +items.weapon.missiles.buildblock.doorblock.desc=一种门块。 + +items.weapon.missiles.buildblock.stoneblock.name=雕块 +items.weapon.missiles.buildblock.stoneblock.desc=一种雕块。 + +items.weapon.missiles.buildblock.bookblock.name=书块 +items.weapon.missiles.buildblock.bookblock.desc=一种书块。 + +items.weapon.missiles.buildblock.woodenblock.name=木块 +items.weapon.missiles.buildblock.woodenblock.desc=一种木块。 + +items.weapon.missiles.buildblock.waterblock.name=水块 +items.weapon.missiles.buildblock.waterblock.desc=一种水块。 + +items.wateritem2.name=水块 +items.wateritem2.pour=使用。 +items.wateritem2.desc=一种水块。 + +##eggs +items.eggs.egg.prevent=这里不是尝试召唤它的最佳地点。 +items.eggs.egg.notready=你的宠物还没有准备好和其他宠物相处。 +items.eggs.egg.yolk=一些能量四下流散。 +items.eggs.egg.name=魔物之魂 +items.eggs.egg.hatch=新的宠物诞生! +items.eggs.egg.scratch=灵魂简单的回应了你的呼喊! +items.eggs.egg.slithers=灵魂回应了你的呼喊! +items.eggs.egg.kick=灵魂强烈的回应了你的呼喊! +items.eggs.egg.slosh=灵魂没什么反应。 +items.eggs.egg.zap=灵魂用强大的能量回应了你的呼喊,并对你造成了伤害! +items.eggs.egg.ac_break=召唤 +items.eggs.egg.ac_shake=呼喊 +items.eggs.egg.warmhome=这个灵魂在你温暖的背包里吸收能量。 +items.eggs.egg.onlyone=只有一个灵魂能在背包里面吸收能量。 +items.eggs.egg.desc=一个怪物的灵魂。根据吸收能量的不同,产生的结果也会不同。 +items.eggs.egg.moves=无属性:%d +items.eggs.egg.burns=火属性:%d +items.eggs.egg.freezes=冰属性:%d +items.eggs.egg.poisons=地属性:%d +items.eggs.egg.lits=雷属性:%d +items.eggs.egg.summons=暗属性:%d +items.eggs.egg.light=光属性:%d + +items.eggs.easteregg.name=节日之魂 +items.eggs.easteregg.desc=来自复活节的怪物之魂。看起来很可爱。 + +items.eggs.cococategg.name=爆破之魂 +items.eggs.cococategg.desc=炸弹,炸弹,炸弹!我想我会弄一个这样的boss的。 + +items.eggs.randomegg.name=随机灵魂 +items.eggs.randomegg.desc=召唤一个随机的基础宠物。 + +items.eggs.shadowdragonegg.name=暗之龙魂 +items.eggs.shadowdragonegg.desc=光明所孕化的龙的灵魂。 + +items.eggs.leryfireegg.name=紊乱之魂 +items.eggs.leryfireegg.desc=如果把一些元素乱七八糟的组合在一起,我想你也可以获得这样一个灵魂。@ + +items.eggs.bluedragonegg.name=蓝龙之魂 +items.eggs.bluedragonegg.desc=冰霜所孕化的龙的灵魂。 + +items.eggs.lightdragonegg.name=白龙之魂 +items.eggs.lightdragonegg.desc=黑暗所孕化的龙的灵魂。 + +items.eggs.greendragonegg.name=绿龙之魂 +items.eggs.greendragonegg.desc=雷电所孕化的龙的灵魂。 + +items.eggs.reddragonegg.name=红龙之魂 +items.eggs.reddragonegg.desc=烈焰所孕化的龙的灵魂。 + +items.eggs.scorpionegg.name=毒蛰之魂 +items.eggs.scorpionegg.desc=看起来是一只巨大的蝎子。 + +items.eggs.spideregg.name=绒毛之魂 +items.eggs.spideregg.desc=看起来是一只巨大的蜘蛛。 + +items.eggs.velociroosteregg.name=鸡神之魂 +items.eggs.velociroosteregg.desc=在某个地方它很强。 + +items.eggs.violetdragonegg.name=紫龙之魂 +items.eggs.violetdragonegg.desc=大地所孕化的龙的灵魂。 + +items.eggs.golddragonegg.name=金龙之魂 +items.eggs.golddragonegg.desc=万物合为一体的龙的灵魂。 + +items.eggs.yearpetegg.name=年兽之魂 +items.eggs.yearpetegg.desc=年兽宝宝的灵魂。 + +##Bombs +items.bombs.bomb.name=炸弹 +items.bombs.bomb.ac_lightthrow=点燃并扔出 +items.bombs.bomb.snuff_fuse=你迅速掐灭了炸弹引线。 +items.bombs.bomb.desc=一颗颇庞大的黑火药炸弹。它炸起来周围全得遭殃。\n\n看起来引信在点燃后能烧几回合。 +items.bombs.bomb.desc_burning=一颗颇庞大的黑火药炸弹。它炸起来周围全得遭殃。\n\n引信快烧完了,保持距离或者赶紧掐灭! + +items.bombs.firebomb.name=火焰炸弹 +items.bombs.firebomb.desc=造成范围油雾和燃烧效果。 + +items.bombs.icebomb.name=寒霜炸弹 +items.bombs.icebomb.desc=造成范围霜冻效果。 + +items.bombs.earthbomb.name=酸蚀炸弹 +items.bombs.earthbomb.desc=造成范围酸蚀和长草效果。 + +items.bombs.fishingbomb.name=鱼饵炸弹 +items.bombs.fishingbomb.no_tp=这里已经没有干燥的地方了。 +items.bombs.fishingbomb.tp=有什么上钩了。 +items.bombs.fishingbomb.desc=转移范围内所有的生物。 + +items.bombs.stormbomb.name=风暴炸弹 +items.bombs.stormbomb.desc=造成范围雷电效果。 + +items.bombs.darkbomb.name=暗黑炸弹 +items.bombs.darkbomb.desc=造成范围伤害,对生物有增益伤害。 + +items.bombs.hugebomb.name=巨大炸弹 +items.bombs.hugebomb.desc=造成大范围伤害,并摧毁墙壁。 + +items.bombs.lightbomb.name=圣光炸弹 +items.bombs.lightbomb.desc=造成范围伤害,对邪物有增益伤害。 + +items.bombs.dungeonbomb.name=地牢炸弹 +items.bombs.dungeonbomb.desc=造成范围伤害,并摧毁墙壁。\n\n看起来引信在点燃后能烧几回合。 +items.bombs.dungeonbomb$doublebomb.name=一对炸弹 +items.bombs.dungeonbomb$doublebomb.desc=两枚装的黑火药重装炸弹,看起来多出来的那个是免费送你的! + +items.bombs.buildbomb.name=土制炸弹 +items.bombs.buildbomb.desc=造成范围伤害,可用于制作其他炸弹。 + +items.bombs.minibomb.name=迷你炸弹 +items.bombs.minibomb.desc=造成伤害。 + +###tp items +items.tengukey.name=匿藏地传送门 +items.tengukey.ac_port=使用 +items.tengukey.desc=一张标有天狗头像的传送道具。没准它通往哪个地方。 + +items.potkey.name=罐罐的挑战函 +items.potkey.ac_port=使用 +items.potkey.desc=蜜蜂罐罐给出的传送道具。没准它通往哪个地方。 + +items.shadoweaterkey.name=暗噬 +items.shadoweaterkey.ac_port=装备 +items.shadoweaterkey.desc=受诅咒的武器,是由测试者们的合作产生的。\n休眠-双刃,低语\n\n这件_4阶_近战武器可以造成_4~22点伤害_,并且需要_16点力量_来正常使用。 + +items.treasuremap.name=密藏宝图 +items.treasuremap.ac_port=使用 +items.treasuremap.desc=是不是有种东西叫12级杀手?我不建议你去看看。 + +items.bone.ac_port=使用 +items.bone.name=亡灵短骨 +items.bone.desc=我十分怀疑这一切是亡灵的阴谋。无论如何,去看看吧。。 + +items.conchshell.name=巨蟹海螺 +items.conchshell.ac_port=使用 +items.conchshell.desc=为什么远古洞穴里会有这种东西?你的直觉告诉你有大家伙在里面。 + +items.ancientcoin.ac_port=使用 +items.ancientcoin.name=上朝贡物 +items.ancientcoin.desc=这东西可以作为信物,用于让盗贼领主召唤你前去。 + +items.triforce.ac_port=使用 +items.triforce.name=起源三角 +items.triforce.desc=你已经通过了三种试炼,现在已经可以去和古神之影战斗了。 + +items.bossrush.name=BossRush挑战 +items.bossrush.ac_read=使用 +items.bossrush.desc=坚果制作的终级挑战,使用它将会带你前往全新Boss面前。 + +items.palantir.name=能源核心 +items.palantir.ac_port=使用 +items.palantir.desc=由Otiluke创建的虚空-能源转化装置。它可以把强大的灵魂保存下来以作为能源。 + +###reward +items.reward.sewerreward.name=下水道奖励包 +items.reward.sewerreward.ac_use=使用 +items.reward.sewerreward.desc=清理奖励,包含20枚原石。 + +items.reward.prisonreward.name=监狱奖励包 +items.reward.prisonreward.ac_use=使用 +items.reward.prisonreward.desc=清理奖励,包含一颗满月莓果。 + +items.reward.cavereward.name=洞穴奖励包 +items.reward.cavereward.ac_use=使用 +items.reward.cavereward.desc=清理奖励,包含每种莓果各10颗。 + +items.reward.cityreward.name=城市奖励包 +items.reward.cityreward.ac_use=使用 +items.reward.cityreward.desc=清理奖励,包含价值1000的食物五个。 + +##summon item +items.summon.honeypot.name=蜂蜜罐 +items.summon.honeypot.ac_shatter=击碎 +items.summon.honeypot.desc=这个巨型蜜罐只是薄薄地涂了一圈蜂蜜,作为替代里头住着一只巨型蜜蜂!这种大型蜜蜂一般只待在蜂巢里,也许罐子本身就是某种特殊陷阱屋?蜜蜂看起来对罐子很满意,当你看向它时它非常警惕地对你回以嗡鸣。 +items.summon.honeypot$shatteredpot.name=破碎的的蜂蜜罐 +items.summon.honeypot$shatteredpot.desc=这个罐子已经被打碎,仅靠罐沿的粘稠蜂蜜勉强维持形状,而且正在缓缓解体。\n\n尽管蜜罐碎了,看来蜜蜂依然想捍卫它的住所。 +items.summon.honeypot$bee.name=金色蜜蜂 +items.summon.honeypot$bee.desc=尽管它们体积小,但金色蜜蜂有着强烈的保护家园的欲望。这只蜜蜂非常疯狂,最好和它保持距离。 +items.summon.honeypot$steelbee.name=钢铁蜜蜂 +items.summon.honeypot$steelbee.desc=升级后的钢铁蜜蜂,非常疯狂,但你没必要和它保持距离。 + +items.summon.activemrdestructo.name=毁灭无人引擎 +items.summon.activemrdestructo.ac_active=使用 +items.summon.activemrdestructo.desc=毁灭无人机是矮人科技和恶魔能量制作出来的一种自律型炮塔。这东西只能使用一次。 +items.summon.activemrdestructo$mrdestructo.name=毁灭无人机 +items.summon.activemrdestructo$mrdestructo.desc=你启动了这个装置。它在攻击附近的怪物! +items.summon.activemrdestructo$mrdestructo2dot0.name=毁灭无人机2.0 +items.summon.activemrdestructo$mrdestructo2dot0.desc=你的转职强化了这个装置,它在攻击附近的怪物! + +items.summon.callcoconut.name=召唤钥匙 +items.summon.callcoconut.ac_active=使用 +items.summon.callcoconut.desc=使用以后,某个强大的家伙会和蘑菇云一起到来。 +items.summon.callcoconut$scococat.name=椰子猫 +items.summon.callcoconut$scococat.desc=来,炸个痛快。 +items.summon.callcoconut$excococat.name=EX椰子猫 +items.summon.callcoconut$excococat.desc=尝尝它的炸弹吧。 + +items.summon.mobile.name=遥控卫星 +items.summon.mobile.ac_active=使用 +items.summon.mobile.desc=用于呼叫一个小型的闪电卫星。 +items.summon.mobile$mobilesatellite.name=蓝色卫星 +items.summon.mobile$mobilesatellite.desc=这个东西貌似出现在外星飞船中。 +items.summon.mobile$exmobilesatellite.name=红色卫星 +items.summon.mobile$exmobilesatellite.desc=由马可少校改制的蓝色卫星,有更高的射速和更高的伤害。 + +items.summon.fairycard.name=精灵卡片 +items.summon.fairycard.ac_active=使用 +items.summon.fairycard.desc=进行一次抽卡,并召唤一只精灵。 +items.summon.fairycard$fairy.name=生命仙女 +items.summon.fairycard$fairy.desc=精灵的一种,出色的治疗者。 +items.summon.fairycard$sugarplumfairy.name=术士仙女 +items.summon.fairycard$sugarplumfairy.desc=精灵的一种,出色战士。 + +###misc items +items.dwarfhammer.prevent=这里不是应该使用这个的地方。 +items.dwarfhammer.unseal=你打开了前往下一层的路。 +items.dwarfhammer.ac_break=破坏封印 +items.dwarfhammer.name=破魔之锤 +items.dwarfhammer.desc=矮人族在战胜古神后,利用他们的科学魔法把古神封印在地牢深处。但如今,这些封印早已成为保护古神的保护伞。这东西可以在封印的交接处(就是楼梯入口)制造一个缺口来方便冒险者前进。另外,这东西的柄上有十分模糊的标记。你只能辨认出一个O字。 + +items.amulet.name=Yendor护身符 +items.amulet.ac_end=结束游戏 +items.amulet.desc=Yendor护身符是来自未知领域中最强大的著名神器。据说它能够实现持有者的一切愿望,只要持有者具备足够的力量来"说服"它去做。 + +items.ankh.name=重生十字架 +items.ankh.ac_bless=祝福 +items.ankh.bless=你用清水祝福了这个重生十字架。 +items.ankh.desc=这枚象征不朽的古老饰品能够起死回生。在复苏时所有未装备的道具都会丢失。 +items.ankh.desc_blessed=这枚象征不朽的古老饰品能够让人起死回生。这枚十字架已被祝福而变得更加强大。它会在危急关头牺牲自己来救你一命。 +items.ankh.revive=十字架迸发出了苏生的能量! + +items.armorkit.name=技能配件包 +items.armorkit.ac_apply=学习 +items.armorkit.desc=使用这配件包里的工具和材料,任何人都能学到他职业的专属技能,而不用付出任何代价。 + +items.dewdrop.name=露珠 +items.dewdrop.value=%+d点生命 +items.dewdrop.already_full=你的生命值已满。 +items.dewdrop.desc=一颗晶莹剔透的露珠。\n\n受这片区域的魔力影响,纯水有着少量治疗效果。 + +items.equipableitem.unequip_cursed=你无法移除一件受诅咒的物品! +items.equipableitem.ac_equip=装备 +items.equipableitem.ac_unequip=取下 + +items.gold.name=金币 +items.gold.desc=一堆金币。收集金币以在随后的商店中消费。 + +items.heap.mimic=这是一个宝箱怪! +items.heap.chest=宝箱 +items.heap.chest_desc=打开前你是看不见里面有什么的! +items.heap.locked_chest=上锁的宝箱 +items.heap.locked_chest_desc=打开前你是看不见里面有什么的!你需要一枚金钥匙才能打开它。 +items.heap.crystal_chest=水晶宝箱 +items.heap.crystal_chest_desc=你看得见里面的%s,但你需要一枚金钥匙才能打开它。 +items.heap.artifact=一件神器 +items.heap.wand=一根法杖 +items.heap.ring=一枚戒指 +items.heap.tomb=坟墓 +items.heap.tomb_desc=这个坟墓里或许埋葬着一些有用的东西,但墓主肯定是不会让你拿走的。 +items.heap.skeleton=遗骸 +items.heap.skeleton_desc=某个不幸的冒险者存在过的唯一证明。或许可以找找里面有什么值钱的东西。 +items.heap.remains=英雄遗骸 +items.heap.remains_desc=你的某个先辈存在过的唯一证明。或许能找到点什么值钱的东西。 + +items.item.pack_full=你的背包放不下%s了。 +items.item.prompt=选择丢出的方位 +items.item.ac_drop=放下 +items.item.ac_throw=扔出 +items.item.not_here=这不是使用这件传送道具的地方。 +items.item.boss_first=你需要先击败boss才能使用这件道具离开。 +items.item.item_first=你需要先站在放有关键道具的台子上,高举关键道具才能使用这件道具离开。 +items.item.reinforced=强化组件已加载。 + +items.kindofmisc.unequip_title=卸下一件装备 +items.kindofmisc.unequip_message=你只能同时装备最多三件饰品。 + +items.kindofweapon.cursed=你的手不受控制地握紧了这件武器。 + +items.kindofarmor.cursed=这件护甲痛苦得依附在你身上。 + +items.kindofweapon.destory=你的武器坏掉了。 +items.kindofweapon.almost_destory=你的武器快要坏了。 + +items.merchantsbeacon.name=商人信标 +items.merchantsbeacon.ac_use=使用 +items.merchantsbeacon.desc=这件矮人科技的奇特产物能够让你和遥远的地方通讯。\n\n激活时,这枚信标可以让你从地牢的任意角落向像素商店出售物品。\n\n不过信标内的魔法只够支撑一次会话,请酌情使用。 + +items.stylus.name=奥术刻笔 +items.stylus.ac_inscribe=蚀刻 +items.stylus.prompt=选择一样要雕刻的盔甲 +items.stylus.inscribed=你用刻笔雕刻了盔甲 +items.stylus.desc=这支奥术蚀笔由一种暗黑色的坚硬石料制成。你能用它在护甲上刻下魔法刻印,不过你无法自主选择,刻笔会替你做出决定。 + +items.torch.name=火把 +items.torch.ac_light=点燃 +items.torch.desc=冒险必备物品,每当地牢陷入黑暗之时,火把能让你走上正确的道路。 + +items.weightstone.name=磨刀石 +items.weightstone.ac_apply=改制 +items.weightstone.select=选择一件要附魔的武器 +items.weightstone.apply=你用磨刀石附魔了武器 +items.weightstone.desc=通过磨刀石,你可以轻松为武器附魔。 + +items.adamantarmor.name=焊接组件-护甲 +items.adamantarmor.desc=用于焊接护甲的组件。 +items.adamantring.name=焊接组件-戒指 +items.adamantring.desc=用于焊接戒指的组件。 +items.adamantwand.name=焊接组件-法杖 +items.adamantwand.desc=用于焊接法杖的组件。 +items.adamantweapon.name=焊接组件-武器 +items.adamantweapon.desc=用于焊接武器的组件。 + +items.dewvial.name=露珠瓶 +items.dewvial.ac_drink=恢复 +items.dewvial.value=%+d点生命 +items.dewvial.collected=你将一滴露珠收集到了瓶子里。 +items.dewvial.full=你的露珠瓶满了! +items.dewvial.empty=你的露珠瓶空了! +items.dewvial.ac_water=种植 +items.dewvial.ac_splash=加速 +items.dewvial.ac_bless=强化 +items.dewvial.ac_light=照明 +items.dewvial.ac_pour=清洗 +items.dewvial.ac_peek=侦测 +items.dewvial.ac_refine=提纯 +items.dewvial.watered=植物在你周围生长。 +items.dewvial.blessed=神秘的能量强化了你的装备。 +items.dewvial.remove_curse=你的背包散发着一股纯洁的光芒,邪恶的力量消散了。 +items.dewvial.curse=你的背包散发着一股纯洁的光芒,但是什么都没有发生。 +items.dewvial.select=选择一项要升级的物品 +items.dewvial.fly=你漂浮到了空中! +items.dewvial.light=你的周围发出幽暗的光芒,将你隐藏在了阴影之中。 +items.dewvial.fast=你的移动速度大幅提升了! +items.dewvial.pour=你用露水清洗了你的身躯,驱散了大量的负面buff。 +items.dewvial.desc=古老而神秘的魔法水瓶,被用于收集各种露珠。\n被收集的露珠可以被用于各种不同的功能。\n基础露珠瓶提供恢复,照明,提纯功能。 +items.dewvial.desc_v1=露珠瓶v1提供强化,种植功能。 +items.dewvial.desc_v2=露珠瓶v2提供清洗,加速功能。 +items.dewvial.desc_v3=露珠瓶v3提升容量,并使加速时浮空。 + +items.orbofzot.name=储能装置 +items.orbofzot.ac_activatethrow=释放能量 +items.orbofzot.ac_break=提取 +items.orbofzot.desc=一种储能装置,使用后会向外发射能量。不知为这个半透明的装置里面有一张纸片,想取出就要把这个装置破坏。 +items.orbofzot.charge=储能装置当前充能数%d,充能上限为%d。 + +items.dolyaslate.prevent=未知地点,拒绝访问。 +items.dolyaslate.ac_return=离开 +items.dolyaslate.ac_add=导入 +items.dolyaslate.ac_read=传送 +items.dolyaslate.ac_set=设置 +items.dolyaslate.ac_back=传回 +items.dolyaslate.prompt=选择导入的内容 +items.dolyaslate.name=多利亚石板 +items.dolyaslate.desc=利用多利亚盛产的魔法矿石所制作的传送道具,被用于不同地方的往返。\n虽然在这片区域里并没有什么值得记录和往返的地方,但是它支持读取其他人所记录的地点,也就是说你可以到其他人所记录的地方去。 +items.dolyaslate.charge=多利亚石板当前充能数%d,充能上限为%d。 +items.dolyaslate.add_page=坐标导入成功 + +items.challengebook.prevent=该挑战已过期。 +items.challengebook.ac_return=离开 +items.challengebook.ac_add=添加 +items.challengebook.ac_read=传送 +items.challengebook.ac_back=传回 +items.challengebook.prompt=添加一项日程 +items.challengebook.name=挑战日志 +items.challengebook.desc=一本普通的记事本,但是来自异世界的魔法使得它可以记录下特殊地点以方便传送。\n你可以把挑战纸片夹进这本记事本中。它上面的魔力会尝试读取挑战信息并帮你打开传送门。\n\n_他是一位对生活保持自然心态的浪漫主义者。人们都叫他REN或者泽智莲华,但令他最喜欢的还是赞赏自己的声音。或许少部分人认为他是个疯子亦或是哑剧演员,但不得不说他所创造的那个世界,是一个充溢着酒的香气、令人向往的幻想世界。\n\n如果这里还写的下的话我会述说鸟船的故事。那是个绿意盎然、蒸汽肆溢的宇宙空间站...\n\n我记得没错的话部分挑战里面存在隐藏奖励。如果你收集了全部的隐藏奖励,我可以考虑给你一把我所在的世界的专属武器。_ +items.challengebook.add_page=挑战记录成功 + +items.puddingcup.name=巧克力布丁 +items.puddingcup.ac_save=记忆 +items.puddingcup.desc=美味的布丁可以使你记住这一美好的瞬间。但仅仅是这一瞬间而已。 + +items.reddewdrop.name=红色露珠 +items.reddewdrop.value=%+d生命 +items.reddewdrop.desc=红色的露珠。 + +items.violetdewdrop.name=紫色露珠 +items.violetdewdrop.value=%+d生命 +items.violetdewdrop.desc=紫色的露珠 + +items.yellowdewdrop.name=黄色露珠 +items.yellowdewdrop.value=%+d生命 +items.yellowdewdrop.desc=黄色的露珠 + +items.triforceofcourage.name=勇气三角 +items.triforceofcourage.desc=起源三角的一部分,代表着勇气 +items.triforceofpower.name=力量三角 +items.triforceofpower.desc=起源三角的一部分,代表着力量 +items.triforceofwisdom.name=智慧三角 +items.triforceofwisdom.desc=起源三角的一部分,代表着智慧 + +items.stoneore.name=原石 +items.stoneore.desc=很普通的石头,可以用来卖钱,也可以拿来当调味料。 + +items.expore.name=经验之石 +items.expore.ac_use=使用 +items.expore.desc=立刻升级。 + +items.tomeofmastery.name=精通之书 +items.tomeofmastery.ac_read=阅读 +items.tomeofmastery.blind=在失明的时候你没法阅读它。 +items.tomeofmastery.way=你选择了走上%s的道路! +items.tomeofmastery.desc=这本皮封典籍没多厚, 但是你隐约感觉到自己能从中学到不少东西. 不过记住\: 阅读这本典籍需要一些时间。 + +items.towel.prevent=现在没必要使用湿巾。 +items.towel.apply=你使用了湿巾。 +items.towel.end=这块湿巾没法用了。 +items.towel.ac_towel=使用 +items.towel.ac_towel_pet=对宠物使用 +items.towel.name=湿巾 +items.towel.desc=湿巾是一项十分便利的发明。它虽然使用次数有限,但它可以清除各种异常状态。 + +items.upgradeblobred.ac_inscribe=使用 +items.upgradeblobred.name=红色强化精华 +items.upgradeblobred.desc=这一坨东西是吞星花的代谢产物。它可以用于强化装备,也可以用来卖钱。 +items.upgradeblobviolet.name=紫色强化精华 +items.upgradeblobviolet.ac_inscribe=使用 +items.upgradeblobviolet.desc=这一坨东西是吞星花的代谢产物。它可以用于强化装备,也可以用来卖钱。 +items.upgradeblobyellow.name=黄色强化精华 +items.upgradeblobyellow.ac_inscribe=使用 +items.upgradeblobyellow.desc=这一坨东西是吞星花的代谢产物。它可以用于强化装备,也可以用来卖钱。 + +items.whistle.ac_call=阅读 +items.whistle.name=灵魂图鉴 +items.whistle.message=待编写... +items.whistle$wndwhistle.title=灵魂图鉴 +items.whistle$wndwhistle.desc=待编写... +items.whistle.desc=一本意义不明的图鉴 + +### new stuff +items.misc.ankhshield.name=神圣护盾 +items.misc.ankhshield.charge=护盾当前充能数%d,充能上限为%d。 +items.misc.ankhshield.ac_defence=防卫 +items.misc.ankhshield.rest=充能不足。 +items.misc.ankhshield.desc=这个世界的缔造者为英雄准备的神圣道具。使用它将对所有视野范围内的敌人施加一个停滞效果。 + +items.misc.jumph.name=猎手之鞋 +items.misc.jumph.ac_jump=跳跃 +items.misc.jumph.desc=在自然母亲的指导下,猎手可以在跳跃同时攻击视野范围内的多个敌人。 + +items.misc.jumpm.name=法师之鞋 +items.misc.jumpm.ac_jump=跳跃 +items.misc.jumpm.desc=在高塔中法师曾专心研究魔法,使得他可以进行短距离的闪烁并有几率获得额外的奥术专注。 + +items.misc.jumpr.name=盗贼之鞋 +items.misc.jumpr.ac_jump=跳跃 +items.misc.jumpr.desc=盗贼并没有训练自己的跳跃能力,使得盗贼跳跃距离很短,但他敏捷的身手可以使他拥有短时间的滞空效果并有几率使其无法被敌人发现。 + +items.misc.jumpshoes.name=弹跳鞋 +items.misc.jumpshoes.charge=鞋子当前充能数%d,充能上限为%d。 +items.misc.jumpshoes.ac_jump=跳跃 +items.misc.jumpshoes.prompt=选择跳跃的目的地点。 +items.misc.jumpshoes.rest=请先休息后再使用。 +items.misc.jumpshoes.desc=来自其他动作游戏里的跳跃动作,用于跳过各种坑。根据职业不同提供的额外效果也不同。 + +items.misc.jumpw.name=战士之鞋 +items.misc.jumpw.ac_jump=跳跃 +items.misc.jumpw.desc=战士的训练当中包含冲锋训练,这使得战士可以跳得更远,并有几率踩晕目标地点范围内的单位。 + +items.misc.jumpp.name=演员之鞋 +items.misc.jumpp.ac_jump=跳跃 +items.misc.jumpp.desc=为了成为偶像,演员时刻注意自己的节奏,这使得演员可以在跳跃中进入自己的节奏,并有几率减少自己受到的下一次攻击。 + +items.misc.jumps.name=星兵之鞋 +items.misc.jumps.ac_jump=跳跃 +items.misc.jumps.desc=作为混乱战争中幸存下来的人类之一,星兵可以在跳跃中快速进行子弹装填,并且有几率为自己的下一次攻击积蓄能量。 + +items.misc.jumpf.name=信徒之鞋 +items.misc.jumpf.ac_jump=跳跃 +items.misc.jumpf.desc=为了方便在不同种族不同信仰的村落之间经商,信徒可以随时准备一块隐蔽的地方重新装饰自己。同时有几率发现一些特别的植物。 + +items.misc.attackshoes.name=水管工皮鞋 +items.misc.attackshoes.ac_jump=跳跃 +items.misc.attackshoes.desc=这个鞋子不需要充能,但跳跃距离恒定且消耗额外的回合。落地后对周围敌人造成伤害。\n我提醒一下,不要踩到刺龟! + +items.misc.shovel.name=铁铲 +items.misc.shovel.ac_use=破坏 +items.misc.shovel.ac_build=造墙 +items.misc.shovel.not_wall=周围没有墙。 +items.misc.shovel.break=现在铁铲没耐久了。 +items.misc.shovel.charge=铁铲当前耐久数%d,耐久上限为%d。 +items.misc.shovel.desc=在大逃狱事件当中,演员发现了这把铲子。使用这把铲子可以轻松破坏周围的墙壁。\n破坏墙壁将消耗铲子的耐久,但这个耐久会随时间恢复。 + +items.misc.bshovel.name=卢老爷的奇迹按钮 +items.misc.bshovel.ac_use=使用 +items.misc.bshovel.break=充能不够 +items.misc.bshovel.charge=按钮当前耐久数%d,耐久上限为%d。 +items.misc.bshovel.desc=一个奇怪的按钮,使用后会发出好听女性的机械声音,并给与奇怪的效果。\n使用的同时会破坏四周墙壁。\n按钮四周刻了奇怪的文字,像什么17张牌,卡布奇诺,牛逼等等。 + +items.misc.bshovel.mob=锁头已激活 +items.misc.bshovel.haste=加速已激活 +items.misc.bshovel.item=透视已激活 +items.misc.bshovel.gold=富有已激活 +items.misc.bshovel.heal=锁血已激活 +items.misc.bshovel.mech=无敌已激活 + +items.misc.potionofmage.name=奇迹烧瓶 +items.misc.potionofmage.ac_use=施放 +items.misc.potionofmage.ac_drink=饮用 +items.misc.potionofmage.ac_shattered=泼洒 +items.misc.potionofmage.prompt=选择要瞄准的地方 +items.misc.potionofmage.break=现在烧瓶里啥都没有。 +items.misc.potionofmage.not_mob=这超出了烧瓶的作用范围。 +items.misc.potionofmage.charge=烧瓶当前质量为%d,质量上限为%d。 +items.misc.potionofmage.desc=法师多年研究结果之一,可以对自身使用来施加增益效果,也可以泼洒出去造成减益效果。 + +items.misc.gunofsoldier.name=脉冲手枪 +items.misc.gunofsoldier.ac_use=射击 +items.misc.gunofsoldier.prompt=选择要瞄准的地方 +items.misc.gunofsoldier.not_mob=那里没有敌人。 +items.misc.gunofsoldier.break=现在没电了。 +items.misc.gunofsoldier.not=你不能选择那个目标。 +items.misc.gunofsoldier.charge=手枪当前充能数%d,充能上限为%d。 +items.misc.gunofsoldier.desc=脉冲手枪是未来的先进科学产物,会对目标敌人造成基于其受伤程度的惊人的伤害。 + +items.misc.mkbox.name=蘑菇王国的问号箱 +items.misc.mkbox.ac_use=顶一下 + +items.misc.mkbox.star=无敌星。 +items.misc.mkbox.flowerf=火焰花。 +items.misc.mkbox.floweri=冰冻花。 +items.misc.mkbox.mushroom=大蘑菇。 +items.misc.mkbox.coin=大金币。 +items.misc.mkbox.1up=1up。 +items.misc.mkbox.hammer=简易锤子。 +items.misc.mkbox.mbox=怪物箱 + +items.misc.mkbox.need_gold=你需要100金币来使用它。 +items.misc.mkbox.charge=剩余刷新时间%d。 +items.misc.mkbox.desc=一个装了各种杂物的箱子,顶一下就会有好东西出来。\n箱子里面多数是蘑菇啦,还有金币,小锤子和花。1up和无敌星非常少见。-某个不愿透露姓名的奇诺比奥。 + +items.misc.missileshield.name=神木圆盾 +items.misc.missileshield.ac_cast=扔出 +items.misc.missileshield.ac_shield=防御 +items.misc.missileshield.rest=体力不足 +items.misc.missileshield.prompt=选择要瞄准的地方 +items.misc.missileshield.not=无法对该目标使用 +items.misc.missileshield.not_mob=无法找到目标 +items.misc.missileshield.desc=一块普通的木质盾牌,上面有一些刮痕。\n这块盾牌被打磨得十分光滑,可以将其投掷出去,消耗体力并击晕敌人。\n也可以将其举起,以减少受到的伤害。 +items.misc.missileshield.damage=这块盾牌可以造成_%d - %d 点伤害_,并对boss造成更高的伤害。 +items.misc.missileshield.charge=剩余体力%d / %d。 + +items.misc.attackshield.name=隆的波动拳 +items.misc.attackshield.ac_cast=释放 +items.misc.attackshield.ac_blast=暴发 +items.misc.attackshield.rest=体力不足 +items.misc.attackshield.prompt=选择要瞄准的地方 +items.misc.attackshield.not=无法对该目标使用 +items.misc.attackshield.not_mob=无法找到目标 +items.misc.attackshield.desc=一种古老的武术,可以在攻击的同时积蓄能量,并将这些能量发射出去。生命越充沛的敌人受到的伤害就越高。当能量聚集满并释放时,使用者将获得额外的力量,并且在空手状态下力量更强。 +items.misc.attackshield.damage=这块道具可以造成_%d - %d 点伤害_。 +items.misc.attackshield.charge=剩余体力%d / %d。 + +items.misc.copyball.name=侵蚀核心 +items.misc.copyball.ac_use=施放 +items.misc.copyball.prompt=选择要瞄准的地方 +items.misc.copyball.break=精华不足。 +items.misc.copyball.charge=精华当前数量为%d,数量上限为%d。 +items.misc.copyball.desc=史莱姆可以在攻击中吸收精华,并可以利用精华来完全控制或扰乱一名敌人。\n系统并不推荐你使用这个,因为可能使这个测试慢到爆炸。 + +items.misc.gnollmark.name=仪式面具 +items.misc.gnollmark.ac_light=光明仪式 +items.misc.gnollmark.ac_dark=黑暗仪式 +items.misc.gnollmark.ac_earth=自然仪式 +items.misc.gnollmark.break=准备不妥。 +items.misc.gnollmark.charge=准备完成度当前为%d,完成度上限为%d。 +items.misc.gnollmark.desc=豺狼人萨满所佩戴的面具,用于仪式准备或者树立地位。在释放法杖后准备度会上升。\n光明仪式会大幅度提升使用者的物理力量,但相对的,使用者的奥术力量会被禁止。黑暗仪式则相反。\n自然仪式将从自然中吸取能量,提升使用者的抗击能力。 + +items.misc.mechpocket.name=机械口袋 +items.misc.mechpocket.ac_use=使用 +items.misc.mechpocket.desc=一个充满神秘感的未来口袋,但里面装的东西有限,并且会一次性全倒出来。\n整理一下比较好-野比大雄 + +items.misc.skillofatk.name=力量之书 +items.misc.skillofatk.ac_read=阅读 +items.misc.skillofatk.desc=看上去是一张普通的羊皮卷,但上面记载了超高的进攻技巧。 +items.misc.skillofatk.skillup=你感觉你的命中能力提升了。 + +items.misc.skillofdef.name=敏捷之书 +items.misc.skillofdef.ac_read=阅读 +items.misc.skillofdef.desc=看上去是一张普通的羊皮卷,但上面记载了超高的闪避技巧。 +items.misc.skillofdef.skillup=你感觉你的闪避能力提升了。 + +items.misc.skillofmig.name=智力之书 +items.misc.skillofmig.ac_read=阅读 +items.misc.skillofmig.desc=看上去是一张普通的羊皮卷,但上面记载了超高的施法技巧。 +items.misc.skillofmig.skillup=你感觉你的魔法能力提升了。 + +items.misc.demoscroll.name=恶魔契约 +items.misc.demoscroll.ac_read=阅读 +items.misc.demoscroll.desc=一张用鲜血达成的契约,可以用生命来换取更强的力量。\n每升一级便可额外使用一次。 +items.misc.demoscroll.hitup=你感觉你的命中能力提升了。 +items.misc.demoscroll.evaup=你感觉你的闪避能力提升了。 +items.misc.demoscroll.migup=你感觉你的魔法能力提升了。 +items.misc.demoscroll.strup=你感觉你的力量提升了。 +items.misc.demoscroll.htdown=你感觉你的生命上限降低了。 + +items.misc.undeadbook.name=亡灵圣经 +items.misc.undeadbook.ac_read=阅读 +items.misc.undeadbook.ac_bless=祈祷 +items.misc.undeadbook.desc=一本用死灵语书写的圣经。为什么亡灵也信圣经? \n借由亡灵圣经的力量,阅读者可以消耗一定量的生命能量,从而从死亡的单位中以露珠的形式提取能量。\n使用者也可以向亡灵圣经祈祷,若使用者的经历得到其神明的赏识,神明会以不死的奥秘回馈使用者。 +items.misc.undeadbook.bless=圣经以露珠回应你的阅读,但你感觉你的身体失去了什么。 +items.misc.undeadbook.1up=圣经以复活十字架回应你的祈祷。 + +items.misc.luckybadge.name=幸运胸章 +items.misc.luckybadge.desc=购买房产后商人老板送你的纪念品之一,据说可以小幅度提升佩戴者的运气,可以被强化。 + +items.misc.fourclover.name=四叶薄荷项链 +items.misc.fourclover.desc=这个四叶草形状的项链能小幅度提升佩戴者升级时的增益,并提供额外的附魔触发几率。 + +items.misc.faithsign.name=信标盒 +items.misc.faithsign.ac_demon=恶魔派系 +items.misc.faithsign.ac_human=神圣派系 +items.misc.faithsign.ac_mech=机械派系 +items.misc.faithsign.ac_life=自然派系 +items.misc.faithsign.ac_balance=平衡派系 +items.misc.faithsign.desc=装有不同信仰的标志的盒子,在必要时可以用于解决争端。 + +items.misc.savagehelmet.name=蛮族头盔 +items.misc.savagehelmet.desc=为狩猎年兽专门准备的头盔,有几率可以减少受到的伤害,并提升相应数量的攻击力。当装备这件头盔时,这个几率提升至100%。 + +items.misc.healbag.name=医疗箱 +items.misc.healbag.ac_heal=群体治疗 +items.misc.healbag.ac_cook=随机调制 +items.misc.healbag.need_charge=需要充能 +items.misc.healbag.desc=为狩猎年兽专门准备的医疗箱,可以很轻松恢复使用者的生命值,可以作用于周围单位。也可以随机调制一瓶药水、药丸或食物。 + +items.misc.rangebag.name=飞镖袋 +items.misc.rangebag.ac_buy=购买 +items.misc.rangebag.need_gold=你需要金币来购买。 +items.misc.rangebag.desc=为狩猎年兽专门准备的袋子,只要花点小钱就能购买投掷武器。当装备时,击杀怪物有几率掉落投掷武器。 + +items.misc.horsetotem.name=赤兔图腾 +items.misc.horsetotem.desc=为狩猎年兽专门准备的图腾,有几率可以提高伤害,并提升移动速度。当装备这件图腾时,这个伤害提升几率提升至100%。 + +items.misc.dancelion.name=舞狮手册 +items.misc.dancelion.ac_spin=旋身 +items.misc.dancelion.ac_stand=力定 +items.misc.dancelion.ac_back=退守 +items.misc.dancelion.ac_rush=猛冲 +items.misc.dancelion.ac_jump=腾跃 +items.misc.dancelion.desc=为狩猎年兽专门准备的手册,在充满能量后能从舞蹈片段中选择一段进行模仿。 + +items.playericon.name=玩家之证 +items.playericon.thank4play=感谢你参加bossrush测试,这个是测试奖励。 +items.playericon.desc=通过还没完成的bossrush的奖励,看上去和没完成的bossrush一样粗糙。 +items.weapon.melee.special.testweapon.name=测试武器 +items.weapon.melee.special.testweapon.desc=测试武器 + +items.elevator.name=社会升降器 +items.elevator.desc=曾经有一位疯狂的古神信徒。他得到了古神的奖励,被封印在这件上流社会的服装中。\n这件道具可以使你自由穿梭于这个地牢的前25个区域。 +items.elevator.ac_up=上楼 +items.elevator.ac_down=下楼 + +items.soulcollect.name=灵魂囚禁石 +items.soulcollect.desc=不敢想象otiluck竟会被这种东西困住。只要破坏掉就可以了。 +items.soulcollect.ac_break=破坏 +items.soulcollect.win=谢谢你。虽然不知道你长啥样,但是还是我们小镇见吧。 + +items.pocketballfull.name=容魂灯 +items.pocketballfull.desc=一只灵魂被保存在里面。使用它可以放出这只灵魂,但首先你要保证当前你没有宠物。警告:刚放出的灵魂十分无力,仅在上下楼或者传送后才会恢复原样。 +items.pocketballfull.ac_use=使用 + +items.powerhand.name=力量之手 +items.powerhand.desc=我们对这样道具一无所知。 +items.powerhand.desc_stones=已经镶嵌了%d枚宝石。 +items.powerhand.prompt=选择要镶嵌的宝石。 +items.powerhand.ac_add=镶嵌 +items.powerhand.ac_use=使用 +items.powerhand.nothing=什么也没发生 +items.powerhand.already_fed=这种宝石已被镶嵌。 +items.powerhand.absorb_stone=你把这枚宝石镶嵌在这个手套上。 + +items.saveyourlife.name=紧急离线装置 +items.saveyourlife.desc=这是什么,这不应该在非测试下出现。 +items.saveyourlife.ac_save=离线 + +items.transmutationball.name=转换笼 +items.transmutationball.prompt=选择要转换的物品。 +items.transmutationball.desc=转换笼的果子,可以用于转换道具。 +items.transmutationball.ac_use=使用 + +items.upgradeeatball.name=吞星花 +items.upgradeeatball.prompt=选择要吞星的物品。 +items.upgradeeatball.desc=吞星花的果子,可以用于提炼道具的精华。 +items.upgradeeatball.ac_use=使用 + +items.flag.name=军旗 +items.flag.desc=祝贺中华人民共和国成立70周年。 + +items.curseblood.name=诅咒之液 +items.curseblood.desc=一瓶被诅咒的浑浊液体。 + +items.chaospack.name=混沌之契 +items.chaospack.desc=一张充满混沌之力的契约。 + +items.emptybody.name=虚无之体 +items.emptybody.desc=一把没有任何改造的材料。 + + diff --git a/resources/com/hmdzl/spspd/messages/levels/levels.properties b/resources/com/hmdzl/spspd/messages/levels/levels.properties new file mode 100644 index 00000000..8eee1a84 --- /dev/null +++ b/resources/com/hmdzl/spspd/messages/levels/levels.properties @@ -0,0 +1,287 @@ +###features +levels.features.alchemypot.select_seed=Select a seed to throw +levels.features.alchemypot.pot=Alchemy Pot +levels.features.alchemypot.fruit=Cook a Blandfruit +levels.features.alchemypot.potion=Brew a Potion +levels.features.alchemypot.options=Do you want to cook a Blandfruit with a seed, or brew a Potion from seeds? + +levels.features.chasm.chasm=Chasm +levels.features.chasm.yes=Yes, I know what I'm doing +levels.features.chasm.no=No, I changed my mind +levels.features.chasm.jump=Do you really want to jump into the chasm? You can probably die. +levels.features.chasm.ondeath=You fell to death... + +levels.features.sign.dead_end=What are you doing here?! +levels.features.sign.tip_1=Welcome to this world. I'm your guide. If this is your first time play this game, you should open your backpack and use that random soul. Pet is strong at the game start, but there are other stronger pet. Try to summon them and feed pet food to them. +levels.features.sign.tip_2=This world is based on magic and time. Check your time and survive in the evening. +levels.features.sign.tip_3=You can create delicious foods by cooking in alchemy. Just make sure you add right number of meat, vegetable, ration, fruit and water. +levels.features.sign.tip_4=Different with other world, upgrade items won't make them lighter. +levels.features.sign.tip_5=Note to all sewer maintenance & cleaning crews: TURN BACK NOW. Some sort of sludge monster has made its home here and several crews have been lost trying to deal with it.\n\nApproval has been given to seal off the lower sewers, this area has been condemned, LEAVE NOW. +levels.features.sign.tip_6=Pixel-Mart - all you need for successful adventure! Also a sweet home is on sell now. +levels.features.sign.tip_7=Some test types made by tower are sold in each shop. You can combine two stone ore in alchemy to create a heavy ammo. Also you can try to combine seed with stone ore. +levels.features.sign.tip_8=Being hungry doesn't hurt, but starving does hurt, and it will reduce your power. +levels.features.sign.tip_9=There are lots of hidden doors, traps and badly weather in this dungeon. Be careful. +levels.features.sign.tip_10=Warning, here is military forbidden zone! +levels.features.sign.tip_11=Pixel-Mart. Spend money. Live longer. Also sell a ticket. +levels.features.sign.tip_12=Weapons is different. Find one you like and put all upgrade into it. There three type of armor: light armor, heavy armor, and normal armor. +levels.features.sign.tip_13=Make sure you have more buffs and less debuffs. +levels.features.sign.tip_14=Bombs and dart can only use once. Use it wisely. +levels.features.sign.tip_15=DANGER! Heavy machinery can cause injury, loss of limbs or death! +levels.features.sign.tip_16=Pixel-Mart. A safer life in dungeon. +levels.features.sign.tip_17=There are more than 30 easter eggs in this game. Try to find them and collect 16 of them. +levels.features.sign.tip_18=It will add doctor mob in next version, if I remember this. +levels.features.sign.tip_19=With your adventure, there will be more and more people join that downtown. +levels.features.sign.tip_20=No weapons allowed in the presence of His Majesty! +levels.features.sign.tip_21=Pixel-Mart. Special prices for demon hunters! +levels.features.sign.tip_22=sadjslkabfjsdkafndalknfadkl +levels.features.sign.tip_23=fgkakfossekfsaldpwldapdl +levels.features.sign.tip_24=dfsadaidjpsiofjisrjaldkfqafk +levels.features.sign.burn=As you try to read the sign it bursts into greenish flames. +levels.features.sign.pit_message=Note to self: Always leave a teleport scroll in the vault. + + +###painters +levels.painters.massgravepainter$bones.name=Mass grave +levels.painters.massgravepainter$bones.desc=bones litter the floor, what happened here? + +levels.painters.ritualsitepainter$ritualmarker.name=Ritual marker +levels.painters.ritualsitepainter$ritualmarker.desc=A painted marker for some dark ritual. Candles are usually placed on the four corners. + +levels.painters.weakfloorpainter$hiddenwell.name=Distant well +levels.painters.weakfloorpainter$hiddenwell.desc=You can just make out a well in the depths below, perhaps there is something down there? + + +###traps +levels.traps.alarmtrap.name=Alarm trap +levels.traps.alarmtrap.alarm=The trap emits a piercing sound that echoes throughout the dungeon! +levels.traps.alarmtrap.desc=This trap seems to be tied to a loud alarm mechanism. Triggering it will likely alert everything on the level + +levels.traps.blazingtrap.name=Blazing trap +levels.traps.blazingtrap.desc=Stepping on this trap will ignite a powerful chemical mixture, setting a wide area ablaze. + +levels.traps.chillingtrap.name=Chilling trap +levels.traps.chillingtrap.desc=When activated, chemicals in this trap will trigger a snap-frost at its location. + +levels.traps.confusiontrap.name=Confusion gas trap +levels.traps.confusiontrap.desc=Triggering this trap will set a cloud of confusion gas loose within the immediate area. + +levels.traps.cursingtrap.name=Cursing trap +levels.traps.cursingtrap.curse=Your worn equipment becomes cursed! +levels.traps.cursingtrap.desc=This trap contains the same malevolent magic found in cursed equipment. Triggering it will curse all worn items, and all items in the immediate area. + +levels.traps.disarmingtrap.name=Disarming trap +levels.traps.disarmingtrap.disarm=Your weapon is teleported away! +levels.traps.disarmingtrap.desc=This trap contains very specific teleportation magic, which will warp the weapon of its victim to some other location. + +levels.traps.disintegrationtrap.name=Disintegration trap +levels.traps.disintegrationtrap.one=The trap disintegrates your %s! +levels.traps.disintegrationtrap.some=The trap disintegrates some of your %s! +levels.traps.disintegrationtrap.ondeath=You were killed by the disintegration trap... +levels.traps.disintegrationtrap.desc=When triggered, this trap will lance the target with beams of disintegration, dealing significant damage and destroying items. + +levels.traps.distortiontrap.name=Distortion trap +levels.traps.distortiontrap.desc=Built from strange magic of unknown origin, this trap will shift and morph the world around you. + +levels.traps.explosivetrap.name=Explosive trap +levels.traps.explosivetrap.desc=This trap contains some powdered explosive and a trigger mechanism. Activating it will cause an explosion in the immediate area. + +levels.traps.firetrap.name=Fire trap +levels.traps.firetrap.desc=Stepping on this trap will ignite a chemical mixture, setting the immediate area aflame. + +levels.traps.flashingtrap.name=Flashing trap +levels.traps.flashingtrap.desc=On activation, this trap will ignite a potent flashing powder stored within, temporarily blinding and crippling its victim. + +levels.traps.flocktrap.name=Flock trap +levels.traps.flocktrap.desc=Perhaps a joke from some amateur mage, triggering this trap will create a flock of magical sheep. + +levels.traps.frosttrap.name=Frost trap +levels.traps.frosttrap.desc=When activated, chemicals in this trap will trigger a powerful snap-frost at its location. + +levels.traps.grimtrap.name=Grim trap +levels.traps.grimtrap.ondeath=You were killed by the blast of a grim trap... +levels.traps.grimtrap.desc=Extremely powerful destructive magic is stored within this trap, enough to instantly kill all but the healthiest of heroes. Triggering it will send a ranged blast of lethal magic towards the nearest character. + +levels.traps.grippingtrap.name=Gripping trap +levels.traps.grippingtrap.desc=Triggering this trap will send barbed claws along the ground, damaging the victims feet and rooting them in place. + +levels.traps.guardiantrap.name=Guardian trap +levels.traps.guardiantrap.alarm=The trap emits a piercing sound that echoes throughout the dungeon! +levels.traps.guardiantrap.desc=This trap is tied to a strange magical mechanism, which will summon guardians and alert all enemies on the floor. +levels.traps.guardiantrap$guardian.name=summoned guardian +levels.traps.guardiantrap$guardian.desc=This blue apparition seems to be a summoned echo of one of the dungeon's stone guardians.\n\nWhile the statue itself is almost incorporeal, the _%s,_ it's wielding, looks real. + +levels.traps.lightningtrap.name=Lightning trap +levels.traps.lightningtrap.ondeath=You were killed by a discharge of a lightning trap... +levels.traps.lightningtrap.desc=A mechanism with a large amount of energy stored into it. Triggering the trap will discharge that energy into whatever activates it. + +levels.traps.oozetrap.name=Ooze trap +levels.traps.oozetrap.desc=This trap will splash out caustic ooze when activated, which will burn until it is washed away. + +levels.traps.paralytictrap.name=Paralytic gas trap +levels.traps.paralytictrap.desc=Triggering this trap will set a cloud of paralytic gas loose within the surrounding area. + +levels.traps.pitfalltrap.name=Pitfall trap +levels.traps.pitfalltrap.desc=This pressure plate rests atop a fairly weak floor, and will likely collapse into a pit if it is pressed. + +levels.traps.poisontrap.name=Poison trap +levels.traps.poisontrap.desc=A small dart-blower must be hidden nearby, activating this trap will cause it to shoot a poisoned dart at you. + +levels.traps.rockfalltrap.name=Rockfall trap +levels.traps.rockfalltrap.ondeath=You were crushed by the rockfall trap... +levels.traps.rockfalltrap.desc=This trap is connected to a series of loose rocks above, triggering it will cause them to come crashing down. + +levels.traps.speartrap.name=Spear trap +levels.traps.speartrap.ondeath=You were skewered by the spear trap... +levels.traps.speartrap.desc=The classic spear trap, primitive but effective. Due to their simple nature, these traps can activate many times without breaking. + +levels.traps.summoningtrap.name=Summoning trap +levels.traps.summoningtrap.desc=Triggering this trap will summon a number of this area's monsters to this location. + +levels.traps.teleportationtrap.name=Teleportation trap +levels.traps.teleportationtrap.desc=Whatever triggers this trap will be warped to some other location on this floor. + +levels.traps.toxictrap.name=Toxic gas trap +levels.traps.toxictrap.desc=Triggering this trap will set a cloud of toxic gas loose within the surrounding area. + +levels.traps.venomtrap.name=Venom gas trap +levels.traps.venomtrap.desc=Triggering this trap will set a cloud of deadly venom gas loose within the immediate area. + +levels.traps.warpingtrap.name=Warping trap +levels.traps.warpingtrap.desc=Whatever triggers this trap will be warped to some other location in the dungeon. + +levels.traps.weakeningtrap.name=Weakening trap +levels.traps.weakeningtrap.desc=Dark magic in this trap sucks the energy out of anything that comes into contact with it. + +levels.traps.worntrap.name=Worn out trap +levels.traps.worntrap.nothing=Nothing happens... +levels.traps.worntrap.desc=Due to age and possibly poor workmanship, it looks like this trap has worn to the point where it won't do anything when triggered. + +levels.traps.shocktrap.name=Shock trap +levels.traps.shocktrap.desc=A mechanism with a large amount of energy stored into it. Triggering this trap will discharge that energy into a field around it. + +levels.traps.stormtrap.name=Storm trap +levels.traps.stormtrap.desc=A mechanism with a massive amount of energy stored into it. Triggering this trap will discharge that energy into a large electrical storm. + +levels.traps.activateportaltrap.name=activate portal trap +levels.traps.changesheeptrap.name=box change trap +levels.traps.fleecingtrap.name=fleecing trap +levels.traps.fleecingtrap.destroy=This trap destory your armor! +levels.traps.heapgentrap.name=reword switch +levels.traps.sokobanportaltrap.name=portal + + +###levels +levels.bossrushlevel.water_name=Strange water +levels.bossrushlevel.grass_name=Some magic dust +levels.bossrushlevel.high_grass_name=Some magic crystal +levels.bossrushlevel.statue_sp_name=Berg crystal +levels.bossrushlevel.water_desc=Very strange water +levels.bossrushlevel.statue_sp_desc=Yello crystal. That is beautiful + +levels.caveslevel.grass_name=Fluorescent moss +levels.caveslevel.high_grass_name=Fluorescent mushrooms +levels.caveslevel.water_name=Freezing cold water. +levels.caveslevel.entrance_desc=The ladder leads up to the upper depth. +levels.caveslevel.exit_desc=The ladder leads down to the lower depth. +levels.caveslevel.high_grass_desc=Huge mushrooms block the view. +levels.caveslevel.wall_deco_desc=A vein of some ore is visible on the wall. Gold? +levels.caveslevel.bookshelf_desc=Who would need a bookshelf in a cave? + +levels.citylevel.water_name=Suspiciously colored water +levels.citylevel.high_grass_name=High blooming flowers +levels.citylevel.entrance_desc=A ramp leads up to the upper depth. +levels.citylevel.exit_desc=A ramp leads down to the lower depth. +levels.citylevel.deco_desc=Several tiles are missing here. +levels.citylevel.sp_desc=Thick carpet covers the floor. +levels.citylevel.statue_desc=The statue depicts some dwarf standing in a heroic stance. +levels.citylevel.bookshelf_desc=The rows of books on different disciplines fill the bookshelf. + +levels.hallslevel.water_name=Cold lava +levels.hallslevel.grass_name=Embermoss +levels.hallslevel.high_grass_name=Emberfungi +levels.hallslevel.statue_name=Pillar +levels.hallslevel.water_desc=It looks like lava, but it's cold and probably safe to touch. +levels.hallslevel.statue_desc=The pillar is made of real humanoid skulls. Awesome. +levels.hallslevel.bookshelf_desc=Books in ancient languages smoulder in the bookshelf. + +levels.level.hidden_plate=A hidden pressure plate clicks! +levels.level.chasm_name=Chasm +levels.level.floor_name=Floor +levels.level.grass_name=Grass +levels.level.water_name=Water +levels.level.wall_name=Wall +levels.level.closed_door_name=Closed door +levels.level.open_door_name=Open door +levels.level.entrace_name=Depth entrance +levels.level.exit_name=Depth exit +levels.level.embers_name=Embers +levels.level.locked_door_name=Locked door +levels.level.pedestal_name=Pedestal +levels.level.barricade_name=Barricade +levels.level.high_grass_name=High grass +levels.level.locked_exit_name=Locked depth exit +levels.level.unlocked_exit_name=Unlocked depth exit +levels.level.sign_name=Sign +levels.level.well_name=Well +levels.level.empty_well_name=Empty well +levels.level.statue_name=Statue +levels.level.statue_ssp_name=Air wall +levels.level.tent_name=Tent +levels.level.bed_name=bed +levels.level.inactive_trap_name=Triggered trap +levels.level.bookshelf_name=Bookshelf +levels.level.alchemy_name=Alchemy pot +levels.level.wool_rug_name=Wool rug +levels.level.fleecing_trap_name=fleecing trap +levels.level.change_sheep_trap_name=change box trap +levels.level.sokoban_item_reveal_name=item switch +levels.level.sokoban_port_switch_name=Portal switch +levels.level.port_well_name=Portal +levels.level.trap_air_name=Chasm +levels.level.default_name=??? + +levels.level.shrub_name=Overgrown Shrub + +levels.level.shrub_desc=Dense srubs block the view. + +levels.level.chasm_desc=You can't see the bottom. +levels.level.water_desc=In case of burning step into the water to extinguish the fire. +levels.level.entrance_desc=Stairs lead up to the upper depth. +levels.level.exit_desc=Stairs lead down to the lower depth. +levels.level.embers_desc=Embers cover the floor. +levels.level.high_grass_desc=Dense vegetation blocks the view. +levels.level.locked_door_desc=This door is locked, you need a matching key to unlock it. +levels.level.locked_exit_desc=Heavy bars block the stairs leading down. +levels.level.barricade_desc=The wooden barricade is firmly set but has dried over the years. Might it burn? +levels.level.sign_desc=You can't read the text from here. +levels.level.inactive_trap_desc=The trap has been triggered before and it's not dangerous anymore. +levels.level.statue_desc=Someone wanted to adorn this place, but failed, obviously. +levels.level.statue_ssp_desc=Looks like a trap, but it is air wall. +levels.level.tent_desc=A small blue tent. +levels.level.bed_desc=A soft and comfortable bed. +levels.level.alchemy_desc=Drop some seeds here to cook a potion. +levels.level.wool_rug_desc=It was destroyed to a few debris. +levels.level.fleecing_trap_desc=This trap can destory everything. Push a box into it. +levels.level.change_sheep_trap_desc=This trap can change one box to another box. +levels.level.sokoban_item_reveal_desc=If you push on box in here, something will drop in this floor. +levels.level.sokoban_port_switch_desc=This is a portal switch. +levels.level.port_well_desc=This is a portal. +levels.level.trap_air_desc=It will deal damage to everything it touch. +levels.level.empty_well_desc=The well has run dry. +levels.level.default_desc=Nothing interesting here. + +levels.prisonlevel.water_name=Dark cold water. +levels.prisonlevel.empty_deco_desc=There are old blood stains on the floor. +levels.prisonlevel.bookshelf_desc=This is probably a vestige of a prison library. Might it burn? + +levels.sewerlevel.water_name=Murky water +levels.sewerlevel.empty_deco_desc=Wet yellowish moss covers the floor. +levels.sewerlevel.bookshelf_desc=The bookshelf is packed with cheap useless books. Might it burn? + +levels.level.crabbosslevel.water_name=Crystal clear pools +levels.level.crabbosslevel.high_grass_name=Seaweed Tangles +levels.level.crabbosslevel.deco_desc=Small crabs and shell fish litter the sandy floor. +levels.level.crabbosslevel.statue_desc=A large sea shell is propped up in the sand. +levels.level.crabbosslevel.bookshelf_desc=Mostly beach reads. + +levels.level.fieldlevel.emptydeco_desc=The grass is worn away to reveal bedrock. diff --git a/resources/com/hmdzl/spspd/messages/levels/levels_zh.properties b/resources/com/hmdzl/spspd/messages/levels/levels_zh.properties new file mode 100644 index 00000000..a730afb6 --- /dev/null +++ b/resources/com/hmdzl/spspd/messages/levels/levels_zh.properties @@ -0,0 +1,287 @@ +###features +levels.features.alchemypot.select_seed=选择一个种子放进去 +levels.features.alchemypot.pot=炼药锅 +levels.features.alchemypot.fruit=煮无味果 +levels.features.alchemypot.potion=酿造药水 +levels.features.alchemypot.options=你想用种子煮食无味果,还是酿造药水?\n\n如果你选择煮无味果,则你可以将无味果和一个种子合成为一个具有特殊功能的可食用果;如果选择酿造药水,则是花费一定数量的种子来合成一瓶药水。 + +levels.features.chasm.chasm=裂缝 +levels.features.chasm.yes=是的,我知道我在做什么 +levels.features.chasm.no=不,我改主意了 +levels.features.chasm.jump=你确定要跳入洞口中?你可能会摔死。 +levels.features.chasm.ondeath=你落地过猛摔死了…… + +levels.features.sign.dead_end=你在这里干嘛?! +levels.features.sign.tip_1=欢迎来到这个地牢。如果你是一名新手的话,请打开背包,使用随机灵魂。那样你就能获得你的第一只宠物。宠物的实力是有限的。如果你并不想提升你自己的实力,那么你需要一只很强的宠物。 +levels.features.sign.tip_2=时间总是在不经意之间流逝。在状态栏里面确认当前时间。不要忘了在夜晚准备足够的光源。 +levels.features.sign.tip_3=肉是肉,蘑菇是蔬菜,口粮是主食,梅果是水果。再加上一些由露珠合成的水,你应该能烧出各种各样的美食。 +levels.features.sign.tip_4=升级装备并不会让它们变轻,但是能让它们更强。 +levels.features.sign.tip_5=所有的下水道维护及清洁人员:_立即离开这里_。某种泥浆类怪物将这片区域当作自己的巢穴,许多特遣队员已经死在它的手里。\n\n下层下水道已被批准并彻底封锁,这一部分已被停用,_请立即离开_。 +levels.features.sign.tip_6="像素商店"——为成功的探险人士提供一切所需。同时,出售一间小屋! +levels.features.sign.tip_7=高塔已将枪械投入测试。如果你想的话,你可以把原石和原石炼制成重铅弹。当然你也可以试试其他配方,比如原石和种子什么的。 +levels.features.sign.tip_8=极度饥饿会让你受伤,但是只要是饥饿就会使你得攻击变得无力。 +levels.features.sign.tip_9=地牢里面隐藏着大量的陷阱和暗门,以及一些极端的气候环境。不要冲得太快。 +levels.features.sign.tip_10=警告,你现在正处于军事保密区,请尽快离开。 +levels.features.sign.tip_11="像素商店"——花更多的钱,走更远的路。出售观光游票。 +levels.features.sign.tip_12=一般来说,武器会自带一个特殊效果。这种特殊效果在低阶武器上表现得更加明显。而防具分成轻,常规,重三种。不同防具提供的额外效果不同。 +levels.features.sign.tip_13=有些状态会互相抵消,而有些状态会互相加强。确保你处于最强状态以便战胜其他敌人。 +levels.features.sign.tip_14=炸弹和飞镖都是一次性的消耗品。明智地使用它们。 +levels.features.sign.tip_15=如果生产线遭到破坏,防御措施就会启动,源源不断的猎杀机器人和危险巨械会肃清入侵者! +levels.features.sign.tip_16="像素集市"——让你在地牢中更加安全。 +levels.features.sign.tip_17=这里有将近30种武器,除了常规16种武器以外还有一些特殊武器。希望你能发现它们。 +levels.features.sign.tip_18=有没有想过如果有医生出现在怪物群中会怎样? +levels.features.sign.tip_19=小镇一直在变化,和你一样。 +levels.features.sign.tip_20=矮人圣地不容侵犯,国王必须被守护! +levels.features.sign.tip_21="像素集市"——为恶魔猎手提供的特价优惠!展示特殊的非卖品! +levels.features.sign.tip_22=sadjslkabfjsdkafndalknfadkl +levels.features.sign.tip_23=fgkakfossekfsaldpwldapdl +levels.features.sign.tip_24=dfsadaidjpsiofjisrjaldkfqafk +levels.features.sign.burn=就在你试图阅读它的那一刻,它爆燃成了一团绿色的火焰。 +levels.features.sign.pit_message=这块地方没有出口,所以你需要传送道具。那个遗骸下面可能会有一个。 + + +###painters +levels.painters.massgravepainter$bones.name=巨大的墓穴 +levels.painters.massgravepainter$bones.desc=骨头镶嵌进了地板,这里发生过什么? + +levels.painters.ritualsitepainter$ritualmarker.name=仪式标记 +levels.painters.ritualsitepainter$ritualmarker.desc=为黑暗仪式而画下的标记。蜡烛通常摆在四个角上。 + +levels.painters.weakfloorpainter$hiddenwell.name=近处的井 +levels.painters.weakfloorpainter$hiddenwell.desc=你可以直接看到下一层有个井,也许这下面有些什么? + + +###traps +levels.traps.alarmtrap.name=警报陷阱 +levels.traps.alarmtrap.alarm=陷阱产生的尖锐的警报声在地牢里回荡! +levels.traps.alarmtrap.desc=这个陷阱看起来有着能造成很大响动的机制。触发它将使本层所有生物对这里产生警觉。 + +levels.traps.blazingtrap.name=烈焰陷阱 +levels.traps.blazingtrap.desc=踩进这个陷阱会点燃某种极具力量的化学混合物,导致很大一块区域起火。 + +levels.traps.chillingtrap.name=冰霜陷阱 +levels.traps.chillingtrap.desc=触发时,这个陷阱里的化学药剂会产生霜冻效果。 + +levels.traps.confusiontrap.name=混乱陷阱 +levels.traps.confusiontrap.desc=触发这个陷阱将在附近释放出一片混乱气体。 + +levels.traps.cursingtrap.name=诅咒陷阱 +levels.traps.cursingtrap.curse=你正穿在身上的装备都被诅咒了! +levels.traps.cursingtrap.desc=这个陷阱中包含与在诅咒装备发现的恶毒魔法同样的东西。触发它会诅咒所有已装备的物品或所有在陷阱上方的物品。 + +levels.traps.disarmingtrap.name=缴械陷阱 +levels.traps.disarmingtrap.disarm=你手中的武器被传送走了! +levels.traps.disarmingtrap.desc=这个陷阱包含着非常有针对性的传送魔法,它会将触发陷阱的受害者的武器传送到其他位置。 + +levels.traps.disintegrationtrap.name=解离陷阱 +levels.traps.disintegrationtrap.one=陷阱解离了你的%s! +levels.traps.disintegrationtrap.some=陷阱解离了你的一些%s! +levels.traps.disintegrationtrap.ondeath=你被解离陷阱击杀… +levels.traps.disintegrationtrap.desc=触发时,这个陷阱将会用解离射线袭击它的目标,造成很高的伤害的同时破坏物品。 + +levels.traps.distortiontrap.name=重构陷阱 +levels.traps.distortiontrap.desc=依赖于来源不明的奇特魔法,陷阱会移动并扭曲你周围的世界。 + +levels.traps.explosivetrap.name=爆炸陷阱 +levels.traps.explosivetrap.desc=这个陷阱包含一些粉状炸药和一个触发机制。激活它会导致一定范围的爆炸。 + +levels.traps.firetrap.name=火焰陷阱 +levels.traps.firetrap.desc=踩进这个陷阱会点燃某种化学混合物,导致陷阱所在的区域起火。 + +levels.traps.flashingtrap.name=闪光陷阱 +levels.traps.flashingtrap.desc=被激活时,这个陷阱将点燃储存在里面的强效闪光粉,使受害者暂时失明并残废。 + +levels.traps.flocktrap.name=羊圈陷阱 +levels.traps.flocktrap.desc=也许是个来自一些业余法师的玩笑,触发这个陷阱就会创造一群魔法绵羊。 + +levels.traps.frosttrap.name=极寒陷阱 +levels.traps.frosttrap.desc=触发时,这个陷阱里的化学药剂会产生强有力的霜冻效果。 + +levels.traps.grimtrap.name=即死陷阱 +levels.traps.grimtrap.ondeath=你被即死陷阱的冲击彻底击杀… +levels.traps.grimtrap.desc=非常强大的破坏魔法储存在这个陷阱里,足以瞬间杀死除了最健康的英雄外的所有东西。触发它将向最近的生物发送一个致命魔法的远程冲击。 + +levels.traps.grippingtrap.name=捕猎陷阱 +levels.traps.grippingtrap.desc=触发这个陷阱将使一对钳子合上,伤害受害者并将他们固定在这里。 + +levels.traps.guardiantrap.name=守卫陷阱 +levels.traps.guardiantrap.alarm=陷阱产生的尖锐的警报声在地牢里回荡! +levels.traps.guardiantrap.desc=这个陷阱有着奇怪的魔法机制,它将召唤守护者并向将使本层所有生物对这里产生警觉。 +levels.traps.guardiantrap$guardian.name=召唤守卫 +levels.traps.guardiantrap$guardian.desc=这个蓝色的幻影似乎是召唤出来的地牢里的石像守卫虚影之一。 \n\n尽管雕像本身几乎没有形体,但它握着的_%s_,看起来像是真的。 + +levels.traps.lightningtrap.name=闪电陷阱 +levels.traps.lightningtrap.ondeath=你被闪电陷阱的电击杀死了... +levels.traps.lightningtrap.desc=一种能储存大量电能的机关。触发陷阱将会释放能量到任何激活它的东西上。 + +levels.traps.oozetrap.name=腐酸陷阱 +levels.traps.oozetrap.desc=这个陷阱将会洒出腐蚀性的淤泥,它将烧灼你的皮肤直到被洗掉。 + +levels.traps.paralytictrap.name=麻痹陷阱 +levels.traps.paralytictrap.desc=触发这个陷阱将在附近释放出一片麻痹气体。 + +levels.traps.pitfalltrap.name=塌陷陷阱 +levels.traps.pitfalltrap.desc=这个压力板安装在一块相当薄弱的地板上,如果被触发这里很可能会塌出一个坑。 + +levels.traps.poisontrap.name=毒镖陷阱 +levels.traps.poisontrap.desc=一个小飞镖发射器一定隐藏在附近,激活这个陷阱将导致它向你射出一个毒镖。 + +levels.traps.rockfalltrap.name=落石陷阱 +levels.traps.rockfalltrap.ondeath=你被落石砸扁了…… +levels.traps.rockfalltrap.desc=这个陷阱连结在一系列的松散的岩石上,触发它会导致整个天花板崩塌。 + +levels.traps.speartrap.name=尖刺陷阱 +levels.traps.speartrap.ondeath=你被尖刺陷阱扎成了筛子…… +levels.traps.speartrap.desc=经典的尖刺陷阱,原始而有效。由于其简单的构造,这些陷阱可被多次激活而不损毁。 + +levels.traps.summoningtrap.name=生成陷阱 +levels.traps.summoningtrap.desc=触发这个陷阱将召唤本区域的一些怪物到这里。 + +levels.traps.teleportationtrap.name=传送陷阱 +levels.traps.teleportationtrap.desc=任何接触这个陷阱的东西都会被传送到本层的其它地方。 + +levels.traps.toxictrap.name=毒气陷阱 +levels.traps.toxictrap.desc=触发这个陷阱将放出一片有毒气体到这附近。 + +levels.traps.venomtrap.name=猛毒陷阱 +levels.traps.venomtrap.desc=触发这个陷阱将在该区域放出一片致命毒气。 + +levels.traps.warpingtrap.name=扭曲陷阱 +levels.traps.warpingtrap.desc=触发这个陷阱的任何东西都会被传送到地牢的其它位置。 + +levels.traps.weakeningtrap.name=虚弱陷阱 +levels.traps.weakeningtrap.desc=这个陷阱里的黑魔法能从任何接触物里吸取能量。 + +levels.traps.worntrap.name=破旧的陷阱 +levels.traps.worntrap.nothing=真的啥事都没发生… +levels.traps.worntrap.desc=由于悠久的历史和糟糕的工艺,看起来这个陷阱老到即使触发也什么都不会发生了。 + +levels.traps.shocktrap.name=休克陷阱 +levels.traps.shocktrap.desc=触发这个陷阱所产生的电流会对周围的单位造成极大的伤害并麻痹它们。 + +levels.traps.stormtrap.name=暴风陷阱 +levels.traps.stormtrap.desc=休克陷阱的加强版,范围更大,持续更长! + +levels.traps.activateportaltrap.name=传送门激活开关 +levels.traps.changesheeptrap.name=转换陷阱 +levels.traps.fleecingtrap.name=摧毁陷阱 +levels.traps.fleecingtrap.destroy=摧毁陷阱摧毁了你的护甲! +levels.traps.heapgentrap.name=奖励开关 +levels.traps.sokobanportaltrap.name=单向传送门 + + +###levels +levels.bossrushlevel.water_name=奇怪的水 +levels.bossrushlevel.grass_name=一些魔法粉尘 +levels.bossrushlevel.high_grass_name=一些魔法晶簇 +levels.bossrushlevel.statue_sp_name=水晶 +levels.bossrushlevel.water_desc=十分奇怪的水滩 +levels.bossrushlevel.statue_sp_desc=黄色的水晶。太漂亮了。 + +levels.caveslevel.grass_name=荧光苔藓 +levels.caveslevel.high_grass_name=荧光蘑菇 +levels.caveslevel.water_name=冰冷刺骨的水。 +levels.caveslevel.entrance_desc=通向上一层的梯子。 +levels.caveslevel.exit_desc=通向下一层的梯子。 +levels.caveslevel.high_grass_desc=庞大的蘑菇阻挡了视线。 +levels.caveslevel.wall_deco_desc=一些矿脉在墙上清晰可见。金子? +levels.caveslevel.bookshelf_desc=谁会需要在矿洞里放个书架? + +levels.citylevel.water_name=有着可疑色调的水 +levels.citylevel.high_grass_name=茂盛的开放花朵 +levels.citylevel.entrance_desc=通向上一层的斜坡。 +levels.citylevel.exit_desc=通向下一层的斜坡。 +levels.citylevel.deco_desc=这里少了一些地砖。 +levels.citylevel.sp_desc=厚地毯覆盖着地板。 +levels.citylevel.statue_desc=这座雕像展示了一些摆出英勇姿态的矮人。 +levels.citylevel.bookshelf_desc=不同学科的书排满了书架。 + +levels.hallslevel.water_name=冷岩浆 +levels.hallslevel.grass_name=灰烬苔藓 +levels.hallslevel.high_grass_name=灰烬真菌 +levels.hallslevel.statue_name=台柱 +levels.hallslevel.water_desc=看起来像是岩浆,不过却是冰凉的,应该可以碰。 +levels.hallslevel.statue_desc=这个柱子由类人生物头骨垒成。真帅。 +levels.hallslevel.bookshelf_desc=用远古语言写就的书籍堆积在书架里。 + +levels.level.hidden_plate=隐藏的压力板发出脆响! +levels.level.chasm_name=洞口 +levels.level.floor_name=地板 +levels.level.grass_name=草 +levels.level.water_name=水 +levels.level.wall_name=墙壁 +levels.level.closed_door_name=关着的门 +levels.level.open_door_name=开着的门 +levels.level.entrace_name=楼层入口 +levels.level.exit_name=楼层出口 +levels.level.embers_name=灰烬 +levels.level.locked_door_name=锁着的门 +levels.level.pedestal_name=基座 +levels.level.barricade_name=路障 +levels.level.high_grass_name=高草 +levels.level.locked_exit_name=锁着的楼层出口 +levels.level.unlocked_exit_name=开放的楼层出口 +levels.level.sign_name=告示牌 +levels.level.well_name=井 +levels.level.empty_well_name=干涸的井 +levels.level.statue_name=雕像 +levels.level.statue_ssp_name=空气墙 +levels.level.tent_name=帐篷 +levels.level.bed_name=床 +levels.level.inactive_trap_name=已触发的陷阱 +levels.level.bookshelf_name=书架 +levels.level.alchemy_name=炼药锅 +levels.level.wool_rug_name=白色碎屑 +levels.level.fleecing_trap_name=破坏陷阱 +levels.level.change_sheep_trap_name=转换陷阱 +levels.level.sokoban_item_reveal_name=奖励开关 +levels.level.sokoban_port_switch_name=传送开关 +levels.level.port_well_name=单向传送门 +levels.level.trap_air_name=深渊陷阱 +levels.level.default_name=??? + +levels.level.shrub_name=茂盛的灌木 + +levels.level.shrub_desc=茂盛的灌木挡住了视线。 + +levels.level.chasm_desc=你看不到底。 +levels.level.water_desc=着火的时候踩进水里可以灭火。 +levels.level.entrance_desc=通向上一层的楼梯。 +levels.level.exit_desc=楼梯一级级向下延伸。 +levels.level.embers_desc=灰烬覆盖着地板。 +levels.level.high_grass_desc=茂密的植被阻挡了视线。 +levels.level.locked_door_desc=门锁着,你需要匹配的钥匙来打开。 +levels.level.locked_exit_desc=沉重的铁栏杆封锁住了下楼楼梯。 +levels.level.barricade_desc=木栅栏依然坚固,但早已风干多年。烧了怎么样? +levels.level.sign_desc=你从这里看不清楚上面写的是什么。 +levels.level.inactive_trap_desc=这个陷阱已经被触发过了,现在一点也不危险。 +levels.level.statue_desc=有人想装饰一下这里,很显然,它没能成功… +levels.level.statue_ssp_desc=看上去就像一个陷阱,但是这是一个空气墙。 +levels.level.tent_desc=一个蓝色的小帐篷。 +levels.level.bed_desc=柔软舒适的床。 +levels.level.alchemy_desc=往这里投入一些种子来酿造药水。 +levels.level.wool_rug_desc=这东西被摧毁到只剩下一些碎屑了。 +levels.level.fleecing_trap_desc=这个陷阱破坏能力很强,推个箱子进去试试。 +levels.level.change_sheep_trap_desc=这个陷阱能完全转换一个箱子。注意,该过程不可逆! +levels.level.sokoban_item_reveal_desc=用箱子压一下就会有东西掉出来,但是你没法知道那东西掉在哪里。 +levels.level.sokoban_port_switch_desc=只有触发这个开关传送门才会启动。但是这个开关能用几次?它又对应着哪个传送门? +levels.level.port_well_desc=只能传送到一个地方的传送门。 +levels.level.trap_air_desc=让人承受掉落伤害的陷阱。 +levels.level.empty_well_desc=这座井已经枯竭了。 +levels.level.default_desc=这里没什么有趣的东西。 + +levels.prisonlevel.water_name=又黑又冷的水。 +levels.prisonlevel.empty_deco_desc=这里的地板上有干涸的血迹。 +levels.prisonlevel.bookshelf_desc=这个书架可能是监狱图书馆的残留物。烧掉怎么样? + +levels.sewerlevel.water_name=浑浊的水 +levels.sewerlevel.empty_deco_desc=湿润的、黄色的苔藓覆盖着地板。 +levels.sewerlevel.bookshelf_desc=这个书架塞满了没用的成功学书籍。烧掉怎么样? + +levels.level.crabbosslevel.water_name=清澈透明的水 +levels.level.crabbosslevel.high_grass_name=水草 +levels.level.crabbosslevel.deco_desc=小型蟹类和贝壳在沙地上散落着。 +levels.level.crabbosslevel.statue_desc=一个大贝壳在沙子里直立着。 +levels.level.crabbosslevel.bookshelf_desc=书架。 + +levels.level.fieldlevel.emptydeco_desc=草被磨损殆尽,露出了基岩。 \ No newline at end of file diff --git a/resources/com/hmdzl/spspd/messages/misc/misc.properties b/resources/com/hmdzl/spspd/messages/misc/misc.properties new file mode 100644 index 00000000..a12fd41b --- /dev/null +++ b/resources/com/hmdzl/spspd/messages/misc/misc.properties @@ -0,0 +1,137 @@ + +badges.endorsed=Badge endorsed: %s +badges.new_super=New super badge: %s +badges.new=New badge: %s +badges$badge.monsters_slain_1=10 enemies slain +badges$badge.monsters_slain_2=50 enemies slain +badges$badge.monsters_slain_3=150 enemies slain +badges$badge.monsters_slain_4=250 enemies slain +badges$badge.gold_collected_1=100 gold collected +badges$badge.gold_collected_2=500 gold collected +badges$badge.gold_collected_3=2500 gold collected +badges$badge.gold_collected_4=7500 gold collected +badges$badge.level_reached_1=Level 10 reached +badges$badge.level_reached_2=Level 20 reached +badges$badge.level_reached_3=Level 30 reached +badges$badge.level_reached_4=Level 40 reached +badges$badge.all_potions_identified=All potions identified +badges$badge.all_scrolls_identified=All scrolls identified +badges$badge.all_rings_identified=All rings identified +badges$badge.all_wands_identified=All wands identified +badges$badge.all_items_identified=All potions, scrolls, rings & wands identified +badges$badge.all_bags_bought=All bags bought +badges$badge.death_from_fire=Death from fire +badges$badge.death_from_poison=Death from poison +badges$badge.death_from_gas=Death from toxic gas +badges$badge.death_from_hunger=Death from hunger +badges$badge.death_from_glyph=Death from a glyph +badges$badge.death_from_falling=Death from falling down +badges$badge.yasd=Death from fire, poison, toxic gas & hunger +badges$badge.boss_slain_1=1st boss slain +badges$badge.boss_slain_2=2nd boss slain +badges$badge.boss_slain_3=3rd boss slain +badges$badge.boss_slain_4=4th boss slain +badges$badge.boss_slain_1_all_classes=1st boss slain by Warrior, Mage, Rogue & Huntress +badges$badge.boss_slain_3_all_subclasses=3rd boss slain by Gladiator, Berserker, Warlock, Battlemage, Freerunner, Assassin, Sniper & Warden +badges$badge.ring_of_haggler=Ring of Haggler obtained +badges$badge.ring_of_thorns=Ring of Thorns obtained +badges$badge.strength_attained_1=13 points of Strength attained +badges$badge.strength_attained_2=15 points of Strength attained +badges$badge.strength_attained_3=17 points of Strength attained +badges$badge.strength_attained_4=19 points of Strength attained +badges$badge.food_eaten_1=10 pieces of food eaten +badges$badge.food_eaten_2=20 pieces of food eaten +badges$badge.food_eaten_3=30 pieces of food eaten +badges$badge.food_eaten_4=40 pieces of food eaten +badges$badge.item_level_1=Item of level 3 acquired +badges$badge.item_level_2=Item of level 6 acquired +badges$badge.item_level_3=Item of level 9 acquired +badges$badge.item_level_4=Item of level 12 acquired +badges$badge.rare=All rare monsters slain +badges$badge.victory=Amulet of Yendor obtained +badges$badge.victory_all_classes=Amulet of Yendor obtained by Warrior, Mage, Rogue & Huntress +badges$badge.mastery_combo=10-hit combo +badges$badge.potions_cooked_1=3 potions cooked +badges$badge.potions_cooked_2=6 potions cooked +badges$badge.potions_cooked_3=9 potions cooked +badges$badge.potions_cooked_4=12 potions cooked +badges$badge.no_monsters_slain=Level completed without killing any monsters +badges$badge.grim_weapon=Monster killed by a Grim weapon +badges$badge.piranhas=6 piranhas killed +badges$badge.night_hunter=15 monsters killed at nighttime +badges$badge.games_played_1=10 games played +badges$badge.games_played_2=100 games played +badges$badge.games_played_3=500 games played +badges$badge.games_played_4=2000 games played +badges$badge.happy_end=Happy end +badges$badge.champion=Challenge won +badges$badge.supporter=Thanks for your support! +badges$badge.orb=Orb of Zot obtained! +badges$badge.otiluke=Otiluke rescued! +badges$badge.tri=Find the TriForce! +badges$badge.egg_break_1=Summon 1 pet! +badges$badge.egg_break_2=Summon 3 pet! +badges$badge.egg_break_3=Summon 5 pet! + +challenges.item_phobia=item phobia +challenges.item_phobia_desc=You think your scrolls and potions is dangerous.\n\n-spend more time on drink potions.\n-use scrolls will harm you and slience by yourself.\n-start with 1000 golds. +challenges.listless=listless +challenges.listless_desc=You feel weekness.\n\n-earn less ht on level up.\n-start with potion of might and potion of honey. +challenges.nightmare_virus=nightmare virus +challenges.nightmare_virus_desc=Everyon is infected by nightmare virus.\n\n- If something die, create a nightmare virus.\n- Start with blessing ankh. +challenges.energy_lost=energy lost +challenges.energy_lost_desc=Based on conservation of energy, lots of energy lost in other ways.\n\n- Gain less hunger on eating foods.\n- Reduce wand's max charge.\n- Start with pasty. +challenges.dew_rejection=dew rejection +challenges.dew_rejection_desc=Dew god hate you.\n\n- Drop less dews.\n- Spend more dews.\n- Start with 2 seed of dewcatcher. +challenges.darkness=Into darkness +challenges.darkness_desc=Darkness grown.\n\n- Can't record map by yourself.\n- Start with 2 scroll of magicmapping. +challenges.abrasion=abrasion +challenges.abrasion_desc=Weapons are almost break.\n\n- Weapon will be destroy by using it.\n- Start with Scroll of upgrade and Scroll of magicimbue. +challenges.test_time=test time +challenges.test_time_desc=This is just a test.\n\n-have fun :) + +skins.title=Choose your hero skin +skins.normal=Classic Hero +skins.first=Birthday Gift +skins.second=Halloween +skins.third=Spring Festival +skins.normal_desc=Classic pixel dungeon skins, including warrior, mage, rogue, hunter, performer, soldier, follower.\n-Start with pet pack. +skins.first_desc=2019 happy birthday skins, including fighter, explorer, ninja, maid, Vtuber, plumber, builder.\n-Start with different personal item.\n-fighter have hadoken. \n-explorer have rainbow cannon. \n-ninja have Legend of Hyrule. \n-maid have thousand knives. \n-Vtuber have effect button. \n-plumber have jump shoes and ? box.\n-builder have diamond pickaxe. +skins.second_desc=Halloween skins, including demon, gnoll, undead, taurcen, slime, mech, protoss.\n-Start with different personal stats. \n-demon attack with fire. \n-gnoll recharge fast. \n-undead stealth higher. \n-taurcen move fast. \n-slime heal quickly. \n-mech gain armor from level.\n-protoss ignore enemy's armor. +skins.third_desc=2020 Spring Festival skins, including heavy-infantry, emcee, samurai, archer, lion-dancer, doctor, merchant.\n-ankh shield and shoes will be replaced by an ex item and hunting pack.\n-heavy-infantry has shield and helmetl.\n-emcee has potion and mask.\n-samurai has cloak and totem .\n-archer has bow and throw bag.\n-lion-dancer has shovel and notation.\n-doctor has pulse pistol and heal bag .\n-merchant has sign box and pylon. +skins.info=Different skin will give different items. +skins.yes=YES +skins.no=NO + +journal$feature.well_of_health=Well of Health +journal$feature.well_of_awareness=Well of Awareness +journal$feature.well_of_transmutation=Well of Transmutation +journal$feature.alchemy=Alchemy pot +journal$feature.garden=Garden +journal$feature.statue=Animated statue +journal$feature.ghost=Sad ghost +journal$feature.wandmaker=Old wandmaker +journal$feature.troll=Troll blacksmith +journal$feature.imp=Ambitious imp + +resultdescriptions.mob=Killed by mobs. +resultdescriptions.unique=Killed by someone. +resultdescriptions.named=Killed by something. +resultdescriptions.item=Killed by some items. +resultdescriptions.glyph=Killed by armor. +resultdescriptions.trap=Killed by trap. +resultdescriptions.burning=Killed by fire. +resultdescriptions.hunger=Killed by hunger. +resultdescriptions.poison=Killed by poison. +resultdescriptions.gas=Killed by gas. +resultdescriptions.bleeding=Killed by bleeding. +resultdescriptions.ooze=Killed by acid. +resultdescriptions.fall=Killed by falling. +resultdescriptions.cheat=Dead because of cheating. +resultdescriptions.countdown=Killed by explode. +resultdescriptions.win=Find the Amulet. +resultdescriptions.win2=Escape? + +journal$feature.memory_fire=fire of memory + + diff --git a/resources/com/hmdzl/spspd/messages/misc/misc_zh.properties b/resources/com/hmdzl/spspd/messages/misc/misc_zh.properties new file mode 100644 index 00000000..9562b248 --- /dev/null +++ b/resources/com/hmdzl/spspd/messages/misc/misc_zh.properties @@ -0,0 +1,137 @@ + +badges.endorsed=取得徽章:%s +badges.new_super=新的超级徽章:%s +badges.new=新的徽章:%s +badges$badge.monsters_slain_1=击杀10名敌人 +badges$badge.monsters_slain_2=击杀50名敌人 +badges$badge.monsters_slain_3=击杀150名敌人 +badges$badge.monsters_slain_4=击杀250名敌人 +badges$badge.gold_collected_1=收集100金币 +badges$badge.gold_collected_2=收集500金币 +badges$badge.gold_collected_3=收集2500金币 +badges$badge.gold_collected_4=收集7500金币 +badges$badge.level_reached_1=达到10级 +badges$badge.level_reached_2=达到20级 +badges$badge.level_reached_3=达到30级 +badges$badge.level_reached_4=达到40级 +badges$badge.all_potions_identified=全部药水鉴定 +badges$badge.all_scrolls_identified=全部卷轴鉴定 +badges$badge.all_rings_identified=全部戒指鉴定 +badges$badge.all_wands_identified=全部法杖鉴定 +badges$badge.all_items_identified=全部药水、卷轴、戒指和法杖鉴定 +badges$badge.all_bags_bought=买下所有包裹 +badges$badge.death_from_fire=死于火焰 +badges$badge.death_from_poison=死于剧毒 +badges$badge.death_from_gas=死于毒气 +badges$badge.death_from_hunger=死于饥饿 +badges$badge.death_from_glyph=死于盔甲刻印 +badges$badge.death_from_falling=死于坠落楼层 +badges$badge.yasd=死于火焰,剧毒,毒气和饥饿 +badges$badge.boss_slain_1=斩杀第1个Boss +badges$badge.boss_slain_2=斩杀第2个Boss +badges$badge.boss_slain_3=斩杀第3个Boss +badges$badge.boss_slain_4=斩杀第4个Boss +badges$badge.boss_slain_1_all_classes=分别使用战士、法师、盗贼和女猎手斩杀第1个Boss +badges$badge.boss_slain_3_all_subclasses=分别使用角斗士、狂战士、术士、战斗法师、疾行者、刺客、狙击手和守望者斩杀第3个Boss +badges$badge.ring_of_haggler=取得砍价戒指 +badges$badge.ring_of_thorns=取得荆棘戒指 +badges$badge.strength_attained_1=达到13点力量 +badges$badge.strength_attained_2=达到15点力量 +badges$badge.strength_attained_3=达到17点力量 +badges$badge.strength_attained_4=达到19点力量 +badges$badge.food_eaten_1=吃掉10个食物 +badges$badge.food_eaten_2=吃掉20个食物 +badges$badge.food_eaten_3=吃掉30个食物 +badges$badge.food_eaten_4=吃掉40个食物 +badges$badge.item_level_1=获得3级物品 +badges$badge.item_level_2=获得6级物品 +badges$badge.item_level_3=获得9级物品 +badges$badge.item_level_4=获得12级物品 +badges$badge.rare=击杀所有稀有怪物 +badges$badge.victory=取得Yendor护符 +badges$badge.victory_all_classes=分别使用战士,法师,盗贼和女猎手取得Yendor护符 +badges$badge.mastery_combo=达成10连击 +badges$badge.potions_cooked_1=一场游戏中酿造3瓶药水 +badges$badge.potions_cooked_2=一场游戏中酿造6瓶药水 +badges$badge.potions_cooked_3=一场游戏中酿造9瓶药水 +badges$badge.potions_cooked_4=一场游戏中酿造12瓶药水 +badges$badge.no_monsters_slain=在不击杀怪物的情况下通过楼层 +badges$badge.grim_weapon=通过"残酷"武器附魔秒杀一个怪物 +badges$badge.piranhas=消灭6只食人鱼 +badges$badge.night_hunter=在夜间击杀15个怪物 +badges$badge.games_played_1=进行10场游戏 +badges$badge.games_played_2=进行100场游戏 +badges$badge.games_played_3=进行500场游戏 +badges$badge.games_played_4=进行2000场游戏 +badges$badge.happy_end=幸福结局 +badges$badge.champion=挑战成功 +badges$badge.supporter=感谢您的支持! +badges$badge.orb=获得zot的能量球! +badges$badge.otiluke=成功解救Otiluke! +badges$badge.tri=获得起源三角! +badges$badge.egg_break_1=召唤1个宠物! +badges$badge.egg_break_2=召唤3个宠物! +badges$badge.egg_break_3=召唤5个宠物! + +challenges.item_phobia=恐物幻觉 +challenges.item_phobia_desc=你感觉你的卷轴和药水都不能使用。\n\n-使用药水花费额外回合。\n-使用卷轴将受到伤害并被沉默。\n-开始时获得1000金币。 +challenges.listless=精神萎靡 +challenges.listless_desc=你感觉浑身无力。\n\n-升级获得最大生命值减少。\n-开始时获得根骨药水和蜂皇浆。 +challenges.nightmare_virus=梦魇病毒 +challenges.nightmare_virus_desc=恐怖的病毒感染了所有的生物。\n\n-怪物死亡时生成病毒体。\n-开始时获得复活十字架。 +challenges.energy_lost=能量流失 +challenges.energy_lost_desc=大量的能量转化为热能散发。\n\n-食物提供的能量大幅度减少。\n-法杖最大充能上限减少。\n-开始时获得大饼。 +challenges.dew_rejection=排异露珠 +challenges.dew_rejection_desc=露珠之神并不喜欢你。\n\n-露珠掉落减少。\n-露珠花费增加。\n-开始时获得2集露草之种。 +challenges.darkness=没入黑暗 +challenges.darkness_desc=黑暗吞噬了周围的环境。 \n\n-无法主动记录地图。\n-开始时获得2探地卷轴 +challenges.abrasion=严重磨损 +challenges.abrasion_desc=武器上的锈迹明显了起来。\n\n-常规武器有耐久度限制。用完即刻报废。\n-开始时获得升级卷轴和注魔卷轴。 +challenges.test_time=测试时间 +challenges.test_time_desc=仅仅是个测试模式。\n\n-玩的开心。 + +skins.title=选择英雄的皮肤 +skins.normal=经典皮肤 +skins.first=暑假特典 +skins.second=万圣逃亡 +skins.third=年兽猎人 +skins.normal_desc=经典的像素地牢皮肤,包括战士,法师,盗贼,猎手,演员,星兵,信徒。\n-开始时获得新手宠物包。 +skins.first_desc=2019年暑期的英雄皮肤,包括格斗家,探险者,忍者,女仆长,游戏主播,水管工,建筑工。\n-开始时用更加专业的道具替换原有道具。\n-格斗家习得升龙拳。\n-探险者发现彩虹大炮。\n-忍者成为传奇。\n-女仆长练习飞刀。\n-游戏主播开挂。\n-水管工顶砖块。\n-建筑工拿矿镐。 +skins.second_desc=怪物皮肤,包括恶魔,豺狼,亡灵,马人,史莱姆,机甲,星灵。\n-开始时获得独有的属性值。\n-恶魔火焰攻击。\n-豺狼快速充能。\n-亡灵潜行牛逼。\n-马人跑得飞快。\n-史莱姆再生恢复。\n-机甲护甲成长。\n-星灵无视防御。 +skins.third_desc=2020年春节皮肤,包括重装,司仪,武者,弩手,舞狮,医疗,行商。\n-失去神圣护盾和鞋子,获得猎杀工具包和一个额外的专属道具。\n-重装有盾牌和头盔。\n-司仪有烧瓶和面具。\n-武者有斗篷和图腾。\n-弩手有弓箭和镖袋。\n-舞狮有铁铲和舞谱。\n-医疗有电枪和血包。\n-行商有信盒和水晶 +skins.info=不同的皮肤将提供不同的初始物品 +skins.yes=是的 +skins.no=不是 + +journal$feature.well_of_health=生命之泉 +journal$feature.well_of_awareness=觉察之泉 +journal$feature.well_of_transmutation=蜕变之泉 +journal$feature.alchemy=炼金釜 +journal$feature.garden=静谧花圃 +journal$feature.statue=活化石像 +journal$feature.ghost=悲伤的幽灵 +journal$feature.wandmaker=法杖工匠 +journal$feature.troll=巨魔铁匠 +journal$feature.imp=野心勃勃的小恶魔 + +resultdescriptions.mob=死于怪物 +resultdescriptions.unique=死于未知怪物 +resultdescriptions.named=死于目标 +resultdescriptions.item=死于物品 +resultdescriptions.glyph=死于护甲刻印 +resultdescriptions.trap=死于机关 +resultdescriptions.burning=烧至灰烬 +resultdescriptions.hunger=饿至昏厥 +resultdescriptions.poison=毒至休克 +resultdescriptions.gas=窒息至死 +resultdescriptions.bleeding=血流不止 +resultdescriptions.ooze=溶于强酸 +resultdescriptions.fall=摔至肉酱 +resultdescriptions.cheat=作弊至死。拜托你很弱诶 +resultdescriptions.countdown=爆体而亡 +resultdescriptions.win=获得护符 +resultdescriptions.win2=逃离试验? + +journal$feature.memory_fire=记忆之火 + + diff --git a/resources/com/hmdzl/spspd/messages/plants/plants.properties b/resources/com/hmdzl/spspd/messages/plants/plants.properties new file mode 100644 index 00000000..1fd763a3 --- /dev/null +++ b/resources/com/hmdzl/spspd/messages/plants/plants.properties @@ -0,0 +1,76 @@ +plants.blandfruitbush.name=Blandfruit +plants.blandfruitbush.desc=Distant cousin of the Rotberry, the pear-shaped produce of the Blandfruit bush tastes like caked dust. The fruit is gross and unsubstantial but isn't poisonous. perhaps it could be cooked. +plants.blandfruitbush$seed.name=seed of blandfruit + +plants.blindweed.name=Blindweed +plants.blindweed.desc=Upon being touched a Blindweed perishes in a bright flash of light. The flash is strong enough to disorient for several seconds. +plants.blindweed$seed.name=seed of blindweed + +plants.dreamfoil.name=Dreamfoil +plants.dreamfoil.refreshed=You feel refreshed. +plants.dreamfoil.desc=The Dreamfoil's prickly flowers contain a chemical which is known for its properties as a strong neutralizing agent. Most weaker creatures are overwhelmed and knocked unconscious, which gives the plant its namesake. +plants.dreamfoil$seed.name=seed of dreamfoil + +plants.earthroot.name=Earthroot +plants.earthroot.desc=When a creature touches an Earthroot, its roots create a kind of immobile natural armor around it. +plants.earthroot$seed.name=seed of earthroot +plants.earthroot$armor.name=Herbal armor +plants.earthroot$armor.desc=A kind of natural, immobile armor is protecting you. The armor forms plates of bark and twine, wrapping around your body.\n\nThis herbal armor will absorb 50%% of all physical damage you take, until it eventually runs out of durability and collapses. The armor is also immobile, if you attempt to move it will break apart and be lost.\n\nArmor remaining: %d. + +plants.fadeleaf.name=Fadeleaf +plants.fadeleaf.desc=Touching a Fadeleaf will teleport any creature to a random place on the current level. +plants.fadeleaf$seed.name=seed of fadeleaf + +plants.firebloom.name=Firebloom +plants.firebloom.desc=When something touches a Firebloom, it bursts into flames. +plants.firebloom$seed.name=seed of firebloom + +plants.icecap.name=Icecap +plants.icecap.desc=Upon being touched, an Icecap lets out a puff of freezing pollen. The freezing effect is much stronger if the environment is wet. +plants.icecap$seed.name=seed of icecap + +plants.plant$seed.seed_of=seed of %s +plants.plant$seed.ac_plant=PLANT +plants.plant$seed.info=Throw this seed to the place where you want to grow a plant.\n\n%s + +plants.rotberry.name=Rotberry +plants.rotberry.desc=The berries of a young rotberry shrub taste like sweet, sweet death.\n\nGiven several days, this rotberry shrub will grow into another rot heart. +plants.rotberry$seed.name=seed of rotberry + +plants.sorrowmoss.name=Sorrowmoss +plants.sorrowmoss.desc=A Sorrowmoss is a flower (not a moss) with razor-sharp petals, coated with a deadly venom. +plants.sorrowmoss$seed.name=seed of sorrowmoss + +plants.starflower.name=Starflower +plants.starflower.desc=An extremely rare plant, Starflower is said to grant holy power to whomever touches it. +plants.starflower$seed.name=seed of starflower + +plants.stormvine.name=Stormvine +plants.stormvine.desc=Gravity affects the Stormvine plant strangely, allowing its whispy blue tendrils to 'hang' on the air. Anything caught in the vine is affected by this, and becomes disoriented. +plants.stormvine$seed.name=seed of stormvine + +plants.sungrass.name=Sungrass +plants.sungrass.desc=Sungrass is renowned for its sap's slow but effective healing properties. +plants.sungrass$seed.name=seed of sungrass +plants.sungrass$health.name=Herbal Healing +plants.sungrass$health.desc=Sungrass possesses excellent healing properties, though its not as fast as a potion of healing.\n\nYou are current slowly regenerating health from the sungrass plant. Taking damage while healing will reduce the healing effectiveness, and moving off the plant will break the healing effect.\n\nHealing remaining: %d. + +plants.dewcatcher.name=Dewcatcher +plants.dewcatcher.desc=Dewcatchers camouflage as grass to avoid attention, but their bulges of collected dew give them away. +plants.dewcatcher$seed.name=seed of dewcatcher + +plants.flytrap.name=Upgrade-eater +plants.flytrap.desc=A new type of plant can destroy one type of item and change it into something like scroll of upgrade. +plants.flytrap$seed.name=seed of upgrade-eater + +plants.phaseshift.name=Phase-pitcher +plants.phaseshift.desc=No one know how it appare or how it grow, but it can change one item into another, like Well of Transmutation. +plants.phaseshift$seed.name=seed of phase-pitcher + +plants.seedpod.name=Seed-Pod +plants.seedpod.desc=Seed Pods look pretty, but the seeds they carry are actually stolen from other plants they kill with their roots. +plants.seedpod$seed.name=seed of seed-pod + +plants.nutplant.name=nut vine +plants.nutplant.desc=A vine with nut. It don't have effect, but both vine and nut are eatable. +plants.nutplant$seed.name=Seed of nut vine diff --git a/resources/com/hmdzl/spspd/messages/plants/plants_zh.properties b/resources/com/hmdzl/spspd/messages/plants/plants_zh.properties new file mode 100644 index 00000000..54a320a1 --- /dev/null +++ b/resources/com/hmdzl/spspd/messages/plants/plants_zh.properties @@ -0,0 +1,76 @@ +plants.blandfruitbush.name=无味果 +plants.blandfruitbush.desc=腐莓的远亲,梨状的无味果果实味同嚼蜡也无营养,但并没有毒性。也许可以煮食。 +plants.blandfruitbush$seed.name=无味果之种 + +plants.blindweed.name=致盲草 +plants.blindweed.desc=在被碰到后,致盲草会瞬间枯萎并释放一道强光。这道光足以刺伤受害者双眼,使其暂时失明。 +plants.blindweed$seed.name=致盲草之种 + +plants.dreamfoil.name=梦夜花 +plants.dreamfoil.refreshed=你感觉浑身清爽。 +plants.dreamfoil.desc=梦夜花带刺的花瓣含有一种净化性极强的化学物质。这种花也因其能够致使多数接触它的生物立刻昏迷而得名。 +plants.dreamfoil$seed.name=梦夜花之种 + +plants.earthroot.name=地缚根 +plants.earthroot.desc=碰到地缚种后,它的根系会在你周边形成某种无法移动的天然护甲。 +plants.earthroot$seed.name=地缚根之种 +plants.earthroot$armor.name=植被护甲 +plants.earthroot$armor.desc=一种不可移动的天然护甲正在保护你。这个护甲由层层树皮和藤蔓盘结而成,紧密地缠绕在你的身体周围。\n\n这种护甲能够吸收你受到的50%%物理伤害,直到其耗尽耐久而瓦解。护甲是不可移动的,这意味着如果你想重新移动的话必须将其彻底破坏。\n\n护盾量剩余:%d点。 + +plants.fadeleaf.name=消逝草 +plants.fadeleaf.desc=任何触碰到消逝草的生物都会被传送到当前层的一个随机地点。 +plants.fadeleaf$seed.name=消逝草之种 + +plants.firebloom.name=烈焰花 +plants.firebloom.desc=烈焰花被任何物品触碰到时,都会化为一团火焰。 +plants.firebloom$seed.name=烈焰花之种 + +plants.icecap.name=冰冠花 +plants.icecap.desc=冰冠花在被接触到时会喷射出一团能冰冻周遭的花粉。潮湿环境下花粉的冰冻能力会大幅增强。 +plants.icecap$seed.name=冰冠花之种 + +plants.plant$seed.seed_of=%s之种 +plants.plant$seed.ac_plant=种植 +plants.plant$seed.info=把这个种子丢到你想产生一株植物的地方。\n\n%s + +plants.rotberry.name=腐莓丛 +plants.rotberry.desc=未成熟的腐败果灌木结出的浆果尝起来更像是甜蜜的死亡。\n\n只要过几天,这棵灌木就会长成另一棵腐败之心。 +plants.rotberry$seed.name=腐败果之种 + +plants.sorrowmoss.name=断肠苔 +plants.sorrowmoss.desc=断肠苔并不是一种苔藓,而是一种有极强毒性,花瓣利如刀片的花。 +plants.sorrowmoss$seed.name=断肠苔之种 + +plants.starflower.name=星陨花 +plants.starflower.desc=星陨花极为罕见,据说其能够为任何接触它的人赋予神圣之力。 +plants.starflower$seed.name=星陨花之种 + +plants.stormvine.name=风暴藤 +plants.stormvine.desc=引力似乎并不能正常地作用在风暴藤上,它蓝色的藤蔓能够"挂"在空中。任何被风暴藤缠到的生物也被这种奇怪的引力影响,并失去方向感。 +plants.stormvine$seed.name=风暴藤之种 + +plants.sungrass.name=阳春草 +plants.sungrass.desc=阳春草因其汁液缓慢但显著的疗伤效果而家喻户晓。 +plants.sungrass$seed.name=阳春草之种 +plants.sungrass$health.name=草药疗养 +plants.sungrass$health.desc=阳春草拥有优秀的治疗能力,尽管没有治疗药水高效地回复速度。 \n\n这株神奇的植物正在缓慢地治疗你的伤势。在此期间受伤会降低治愈效率,而且离开这里会打断治疗效果。\n\n剩余治疗量:%d。 + +plants.dewcatcher.name=集露草 +plants.dewcatcher.desc=集露草是一种特殊的高草。它上面集满了露珠。摇晃叶子露珠就会掉下来。 +plants.dewcatcher$seed.name=集露草之种 + +plants.flytrap.name=吞星花 +plants.flytrap.desc=这种植物的花像是巨口,可以吞噬一件装备,并保留那件装备的精华,移作他用。 +plants.flytrap$seed.name=吞星花之种 + +plants.phaseshift.name=转换笼 +plants.phaseshift.desc=这种植物来源不明,但它看起来和转化井差不多。没准这是转化井的原型? +plants.phaseshift$seed.name=转换笼之种 + +plants.seedpod.name=种子荚 +plants.seedpod.desc=一种装满种子的植物。它肯定是从其他植物上偷的种子。 +plants.seedpod$seed.name=种子荚之种 + +plants.nutplant.name=坚果藤 +plants.nutplant.desc=可以生成坚果的藤曼,但是已经失去了这种功能。好在这种藤曼可以食用。 +plants.nutplant$seed.name=坚果藤之种 \ No newline at end of file diff --git a/resources/com/hmdzl/spspd/messages/scenes/scenes.properties b/resources/com/hmdzl/spspd/messages/scenes/scenes.properties new file mode 100644 index 00000000..fd34e418 --- /dev/null +++ b/resources/com/hmdzl/spspd/messages/scenes/scenes.properties @@ -0,0 +1,82 @@ +#scenes.aboutscene.= + +scenes.amuletscene.exit=Let's call it a day +scenes.amuletscene.stay=I'm not done yet +scenes.amuletscene.text=You finally hold it in your hands, the Amulet of Yendor. Using its power you can take over the world or bring peace and prosperity to people or whatever. Anyway, your life will change forever and this game will end here. Or you can stay a mere mortal a little longer. + +scenes.pudding_cupscene.exit=Wait, it is just a pudding cup +scenes.pudding_cupscene.stay=I went here for treasure, not pudding +scenes.pudding_cupscene.text=Finally, you find this pudding cup in the deep of the hell. Well your journey is not end now. Back to imp's shop and buy three trial, keep write your own story. + +scenes.powerhandscene.exit=End Game +scenes.powerhandscene.stay=Keep searching +scenes.powerhandscene.text=Looks like you escape from this game. Good work. + +scenes.badgesscene.title=Your Badges + +scenes.gamescene.welcome=You descend to floor %d of SPecial Surprise Pixel Dungeon! +scenes.gamescene.welcome_back=You return to floor %d of SPecial Surprise Pixel Dungeon! +scenes.gamescene.chasm=Your steps echo across the dungeon. +scenes.gamescene.water=You hear water splashing around you. +scenes.gamescene.grass=The smell of vegetation is thick in the air. +scenes.gamescene.dark=You can hear enemies moving in the darkness... +scenes.gamescene.secrets=The atmosphere hints that this floor hides many secrets. +scenes.gamescene.dont_know=You don't know what is there. + +scenes.interlevelscene$mode.descend=Descending... +scenes.interlevelscene$mode.ascend=Ascending... +scenes.interlevelscene$mode.continue=Loading... +scenes.interlevelscene$mode.resurrect=Resurrecting... +scenes.interlevelscene$mode.return=Returning... +scenes.interlevelscene$mode.fall=Falling... +scenes.interlevelscene$mode.port4=May Triforce bless you... +scenes.interlevelscene$mode.portshadoweater=YOU ARE COMA... +scenes.interlevelscene$mode.portpot=JUST LEAVE... +scenes.interlevelscene$mode.porthalls=You should fear, Yog comes!!! +scenes.interlevelscene$mode.portcrab=Warning, high-voltage electricity!!! +scenes.interlevelscene$mode.porttengu=A great place to hidding… +scenes.interlevelscene$mode.portcoin=Overthrow the local despots, distribute land!!! +scenes.interlevelscene$mode.portbone=Feel the anger of the bones! +scenes.interlevelscene$mode.returnsave=Return to save place... +scenes.interlevelscene$mode.journal=Loading, please wait... +scenes.interlevelscene$mode.sokobanfail=Falling... +scenes.interlevelscene$mode.palantir=Vs Zot!!! +scenes.interlevelscene$mode.bossrush=New test start... +scenes.interlevelscene$mode.portmap=Catch that gnoll!!! +scenes.interlevelscene$mode.save=Saving now, don't turn power off... +scenes.interlevelscene$mode.sleep=Sleeping Time... +scenes.interlevelscene$mode.reset=Resetting... +scenes.interlevelscene$mode.chaos=Endless world +scenes.interlevelscene$mode.challengebook=check your challenge... +scenes.interlevelscene.file_not_found=Save file not found. If this error persists after restarting, it may mean this save game is corrupted. Sorry about that. +scenes.interlevelscene.io_error=Cannot read save file. If this error persists after restarting, it may mean this save game is corrupted. Sorry about that. + +scenes.introscene.text=Many heroes have ventured into the dungeon before you from the city above. Some have returned with treasures and magical artifacts, most have never been heard from again.\n\nNone, however, have ventured to the bottom and retrieved the Amulet of Yendor, which is said to be guarded by an ancient evil in the depths. Even now dark energy radiates from below, making its way up into the city.\n\nYou consider yourself ready for the challenge. Most importantly, you feel that fortune smiles upon you. It's time to start your own adventure! + +scenes.rankingsscene.title=Top Rankings +scenes.rankingsscene.total=Games Played: +scenes.rankingsscene.no_games=No games have been played yet. +scenes.rankingsscene.no_info=No additional information + +scenes.startscene.load=Load Game +scenes.startscene.erase=Erases Progress +scenes.startscene.depth_level=Depth: %d, Level: %d +scenes.startscene.really=Do you really want to start new game? +scenes.startscene.warning=Your current game progress will be erased. +scenes.startscene.yes=Yes, start new game +scenes.startscene.no=No, return to main menu + +scenes.startscene.title=Game In Progress +scenes.startscene.new=New Game + +scenes.surfacescene.exit=Game Over + +scenes.titlescene.play=Play +scenes.titlescene.rankings=Rankings +scenes.titlescene.badges=Badges +scenes.titlescene.about=About + +scenes.welcomescene.title=SPecial Surprise Pixel Dungeon +scenes.welcomescene.new_things=At the start of 2020, a horrible virus attack our world. We don't know where it from, but we survival from it... for now. Home quarantine is borning, so some testers decide to improve this test. The first part of testers' Internet Party is start. +scenes.welcomescene.continue=OK! + diff --git a/resources/com/hmdzl/spspd/messages/scenes/scenes_zh.properties b/resources/com/hmdzl/spspd/messages/scenes/scenes_zh.properties new file mode 100644 index 00000000..1055355a --- /dev/null +++ b/resources/com/hmdzl/spspd/messages/scenes/scenes_zh.properties @@ -0,0 +1,82 @@ +#scenes.aboutscene.= + +scenes.amuletscene.exit=现在就到此为止吧 +scenes.amuletscene.stay=这一切还不该结束 +scenes.amuletscene.text=你终于握住了它——传说中的Yendor护符。通过它的力量你能够征服世界或者为人民带来繁荣幸福或者任何你能想到的事。不论如何,你的一生被永远改变了,游戏也即将在这里结束。或者你也可以继续以一个凡人的姿态再在这里逗留一会。 + +scenes.pudding_cupscene.exit=嗨,这玩意不是护符 +scenes.pudding_cupscene.stay=我没法用这玩意离开 +scenes.pudding_cupscene.text=看起来有人拿走了Yendor护符并留下这个布丁。看来你的冒险还要继续进行下去。 + +scenes.powerhandscene.exit=结束游戏 +scenes.powerhandscene.stay=向下探索 +scenes.powerhandscene.text=你启动了这个手套,瞬间你来到了一个由1和0构成的世界里。看起来你成功逃离了那个地牢,但前方已经没有路了。好好休息吧。 + +scenes.badgesscene.title=你获得的徽章 + +scenes.gamescene.welcome=你进入了特别惊喜地牢的第%d区域! +scenes.gamescene.welcome_back=你回到了特别惊喜地牢的第%d区域! +scenes.gamescene.chasm=你的脚步声回荡在地牢中。 +scenes.gamescene.water=你听见周围水花铺洒的声音。 +scenes.gamescene.grass=空气中弥漫着浓郁的植物清香。 +scenes.gamescene.dark=你依稀听到敌人在黑暗中涌动。 +scenes.gamescene.secrets=诡秘的气氛正暗示这层隐藏着众多秘密。 +scenes.gamescene.dont_know=你不清楚那里有什么。 + +scenes.interlevelscene$mode.descend=下楼中… +scenes.interlevelscene$mode.ascend=上楼中… +scenes.interlevelscene$mode.continue=读取中… +scenes.interlevelscene$mode.resurrect=复活中… +scenes.interlevelscene$mode.return=返回中… +scenes.interlevelscene$mode.fall=跌落中… +scenes.interlevelscene$mode.port4=愿三角之力保护你… +scenes.interlevelscene$mode.portshadoweater=你眼前一黑 +scenes.interlevelscene$mode.portpot=这里没什么测试内容,离开吧 +scenes.interlevelscene$mode.porthalls=恐惧绝望,古神降临 +scenes.interlevelscene$mode.portcrab=你听到了强电流的声音... +scenes.interlevelscene$mode.porttengu=这是个适合躲藏的地方… +scenes.interlevelscene$mode.portcoin=金色再次闪瞎了你的眼睛… +scenes.interlevelscene$mode.portbone=感受白骨之王的愤怒! +scenes.interlevelscene$mode.returnsave=返回安全区域… +scenes.interlevelscene$mode.journal=传送中… +scenes.interlevelscene$mode.sokobanfail=跌落中… +scenes.interlevelscene$mode.palantir=最终的战斗! +scenes.interlevelscene$mode.bossrush=新一轮测试开始! +scenes.interlevelscene$mode.portmap=别让霍格跑了! +scenes.interlevelscene$mode.save=记忆中,请勿关闭电源。 +scenes.interlevelscene$mode.sleep=睡觉时间。 +scenes.interlevelscene$mode.reset=重置中... +scenes.interlevelscene$mode.chaos=无尽世界 +scenes.interlevelscene$mode.challengebook=读取任务中... +scenes.interlevelscene.file_not_found=未能找到存档文件。如果重启后问题依旧存在, 那这个存档可能已经损坏。我很抱歉。 +scenes.interlevelscene.io_error=未能找到存档文件。如果重启后问题依旧存在, 那这个存档可能已经损坏。我很抱歉。 + +scenes.introscene.text=在你之前,曾经有很多来自上方城镇的英雄向这个地城进发。有的人带回了财宝和魔法道具,而大多数人彻底销声匿迹。\n\n不过,从未有人能成功到达过底层,染指Yendor护符,传说它被深渊中的远古邪物守卫着,哪怕是现在,黑暗之力也从地下辐射而来,一路渗透到城镇中。\n\n你认为你准备好接受挑战了,更重要的是,你觉得命运女神正对你微笑. 是时候开始你自己的冒险了! + +scenes.rankingsscene.title=最高纪录 +scenes.rankingsscene.total=游戏次数: +scenes.rankingsscene.no_games=目前为止还没有已经结束的游戏。 +scenes.rankingsscene.no_info=没有额外信息 + +scenes.startscene.load=读取游戏 +scenes.startscene.erase=清除进度 +scenes.startscene.depth_level=区域:%d,等级:%d +scenes.startscene.really=确认要重新开始吗? +scenes.startscene.warning=你当前的进度会被清除。 +scenes.startscene.yes=是的,重新开始 +scenes.startscene.no=不,返回主菜单 + +scenes.startscene.title=进行中的游戏 +scenes.startscene.new=新游戏 + +scenes.surfacescene.exit=游戏结束 + +scenes.titlescene.play=开始 +scenes.titlescene.rankings=排行榜 +scenes.titlescene.badges=成就 +scenes.titlescene.about=关于 + +scenes.welcomescene.title=特别惊喜像素地牢(发芽改) +scenes.welcomescene.new_things=2020春节快乐!年兽带着几个新怪物来到了这里,同时引来了新英雄信徒。现在猎手们已经准备好去狩猎年兽了!在额外的英雄皮肤下享受这场长达6个小时的冒险。这里包含大量的彩蛋,你可以和以前一样去打败强大的敌人,但你也可以用其他方式来获得胜利。祝你好运。 +scenes.welcomescene.continue=我懂了 + diff --git a/resources/com/hmdzl/spspd/messages/ui/ui.properties b/resources/com/hmdzl/spspd/messages/ui/ui.properties new file mode 100644 index 00000000..8bd8a0d3 --- /dev/null +++ b/resources/com/hmdzl/spspd/messages/ui/ui.properties @@ -0,0 +1,3 @@ +ui.quickslotbutton.select_item=Select an item to quickslot + +ui.toolbar.examine_prompt=Press for info, again to search diff --git a/resources/com/hmdzl/spspd/messages/ui/ui_zh.properties b/resources/com/hmdzl/spspd/messages/ui/ui_zh.properties new file mode 100644 index 00000000..d15d9860 --- /dev/null +++ b/resources/com/hmdzl/spspd/messages/ui/ui_zh.properties @@ -0,0 +1,3 @@ +ui.quickslotbutton.select_item=选择放入快捷栏的道具 + +ui.toolbar.examine_prompt=选择查询信息,双击进行搜索。 diff --git a/resources/com/hmdzl/spspd/messages/windows/windows.properties b/resources/com/hmdzl/spspd/messages/windows/windows.properties new file mode 100644 index 00000000..df721441 --- /dev/null +++ b/resources/com/hmdzl/spspd/messages/windows/windows.properties @@ -0,0 +1,296 @@ +windows.wndblacksmith.prompt=Ok, a deal is a deal, dat's what I can do for you: I can reforge any 2 items and turn them into one of a better quality. The first item will get upgrades from the second. The second item will be destroyed. The more dark gold you have, the less upgrades will be lost. +windows.wndblacksmith.select1=Select an item to reforge +windows.wndblacksmith.select2=Select an item for reforge +windows.wndblacksmith.reforge=Reforge them + +windows.wndblacksmith2.prompt=Ok. if you have _50 darkgold_ , I can help you welding your item and adamant stuff. +windows.wndblacksmith2.select1=Select an item to weld +windows.wndblacksmith2.select2=Select an adamant for weld +windows.wndblacksmith2.reforge=weld them +windows.wndblacksmith2.success=Great, let's start work! + +windows.wndcatalogus.potions=Potions +windows.wndcatalogus.scrolls=Scrolls +windows.wndcatalogus.title=Catalogs + +windows.wndchallenges.title=Challenges + +windows.wndchooseway.message=Which way will you follow? +windows.wndchooseway.cancel=I'll decide later + +windows.wndclass.mastery=Mastery + +windows.wnddescend.message=Are you sure you want to descend? Your _dew charge_ might be wasted. +windows.wnddescend.reward=Descend + +windows.wnderror.title=ERROR + +windows.wndgame.settings=Settings +windows.wndgame.challenges=Challenges +windows.wndgame.rankings=Rankings +windows.wndgame.start=Start New Game +windows.wndgame.loadsave=Load memory +windows.wndgame.menu=Main Menu +windows.wndgame.exit=Exit Game +windows.wndgame.return=Return to Game + +windows.wndhero.stats=Stats +windows.wndhero.dew=Dew +windows.wndhero.pet=Pet +windows.wndhero.buffs=Buffs +windows.wndhero$statstab.title=Level %d %s +windows.wndhero$statstab.catalogs=Catalogs +windows.wndhero$statstab.journal=Journal +windows.wndhero$statstab.exp=Experience +windows.wndhero$statstab.str=Strength +windows.wndhero$statstab.health=Health +windows.wndhero$statstab.gold=Gold Collected +windows.wndhero$statstab.depth=Maximum Depth +windows.wndhero$statstab.move=Game steps +windows.wndhero$statstab.time=Time +windows.wndhero$statstab.atkskill=ACU +windows.wndhero$statstab.defskill=DEX +windows.wndhero$statstab.magskill=MIG +windows.wndhero$statstab.hunger=Hungry +windows.wndhero$levelstatstab.title=Level %d %s +windows.wndhero$levelstatstab.catalogs=Catalogs +windows.wndhero$levelstatstab.journal=Journal +windows.wndhero$levelstatstab.level_move=Floor Moves +windows.wndhero$levelstatstab.level_max=Floor Move Goal +windows.wndhero$levelstatstab.level_prefect=Prev Under Goal +windows.wndhero$levelstatstab.level_left=Dew Charge Moves +windows.wndhero$pettab.title=Level %d %s +windows.wndhero$pettab.pet_feed=Feed +windows.wndhero.choose_food=Choose food to feed +windows.wndhero$pettab.pet_call=Call +windows.wndhero$pettab.pet_move=Move +windows.wndhero$pettab.pet_stay=Stay +windows.wndhero$pettab.pet_attack=ACU +windows.wndhero$pettab.pet_hp=Health +windows.wndhero$pettab.pet_kill=mobs killed +windows.wndhero$pettab.pet_exp=Exp +windows.wndhero$pettab.pet_skills=Skills +windows.wndhero$pettab.pet_skills_ready=ready +windows.wndhero$pettab.pet_skills_turn=turns +windows.wndhero.pet_eat=Your pet eat %s +windows.wndhero.pet_faraway=You pet is too far away +windows.wndhero.pet_noeat=You pet don't eat %s. +windows.wndhero.heals=%+d HP + +windows.wndimp.message=Oh yes! You are my hero!\nRegarding your reward, I don't have cash with me right now, but I have something better for you. This is my family heirloom ring: my granddad took it off a dead paladin's finger. +windows.wndimp.reward=Take the ring + +windows.wndinfocell.nothing=There have nothing interesting. + +windows.wndinfoitem.chest=Chest +windows.wndinfoitem.locked_chest=Locked chest +windows.wndinfoitem.crystal_chest=Crystal chest +windows.wndinfoitem.tomb=Tomb +windows.wndinfoitem.skeleton=Skeletal remains +windows.wndinfoitem.remains=Heroes remains +windows.wndinfoitem.wont_know=You won't know what's inside until you open it! +windows.wndinfoitem.need_key=You won't know what's inside until you open it! But to open it you need a golden key. +windows.wndinfoitem.inside=You can see %s inside, but to open the chest you need a golden key. +windows.wndinfoitem.owner=This ancient tomb may contain something useful, but its owner will most certainly object to checking. +windows.wndinfoitem.skeleton_desc=This is all that's left of some unfortunate adventurer. Maybe it's worth checking for any valuables. +windows.wndinfoitem.remains_desc=This is all that's left from one of your predecessors. Maybe it's worth checking for any valuables. +windows.wndinfoitem.artifact=an artifact +windows.wndinfoitem.wand=a wand +windows.wndinfoitem.ring=a ring +windows.wndinfotrap.inactive=This trap is inactive, and can no longer be triggered. + +windows.wndjournal.title=Journal + +windows.wndlangs.completed=This language has been fully translated and reviewed. +windows.wndlangs.unreviewed=This language has not yet been reviewed.\n\nIt may contain errors, but all text has been translated. +windows.wndlangs.unfinished=This language has not been fully translated.\n\nLarge amounts of text may still be in English. +windows.wndlangs.transifex=All translation provided by volunteers through _Transifex._ +windows.wndlangs.credits=credits +windows.wndlangs.reviewers=reviewers +windows.wndlangs.translators=translators + +windows.wndranking.error=Unable to load additional information +windows.wndranking.stats=Stats +windows.wndranking.items=Items +windows.wndranking.badges=Badges +windows.wndranking$statstab.title=Level %d %s +windows.wndranking$statstab.challenges=Challenges +windows.wndranking$statstab.health=Health +windows.wndranking$statstab.str=Strength +windows.wndranking$statstab.duration=Game Duration +windows.wndranking$statstab.depth=Maximum Depth +windows.wndranking$statstab.enemies=Mobs Killed +windows.wndranking$statstab.gold=Gold Collected +windows.wndranking$statstab.food=Food Eaten +windows.wndranking$statstab.alchemy=Potions Cooked +windows.wndranking$statstab.ankhs=Ankhs Used +windows.wndranking$statstab.water=Plant Watered + +windows.wndresurrect.message=You died, but you were given another chance to win this dungeon. Will you take it? +windows.wndresurrect.yes=Yes, I will fight! +windows.wndresurrect.no=No, I give up + +windows.wndsadghost.rat_title=DEFEATED FETID RAT +windows.wndsadghost.gnoll_title=DEFEATED GNOLL TRICKSTER +windows.wndsadghost.crab_title=DEFEATED GREAT CRAB +windows.wndsadghost.rat=Thank you, that horrid rat is slain and I can finally rest... I wonder what twisted magic created such a foul creature... +windows.wndsadghost.gnoll=Thank you, that scheming gnoll is slain and I can finally rest... I wonder what twisted magic made it so smart... +windows.wndsadghost.crab=Thank you, that giant crab is slain and I can finally rest... I wonder what twisted magic allowed it to live so long... +windows.wndsadghost.give_item=\n\nPlease take one of these items, they are useless to me now... Maybe they will help you in your journey...\n\nAlso... There is an item lost in this dungeon that is very dear to me... If you ever... find my... rose...... +windows.wndsadghost.weapon=Ghost's weapon +windows.wndsadghost.armor=Ghost's armor +windows.wndsadghost.farewell=Farewell, adventurer! + +windows.wndsettings.zoom_out=- +windows.wndsettings.zoom_in=+ +windows.wndsettings.zoom_default=Default Zoom +windows.wndsettings.scale_up=Scale up UI +windows.wndsettings.immersive=Immersive mode +windows.wndsettings.music=Music +windows.wndsettings.sound=Sound FX +windows.wndsettings.brightness=Brightness +windows.wndsettings.quickslot=More QuickSlot +windows.wndsettings.switch_port=Switch to portrait +windows.wndsettings.switch_land=Switch to landscape +windows.wndsettings.system_font=System_font +windows.wndsettings.else=else + +windows.wndstory.sewers=The Dungeon lies right beneath the City, its upper levels actually constitute the City's sewer system.\n\nAs dark energy has crept up from below the usually harmless sewer creatures have become more and more dangerous. The city sends guard patrols down here to try and maintain safety for those above, but they are slowly failing.\n\nThis place is dangerous, but at least the evil magic at work here is weak. +windows.wndstory.prison=Many years ago a prison was built here to house dangerous criminals. Tightly regulated and secure, convicts from all over the land were brought here to serve time.\n\nBut soon dark miasma started to creep from below, twisting the minds of guard and prisoner alike.\n\nIn response to the mounting chaos, the city sealed off the entire prison. Nobody knows what became of those who were left for dead within these walls... +windows.wndstory.caves=The caves, which stretch down under the abandoned prison, are sparcely populated. They lie too deep to be exploited by the City and they are too poor in minerals to interest the dwarves. In the past there was a trade outpost somewhere here on the route between these two states, but it has perished since the decline of Dwarven Metropolis. Only omnipresent gnolls and subterranean animals dwell here now. +windows.wndstory.city=Dwarven Metropolis was once the greatest of dwarven city-states. In its heyday the mechanized army of dwarves has successfully repelled the invasion of the old god and his demon army. But it is said, that the returning warriors have brought seeds of corruption with them, and that victory was the beginning of the end for the underground kingdom. +windows.wndstory.halls=In the past these levels were the outskirts of Metropolis. After the costly victory in the war with the old god dwarves were too weakened to clear them of remaining demons. Gradually demons have tightened their grip on this place and now it's called Demon Halls.\n\nVery few adventurers have ever descended this far... +windows.wndstory.sokoban1=Finally, I start my adventure for my hometown.\n\nI went to tower, an old magic school, was famous of its laboratory and library.\n\nAfter that, I hear a story about weird box, deadly traps and hidden treasure.\n\nI know what should I do.\n\n-Otiluke, 1345 in empire +windows.wndstory.sokoban2=I complete that quest, and find something. A treasure box surrounded by strange energies.\n\nI open it in tower, and find a map in there. .It seems like... a co-ordinate, and point to a small island. I hope my Dolye stone is still can work...\n\n-Otiluke, 1348 in empire +windows.wndstory.sokoban3=Kill that mirror spent lots of times, but I find that artifact at last.\n\nBased report by laboratory, that glasses can open a portal to another world. There are some unknown creatures lived in there.\n\nI am ready to enter this portal.\n\n-Otiluke, 1355 in empire +windows.wndstory.sokoban4=I can't remember how many time I spend in translate that language, but at last, I success.\n\n\nThis world is create by zot, one powerful void leader. He was try to ruled every world, but he failed. With the help of different hero in different world, zot lost his power and can't move anymore.\n\nThen, I have a great idea. If I control that zot, I will have enough energy to save my hometown.\n\nI will do that! But first of all, I need enter his fortress\n\n-Otiluke, 1361 in empire maybe +windows.wndstory.safelevel=The seller: shopkeeper\nThe buyer: hero\n\nthe seller and buyer, based on equality, voluntariness and negotiated consensus, hereby conclude the following agreement on the purchase and sale of commodity house:\nSeller will sell sweet house to Buyer.\nBuyer will give Seller 1500 golds.\nThis Agreement is in duplicate and has the same legal effect. It shall come into force on the date of signature by both parties. +windows.wndstory.town=Dolye , located in the northwest of empire is famous for its beautiful and unique scenery. xianQuan mountain is sheer and cliffy , which is known as natural screen of Dolye.\n\n\n\nSorry, there are no tours and other services available in this scenic spot at present +windows.wndstory.zot=I did it, I catch zot so that I can use his power. Wait for me, my hometown.\n\n...........\n\nSomething wrong...\n\nYou can't... I will save...\n\n---date delete---\n\n- Otiluke, 1405 in empire +windows.wndstory.chaos=Can you hear me? I'm Ada, an agent from the assassin home. \n\nYou must wake up, this world is just a illusion.\n\nTrust me, we don't have much time. + +windows.wndtradeitem.sale=FOR SALE: %s - %dg +windows.wndtradeitem.buy=Buy for %dg +windows.wndtradeitem.steal=Buy with %d%% off +windows.wndtradeitem.sell=Sell for %dg +windows.wndtradeitem.sell_1=Sell 1 for %dg +windows.wndtradeitem.sell_all=Sell all for %dg +windows.wndtradeitem.cancel=Never mind +windows.wndtradeitem.sold=You've sold your %s for %dg +windows.wndtradeitem.bought=You've bought %s for %dg +windows.wndtradeitem.donot=You can't sell this item + +windows.wndwandmaker.dust=Oh, I see you have the dust! Don't worry about the wraiths, I can deal with them. As I promised, you can choose one of my high quality wands. +windows.wndwandmaker.ember=Oh, I see you have the embers! I do hope the fire elemental wasn't too much trouble. As I promised, you can choose one of my high quality wands. +windows.wndwandmaker.berry=Oh, I see you have the berry! I do hope the rotberry plant didn't trouble you too much. As I promised, you can choose one of my high quality wands. +windows.wndwandmaker.message=As I promised, you can choose one of my high quality wands. +windows.wndwandmaker.battle=Battle Wand +windows.wndwandmaker.no_battle=Non-Battle Wand +windows.wndwandmaker.farewell=Good luck in your quest, %s! + +windows.wndtinkerer.info1=Well, you find what I want. As reword, I can upgrade your dew vial. Also you should choose how to upgrade your items with dews. +windows.wndtinkerer.water=Random bless +windows.wndtinkerer.draw=Accurate upgrade +windows.wndtinkerer.spinfo=What is the difference? +windows.wndtinkerer.dungeon=You feel that your bag is filled with exotic energy. +windows.wndtinkerer.farewell=Good kuck,%s! + +windows.wndtinkerer2.info=Oh... Thank you for your help. I can upgrade your dewvial and create a summon item for you. +windows.wndtinkerer2.mr=Create Mr. Destructo +windows.wndtinkerer2.call=Create Fairy Card +windows.wndtinkerer2.mob=Create Mobile Satellite +windows.wndtinkerer2.farewell=See you in town,%s! + +windows.wndtinkerer3.info=All right, you find another dew mushroom. This place is power trial, after this your power will be stronger. Okay, I know how to upgrade your dew vial. It will hold much more dew, and you will fly if you use speed. +windows.wndtinkerer3.upgrade=Dew vial upgrade v3 +windows.wndtinkerer3.farewell=Good kuck,%s! + +windows.wnddewdrawinfo.info1=Drawing out dew makes it so that mobs on special levels drop dew to fill your vial. Additionally, your character is buffed with _dew charge_ at the start of each normal level. As long as you are dew charged, enemies drop dew to fill your vial. +windows.wnddewdrawinfo.info2=Each level dew charges you for a set amount of moves. Each level also has a move goal for killing all regular generated enemies. Killing all regular enemies that were generated with the level clears that level. If you clear a level in less moves than the goal, the additional moves are added to your dew charge for the next level. You will need to clear the levels as fast as you can to get dew upgrades. +windows.wnddewdrawinfo.info3=_Random bless_ will remove your curse, but its upgrade effect is random, that is, there might be nothing happend after you use dew upgrade. +windows.wnddewdrawinfo.info4=_Accurate upgrade_ can upgrade one item many time and identify it. +windows.wnddewdrawinfo.ok=I see. + +windows.wndegoalinfo.title=test by egoal +windows.wndegoalinfo.info1=Meow. adventurer. A peaceful town, isn't it? I can‘t feel any jpressure in your face, because your journey is very easy?\n\nSo my question is: \n_Egoal_ is a good person, right? +windows.wndegoalinfo.yes=Right +windows.wndegoalinfo.tell1=I'm glad of your answer, but I don't have a present for you this time. Good luck. +windows.wndegoalinfo.no=Who is he? +windows.wndegoalinfo.tell2=Meow, do you know _darkest pixel dungeon_? I hope you can go there to continue your adventure, You will do that, right? Good luck. + +windows.wndotiluke.title=Choose one location +windows.wndotiluke.room1=Sweet home +windows.wndotiluke.room2=Sokoban 1 +windows.wndotiluke.room3=Sokoban 2 +windows.wndotiluke.room4=Sokoban 3 +windows.wndotiluke.room5=Sokoban 4 +windows.wndotiluke.room6=Dolya town +windows.wndotiluke.room7=Spring Festival Town +windows.wndotiluke.room8=Energy core + +windows.wndchallengebook.title=Choose your challenge +windows.wndchallengebook.room1=sewer challenge +windows.wndchallengebook.room2=prison challenge +windows.wndchallengebook.room3=cave challenge +windows.wndchallengebook.room4=city challenge +windows.wndchallengebook.room5=Courage Trial +windows.wndchallengebook.room6=Power Trial +windows.wndchallengebook.room7=Wisdom Trial + +windows.wndhotel.message=Do you want stay for one night in here? It only cost 100 golds. +windows.wndhotel.buy=Yes, I am. +windows.wndhotel.more_gold=You don't have enough money, come next time. + +windows.wndons.message=Give him a clothes. +windows.wndons.give=Give it to him. +windows.wndsaidbysun.message=A chaos item. only need 100000 gold. +windows.wndsaidbysun.buy=Yes +windows.wndgoblin.message=Want a shield? 3000 gold. +windows.wndgoblin.buy=Yes +windows.wnddream.message=WanT fUnNy? +windows.wnddream.buy=funny +windows.wndissic.message=(You see a donating machine in his hand) +windows.wndissic.buy=Sell blood +windows.wndshower.message= +windows.wndshower.buy=Ok +windows.wndhate.message=Need a wand of flock? +windows.wndhate.buy=Ok +windows.wndice13.message=This world need more chaos... +windows.wndice13.buy=This? +windows.wndalchemy.title=Cooking Alchemy +windows.wndalchemy.text=Combine ingredients to create something new! +windows.wndalchemy.select=Select an item +windows.wndalchemy.combine=Combine +windows.wndalchemy.cancel=Cancel + +windows.wndmix.title=A Wonderful Experiments from ARealMan +windows.wndmix.text=Put three rings in here to make a random artifact. It will cost 1000 golds. +windows.wndmix.select=Select an item +windows.wndmix.combine=Combine +windows.wndmix.cancel=Cancel + +windows.wndaflyinfo.title=Hungry Abbey. +windows.wndaflyinfo.text=Abbey is hungry, but I don't have any food now. Can you give me a ration, meat and fruit? I'll give you one after I finish cooking. +windows.wndaflyinfo.select=Select a food +windows.wndaflyinfo.combine=Combine +windows.wndaflyinfo.cancel=Cancel + +windows.wndstartgame.title=Choose your hero skin +windows.wndstartgame.start=Play + +windows.wndgameinprogress.title=Level%1$d %2$s +windows.wndgameinprogress.challenges=Challenges +windows.wndgameinprogress.exp=EXP +windows.wndgameinprogress.str=STR +windows.wndgameinprogress.health=HP +windows.wndgameinprogress.gold=Gold Collected +windows.wndgameinprogress.depth=Maximum Depth +windows.wndgameinprogress.continue=Continue +windows.wndgameinprogress.erase=Erase +windows.wndgameinprogress.erase_warn_title=Really want erase this game? +windows.wndgameinprogress.erase_warn_body=This game will be erase +windows.wndgameinprogress.erase_warn_yes=Yes +windows.wndgameinprogress.erase_warn_no=No + +windows.wndsavegame.title=Save this game +windows.wndsavegame.start=Yes diff --git a/resources/com/hmdzl/spspd/messages/windows/windows_zh.properties b/resources/com/hmdzl/spspd/messages/windows/windows_zh.properties new file mode 100644 index 00000000..dffd3ae7 --- /dev/null +++ b/resources/com/hmdzl/spspd/messages/windows/windows_zh.properties @@ -0,0 +1,304 @@ +windows.wndblacksmith.prompt=好吧,按之前说好的,我得帮你做点事:我可以重铸2件物品并将它们制成一个品质更好的。你携带的_暗金_越多,升级的损失也就越少。 +windows.wndblacksmith.select1=选择要重铸的物品 +windows.wndblacksmith.select2=选择作为素材的物品 +windows.wndblacksmith.reforge=重铸物品 + +windows.wndblacksmith2.prompt=好了。我想我能够帮你焊接强化组件和物品了。只要你带着_50枚暗金_。 +windows.wndblacksmith2.select1=选择要强化的物品 +windows.wndblacksmith2.select2=选择素材组件 +windows.wndblacksmith2.reforge=焊接它们 +windows.wndblacksmith2.success=好极了,让我们开始吧! + +windows.wndcatalogus.potions=药水 +windows.wndcatalogus.scrolls=卷轴 +windows.wndcatalogus.title=图鉴 + +windows.wndchallenges.title=挑战 + +windows.wndchooseway.message=你要选择哪个专精方向? +windows.wndchooseway.cancel=稍后决定 + +windows.wndclass.mastery=专精 + +windows.wnddescend.message=你真的确定要下楼吗,这样的话你当前的_露珠爆炸_效果会被完全清除。 +windows.wnddescend.reward=不要再说了 + +windows.wnderror.title=错误 + +windows.wndgame.settings=设置 +windows.wndgame.challenges=挑战 +windows.wndgame.rankings=排行榜 +windows.wndgame.start=踏上征途 +windows.wndgame.loadsave=读取记忆 +windows.wndgame.menu=主菜单 +windows.wndgame.exit=退出游戏 +windows.wndgame.return=继续冒险 + +windows.wndhero.stats=属性 +windows.wndhero.dew=露珠 +windows.wndhero.pet=宠物 +windows.wndhero.buffs=状态 +windows.wndhero$statstab.title=%d 级 %s +windows.wndhero$statstab.catalogs=图鉴 +windows.wndhero$statstab.journal=事件记录 +windows.wndhero$statstab.exp=经验 +windows.wndhero$statstab.str=力量 +windows.wndhero$statstab.health=生命 +windows.wndhero$statstab.gold=金币收集数 +windows.wndhero$statstab.depth=最高层数 +windows.wndhero$statstab.move=游戏时长 +windows.wndhero$statstab.time=当前时间 +windows.wndhero$statstab.atkskill=命中 +windows.wndhero$statstab.defskill=闪避 +windows.wndhero$statstab.magskill=法强 +windows.wndhero$statstab.hunger=饥饿值 +windows.wndhero$levelstatstab.title=%d 级 %s +windows.wndhero$levelstatstab.catalogs=图鉴 +windows.wndhero$levelstatstab.journal=事件记录 +windows.wndhero$levelstatstab.level_move=清层已用时间 +windows.wndhero$levelstatstab.level_max=限定时间上限 +windows.wndhero$levelstatstab.level_prefect=下层持续时间 +windows.wndhero$levelstatstab.level_left=剩余时间 +windows.wndhero$pettab.title=%d 级 %s +windows.wndhero$pettab.pet_feed=喂食 +windows.wndhero.choose_food=选择喂食的食物 +windows.wndhero$pettab.pet_call=呼唤 +windows.wndhero$pettab.pet_move=巡逻 +windows.wndhero$pettab.pet_stay=留守 +windows.wndhero$pettab.pet_attack=命中 +windows.wndhero$pettab.pet_hp=生命 +windows.wndhero$pettab.pet_kill=击杀数量 +windows.wndhero$pettab.pet_exp=经验 +windows.wndhero$pettab.pet_skills=技能 +windows.wndhero$pettab.pet_skills_ready=就绪 +windows.wndhero$pettab.pet_skills_turn=冷却 +windows.wndhero.pet_eat=你的宠物吃了%s +windows.wndhero.pet_faraway=你的宠物太远了 +windows.wndhero.pet_noeat=你的宠物不吃%s +windows.wndhero.heals=%+d生命 + +windows.wndimp.message=哦太棒了!你简直就是我的英雄!\n关于你的奖励,我现在没带钱,但我这有个更好的东西。这个戒指是我们的传家宝物,是我爷爷从一个死掉的圣骑士手上摘下来的。 +windows.wndimp.reward=接受戒指 + +windows.wndinfocell.nothing=那儿什么也没有。 + +windows.wndinfoitem.chest=宝箱 +windows.wndinfoitem.locked_chest=上锁的宝箱 +windows.wndinfoitem.crystal_chest=水晶宝箱 +windows.wndinfoitem.tomb=坟墓 +windows.wndinfoitem.skeleton=遗骸 +windows.wndinfoitem.remains=英雄遗骸 +windows.wndinfoitem.wont_know=打开前你是看不见里面有什么的! +windows.wndinfoitem.need_key=打开前你是看不见里面有什么的!你需要一枚金钥匙才能打开它。 +windows.wndinfoitem.inside=你看得见里面的%s,但你需要一枚金钥匙才能打开它。 +windows.wndinfoitem.owner=这个坟墓里或许埋葬着一些有用的东西,但墓主肯定是不会让你拿走的。 +windows.wndinfoitem.skeleton_desc=某个不幸的冒险者存在过的唯一证明。或许可以找找里面有什么值钱的东西。 +windows.wndinfoitem.remains_desc=你的某个先辈存在过的唯一证明。或许能找到点什么值钱的东西。 +windows.wndinfoitem.artifact=一件神器 +windows.wndinfoitem.wand=一根法杖 +windows.wndinfoitem.ring=一枚戒指 +windows.wndinfotrap.inactive=这个陷阱已经失效了,且不会被再次触发。 + +windows.wndjournal.title=日志 + +windows.wndlangs.completed=这个语言已被完全翻译并审核完毕。 +windows.wndlangs.unreviewed=这个语言尚未被完全审核。\n\n它也许还存在一些问题,不过所有的文本都已被翻译。 +windows.wndlangs.unfinished=这个语言尚未被完全翻译。\n\n大量文本可能仍然为英语。 +windows.wndlangs.transifex=所有翻译都由_Transifex_网站上的志愿者提供。 +windows.wndlangs.credits=制作名单 +windows.wndlangs.reviewers=审核者 +windows.wndlangs.translators=翻译者 + +windows.wndranking.error=无法载入更多信息。 +windows.wndranking.stats=属性 +windows.wndranking.items=物品 +windows.wndranking.badges=徽章 +windows.wndranking$statstab.title=%d 级 %s +windows.wndranking$statstab.challenges=挑战 +windows.wndranking$statstab.health=生命 +windows.wndranking$statstab.str=力量 +windows.wndranking$statstab.duration=游戏时长 +windows.wndranking$statstab.depth=最高层数 +windows.wndranking$statstab.enemies=怪物击杀数 +windows.wndranking$statstab.gold=金币收集数 +windows.wndranking$statstab.food=食物消耗量 +windows.wndranking$statstab.alchemy=药水酿造数 +windows.wndranking$statstab.ankhs=重生十字架使用量 +windows.wndranking$statstab.water=种植次数 + +windows.wndresurrect.message=你死了,但你同时被给予了第二次挑战这个地牢的机会。你愿意接受吗? +windows.wndresurrect.yes=是的,我要继续战斗! +windows.wndresurrect.no=不,我放弃了 + +windows.wndsadghost.rat_title=击败腐臭老鼠 +windows.wndsadghost.gnoll_title=击败豺狼诡术师 +windows.wndsadghost.crab_title=击败巨大螃蟹 +windows.wndsadghost.rat=谢谢你,那个可怕的老鼠被杀,我也终于可以安息了…不知道究竟是什么样畸形的魔法才能创造这样一个肮脏的生物… +windows.wndsadghost.gnoll=谢谢你,那个诡计多端的豺狼被杀,我也终于可以安息了……不知道究竟是什么样畸形的魔法使它如此诡诈… +windows.wndsadghost.crab=谢谢你,那只巨蟹被杀,我也终于可以安息了……不知道究竟是什么样畸形的魔法能让它活得那么长…… +windows.wndsadghost.give_item=\n\n请从这些东西里拿一件吧,现在对我来说都没用了…也许他们在你的旅程里能起到作用…\n\n对了,在这个地牢里还有一样物品,对我来说非常珍贵…如果你能…找到我的…玫瑰…… +windows.wndsadghost.weapon=幽灵的武器 +windows.wndsadghost.armor=幽灵的盔甲 +windows.wndsadghost.farewell=一路顺风,冒险者! + +windows.wndsettings.zoom_out=- +windows.wndsettings.zoom_in=+ +windows.wndsettings.zoom_default=界面大小 +windows.wndsettings.scale_up=系统UI比例 +windows.wndsettings.immersive=沉浸模式 +windows.wndsettings.music=音乐 +windows.wndsettings.sound=音效 +windows.wndsettings.brightness=明亮 +windows.wndsettings.quickslot=更多快捷栏 +windows.wndsettings.switch_port=转为竖屏模式 +windows.wndsettings.switch_land=转为横屏模式 +windows.wndsettings.system_font=系统字体 +windows.wndsettings.else=其他 + +windows.wndstory.sewers=这片地牢位于城市的正下方,它的最上层其实是由城市的下水道系统组成的。\n\n由于下方不断渗透的黑暗能量,这些本应无害的下水道生物变得越来越危险。城市向这里派出巡逻队并试图以此保护其上方的区域,但他们的影响也在逐渐式微。\n\n这片区域已经算是足够危险了,不过至少大部分邪恶魔法还不足以对这里造成影响。 +windows.wndstory.prison=多年以前一座地下监狱为了收容危险的犯罪者而建立于此。由于其严格的监管和高安全性,地表各处的囚犯都被带到这里经受时间的折磨。 \n\n但不久之后下方充斥着黑暗的瘴气在这里弥漫开来,扭曲了罪犯和狱卒的心智。\n\n监狱里充斥开来的混乱使其彻底失去了秩序,于是城市封锁了整个监狱。现今已经没有人知道这些高墙之下经历过无数死亡的生物究竟会是什么样子... +windows.wndstory.caves=这座从废弃监狱延伸而下的洞穴,早已空无一人。这里对于城市而言过于深入且很难开发,其中极度匮乏的矿物也无法激起矮人的兴趣。曾经在这里有一个为两个势力建立的贸易站,但在矮人国度衰落之后,只有无所不在的豺狼人和地下生物还居住在这里。 +windows.wndstory.city=矮人都市曾经是最宏伟的矮人城邦。在其鼎盛时期矮人的机械化部队曾成功击退过古神及其恶魔军队的入侵。但是也有传闻说,凯旋而归的战士同时带来了腐坏的种子,矮人王国的胜利正是其毁灭的开端。 +windows.wndstory.halls=很久以前这片区域曾是矮人都市的郊区。在与古神的战争中取得惨胜的矮人已经无力掌控并清理这片地区。于是存活的恶魔逐渐巩固了对这里的控制,现在,这里被称作恶魔大厅。\n\n很少有冒险者能够深入到这种地方... +windows.wndstory.sokoban1=最终我还是出发了,为了我的家乡。\n\n经过几个星期的时间,我来到了高塔,一个以奥术闻名的地方。\n\n 在高塔的食堂里我听到了这样一个传闻,有一块地方充斥着各种奇怪的箱子和陷阱,无数的赏金猎人尝试去取走那个地方的宝物,但都失败了。\n\n我想我知道该去哪了。\n\n-Otiluke,1345年。 +windows.wndstory.sokoban2=我以我的智慧轻松通过了第一个挑战,并获得了一些财宝,其中我发现有个金币上面附着了一些奇怪的能量。\n\n回到高塔后,我尝试解析这股能量,它似乎...是一个坐标。我希望我的石板还有用...\n\n-Otiluke,1348年。 +windows.wndstory.sokoban3=之前城堡里面的守卫给我造成了很大的麻烦,但是我还是成功取得了宝物。\n\n那是一件奇怪的眼镜,当我戴上它后,我看到整个世界都变了,充满了混沌和各种不知名的生物。\n\n我甚至想和它们来个接触...\n\n-Otiluke,1355年。 +windows.wndstory.sokoban4=经过多长时间我已经记不清了,但是我成功解析了那些生物的语言。\n\n 这个世界由zot创造,作为它的据点来攻击正常世界。先贤与之交战,并成功将两个世界隔离。\n\n 我突然有个大胆的想法,假如我能控制zot,我就有足够的力量来恢复我老家的荣光。\n\n zot的宫殿就在眼前。不过在那之前,我得要解决这个谜题。 \n\n-Otiluke,1361年。 +windows.wndstory.safelevel=甲方:商人\n乙方:英雄\n\n甲、乙双方就房屋买卖事项,经协商一致,达成以下合同:\n甲方自愿将休息小屋出卖给乙方,同时将该小屋的相关使用权出卖给乙方。\n双方议定上述房产及附属品总价款为1500金币。\n本协议一式两份,具有同等法律效力,自双方签字之日生效。 +windows.wndstory.town=多利亚小镇位于帝国边缘,属仙泉山脉腹地,为帝国最重要的旅游景点以及魔法产地之一。多利亚小镇的核心特产是魔法矿石,一般到这里游玩或者商业洽谈的人主要是为了购买各种魔法道具。此外,仙泉山“帝国第一大洞”魔岩洞,也是观光游览的佳处之一。\n\n\n\n抱歉,现在本景区暂不提供旅游观光以及其他服务。 +windows.wndstory.zot=成功了,我终于可以使用zot的力量了。重建老家简直轻而易举。\n\n哈哈哈...\n\n 我高估...\n\n...我不会...\n\n...===数据损坏===...\n\n-Otiluke,1405年。 +windows.wndstory.chaos=听的见吗,我是艾达,刺客协会的特工。\n\n你必须醒来,你所在的世界全是假象。\n\n相信我,我们的时间不多了。 + +windows.wndtradeitem.sale=正在出售:%s——%d金币 +windows.wndtradeitem.buy=花%d金币购买 +windows.wndtradeitem.steal=以%d%%减价购买 +windows.wndtradeitem.sell=卖出以获得%d金币 +windows.wndtradeitem.sell_1=卖出1个以获得%d金币 +windows.wndtradeitem.sell_all=全部卖出以获得%d金币 +windows.wndtradeitem.cancel=算了 +windows.wndtradeitem.sold=你卖出了你的%s并获得了%d金币。 +windows.wndtradeitem.bought=你买到了%s并花费了%d金币。 +windows.wndtradeitem.donot=你没法出售这件物品。 + +windows.wndwandmaker.dust=哦,我注意到你已经获得了灰尘!别担心那些幽灵,我能解决它们。就像我承诺的,你可以选择我制作的一把高品质法杖。 +windows.wndwandmaker.ember=哦,我注意到你已经获得了余烬!希望那个火元素没有造成太多麻烦。就像我承诺的,你可以选择我制作的一把高品质法杖。 +windows.wndwandmaker.berry=哦,我注意到你已经获得了莓果!希望那株植物没有对你造成太多困扰。就像我承诺的,你可以选择我制作的一把高品质法杖。 +windows.wndwandmaker.message=哦,你成功了,希望没给你带来太多麻烦。选择你的奖励吧。 +windows.wndwandmaker.battle=战斗法杖 +windows.wndwandmaker.no_battle=辅助法杖 +windows.wndwandmaker.farewell=祝你在试炼中好运,%s! + +windows.wndtinkerer.info1=嗯...这就是露珠菌孢啊...稍等...好了,完成了。作为回报,我可以提升你的露珠瓶的等级。同时,你需要做出选择,决定你强化装备的方式。 +windows.wndtinkerer.water=祝福强化 +windows.wndtinkerer.draw=精确强化 +windows.wndtinkerer.spinfo=告诉我它们之间的区别 +windows.wndtinkerer.dungeon=你感觉你的背包里面充满了奇异的能量。 +windows.wndtinkerer.farewell=祝你好运,%s! + +windows.wndtinkerer2.info=喔,你找到哪个啦。万分感谢,我可以稍微改进一下你的露珠瓶。同时,选择一个奖励吧。 +windows.wndtinkerer2.mr=无人机 +windows.wndtinkerer2.call=仙女卡牌 +windows.wndtinkerer2.mob=遥控卫星 +windows.wndtinkerer2.farewell=小镇见,%s! + +windows.wndtinkerer3.info=好吧看,看起来你又找到了我所需要的。啊...这是力量试练里的菌孢...太神奇了。好了,作为回报,我会继续升级你的露珠瓶。它的容量会大幅度的扩大,并且在使用加速时有几率提供额外的飞行能力。 +windows.wndtinkerer3.upgrade=露珠瓶升级v3 +windows.wndtinkerer3.farewell=祝你好运,%s! + +windows.wnddewdrawinfo.info1=露珠强化是你的露珠瓶升级后的功能之一。它不仅可以给你提供升级功能,并且会给你一个叫做_露珠爆炸_的状态。当你处于_露珠爆炸_的状态时,无论你击杀任何东西,它的尸体周围都会出现超多的露珠。 +windows.wnddewdrawinfo.info2=但是,_露珠爆炸_的效果并不是永久的。它只会在进入新的楼层是为你提供,并且根据你该层的清图速度来给你提供下层的持续时间。只要该层未被清理完全,新的怪物就不会生成。 +windows.wnddewdrawinfo.info3=_祝福强化_将清除你身上的诅咒,并随机强化你身上的装备。 +windows.wnddewdrawinfo.info4=_精确强化_仅强化一件道具几次,但它可以提供一个鉴定效果。 +windows.wnddewdrawinfo.ok=我懂了 + +windows.wndegoalinfo.title=西西的测试 +windows.wndegoalinfo.info1=喵呜,你好啊,冒险者。这里真是一个平静安宁的地方,你也这么觉得对吧?你是我见过的最阳光的冒险者,因为本喵没有感觉到你心头的压力。\n\n喵呜,那么问题来了:\n_Egoal_是不是个很不错的家伙呢? +windows.wndegoalinfo.yes=当然 +windows.wndegoalinfo.tell1=你的回答真令本喵很高兴,喵呜~不过这次我没有礼物给你喵。祝你好运。 +windows.wndegoalinfo.no=他是谁? +windows.wndegoalinfo.tell2=喵呜,你听说过_黑暗的像素地牢_吗?如果有机会,希望你也能去那里继续你的冒险,喵,你会去的对吧,以一个冒险者的身份。 + +windows.wndotiluke.title=选择目的地点 +windows.wndotiluke.room1=休息小屋 +windows.wndotiluke.room2=解谜-推箱教程 +windows.wndotiluke.room3=解谜-奇异城堡 +windows.wndotiluke.room4=解谜-传送迷阵 +windows.wndotiluke.room5=解谜-终极挑战 +windows.wndotiluke.room6=多利亚小镇 +windows.wndotiluke.room7=春节宝地 +windows.wndotiluke.room8=能源核心 + +windows.wndchallengebook.title=选择挑战目标 +windows.wndchallengebook.room1=下水道挑战 +windows.wndchallengebook.room2=监狱挑战 +windows.wndchallengebook.room3=洞窟挑战 +windows.wndchallengebook.room4=城市挑战 +windows.wndchallengebook.room5=勇气试炼 +windows.wndchallengebook.room6=力量试炼 +windows.wndchallengebook.room7=智慧试炼 + +windows.wndhotel.message=想住这个旅馆的VIP房间吗?一次100金币 +windows.wndhotel.buy=我要住 +windows.wndhotel.more_gold=你的金币不够啊,下次再来吧。 + +windows.wndons.message=看起来这个件衣服给这位豺狼先生穿十分合适,要给他吗? +windows.wndons.give=给他吧 + +windows.wndsaidbysun.message=当测试结束后,有许多乱七八糟的材料将被丢弃。我这里正好有一些废料,你给我100000金币我就给你。 +windows.wndsaidbysun.buy=我有钱 + +windows.wndgoblin.message=看上这块盾牌了?这是哥布林一族通过试炼的标志。给我3000金币我就卖一个仿制品给你。 +windows.wndgoblin.buy=买来瞧瞧 + +windows.wnddream.message=想要滑稽一下吗? +windows.wnddream.buy=滑稽 + +windows.wndissic.message=测试太可怕了...你能给我一些温暖吗?我会给东西作为回报的。 +windows.wndissic.buy=拥抱...卖血机? + +windows.wndshower.message=我刚刚拿到了强化的指虎...你想买一个吗?3000一个。 +windows.wndshower.buy=指虎教我入了 + +windows.wndhate.message=错过了推羊关的特殊奖励?给我3000我就卖你一个。 +windows.wndhate.buy=拜托了 + +windows.wndice13.message=混沌的力量...需要更多混沌的力量... +windows.wndice13.buy=你指力量之手? + +windows.wndalchemy.title=海拉尔的烹饪锅 +windows.wndalchemy.text=放入材料以制作新的物品! +windows.wndalchemy.select=选择一件食材 +windows.wndalchemy.combine=合成 +windows.wndalchemy.cancel=取消 + +windows.wndmix.title=矮人的奇妙实验 +windows.wndmix.text=放入法杖或戒指,然后来进行一次奇妙的实验吧。这花费1000金币。 +windows.wndmix.select=选择一件道具 +windows.wndmix.combine=合成 +windows.wndmix.cancel=取消 + +windows.wndaflyinfo.title=为了饥饿的阿比 +windows.wndaflyinfo.text=阿比饿了,但是我现在没有食材。你能给我找一个干粮,烤肉和浆果吗?这样我就可以给他们做吃的了。当然我也会把做好的吃的给你一份。别给我什么奇怪的材料,我可能做出奇怪的东西,比如装备什么的。 +windows.wndaflyinfo.select=选择一件食材 +windows.wndaflyinfo.combine=合成 +windows.wndaflyinfo.cancel=取消 + +windows.wndstartgame.title=选择一位英雄 +windows.wndstartgame.start=开始游戏 + +windows.wndgameinprogress.title=%1$d级%2$s +windows.wndgameinprogress.challenges=挑战 +windows.wndgameinprogress.exp=经验 +windows.wndgameinprogress.str=力量 +windows.wndgameinprogress.health=生命 +windows.wndgameinprogress.gold=金币收集数 +windows.wndgameinprogress.depth=最高层数 +windows.wndgameinprogress.continue=继续 +windows.wndgameinprogress.erase=删除 +windows.wndgameinprogress.erase_warn_title=你确定要删除这个存档吗? +windows.wndgameinprogress.erase_warn_body=你将失去这局游戏的所有进度 +windows.wndgameinprogress.erase_warn_yes=是,删除这个存档 +windows.wndgameinprogress.erase_warn_no=不,我要接着玩 + +windows.wndsavegame.title=保存游戏 +windows.wndsavegame.start=确定 \ No newline at end of file