Update-V0.4.6.0-Beta2.0

This commit is contained in:
LingASDJ 2023-07-28 12:08:36 +08:00
parent 95b5688e0a
commit 5b3c36a1c6
49 changed files with 2154 additions and 504 deletions

View File

@ -79,7 +79,6 @@ public class AndroidGame extends AndroidApplication {
FileUtils.setDefaultFileProperties(Files.FileType.Local, "");
// grab preferences directly using our instance first

View File

@ -18,8 +18,8 @@ allprojects {
appName = 'Magic Ling Pixel Dungeon'
appPackageName = 'com.ansdomagiclingpixeldungeon.ling'
appVersionCode =900927
appVersionName = '0.6.3.0-Beta5.2'
appVersionCode =901000
appVersionName = '0.6.4.0-Beta1'
appJavaCompatibility = JavaVersion.VERSION_11

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@ -1,8 +1,31 @@
#####MLPD-P3文本
actors.mobs.bosses.sakafishboss.name=”远古意志“\n萨卡班甲鱼
actors.mobs.bosses.sakafishboss.name=萨卡班甲鱼
actors.mobs.bosses.sakafishboss.desc=曾经远古时代的海洋王者,因为不可避免的末日来临时,潜入了地底的阴暗水潭进入了沉睡。想着有朝一日回到大海,然而地牢的魔力和陆上的变化,它再也不可能回到那片理想的海洋。
actors.mobs.bosses.sakafishboss.notice=sakasaka……saka腻……系……甚磨
actors.mobs.bosses.sakafishboss.attack=吧嗒吧嗒—呜呜……好怀念上面的风景和底栖生物
actors.mobs.bosses.sakafishboss.leap=萨卡班甲鱼正在蓄力泥头车冲撞!哦——创似——李——!!!
actors.mobs.bosses.sakafishboss.king=泰山压顶biu——
actors.mobs.npcs.nxhy.talk=交谈
actors.mobs.npcs.nxhy.buyback=回忆很爽快的退还了相应的商品。
actors.mobs.npcs.nxhy.talk_prison_intro=冒险者,欢迎来到这个危机四伏的地牢。
actors.mobs.npcs.nxhy.talk_prison_warrior=蕾零安洁,你也是前往这里寻找水晶之心的吗?哦,嗯,我知道,地表三巨头的行动我可是了如指掌的,但本人已经不想参与这些事情,现在,我还是当个商人最好吧。
actors.mobs.npcs.nxhy.talk_prison_mage=茉莉姐,我知道你来到这里的目的不是寻找那个东西,而是听到了来自深渊的求救。但我能告诉你的事,别去参和他们的事情,这里毕竟不是你的家,你的力量无法完全展露的。
actors.mobs.npcs.nxhy.talk_prison_rogue=哦,这不是人人歌颂的皇家盗贼吗?你打算在我这里偷点东西吗?哈哈哈,骗你的,事实上,我很敬佩你,为了穷人,你不惜舍去皇室血脉也要和穷人一起同甘共苦。你的父王可能早就知道了,不信的话,你的斗篷已经被他秘密改造了,什么,你还不知道?哈哈哈,我为什么知道,这是秘密哦!
actors.mobs.npcs.nxhy.talk_prison_huntress=我曾经和小姐一样也是一位侠客,只不过瞬时变迁,我现在已经不再追求这些。小姐,你知道自从你走后你的部族就发生……,哎呀,别拿弓指着我,我不说就是了。还是希望小姐能在地牢中试炼中找到自己的目标吧。
actors.mobs.npcs.nxhy.talk_caves=这里的矿洞常年都是这么的冷,但曾经并不是这样。曾经有一位蓝发少女在我这里留了一本书,此后矿洞就变得如此寒冷,但那位少女再也找不到人影……
actors.mobs.npcs.nxhy.talk_city=矮人都市是我最后给你的物资中转站,再往下,已经不是我可以涉及的区域,曾经这里也是一片繁华,但是那场事变后,一切都变了……
actors.mobs.npcs.nxhy.guards=看来你需要更加艰难的试炼了。
actors.mobs.npcs.nxhy.thief=看来你需要更加艰难的试炼了。
actors.mobs.npcs.nxhy.why=抢劫商店?你可真有趣!
actors.mobs.npcs.nxhy.sell=选择一件要出售的物品
actors.mobs.npcs.nxhy.name=那些回忆
actors.mobs.npcs.nxhy.desc=这是一个拥有很多东西的商人他的名字叫那些回忆。据说他知道300年前这地牢究竟发生了什么事情的他在这里等着每一位冒险者的前来。他会给予冒险者相应的补给但是他从来不告诉冒险者这个地牢的危险程度是多么的高。传言说他曾经是一个侠客只不过现在他已经成为了一个商人了。
actors.mobs.npcs.nxhy.greetings=你好,%s。欢迎来到我的大商店。
actors.hero.hero.heartdied=死亡不是终点,而是新的开始。
@ -705,15 +728,6 @@ actors.mobs.npcs.slyl.def_verb=风暴将临
actors.mobs.npcs.slyl.desc=_冷群_是一位掌握冰系力量的魔女是300年前_寒冰圣都_的管理者。\n由于地下异常的不断出现她来到这里调查异常的原因。\n看起来她似乎正在摸鱼。
actors.mobs.npcs.slyl.howuse=你好,我是冷群。\n\n欢迎使用我们_寒冰圣都_的可以扰乱_魔力流_的_魔法金币_,通过它我们可以看见_特定的首领_。\n\n其中_抛动一次_会出现_天痕粘咕(5层),天狗(10层)DM300(15层),矮人国王(20层),Yog(25层)_\n]抛动两次]是_史莱姆王(5层),钻石宝箱王(10层)DM720(15层),矮人将军(20层),Yog-Zot(25层)_\n[抛动三次[是_(15层 寒冰魔女)_(抛动三次次仅在_特定楼层显示_)\n\n同时仅在Boss前一楼层显示每一次的最后的一次抛动将会决定下一层Boss的生成。\n\n好的以上就是_使用方法和介绍了_祝你_地牢冒险愉快_。
actors.mobs.npcs.nxhy.guards=看来你需要更加艰难的试炼了。
actors.mobs.npcs.nxhy.thief=看来你需要更加艰难的试炼了。
actors.mobs.npcs.nxhy.why=抢劫商店?你可真有趣!
actors.mobs.npcs.nxhy.sell=选择一件要出售的物品
actors.mobs.npcs.nxhy.name=那些回忆
actors.mobs.npcs.nxhy.desc=这是一个拥有很多东西的商人他的名字叫那些回忆。据说他知道300年前这地牢究竟发生了什么事情的他在这里等着每一位冒险者的前来。他会给予冒险者相应的补给但是他从来不告诉冒险者这个地牢的危险程度是多么的高。传言说他曾经是一个侠客只不过现在他已经成为了一个商人了。\n\n{ 请不要攻击他!!!否则他会让你痛不欲生!!! {
actors.mobs.npcs.nxhy.greetings=你好,%s。欢迎来到我的大商店。
actors.mobs.npcs.renshop.guards=看来你并不是好人。
actors.mobs.npcs.renshop.thief=看来你的命运多舛。
actors.mobs.npcs.renshop.sell=选择一件要出售的物品
@ -1750,6 +1764,7 @@ actors.mobs.npcs.impshopkeeper.name=野心勃勃的小恶魔
actors.mobs.npcs.impshopkeeper.greetings=你好,%s
actors.mobs.npcs.impshopkeeper.thief=我以为我可以相信你!
actors.mobs.npcs.impshopkeeper.desc=小恶魔是一种低等恶魔。它们既没有强大的力量也没有魔法天赋,但她们相当聪明而且善于交际,因此许多小恶魔喜欢生活在没有其他恶魔存在的地方。
actors.mobs.npcs.impshopkeeper.buyback=小恶魔很爽快的退还了相应的商品。
actors.mobs.npcs.mirrorimage.name=镜像
actors.mobs.npcs.mirrorimage.desc=这个幻象和你非常相似,甚至还装备着你当前的武器和护甲。\n\n镜像会猎寻敌人并用它们的镜像武器对其发动攻击。镜像武器的使用方式与特性和你手中的一样但造成的伤害会低些。镜像出生的时候没有实体但攻击后会显形。\n\n镜像有一定的攻击能力但非常脆弱受到伤害就会瞬间消散。
@ -1792,6 +1807,17 @@ actors.mobs.npcs.shopkeeper.zcz=商人喊来了制裁者!
actors.mobs.npcs.shopkeeper.eye=商人喊来了真眼者!
actors.mobs.npcs.shopkeeper.dead=商人为敌人们购买了精英系统,选好东西,迅速离开本层!!!
actors.mobs.npcs.shopkeeper.live=商人还为首领购买了精英系统,选好东西,迅速离开本层!!!
actors.mobs.npcs.shopkeeper.talk=交谈
actors.mobs.npcs.shopkeeper.buyback=店主不情不愿地退还了你的物品。
actors.mobs.npcs.shopkeeper.talk_prison_intro=我这有你成功冒险所需的一切东西!
actors.mobs.npcs.shopkeeper.talk_prison_warrior=你的那个纹章挺有意思的嘛,它们通常来讲都是一整个的。难不成你是一位蒙受了耻辱的英雄,还是别的什么人物?好啦,不管你做了些什么,都与我无关。我只对你的金币感兴趣。
actors.mobs.npcs.shopkeeper.talk_prison_mage=嘻嘻,我想我在城里的什么地方有见过你的通缉令。在逃亡对吧?哦?你说你是无辜的,真的吗?行行行...放轻松,比起举报你,我还有更值得做的事情。但也许你应该消费消费以确保这一点?
actors.mobs.npcs.shopkeeper.talk_prison_rogue=你是盗贼公会指派来清理这片区域的吗?不是?只是来交易?好吧,虽然你确实在这杀了些怪物,但也别指望我会给你打折。我已经交足了保护费,而你们几乎不能确保这里的安全。
actors.mobs.npcs.shopkeeper.talk_prison_huntress=小姐,这似乎不是你该待的地方。狭窄的地牢走廊想来不如城镇大厅或者市郊森林那样宽敞,不是吗?嘿嘿,哦,请别在意我这碎嘴巴,为什么不买点东西呢?
actors.mobs.npcs.shopkeeper.talk_prison_duelist=哇偶,这不是闯荡天下的大英雄嘛!如果你在尝试着拯救又一个小镇,那我只能说祝你好运了。毕竟这里的危机可比土匪帮派什么的糟糕多了。当然,我相信你会比任何人做得更棒,只是千万别死在我的店门口。
actors.mobs.npcs.shopkeeper.talk_caves=花钱,你才能活得更久。\n\n哦如果你看到那个巨魔铁匠代我向他问好。顺便提醒这个笨蛋他上周从我这买锤子的钱还没结清呢
actors.mobs.npcs.shopkeeper.talk_city=我的货可以保你平安。\n\n…另外劳烦您别在这瞎晃悠。我花了很长很长时间才让这里的怪物离我远点可不希望你把麻烦惹回来
actors.mobs.npcs.shopkeeper.talk_halls=嘿,那边那位!我为狩猎恶魔的人提供特别优惠!\n\n哦还有在下面可要当心底下的恶魔可不在乎你有多勇敢。而且如果你挂掉了你就没法回来花掉金币啦(>ω^)\n\n那些恶魔都和我一样吗嘿嘿并不。我只是一个小小跟班儿算不上战士况且我还设法保全了心智呢。下面那些恶魔都比我猛得多并且它们都遭到了...呃......的奴役,总之,你在下面当心点吧。
actors.mobs.npcs.wandmaker.name=老杖匠
actors.mobs.npcs.wandmaker.intro_warrior=啊,能在这片压抑的地方遇见一位英雄可真是个惊喜!如果你愿意帮助我这个老人家脱离苦海的话,你可以帮忙做一个任务。

View File

@ -2248,6 +2248,9 @@ items.heap.skeleton_desc=某个不幸的冒险者存在过的唯一证明。或
items.heap.remains=英雄遗骸
items.heap.remains_desc=你的某个先辈存在过的唯一证明。或许能找到点什么值钱的东西。
items.heap.wtomb=苍白之墓
items.heap.wtomb_desc=这个坟墓相对于其他的坟墓很不对劲,直觉告诉你不应该挖这里的东西。
items.honeypot.name=蜂蜜罐
items.honeypot.ac_shatter=击碎
items.honeypot.desc=这个巨型蜜罐只是薄薄地涂了一圈蜂蜜,作为替代里头住着一只巨型蜜蜂!这种大型蜜蜂一般只待在蜂巢里,也许罐子本身就是某种特殊陷阱屋?蜜蜂看起来对罐子很满意,当你看向它时它非常警惕地对你回以嗡鸣。

View File

@ -277,6 +277,13 @@ badges$badge.read_book_three.desc=一局累计阅读五本不同的书籍。
badges$badge.read_book_four.title=书籍博学家
badges$badge.read_book_four.desc=一局累计阅读七本不同的书籍。
badges$badge.saka_died.title=远古生物档案调查员
badges$badge.saka_died.desc=击败栖息在阴暗水潭的神秘古生物
badges$badge.reset_day.title=重见天日?
badges$badge.reset_day.desc=携带神秘生物的遗物离开地牢,完成它未尽的心愿。

View File

@ -174,6 +174,7 @@ scenes.interlevelscene$mode.fall=跌落中…
scenes.interlevelscene$mode.reset=重置中…
scenes.interlevelscene$mode.exboss=你突然眼前一黑\n\n,随后便是守卫低沉的声音:\n\n将此人押送到雪凛峡谷处置。
scenes.interlevelscene$mode.frgirlboss=正在前往雪凛峡谷深处……
scenes.interlevelscene$mode.ancityboss=正在前往远古遗迹深处……
scenes.interlevelscene.install=安装游戏
scenes.interlevelscene.file_not_found=未能找到存档文件。如果重启后问题依旧存在, 那这个存档可能已经损坏。节哀顺变。
scenes.interlevelscene.io_error=未能找到存档文件。如果重启后问题依旧存在, 那这个存档可能已经损坏。节哀顺变。

View File

@ -548,4 +548,6 @@ ui.changelist.mlpd.vm0_6_7_x_changes.bug_06x79=-V0.6.3-Beta4.8\n1.修复一些
ui.changelist.mlpd.vm0_6_7_x_changes.bug_06x80=1.修复灯火值不扣减的错误\n2.其他小错误修复
ui.changelist.mlpd.vm0_6_7_x_changes.bug_06x81=1.优化灯火体验\n其他错误修复。
//ui.changelist.mlpd.vm0_5_x_changes.xxx//

Binary file not shown.

Before

Width:  |  Height:  |  Size: 429 B

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

View File

@ -29,6 +29,9 @@ public class Assets {
public static final String BGM_5 = "music/Level5.ogg";
public static final String BGM_0 = "music/Level0.ogg";
public static final String SNOWCYON = "music/SnowCyon.ogg";
public static final String SKBJY = "music/Boss-Saka.ogg";
public static final String TOWN = "music/town.ogg";
public static final String BGM_BOSSA = "music/Boss1.ogg";
public static final String BGM_BOSSB = "music/Boss2.ogg";
@ -103,7 +106,8 @@ public class Assets {
public static final String QliPhoth_Title = "interfaces/bosslogo/qliphoth-title.png";
public static final String QliPhoth_Clear = "interfaces/bosslogo/qliphoth-clear.png";
public static final String SakaBJY_Title = "interfaces/bosslogo/sakabjy-title.png";
public static final String SakaBJY_Clear = "interfaces/bosslogo/sakabjy-clear.png";
public static final String ARCS_BG = "interfaces/arcs1.png";
public static final String ARCS_FG = "interfaces/arcs2.png";
@ -310,7 +314,9 @@ public class Assets {
//BOSS
public static final String FRDG = "sprites/boss/fireDragon.png";
public static final String DICT = "sprites/boss/DictFish.png";
public static final String ROOMSTONE = "sprites/boss/RoomStone.png";
public static final String VSGR = "sprites/boss/SeaVastGirl.png";
public static final String SKFS = "sprites/boss/SakaFishBoss.png";

View File

@ -10,6 +10,7 @@ import com.watabou.utils.Callback;
public class BGMPlayer {
//解决电脑端高质量ogg的闪退问题
public static void playBGM(String name, boolean loop) {
Game.runOnRenderThread(new Callback() {
@Override
@ -33,7 +34,7 @@ public class BGMPlayer {
if (d == -1) {
playBGM(Assets.SNOWCYON, true);
}else if (d == 0||d==27) {
playBGM(Assets.SNOWCYON, true);
playBGM(Assets.SKBJY, true);
} else if (d > 0 && d <= 5) {
playBGM(Assets.BGM_1, true);
} else if (d > 5 && d <= 10) {

View File

@ -209,7 +209,11 @@ public class Badges {
EXSG (135),
BRCLER (136),
HIGH_SCORE_5 ( 137 );
HIGH_SCORE_5 ( 137 ),
SAKA_DIED ( 138 ),
RESET_DAY ( 139 );
public boolean meta;

View File

@ -23,20 +23,19 @@ package com.shatteredpixel.shatteredpixeldungeon;
import static com.shatteredpixel.shatteredpixeldungeon.Challenges.PRO;
import static com.shatteredpixel.shatteredpixeldungeon.actors.hero.HeroClass.ROGUE;
import static com.shatteredpixel.shatteredpixeldungeon.levels.LevelRules.createBossRushLevel;
import static com.shatteredpixel.shatteredpixeldungeon.levels.LevelRules.createStandardLevel;
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Amok;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Awareness;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.ClearBleesdGoodBuff.BlessAnmy;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.LighS;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Light;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.MagicalSight;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.MindVision;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.RandomBuff;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.RevealedArea;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.TestDwarfMasterLock;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Talent;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.abilities.huntress.SpiritHawk;
@ -59,34 +58,11 @@ import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfRegrowth;
import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfWarding;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.MagicTorch;
import com.shatteredpixel.shatteredpixeldungeon.journal.Notes;
import com.shatteredpixel.shatteredpixeldungeon.levels.AncityLevel;
import com.shatteredpixel.shatteredpixeldungeon.levels.CaveTwoBossLevel;
import com.shatteredpixel.shatteredpixeldungeon.levels.CavesGirlDeadLevel;
import com.shatteredpixel.shatteredpixeldungeon.levels.CavesLevel;
import com.shatteredpixel.shatteredpixeldungeon.levels.CityLevel;
import com.shatteredpixel.shatteredpixeldungeon.levels.ColdChestBossLevel;
import com.shatteredpixel.shatteredpixeldungeon.levels.DM920BossLevel;
import com.shatteredpixel.shatteredpixeldungeon.levels.DeadEndLevel;
import com.shatteredpixel.shatteredpixeldungeon.levels.DimandKingLevel;
import com.shatteredpixel.shatteredpixeldungeon.levels.DwarfMasterBossLevel;
import com.shatteredpixel.shatteredpixeldungeon.levels.ForestBossLevel;
import com.shatteredpixel.shatteredpixeldungeon.levels.HallsLevel;
import com.shatteredpixel.shatteredpixeldungeon.levels.ItemLevel;
import com.shatteredpixel.shatteredpixeldungeon.levels.LastLevel;
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
import com.shatteredpixel.shatteredpixeldungeon.levels.LinkLevel;
import com.shatteredpixel.shatteredpixeldungeon.levels.NewCavesBossLevel;
import com.shatteredpixel.shatteredpixeldungeon.levels.NewCityBossLevel;
import com.shatteredpixel.shatteredpixeldungeon.levels.NewHallsBossLevel;
import com.shatteredpixel.shatteredpixeldungeon.levels.PrisonBossLevel;
import com.shatteredpixel.shatteredpixeldungeon.levels.PrisonLevel;
import com.shatteredpixel.shatteredpixeldungeon.levels.RegularLevel;
import com.shatteredpixel.shatteredpixeldungeon.levels.SLMKingLevel;
import com.shatteredpixel.shatteredpixeldungeon.levels.SewerBossLevel;
import com.shatteredpixel.shatteredpixeldungeon.levels.SewerLevel;
import com.shatteredpixel.shatteredpixeldungeon.levels.ShopBossLevel;
import com.shatteredpixel.shatteredpixeldungeon.levels.YogGodHardBossLevel;
import com.shatteredpixel.shatteredpixeldungeon.levels.ZeroLevel;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.secret.SecretRoom;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.special.SpecialRoom;
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
@ -143,7 +119,28 @@ public class Dungeon {
return level;
}
//雪凛峡谷B
//远古副本
public static Level AncityWaterLevel(){
Dungeon.level = null;
Actor.clear();
depth = -20;
if (depth > Statistics.realdeepestFloor) {
Statistics.realdeepestFloor = depth;}
Level level;
level = new ShopBossLevel();
level.create();
Statistics.qualifiedForNoKilling = !bossLevel();
return level;
}
public static Level ColdFlowerCanyonDie(){
@ -391,145 +388,9 @@ public class Dungeon {
Level level;
if (branch == 0) {
if (Dungeon.isDLC(Conducts.Conduct.BOSSRUSH)) {
switch (depth) {
case 17:
case 27:
case 0:
level = new AncityLevel();
Buff.affect(hero, RandomBuff.class).set((5), 1);
break;
case 1:
case 3:
case 6:
case 7:
case 9:
case 11:
case 13:
case 15:
case 18:
case 20:
case 24:
level = new ItemLevel();
break;
case 2:
level = new ForestBossLevel();
break;
case 4:
level = new SewerBossLevel();
break;
case 5:
level = new SLMKingLevel();
break;
case 8:
level = new PrisonBossLevel();
break;
case 10:
level = new DimandKingLevel();
break;
case 12:
level = new NewCavesBossLevel();
break;
case 14:
level = new CaveTwoBossLevel();
break;
case 16:
level = new CavesGirlDeadLevel();
break;
case 19:
level = new ShopBossLevel();
break;
case 21:
level = new NewCityBossLevel();
break;
case 22:
case 23:
level = new CityLevel();
Buff.affect(hero, TestDwarfMasterLock.class).set((10), 1);
break;
//TODO FIXED LIST:矮人将军那里用没祝福的十字架复活,Boss会消失不见
case 25:
level = new DwarfMasterBossLevel();
break;
case 26:
level = new YogGodHardBossLevel();
break;
case 28:
level = new DM920BossLevel();
Buff.affect(hero, TestDwarfMasterLock.class).set((1), 1);
break;
default:
level = new DeadEndLevel();
Statistics.deepestFloor--;
}
level = createBossRushLevel();
} else
switch (depth) {
case 0:
level = new ZeroLevel();
break;
case 1:
case 2:
case 3:
case 4:
level = new SewerLevel();
break;
case 5:
level = new ForestBossLevel();
break;
case 6:
case 7:
case 8:
case 9:
level = new PrisonLevel();
break;
case 10:
if ((Statistics.boss_enhance & 0x2) != 0 || Statistics.mimicking) {
level = new ColdChestBossLevel();
} else
level = new PrisonBossLevel();
break;
case 11:
case 12:
case 13:
case 14:
level = new CavesLevel();
break;
case 15:
if ((Statistics.boss_enhance & 0x4) != 0) {
level = new CavesGirlDeadLevel();
} else
level = Random.Float() <= 0.4f ? new CaveTwoBossLevel() : new NewCavesBossLevel();
break;
case 16:
case 17:
case 18:
case 19:
level = new CityLevel();
break;
case 20:
if ((Statistics.boss_enhance & 0x8) != 0) {
Buff.affect(hero, TestDwarfMasterLock.class).set((1), 1);
level = new DwarfMasterBossLevel();
break;
} else
level = new NewCityBossLevel();
break;
case 21:
case 22:
case 23:
case 24:
level = new HallsLevel();
break;
case 25:
if ((Statistics.boss_enhance & 0x10) != 0) level = new YogGodHardBossLevel();
else level = new NewHallsBossLevel();
break;
case 26:
level = new LastLevel();
break;
default:
level = new DeadEndLevel();
Statistics.deepestFloor--;
}
level = createStandardLevel();
} else {
level = new DeadEndLevel();
Statistics.deepestFloor--;
@ -574,7 +435,7 @@ public class Dungeon {
}
public static boolean NxhyshopOnLevel() {
return depth == 9 || depth == 18;
return depth == 9 || depth == 13 || depth == 18;
}
public static boolean FireLevel() {
@ -738,7 +599,7 @@ public class Dungeon {
int souLeftThisSet;
//3 SOU each floor set, 1.5 (rounded) on forbidden runes challenge
if (isChallenged(Challenges.NO_SCROLLS)){
souLeftThisSet = Math.round(1.5f - (LimitedDrops.UPGRADE_SCROLLS.count - (depth / 5) * 1.5f));
souLeftThisSet = Math.round(1.5f - (LimitedDrops.UPGRADE_SCROLLS.count - (depth / 5f) * 1.5f));
} else {
souLeftThisSet = 3 - (LimitedDrops.UPGRADE_SCROLLS.count - (depth / 5) * 3);
}

View File

@ -955,7 +955,7 @@ public class Hero extends Char {
}
///测试坐标用
//GLog.w(String.valueOf(hero.pos));
GLog.w(String.valueOf(hero.pos));
//携带该物品时玩家血量低于一半后自动隐身一段回合
//actMove实现
@ -1166,7 +1166,7 @@ public class Hero extends Char {
}
switch (heap.type) {
case TOMB:
case TOMB: case WHITETOMB:
Sample.INSTANCE.play( Assets.Sounds.TOMB );
Camera.main.shake( 1, 0.5f );
break;

View File

@ -169,6 +169,9 @@ public enum HeroClass {
new PotionOfDragonKingBreath().quantity(50).identify().collect();
new PotionOfHealing().quantity(50).identify().collect();
new PotionOfMindVision().quantity(50).identify().collect();
new PotionOfLiquidFlame().quantity(50).identify().collect();
new DimandBook().quantity(50).identify().collect();
new PotionOfExperience().quantity(100).identify().collect();

View File

@ -54,7 +54,7 @@ public class CrystalMimic extends Mimic {
{
spriteClass = MimicSprite.Crystal.class;
flying = true;
FLEEING = new Fleeing();
}

View File

@ -43,35 +43,28 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Paralysis;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Sleep;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Terror;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Vertigo;
import com.shatteredpixel.shatteredpixeldungeon.effects.Beam;
import com.shatteredpixel.shatteredpixeldungeon.effects.CellEmitter;
import com.shatteredpixel.shatteredpixeldungeon.effects.Pushing;
import com.shatteredpixel.shatteredpixeldungeon.effects.TargetedCell;
import com.shatteredpixel.shatteredpixeldungeon.effects.particles.PurpleParticle;
import com.shatteredpixel.shatteredpixeldungeon.effects.particles.ShadowParticle;
import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.DriedRose;
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
import com.shatteredpixel.shatteredpixeldungeon.mechanics.Ballistica;
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
import com.shatteredpixel.shatteredpixeldungeon.sprites.CharSprite;
import com.shatteredpixel.shatteredpixeldungeon.sprites.LarvaSprite;
import com.shatteredpixel.shatteredpixeldungeon.sprites.YogSprite;
import com.shatteredpixel.shatteredpixeldungeon.tiles.DungeonTilemap;
import com.shatteredpixel.shatteredpixeldungeon.ui.BossHealthBar;
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
import com.watabou.noosa.Game;
import com.watabou.noosa.audio.Music;
import com.watabou.utils.Bundle;
import com.watabou.utils.Callback;
import com.watabou.utils.GameMath;
import com.watabou.utils.PathFinder;
import com.watabou.utils.Random;
import com.watabou.utils.Reflection;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
public class YogDzewa extends Mob {
@ -196,98 +189,7 @@ public class YogDzewa extends Mob {
return true;
} else {
boolean terrainAffected = false;
HashSet<Char> affected = new HashSet<>();
//delay fire on a rooted hero
if (!Dungeon.hero.rooted) {
for (int i : targetedCells) {
Ballistica b = new Ballistica(pos, i, Ballistica.WONT_STOP);
//shoot beams
sprite.parent.add(new Beam.DeathRay(sprite.center(), DungeonTilemap.raisedTileCenterToWorld(b.collisionPos)));
for (int p : b.path) {
Char ch = Actor.findChar(p);
if (ch != null && (ch.alignment != alignment || ch instanceof Bee)) {
affected.add(ch);
}
if (Dungeon.level.flamable[p]) {
Dungeon.level.destroy(p);
GameScene.updateMap(p);
terrainAffected = true;
}
}
}
if (terrainAffected) {
Dungeon.observe();
}
for (Char ch : affected) {
if (ch == Dungeon.hero) {
Statistics.bossScores[4] -= 1000;
}
if (Dungeon.isChallenged(Challenges.STRONGER_BOSSES)){
ch.damage(Random.NormalIntRange(30, 50), new Eye.DeathGaze());
} else {
ch.damage(Random.NormalIntRange(20, 30), new Eye.DeathGaze());
}
if (Dungeon.level.heroFOV[pos]) {
ch.sprite.flash();
CellEmitter.center(pos).burst(PurpleParticle.BURST, Random.IntRange(1, 2));
}
if (!ch.isAlive() && ch == Dungeon.hero) {
Dungeon.fail(getClass());
GLog.n(Messages.get(Char.class, "kill", name()));
}
}
targetedCells.clear();
}
if (abilityCooldown <= 0){
int beams = 1 + (HT - HP)/400;
HashSet<Integer> affectedCells = new HashSet<>();
for (int i = 0; i < beams; i++){
int targetPos = Dungeon.hero.pos;
if (i != 0){
do {
targetPos = Dungeon.hero.pos + PathFinder.NEIGHBOURS8[Random.Int(8)];
} while (Dungeon.level.trueDistance(pos, Dungeon.hero.pos)
> Dungeon.level.trueDistance(pos, targetPos));
}
targetedCells.add(targetPos);
Ballistica b = new Ballistica(pos, targetPos, Ballistica.WONT_STOP);
affectedCells.addAll(b.path);
}
//remove one beam if multiple shots would cause every cell next to the hero to be targeted
boolean allAdjTargeted = true;
for (int i : PathFinder.NEIGHBOURS9){
if (!affectedCells.contains(Dungeon.hero.pos + i) && Dungeon.level.passable[Dungeon.hero.pos + i]){
allAdjTargeted = false;
break;
}
}
if (allAdjTargeted){
targetedCells.remove(targetedCells.size()-1);
}
for (int i : targetedCells){
Ballistica b = new Ballistica(pos, i, Ballistica.WONT_STOP);
for (int p : b.path){
sprite.parent.add(new TargetedCell(p, 0xFF0000));
affectedCells.add(p);
}
}
//don't want to overly punish players with slow move or attack speed
spend(GameMath.gate(TICK, Dungeon.hero.cooldown(), 3*TICK));
Dungeon.hero.interrupt();
abilityCooldown += Random.NormalFloat(MIN_ABILITY_CD, MAX_ABILITY_CD);
abilityCooldown -= (phase - 1);
} else {
spend(TICK);
}
while (summonCooldown <= 0){
@ -640,4 +542,6 @@ public class YogDzewa extends Mob {
maxLvl = -2;
}
}
}

View File

@ -1,22 +1,643 @@
package com.shatteredpixel.shatteredpixeldungeon.actors.mobs.bosses;
import static com.shatteredpixel.shatteredpixeldungeon.Dungeon.hero;
import com.shatteredpixel.shatteredpixeldungeon.Assets;
import com.shatteredpixel.shatteredpixeldungeon.Badges;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
import com.shatteredpixel.shatteredpixeldungeon.actors.Boss;
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.Blob;
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.HalomethaneFire;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Bleeding;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Frost;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.LockedFloor;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.NewDM720;
import com.shatteredpixel.shatteredpixeldungeon.effects.CellEmitter;
import com.shatteredpixel.shatteredpixeldungeon.effects.MagicMissile;
import com.shatteredpixel.shatteredpixeldungeon.effects.Pushing;
import com.shatteredpixel.shatteredpixeldungeon.effects.TargetedCell;
import com.shatteredpixel.shatteredpixeldungeon.effects.particles.RainbowParticle;
import com.shatteredpixel.shatteredpixeldungeon.items.keys.SkeletonKey;
import com.shatteredpixel.shatteredpixeldungeon.items.quest.GooBlob;
import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfBlastWave;
import com.shatteredpixel.shatteredpixeldungeon.levels.CaveTwoBossLevel;
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain;
import com.shatteredpixel.shatteredpixeldungeon.mechanics.Ballistica;
import com.shatteredpixel.shatteredpixeldungeon.mechanics.ConeAOE;
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
import com.shatteredpixel.shatteredpixeldungeon.sprites.CharSprite;
import com.shatteredpixel.shatteredpixeldungeon.sprites.SakaFishBossSprites;
import com.shatteredpixel.shatteredpixeldungeon.ui.BossHealthBar;
import com.shatteredpixel.shatteredpixeldungeon.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.GameMath;
import com.watabou.utils.PathFinder;
import com.watabou.utils.Random;
public class SakaFishBoss extends Boss {
private int leapPos = -1;
private float leapCooldown = 0;
private int lastEnemyPos = -1;
private Ballistica beam;
private int beamTarget = -1;
private int beamCooldown;
public boolean beamCharged;
/**隐藏Boss 萨卡班甲鱼*/
{
spriteClass = SakaFishBossSprites.class;
initBaseStatus(19, 25, 6, 0, 700, 5, 12);
initBaseStatus(19, 25, 6, 0, 480, 5, 12);
state = SLEEPING;
initProperty();
HUNTING = new Hunting();
baseSpeed = 1.75f;
initStatus(76);
HP=700;
HP=480;
defenseSkill = 10;
HT=700;
baseSpeed=1.5f;
HT=480;
properties.add(Property.ICY);
viewDistance = 30;
}
private int pumpedUp = 0;
private int healInc = 1;
public void damage(int dmg, Object src) {
if (!Dungeon.level.mobs.contains(this)){
return;
}
int hpBracket = HT / 8;
int beforeHitHP = HP;
super.damage(dmg, src);
dmg = beforeHitHP - HP;
//tengu cannot be hit through multiple brackets at a time
if ((beforeHitHP/hpBracket - HP/hpBracket) >= 2){
HP = hpBracket * ((beforeHitHP/hpBracket)-1) + 1;
}
LockedFloor lock = hero.buff(LockedFloor.class);
if (lock != null) {
lock.addTime(dmg*3f);
}
//phase 1 of the fight is over
if (HP <= HT/2){
HP = (HT/2);
yell(Messages.get(this, "interesting"));
// ((PrisonBossLevel)Dungeon.level).progress();
BossHealthBar.bleed(true);
}
}
@Override
protected boolean canAttack( Char enemy ) {
if (beamCooldown == 0) {
Ballistica aim = new Ballistica(pos, enemy.pos, Ballistica.STOP_SOLID);
if (enemy.invisible == 0 && !isCharmedBy(enemy) && 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
public int damageRoll() {
int min = 1;
int max = (HP*2 <= HT) ? 12 : 8;
if (pumpedUp > 0) {
pumpedUp = 0;
return Random.NormalIntRange( min*3, max*3 );
} else {
return Random.NormalIntRange( min, max );
}
}
@Override
public int attackSkill( Char target ) {
int attack = 10;
if (HP*2 <= HT) attack = 15;
if (pumpedUp > 0) attack *= 2;
return attack;
}
@Override
public int defenseSkill(Char enemy) {
return (int)(super.defenseSkill(enemy) * ((HP*2 <= HT)? 1.5 : 1));
}
@Override
public int drRoll() {
return Random.NormalIntRange(0, 2);
}
public void activate(){
((SakaFishBossSprites) sprite).activate();
}
@Override
protected boolean act() {
AiState lastState = state;
boolean result = super.act();
if (paralysed <= 0) leapCooldown --;
//if state changed from wandering to hunting, we haven't acted yet, don't update.
if (!(lastState == WANDERING && state == HUNTING)) {
if (enemy != null) {
lastEnemyPos = enemy.pos;
} else {
lastEnemyPos = hero.pos;
}
}
if (beamCharged && state != HUNTING){
beamCharged = false;
sprite.operate(this.pos);
}
if (beam == null && beamTarget != -1) {
beam = new Ballistica(pos, beamTarget, Ballistica.STOP_SOLID);
sprite.turnTo(pos, beamTarget);
}
if (beamCooldown > 0)
beamCooldown--;
return result;
}
@Override
protected boolean doAttack( Char enemy ) {
if (beamCooldown > 0) {
return super.doAttack(enemy);
} else if (!beamCharged){
((SakaFishBossSprites)sprite).charge( enemy.pos );
spend( attackDelay()*2f );
beamCharged = true;
return true;
} else if(HP*2>=HT) {
spend( attackDelay()*3f );
beam = new Ballistica(pos, beamTarget, Ballistica.STOP_SOLID);
if (Dungeon.level.heroFOV[pos] || Dungeon.level.heroFOV[beam.collisionPos] ) {
sprite.zap( beam.collisionPos );
return false;
} else {
sprite.operate(this.pos);
deathGaze();
return true;
}
} else {
return true;
}
}
// @Override
// public boolean attack( Char enemy, float dmgMulti, float dmgBonus, float accMulti ) {
// boolean result = super.attack( enemy, dmgMulti, dmgBonus, accMulti );
// pumpedUp = 0;
// return result;
// }
//
// @Override
// protected boolean getCloser( int target ) {
// if (pumpedUp != 0) {
// pumpedUp = 0;
// sprite.idle();
// }
// return super.getCloser( target );
// }
//
// @Override
// public void damage(int dmg, Object src) {
// if (!BossHealthBar.isAssigned()){
// BossHealthBar.assignBoss( this );
// Dungeon.level.seal();
// }
// boolean bleeding = (HP*2 <= HT);
// super.damage(dmg, src);
// if ((HP*2 <= HT) && !bleeding){
// BossHealthBar.bleed(true);
// sprite.showStatus(CharSprite.NEGATIVE, Messages.get(this, "enraged"));
// ((GooSprite)sprite).spray(true);
// yell(Messages.get(this, "gluuurp"));
// }
// LockedFloor lock = Dungeon.hero.buff(LockedFloor.class);
// if (lock != null) lock.addTime(dmg*2);
// }
@Override
public void die( Object cause ) {
super.die( cause );
if(Dungeon.depth!=28){
Dungeon.level.unseal();
GetBossLoot();
GameScene.bossSlain();
Dungeon.level.drop( new SkeletonKey( Dungeon.depth ), pos ).sprite.drop();
//60% chance of 2 blobs, 30% chance of 3, 10% chance for 4. Average of 2.5
int blobs = Random.chances(new float[]{0, 0, 6, 3, 1});
for (int i = 0; i < blobs; i++){
int ofs;
do {
ofs = PathFinder.NEIGHBOURS8[Random.Int(8)];
} while (!Dungeon.level.passable[pos + ofs]);
Dungeon.level.drop( new GooBlob(), pos + ofs ).sprite.drop( pos );
}
Badges.validateBossSlain();
yell( Messages.get(this, "defeated") );
}
}
@Override
public void notice() {
super.notice();
if (!BossHealthBar.isAssigned()) {
BossHealthBar.assignBoss(this);
Dungeon.level.seal();
yell(Messages.get(this, "notice"));
Camera.main.shake(1f,3f);
GameScene.bossReady();
activate();
}
}
private final String PUMPEDUP = "pumpedup";
private final String HEALINC = "healinc";
private static final String LAST_ENEMY_POS = "last_enemy_pos";
private static final String LEAP_POS = "leap_pos";
private static final String LEAP_CD = "leap_cd";
private static final String BEAM_TARGET = "beamTarget";
private static final String BEAM_COOLDOWN = "beamCooldown";
private static final String BEAM_CHARGED = "beamCharged";
@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( PUMPEDUP , pumpedUp );
bundle.put( HEALINC, healInc );
bundle.put(LAST_ENEMY_POS, lastEnemyPos);
bundle.put(LEAP_POS, leapPos);
bundle.put(LEAP_CD, leapCooldown);
}
@Override
public void restoreFromBundle( Bundle bundle ) {
super.restoreFromBundle( bundle );
pumpedUp = bundle.getInt( PUMPEDUP );
if (state != SLEEPING) BossHealthBar.assignBoss(this);
if ((HP*2 <= HT)) BossHealthBar.bleed(true);
//if check is for pre-0.9.3 saves
healInc = bundle.getInt(HEALINC);
if (bundle.contains(BEAM_TARGET))
beamTarget = bundle.getInt(BEAM_TARGET);
beamCooldown = bundle.getInt(BEAM_COOLDOWN);
beamCharged = bundle.getBoolean(BEAM_CHARGED);
lastEnemyPos = bundle.getInt(LAST_ENEMY_POS);
leapPos = bundle.getInt(LEAP_POS);
leapCooldown = bundle.getFloat(LEAP_CD);
}
public void dropRocks( Char target ) {
hero.interrupt();
final int rockCenter;
if (Dungeon.level.adjacent(pos, target.pos)){
int oppositeAdjacent = target.pos + (target.pos - pos);
Ballistica trajectory = new Ballistica(target.pos, oppositeAdjacent, Ballistica.MAGIC_BOLT);
WandOfBlastWave.throwChar(target, trajectory, 20, false, false, getClass());
if (target == hero){
hero.interrupt();
}
rockCenter = trajectory.path.get(Math.min(trajectory.dist, 200));
} else {
rockCenter = target.pos;
}
//we handle this through an actor as it gives us fine-grainted control over when the blog acts vs. when the hero acts
//FIXME this is really messy to just get some fine-grained control. would be nice to build this into blob functionality, or just not use blobs for this at all
Actor a = new Actor() {
{
actPriority = HERO_PRIO+1;
}
private static final float TIME_TO_ZAP = 1f;
@Override
protected boolean act() {
//pick an adjacent cell to the hero as a safe cell. This cell is less likely to be in a wall or containing hazards
int safeCell;
do {
safeCell = rockCenter + PathFinder.NEIGHBOURS8[Random.Int(8)];
} while (safeCell == pos
|| (Dungeon.level.solid[safeCell] && Random.Int(2) == 0)
|| (Blob.volumeAt(safeCell, CaveTwoBossLevel.PylonEnergy.class) > 0 && Random.Int(2) == 0));
int start = rockCenter - Dungeon.level.width() * 3 - 3;
int pos;
for (int y = 0; y < 7; y++) {
pos = start + Dungeon.level.width() * y;
for (int x = 0; x < 7; x++) {
if (!Dungeon.level.insideMap(pos)) {
pos++;
continue;
}
//add rock cell to pos, if it is not solid, and isn't the safecell
if (!Dungeon.level.solid[pos] && pos != safeCell && Random.Int(Dungeon.level.distance(rockCenter, pos)) == 0) {
//don't want to overly punish players with slow move or attack speed
GameScene.add(Blob.seed(pos, 1, NewDM720.FallingRocks.class));
}
pos++;
}
}
Actor.remove(this);
return true;
}
};
Actor.addDelayed(a, Math.min(target.cooldown(), 3*TICK));
}
public class Hunting extends Mob.Hunting {
@Override
public boolean act( boolean enemyInFOV, boolean justAlerted ) {
if (leapPos != -1){
leapCooldown = Random.NormalIntRange(2, 4);
Ballistica b = new Ballistica(pos, leapPos, Ballistica.STOP_TARGET | Ballistica.STOP_SOLID);
//check if leap pos is not obstructed by terrain
if (rooted || b.collisionPos != leapPos){
leapPos = -1;
return true;
}
final Char leapVictim = Actor.findChar(leapPos);
final int endPos;
//ensure there is somewhere to land after leaping
if (leapVictim != null){
int bouncepos = -1;
for (int i : PathFinder.NEIGHBOURS8){
if ((bouncepos == -1 || Dungeon.level.trueDistance(pos, leapPos+i) < Dungeon.level.trueDistance(pos, bouncepos))
&& Actor.findChar(leapPos+i) == null && Dungeon.level.passable[leapPos+i]){
bouncepos = leapPos+i;
}
}
if (bouncepos == -1) {
leapPos = -1;
return true;
} else {
endPos = bouncepos;
}
} else {
endPos = leapPos;
}
//do leap
sprite.visible = Dungeon.level.heroFOV[pos] || Dungeon.level.heroFOV[leapPos] || Dungeon.level.heroFOV[endPos];
sprite.dirtcar(pos, leapPos, new Callback() {
@Override
public void call() {
if (leapVictim != null && alignment != leapVictim.alignment){
Buff.affect(leapVictim, Bleeding.class).set(0.75f*damageRoll());
dropRocks(enemy);
Sample.INSTANCE.play(Assets.Sounds.ROCKS);
leapVictim.sprite.flash();
Sample.INSTANCE.play(Assets.Sounds.HIT);
}
if (endPos != leapPos){
Actor.addDelayed(new Pushing(SakaFishBoss.this, leapPos, endPos), -1);
}
pos = endPos;
leapPos = -1;
sprite.operate(pos);
Dungeon.level.occupyCell(SakaFishBoss.this);
next();
}
});
sprite.visible = Dungeon.level.heroFOV[pos] || Dungeon.level.heroFOV[leapPos] || Dungeon.level.heroFOV[endPos];
sprite.dirtcar(pos, leapPos, new Callback() {
@Override
public void call() {
if (leapVictim != null && alignment != leapVictim.alignment){
Buff.affect(leapVictim, Bleeding.class).set(0.75f*damageRoll());
//TODO 魔法风暴
FishStorm(enemy);
enemy.damage( Random.NormalIntRange( 10, 20 ), this );
Sample.INSTANCE.play(Assets.Sounds.ROCKS);
leapVictim.sprite.flash();
Sample.INSTANCE.play(Assets.Sounds.HIT);
}
if (endPos != leapPos){
Actor.addDelayed(new Pushing(SakaFishBoss.this, leapPos, endPos), -1);
}
pos = endPos;
leapPos = -1;
sprite.operate(pos);
Dungeon.level.occupyCell(SakaFishBoss.this);
next();
}
});
return false;
}
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( SakaFishBoss.this );
return true;
}
if (leapCooldown <= 0 && enemyInFOV && !rooted
&& Dungeon.level.distance(pos, enemy.pos) >= 3) {
int targetPos = enemy.pos;
if (lastEnemyPos != enemy.pos){
int closestIdx = 0;
for (int i = 1; i < PathFinder.CIRCLE8.length; i++){
if (Dungeon.level.trueDistance(lastEnemyPos, enemy.pos+PathFinder.CIRCLE8[i])
< Dungeon.level.trueDistance(lastEnemyPos, enemy.pos+PathFinder.CIRCLE8[closestIdx])){
closestIdx = i;
}
}
targetPos = enemy.pos + PathFinder.CIRCLE8[(closestIdx+4)%8];
}
Ballistica b = new Ballistica(pos, targetPos, Ballistica.STOP_TARGET | Ballistica.STOP_SOLID);
//try aiming directly at hero if aiming near them doesn't work
if (b.collisionPos != targetPos && targetPos != enemy.pos){
targetPos = enemy.pos;
b = new Ballistica(pos, targetPos, Ballistica.STOP_TARGET | Ballistica.STOP_SOLID);
}
if (b.collisionPos == targetPos){
//get ready to leap
leapPos = targetPos;
//don't want to overly punish players with slow move or attack speed
spend(GameMath.gate(TICK, enemy.cooldown(), 3*TICK));
if (Dungeon.level.heroFOV[pos] || Dungeon.level.heroFOV[leapPos]){
GLog.w(Messages.get(SakaFishBoss.this, "leap"));
sprite.parent.addToBack(new TargetedCell(leapPos, 0xFF0000));
((SakaFishBossSprites)sprite).leapPrep( leapPos );
hero.interrupt();
}
return true;
}
}
int oldPos = pos;
if (target != -1 && getCloser( target )) {
spend( 6f );
return moveSprite( oldPos, pos );
} else {
spend(TICK);
if (!enemyInFOV) {
sprite.showLost();
state = WANDERING;
target = Dungeon.level.randomDestination( SakaFishBoss.this );
}
return true;
}
}
}
}
public static class DeathGaze{}
public void deathGaze(){
if (!beamCharged || beamCooldown > 0 || beam == null)
return;
beamCharged = false;
beamCooldown = Random.IntRange(4, 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, 40 ), new DeathGaze() );
if (Dungeon.level.heroFOV[pos]) {
ch.sprite.flash();
CellEmitter.center( pos ).burst( RainbowParticle.BURST, Random.IntRange( 1, 2 ) );
}
if (!ch.isAlive() && ch == hero) {
Dungeon.fail( getClass() );
GLog.n( Messages.get(this, "deathgaze_kill") );
}
} else {
ch.sprite.showStatus( CharSprite.NEUTRAL, ch.defenseVerb() );
}
}
if (terrainAffected) {
Dungeon.observe();
}
beam = null;
beamTarget = -1;
}
public void FishStorm(Char ch){
Ballistica aim;
aim = new Ballistica(ch.pos, ch.pos - 1, Ballistica.WONT_STOP);
int projectileProps = Ballistica.STOP_SOLID | Ballistica.STOP_TARGET;
int aoeSize = 4;
ConeAOE aoe = new ConeAOE(aim, aoeSize, 360, projectileProps);
for (Ballistica ray : aoe.outerRays){
((MagicMissile)ch.sprite.parent.recycle( MagicMissile.class )).reset(
MagicMissile.FROST,
ch.sprite,
ray.path.get(ray.dist),
null
);
if( ray.collisionPos == hero.pos){
Buff.prolong(enemy, Frost.class, Frost.DURATION);
} else {
GameScene.add(Blob.seed(ray.path.get(ray.dist),5, HalomethaneFire.class));
Level.set(ray.path.get(ray.dist), Terrain.EMPTY);
GameScene.updateMap( ray.path.get(ray.dist) );
}
}
}
}

View File

@ -0,0 +1,476 @@
//package com.shatteredpixel.shatteredpixeldungeon.actors.mobs.bosses;
//
//import static com.shatteredpixel.shatteredpixeldungeon.Dungeon.hero;
//
//import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
//import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
//import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
//import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Adrenaline;
//import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Amok;
//import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Blindness;
//import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
//import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.ChaosTime;
//import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Charm;
//import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.FireImbue;
//import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.MaxGuard;
//import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Paralysis;
//import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Sleep;
//import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.SoulMark;
//import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Terror;
//import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Vertigo;
//import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Weakness;
//import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob;
//import com.shatteredpixel.shatteredpixeldungeon.effects.Beam;
//import com.shatteredpixel.shatteredpixeldungeon.effects.CellEmitter;
//import com.shatteredpixel.shatteredpixeldungeon.effects.Speck;
//import com.shatteredpixel.shatteredpixeldungeon.effects.TargetedCell;
//import com.shatteredpixel.shatteredpixeldungeon.effects.particles.PurpleParticle;
//import com.shatteredpixel.shatteredpixeldungeon.mechanics.Ballistica;
//import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
//import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
//import com.shatteredpixel.shatteredpixeldungeon.sprites.PillarSprite;
//import com.shatteredpixel.shatteredpixeldungeon.tiles.DungeonTilemap;
//import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
//import com.watabou.utils.Bundle;
//import com.watabou.utils.GameMath;
//import com.watabou.utils.PathFinder;
//import com.watabou.utils.Random;
//
//import java.util.ArrayList;
//import java.util.HashSet;
//
//public abstract class SeptiumPillar extends Mob {
//
// private boolean firstactive = false;
// private boolean secondactive = false;
// private boolean thirdactive = false;
//
// {
// HP = HT = 100;
//
// viewDistance = 99;
//
// //for doomed resistance
// EXP = 25;
// maxLvl = -2;
// baseSpeed = 0;
//
// state = PASSIVE;
// alignment = Alignment.NEUTRAL;
//
// properties.add(Property.BOSS);
// properties.add(Property.KISEKI);
// properties.add(Property.IMMOVABLE);
// properties.add(Property.INORGANIC);
// immunities.add( Terror.class );
// immunities.add( Amok.class );
// immunities.add( Charm.class );
// immunities.add( Sleep.class );
// immunities.add( Vertigo.class );
// immunities.add( Paralysis.class );
// immunities.add( SoulMark.class );
// immunities.add( Weakness.class );
// immunities.add( Blindness.class );
// }
//
// @Override
// protected boolean act()
//
// {
// if (alignment == Alignment.NEUTRAL){
// next();
// }
// else
// {
// onZapComplete();
// state = PASSIVE;
// }
// return super.act();
// }
//
// @Override
// public void notice() {
// //do nothing
// }
//
//
//
// @Override
// public void add(Buff buff) {
// //immune to all buffs/debuffs when inactive
// if (alignment != Alignment.NEUTRAL) {
// super.add(buff);
// }
// }
//
// private static final String ALIGNMENT = "alignment";
//
// @Override
// public void storeInBundle(Bundle bundle) {
// super.storeInBundle(bundle);
// bundle.put(ALIGNMENT, alignment);
//
// }
//
// @Override
// public void restoreFromBundle(Bundle bundle) {
// super.restoreFromBundle(bundle);
// alignment = bundle.getEnum(ALIGNMENT, Alignment.class);
//
// }
//
// @Override
// public boolean interact(Char c) {
// return true;
// }
//
// protected abstract void zap();
//
//
//
// public void onZapComplete(){
// zap();
// next();
// }
//
//
//
// public void activate(){
// alignment = Alignment.ENEMY;
// ((PillarSprite) sprite).activate();
// }
//
// @Override
// public String description() {
// return Messages.get(SeptiumPillar.class, "desc") + "\n\n" + Messages.get(this, "desc");
// }
//
// {
// immunities.add( Terror.class );
// immunities.add( Amok.class );
// immunities.add( Charm.class );
// immunities.add( Sleep.class );
// immunities.add( Vertigo.class );
// immunities.add( Paralysis.class );
// immunities.add( SoulMark.class );
// immunities.add( Weakness.class );
// immunities.add( Blindness.class );
// }
//
// public static class FlamePillar extends SeptiumPillar {
//
// {
// spriteClass = PillarSprite.Flame.class;
// }
//
// @Override
// protected boolean act() {
// {
// state = PASSIVE;
// }
// return super.act();
// }
//
// @Override
// protected void zap() {
// for (Mob mob : Dungeon.level.mobs.toArray(new Mob[0])) {
// if(!mob.properties().contains(Property.KISEKI)) {
// Buff.affect(mob, FireImbue.class).set( 10f);
// }
// next();
// }
// GLog.w(Messages.get( this, "message") );
// spend(15f);
// }
//
// }
//
// public static class GroundPillar extends SeptiumPillar {
//
// {
// spriteClass = PillarSprite.Ground.class;
// }
//
// @Override
// protected boolean act() {
// {
// state = PASSIVE;
// }
// return super.act();
// }
//
//
// @Override
// protected void zap() {
// for (Mob mob : Dungeon.level.mobs.toArray(new Mob[0])) {
// if(!mob.properties().contains(Property.KISEKI)) {
// Buff.affect(mob, MaxGuard.class);
// }
// next();
// }
// GLog.w(Messages.get( this, "message") );
// spend(15f);
// };
//
//
//
//
//
// }
//
// public static class WaterPillar extends SeptiumPillar {
//
// {
// spriteClass = PillarSprite.Water.class;
//
// }
//
// @Override
// protected boolean act() {
// {
// state = PASSIVE;
// }
// return super.act();
// }
//
// @Override
// protected void zap() {
// for (Mob mob : Dungeon.level.mobs.toArray(new Mob[0])) {
// if(!mob.properties().contains(Property.KISEKI)) {
// if (mob.HP < mob.HT/3){
//
// mob.HP = mob.HP+20;
//
// }
//
//
// }
//
// }
// GLog.w(Messages.get( this, "message") );
// spend(15f);
// };
//
//
//
// }
//
// public static class WindPillar extends SeptiumPillar {
//
// {
// spriteClass = PillarSprite.Wind.class;
//
// }
//
// @Override
// protected boolean act() {
// {
// state = PASSIVE;
// }
// return super.act();
// }
//
// @Override
// protected void zap() {
// for (Mob mob : Dungeon.level.mobs.toArray(new Mob[0])) {
// if(!mob.properties().contains(Property.KISEKI)) {
// Buff.affect(mob, Adrenaline.class,3f);
// }
// next();
// }
// GLog.w(Messages.get( this, "message") );
// spend(15f);
// }
// }
//
// public static class ChronosPillar extends SeptiumPillar {
//
// {
// spriteClass = PillarSprite.Chronos.class;
//
// }
//
// @Override
// protected boolean act() {
// {
// state = PASSIVE;
// }
// return super.act();
// }
//
// @Override
// protected void zap() {
//
// spend(15f);
// Buff.affect( hero, ChaosTime.class, 15f);
// GLog.w(Messages.get( this, "message") );
//
// }
//
//
// }
//
//
// public static class HeavenPillar extends SeptiumPillar {
//
// {
// spriteClass = PillarSprite.Heaven.class;
// }
//
// private ArrayList<Integer> targetedCells = new ArrayList<>();
//
// private float abilityCooldown;
// private static final int MIN_ABILITY_CD = 10;
// private static final int MAX_ABILITY_CD = 15;
//
// // 添加一个计数器用来记录回合数
// private int turnCount = 0;
//
// @Override
// protected boolean act() {
// boolean terrainAffected = false;
// HashSet<Char> affected = new HashSet<>();
// //delay fire on a rooted hero
// if (!hero.rooted && alignment == Alignment.ENEMY && firstActive) {
// for (int i : targetedCells) {
// Ballistica b = new Ballistica(pos, i, Ballistica.WONT_STOP);
// //shoot beams
// sprite.parent.add(new Beam.DeathRay(sprite.center(), DungeonTilemap.raisedTileCenterToWorld(b.collisionPos)));
// for (int p : b.path) {
// Char ch = Actor.findChar(p);
// if (ch != null && (ch.alignment != alignment || ch instanceof Bee)) {
// affected.add(ch);
// }
// if (Dungeon.level.flamable[p]) {
// Dungeon.level.destroy(p);
// GameScene.updateMap(p);
// terrainAffected = true;
// }
// }
// }
// if (terrainAffected) {
// Dungeon.observe();
// }
// for (Char ch : affected) {
// ch.damage(Random.NormalIntRange(20, 30), new Eye.DeathGaze());
//
// if (Dungeon.level.heroFOV[pos]) {
// ch.sprite.flash();
// CellEmitter.center(pos).burst(PurpleParticle.BURST, Random.IntRange(1, 2));
// }
// if (!ch.isAlive() && ch == hero) {
// Dungeon.fail(getClass());
// GLog.n(Messages.get(Char.class, "kill", name()));
// }
// }
// targetedCells.clear();
// }
//
// if (abilityCooldown <= 0 && alignment == Alignment.ENEMY && firstActive) {
// int beams = 1;
// GLog.w(Messages.get(this, "message"));
// HashSet<Integer> affectedCells = new HashSet<>();
// for (int i = 0; i < beams; i++) {
//
// int targetPos = hero.pos;
// if (i != 0) {
// do {
// targetPos = hero.pos + PathFinder.NEIGHBOURS8[Random.Int(8)];
// } while (Dungeon.level.trueDistance(pos, hero.pos)
// > Dungeon.level.trueDistance(pos, targetPos));
// }
// targetedCells.add(targetPos);
// Ballistica b = new Ballistica(pos, targetPos, Ballistica.WONT_STOP);
// affectedCells.addAll(b.path);
// }
//
// //remove one beam if multiple shots would cause every cell next to the hero to be targeted
// boolean allAdjTargeted = true;
// for (int i : PathFinder.NEIGHBOURS9) {
// if (!affectedCells.contains(hero.pos + i) && Dungeon.level.passable[hero.pos + i]) {
// allAdjTargeted = false;
// break;
// }
// }
// if (allAdjTargeted) {
// targetedCells.remove(targetedCells.size() - 1);
// }
// for (int i : targetedCells) {
// Ballistica b = new Ballistica(pos, i, Ballistica.WONT_STOP);
// for (int p : b.path) {
// sprite.parent.add(new TargetedCell(p, 0xFF0000));
// affectedCells.add(p);
// }
// }
//
// // 在14回合时发出警告
// if (turnCount == 14) {
// for (int i : affectedCells) {
// sprite.parent.add(new TargetedCell(i, 0xFF0000));
// }
// }
//
// // don't want to overly punish players with slow move or attack speed
// spend(GameMath.gate(TICK, hero.cooldown(), 3 * TICK));
// hero.interrupt();
//
// abilityCooldown += Random.NormalFloat(MIN_ABILITY_CD, MAX_ABILITY_CD);
//
// } else {
// spend(TICK);
// if (abilityCooldown > 0) abilityCooldown--;
// }
//
// turnCount++; // 回合数自增
//
//
// return true;
// }
//
// @Override
// protected void zap() {
// next();
// }
// }
//
//
//
//
//
//
// public static class PhantomPillar extends SeptiumPillar {
//
// {
// spriteClass = PillarSprite.Phantom.class;
//
// }
//
// @Override
// protected boolean act() {
// {
// state = PASSIVE;
// }
// return super.act();
// }
//
// @Override
// protected void zap() {
//
// Buff.affect( hero, Vertigo.class, 3f);
// for (Mob mob : Dungeon.level.mobs.toArray( new Mob[0] )) {
// mob.beckon( hero.pos );
// }
// hero.sprite.centerEmitter().start( Speck.factory( Speck.SCREAM ), 0.3f, 3 );
// GLog.w(Messages.get( this, "message") );
// spend(15f);
// }
//
//
//
//
// }
//
//
//
//}
//

View File

@ -21,10 +21,7 @@
package com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs;
import static com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.Shopkeeper.sell;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
import com.shatteredpixel.shatteredpixeldungeon.effects.CellEmitter;
import com.shatteredpixel.shatteredpixeldungeon.effects.Speck;
@ -32,10 +29,8 @@ import com.shatteredpixel.shatteredpixeldungeon.effects.particles.ElmoParticle;
import com.shatteredpixel.shatteredpixeldungeon.items.Heap;
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ImpSprite;
import com.watabou.noosa.Game;
import com.watabou.utils.Callback;
public class ImpShopkeeper extends NPC {
public class ImpShopkeeper extends Shopkeeper {
{
spriteClass = ImpSprite.class;
@ -54,20 +49,6 @@ public class ImpShopkeeper extends NPC {
return super.act();
}
@Override
public boolean interact(Char c) {
if (c != Dungeon.hero) {
return true;
}
Game.runOnRenderThread(new Callback() {
@Override
public void call() {
sell();
}
});
return true;
}
@Override
public void damage( int dmg, Object src ) {
//flee();

View File

@ -1,22 +1,15 @@
package com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
import com.shatteredpixel.shatteredpixeldungeon.effects.CellEmitter;
import com.shatteredpixel.shatteredpixeldungeon.effects.particles.ElmoParticle;
import com.shatteredpixel.shatteredpixeldungeon.items.Heap;
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
import com.shatteredpixel.shatteredpixeldungeon.journal.Notes;
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
import com.shatteredpixel.shatteredpixeldungeon.sprites.NxhySprite;
import com.shatteredpixel.shatteredpixeldungeon.windows.WndBag;
import com.shatteredpixel.shatteredpixeldungeon.windows.WndTradeItem;
import com.watabou.noosa.Game;
import com.watabou.utils.Callback;
public class Nxhy extends NPC {
public class Nxhy extends Shopkeeper {
{
spriteClass = NxhySprite.class;
@ -74,48 +67,5 @@ public class Nxhy extends NPC {
}
}
}
@Override
public boolean reset() {
return true;
}
public static WndBag sell() {
return GameScene.selectItem( itemSelector );
}
private static WndBag.ItemSelector itemSelector = new WndBag.ItemSelector() {
@Override
public String textPrompt() {
return Messages.get(Shopkeeper.class, "sell");
}
@Override
public boolean itemSelectable(Item item) {
return Shopkeeper.canSell(item);
}
@Override
public void onSelect( Item item ) {
if (item != null) {
WndBag parentWnd = sell();
GameScene.show( new WndTradeItem( item, parentWnd ) );
}
}
};
@Override
public boolean interact(Char c) {
if (c != Dungeon.hero) {
return true;
}
Game.runOnRenderThread(new Callback() {
@Override
public void call() {
sell();
}
});
return true;
}
}

View File

@ -21,142 +21,92 @@
package com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs;
import static com.shatteredpixel.shatteredpixeldungeon.Dungeon.hero;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.ShatteredPixelDungeon;
import com.shatteredpixel.shatteredpixeldungeon.Statistics;
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.ClearBleesdGoodBuff.BlessNoMoney;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.MagicGirlDebuff.MagicGirlSayMoneyMore;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
import com.shatteredpixel.shatteredpixeldungeon.effects.CellEmitter;
import com.shatteredpixel.shatteredpixeldungeon.effects.particles.ElmoParticle;
import com.shatteredpixel.shatteredpixeldungeon.items.Ankh;
import com.shatteredpixel.shatteredpixeldungeon.items.Heap;
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
import com.shatteredpixel.shatteredpixeldungeon.items.armor.Armor;
import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.DriedRose;
import com.shatteredpixel.shatteredpixeldungeon.items.food.Food;
import com.shatteredpixel.shatteredpixeldungeon.items.potions.PotionOfHealing;
import com.shatteredpixel.shatteredpixeldungeon.journal.Notes;
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSprite;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ShopkeeperSprite;
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
import com.shatteredpixel.shatteredpixeldungeon.windows.WndBag;
import com.shatteredpixel.shatteredpixeldungeon.windows.WndOptions;
import com.shatteredpixel.shatteredpixeldungeon.windows.WndTitledMessage;
import com.shatteredpixel.shatteredpixeldungeon.windows.WndTradeItem;
import com.watabou.noosa.Game;
import com.watabou.noosa.Image;
import com.watabou.utils.Bundlable;
import com.watabou.utils.Bundle;
import com.watabou.utils.Callback;
import java.util.ArrayList;
public class Shopkeeper extends NPC {
{
spriteClass = ShopkeeperSprite.class;
properties.add(Property.IMMOVABLE);
}
public static boolean seenBefore = false;
@Override
public boolean interact(Char c) {
if (c != hero) {
return true;
}
Game.runOnRenderThread(new Callback() {
@Override
public void call() {
sell();
}
});
return true;
}
@Override
public void storeInBundle(Bundle bundle) {
super.storeInBundle(bundle);
}
public static int MAX_BUYBACK_HISTORY = 4;
public ArrayList<Item> buybackItems = new ArrayList<>();
@Override
protected boolean act() {
if (!seenBefore && Dungeon.level.heroFOV[pos]) {
yell(Messages.get(this, "greetings", Dungeon.hero.name()));
seenBefore = true;
//Buff.affect(this, ChampionEnemy.AntiMagic.class);
//Buff.affect(this, ChampionEnemy.Halo.class);
} else if(seenBefore && !Dungeon.level.heroFOV[pos]) {
seenBefore = false;
yell(Messages.get(this, "goodbye", Dungeon.hero.name()));
if (Dungeon.level.visited[pos]){
Notes.add(Notes.Landmark.SHOP);
}
throwItem();
sprite.turnTo( pos, Dungeon.hero.pos );
spend( TICK );
return true;
return super.act();
}
@Override
public void damage( int dmg, Object src ) {
flee();
}
@Override
public int defenseSkill( Char enemy ) {
return INFINITE_EVASION;
public void add(Buff buff ) {
}
/*
Buff.prolong(Dungeon.hero, Blindness.class, Blindness.DURATION * 4f);
GameScene.flash(0x80FFFFFF);
Buff.affect(hero, Burning.class).reignite(hero, 15f);
Dungeon.level.seal();
Mob moa = new MoloHR();
moa.pos = pos;
GameScene.add(moa);
yell(Messages.get(this, "arise"));
new ShopGuardEye().spawnAround(pos);
new ShopGuard().spawnAround(pos);
Buff.affect(moa, ChampionEnemy.Growing.class);
Buff.affect(moa, ChampionEnemy.Projecting.class);
Buff.affect(moa, ChampionEnemy.AntiMagic.class);
Buff.affect(moa, ChampionEnemy.Giant.class);
Buff.affect(moa, ChampionEnemy.Blessed.class);
Buff.affect(moa, ChampionEnemy.Halo.class);
for (Mob mob : Dungeon.level.mobs) {
switch (Random.Int(7)) {
case 0:
default:
Buff.affect(mob, ChampionEnemy.Blazing.class);
break;
case 1:
Buff.affect(mob, ChampionEnemy.Projecting.class);
break;
case 2:
Buff.affect(mob, ChampionEnemy.AntiMagic.class);
break;
case 3:
Buff.affect(mob, ChampionEnemy.Giant.class);
break;
case 4:
Buff.affect(mob, ChampionEnemy.Blessed.class);
break;
case 5:
Buff.affect(mob, ChampionEnemy.Growing.class);
break;
case 6:
Buff.affect(mob, ChampionEnemy.Halo.class);
break;
}
}
yell(Messages.get(this, "dead"));*/
public void flee() {
destroy();
CellEmitter.get(pos).burst(ElmoParticle.FACTORY, 6);
hero.sprite.burst(15597568, 9);
Notes.remove(Notes.Landmark.SHOP);
if (sprite != null) {
sprite.killAndErase();
CellEmitter.get(pos).burst(ElmoParticle.FACTORY, 6);
}
private DriedRose.GhostHero ghost = null;
}
@Override
public void destroy() {
super.destroy();
for (Heap heap: Dungeon.level.heaps.valueList()) {
if (heap.type == Heap.Type.FOR_SALE) {
CellEmitter.get( heap.pos ).burst( ElmoParticle.FACTORY, 4 );
heap.type = Heap.Type.HEAP;//Allow them to be picked up
if (ShatteredPixelDungeon.scene() instanceof GameScene) {
CellEmitter.get(heap.pos).burst(ElmoParticle.FACTORY, 4);
}
if (heap.size() == 1) {
heap.destroy();
} else {
heap.items.remove(heap.size()-1);
heap.type = Heap.Type.HEAP;
}
}
}
}
@ -168,18 +118,7 @@ public class Shopkeeper extends NPC {
//shopkeepers are greedy!
public static int sellPrice(Item item){
int price = item.value() * 5 * (Dungeon.depth / 5 + 1);
if(Dungeon.hero.buff(MagicGirlSayMoneyMore.class) != null){
if(item instanceof Ankh ||item instanceof Food || item instanceof PotionOfHealing){
price *= 0.1;
}
price *= 1.5;
//todo 3折
} else if (Dungeon.hero.buff(BlessNoMoney.class) != null) {
price *= 0.3;
}
return price;
return item.value() * 5 * (Dungeon.depth / 5 + 1);
}
public static WndBag sell() {
@ -213,4 +152,100 @@ public class Shopkeeper extends NPC {
}
}
};
@Override
public boolean interact(Char c) {
if (c != Dungeon.hero) {
return true;
}
Game.runOnRenderThread(new Callback() {
@Override
public void call() {
String[] options = new String[2+ buybackItems.size()];
int i = 0;
options[i++] = Messages.get(Shopkeeper.this, "sell");
options[i++] = Messages.get(Shopkeeper.this, "talk");
for (Item item : buybackItems){
options[i] = Messages.get(Heap.class, "for_sale", item.value(),
Messages.titleCase(item.trueName()+"x"+item.quantity()));
if (options[i].length() > 26) options[i] = options[i].substring(0, 23) + "...";
i++;
}
GameScene.show(new WndOptions(sprite(), Messages.titleCase(name()), description(), options){
@Override
protected void onSelect(int index) {
super.onSelect(index);
if (index == 0){
sell();
} else if (index == 1){
GameScene.show(new WndTitledMessage(sprite(), Messages.titleCase(name()), chatText()));
} else if (index > 1){
GLog.i(Messages.get(Shopkeeper.this, "buyback"));
Item returned = buybackItems.remove(index-2);
Dungeon.gold -= returned.value();
Statistics.goldCollected -= returned.value();
if (!returned.doPickUp(Dungeon.hero)){
Dungeon.level.drop(returned, Dungeon.hero.pos);
}
}
}
@Override
protected boolean enabled(int index) {
if (index > 1){
return Dungeon.gold >= buybackItems.get(index-2).value();
} else {
return super.enabled(index);
}
}
@Override
protected boolean hasIcon(int index) {
return index > 1;
}
@Override
protected Image getIcon(int index) {
if (index > 1){
return new ItemSprite(buybackItems.get(index-2));
}
return null;
}
});
}
});
return true;
}
public String chatText(){
switch (Dungeon.depth){
case 6: default:
return Messages.get(this, "talk_prison_intro") + "\n\n" + Messages.get(this, "talk_prison_" + Dungeon.hero.heroClass.name());
case 11:case 13:
return Messages.get(this, "talk_caves");
case 16: case 18:
return Messages.get(this, "talk_city");
case 20:
return Messages.get(this, "talk_halls");
}
}
public static String BUYBACK_ITEMS = "buyback_items";
@Override
public void storeInBundle(Bundle bundle) {
super.storeInBundle(bundle);
bundle.put(BUYBACK_ITEMS, buybackItems);
}
@Override
public void restoreFromBundle(Bundle bundle) {
super.restoreFromBundle(bundle);
buybackItems.clear();
if (bundle.contains(BUYBACK_ITEMS)){
for (Bundlable i : bundle.getCollection(BUYBACK_ITEMS)){
buybackItems.add((Item) i);
}
}
}
}

View File

@ -21,8 +21,9 @@
package com.shatteredpixel.shatteredpixeldungeon.items;
import static com.shatteredpixel.shatteredpixeldungeon.Dungeon.level;
import com.shatteredpixel.shatteredpixeldungeon.Assets;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Wraith;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.Shopkeeper;
@ -42,6 +43,7 @@ import com.shatteredpixel.shatteredpixeldungeon.items.potions.Potion;
import com.shatteredpixel.shatteredpixeldungeon.items.rings.Ring;
import com.shatteredpixel.shatteredpixeldungeon.items.rings.RingOfWealth;
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.Scroll;
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfTeleportation;
import com.shatteredpixel.shatteredpixeldungeon.items.wands.Wand;
import com.shatteredpixel.shatteredpixeldungeon.journal.Document;
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
@ -64,6 +66,8 @@ public class Heap implements Bundlable {
LOCKED_CHEST,
CRYSTAL_CHEST,
TOMB,
TELECRYSTL,
WHITETOMB,
SKELETON,
REMAINS,
BLACK
@ -85,6 +89,12 @@ public class Heap implements Bundlable {
case TOMB:
Wraith.spawnAround( hero.pos );
break;
case WHITETOMB:
ScrollOfTeleportation.appear( hero,hero.pos+5 );
break;
case TELECRYSTL:
ScrollOfTeleportation.appear( hero,level.entrance );
break;
case REMAINS:
case SKELETON:
CellEmitter.center( pos ).start(Speck.factory(Speck.RATTLE), 0.1f, 3);
@ -227,7 +237,7 @@ public class Heap implements Bundlable {
if (burnt || evaporated) {
if (Dungeon.level.heroFOV[pos]) {
if (level.heroFOV[pos]) {
if (burnt) {
burnFX( pos );
} else {
@ -248,7 +258,7 @@ public class Heap implements Bundlable {
public void explode() {
//breaks open most standard containers, mimics die.
if (type == Type.CHEST || type == Type.SKELETON) {
if (type == Type.CHEST || type == Type.SKELETON || type == Type.TELECRYSTL) {
type = Type.HEAP;
sprite.link();
sprite.drop();
@ -343,7 +353,7 @@ public class Heap implements Bundlable {
}
public void destroy() {
Dungeon.level.heaps.remove( this.pos );
level.heaps.remove( this.pos );
if (sprite != null) {
sprite.kill();
}
@ -364,10 +374,12 @@ public class Heap implements Bundlable {
return Messages.get(this, "chest");
case LOCKED_CHEST:
return Messages.get(this, "locked_chest");
case CRYSTAL_CHEST:
case CRYSTAL_CHEST: case TELECRYSTL:
return Messages.get(this, "crystal_chest");
case TOMB:
return Messages.get(this, "tomb");
case WHITETOMB:
return Messages.get(this, "wtomb");
case SKELETON:
return Messages.get(this, "skeleton");
case REMAINS:
@ -381,7 +393,7 @@ public class Heap implements Bundlable {
public String info(){
switch(type){
case CHEST:
case CHEST:case TELECRYSTL:
return Messages.get(this, "chest_desc");
case LOCKED_CHEST:
return Messages.get(this, "locked_chest_desc");
@ -396,6 +408,8 @@ public class Heap implements Bundlable {
return Messages.get(this, "crystal_chest_desc", Messages.get(this, "unknow") );
case TOMB:
return Messages.get(this, "tomb_desc");
case WHITETOMB:
return Messages.get(this, "wtomb_desc");
case BLACK:
return Messages.get(this, "black_chest_desc");
case SKELETON:

View File

@ -23,6 +23,8 @@ package com.shatteredpixel.shatteredpixeldungeon.items.spells;
import com.shatteredpixel.shatteredpixeldungeon.Assets;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.Shopkeeper;
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
@ -108,14 +110,21 @@ public class Alchemize extends Spell {
this.owner = owner;
float pos = height;
Shopkeeper shop = null;
for (Char ch : Actor.chars()){
if (ch instanceof Shopkeeper){
shop = (Shopkeeper) ch;
break;
}
}
final Shopkeeper finalShop = shop;
if (Shopkeeper.canSell(item)) {
if (item.quantity() == 1) {
RedButton btnSell = new RedButton(Messages.get(this, "sell", item.value())) {
@Override
protected void onClick() {
WndTradeItem.sell(item);
WndTradeItem.sell(item,finalShop);
hide();
consumeAlchemize();
}
@ -143,7 +152,7 @@ public class Alchemize extends Spell {
RedButton btnSellAll = new RedButton(Messages.get(this, "sell_all", priceAll)) {
@Override
protected void onClick() {
WndTradeItem.sell(item);
WndTradeItem.sell(item,finalShop);
hide();
consumeAlchemize();
}

View File

@ -18,11 +18,17 @@ import com.watabou.utils.Bundle;
import com.watabou.utils.Random;
public class LockSword extends MeleeWeapon {
private int lvl = 0;
public LockSword() {
super.image = ItemSpriteSheet.DG3;
super.tier = 5;
// InterlevelScene.mode = InterlevelScene.Mode.ANCITYBOSS;
// Game.switchScene(InterlevelScene.class);
}
@Override

View File

@ -1,7 +1,13 @@
package com.shatteredpixel.shatteredpixeldungeon.levels;
import com.shatteredpixel.shatteredpixeldungeon.Assets;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.bosses.SakaFishBoss;
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
import com.watabou.utils.PathFinder;
import com.watabou.utils.Random;
public class AncientMysteryCityBossLevel extends Level{
@ -26,7 +32,7 @@ public class AncientMysteryCityBossLevel extends Level{
private static final short E = Terrain.STATUE;
private static final short C = Terrain.HIGH_GRASS;
private static final short M = Terrain.CRYSTAL_DOOR;
private static final short G = Terrain.LOCKED_DOOR;
private static final short G = Terrain.DOOR;
private static final short K = Terrain.WELL;
@ -76,14 +82,54 @@ public class AncientMysteryCityBossLevel extends Level{
return true;
}
@Override
public int randomRespawnCell( Char ch ) {
int pos = WIDTH + 16; //random cell adjacent to the entrance.
int cell;
do {
cell = pos + PathFinder.NEIGHBOURS8[Random.Int(8)];
} while (!passable[cell]
|| (Char.hasProp(ch, Char.Property.LARGE) && !openSpace[cell])
|| Actor.findChar(cell) != null);
return cell;
}
private static final int getBossDoor = 688;
private static final int LDBossDoor = 661;
@Override
public void occupyCell( Char ch ) {
super.occupyCell( ch );
boolean isTrue = ch.pos == LDBossDoor && ch == Dungeon.hero;
//如果有生物来到BossDoor的下一个坐标且生物是玩家那么触发seal().
if (map[getBossDoor] == Terrain.DOOR && isTrue || map[getBossDoor] == Terrain.EMBERS && isTrue) {
seal();
}
}
@Override
public void seal() {
super.seal();
set( getBossDoor, Terrain.WALL );
GameScene.updateMap( getBossDoor );
set( 688, Terrain.LOCKED_DOOR );
GameScene.updateMap( 688 );
Dungeon.observe();
}
/**
*
*/
@Override
protected void createMobs() {
SakaFishBoss saka= new SakaFishBoss();
saka.pos = (WIDTH*20+13);
mobs.add(saka);
SakaFishBoss boss = new SakaFishBoss();
boss.pos = 337;
mobs.add(boss);
}
/**

View File

@ -0,0 +1,146 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2015 Oleg Dolya
*
* Shattered Pixel Dungeon
* Copyright (C) 2014-2022 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 <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.levels;
import static com.shatteredpixel.shatteredpixeldungeon.Dungeon.depth;
import static com.shatteredpixel.shatteredpixeldungeon.Dungeon.hero;
import com.shatteredpixel.shatteredpixeldungeon.Statistics;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.RandomBuff;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.TestDwarfMasterLock;
import com.watabou.utils.Random;
//Level Rules
public class LevelRules {
public static Level createBossRushLevel() {
switch (depth) {
case 0:
case 17:
case 27:
Buff.affect(hero, RandomBuff.class).set(5, 1);
return new AncientMysteryCityBossLevel();
case 1: case 3: case 6: case 7: case 9:
case 11: case 13: case 15: case 18: case 20: case 24:
return new ItemLevel();
case 2:
return new ForestBossLevel();
case 4:
return new SewerBossLevel();
case 5:
return new SLMKingLevel();
case 8:
return new PrisonBossLevel();
case 10:
return new DimandKingLevel();
case 12:
return new NewCavesBossLevel();
case 14:
return new CaveTwoBossLevel();
case 16:
return new CavesGirlDeadLevel();
case 19:
return new ShopBossLevel();
case 21:
return new NewCityBossLevel();
case 22: case 23:
Buff.affect(hero, TestDwarfMasterLock.class).set(10, 1);
return new CityLevel();
case 25:
return new DwarfMasterBossLevel();
case 26:
return new YogGodHardBossLevel();
case 28:
Buff.affect(hero, TestDwarfMasterLock.class).set(1, 1);
return new DM920BossLevel();
default:
Statistics.deepestFloor--;
return new DeadEndLevel();
}
}
public static Level createStandardLevel() {
switch (depth) {
case 0:
return new ZeroLevel();
case 1:
case 2:
case 3:
case 4:
return new SewerLevel();
case 5:
return new ForestBossLevel();
case 6:
case 7:
case 8:
case 9:
return new PrisonLevel();
case 10:
if ((Statistics.boss_enhance & 0x2) != 0 || Statistics.mimicking) {
return new ColdChestBossLevel();
} else {
return new PrisonBossLevel();
}
case 11:
case 12:
case 13:
case 14:
return new CavesLevel();
case 15:
if ((Statistics.boss_enhance & 0x4) != 0) {
return new CavesGirlDeadLevel();
} else {
return Random.Float() <= 0.4f ? new CaveTwoBossLevel() : new NewCavesBossLevel();
}
case 16:
case 17:
case 18:
case 19:
return new CityLevel();
case 20:
if ((Statistics.boss_enhance & 0x8) != 0) {
Buff.affect(hero, TestDwarfMasterLock.class).set(1, 1);
return new DwarfMasterBossLevel();
} else {
return new NewCityBossLevel();
}
case 21:
case 22:
case 23:
case 24:
return new HallsLevel();
case 25:
if ((Statistics.boss_enhance & 0x10) != 0) {
return new YogGodHardBossLevel();
} else {
return new NewHallsBossLevel();
}
case 26:
return new LastLevel();
default:
Statistics.deepestFloor--;
return new DeadEndLevel();
}
}
}

View File

@ -256,6 +256,9 @@ public abstract class RegularLevel extends Level {
initRooms.add(new MagicDimandRoom());
}
// initRooms.add(new EyeRoom());
// initRooms.add(new YinYangRoom());
if (Dungeon.NxhyshopOnLevel()) {
initRooms.add(new NxhyShopRoom());
}

View File

@ -39,6 +39,22 @@ public abstract class Painter {
// Static methods
//绘制圆形
public static void drawCircle(Level level, Point center, int radius, int terrain) {
int cx = center.x;
int cy = center.y;
for (int x = cx - radius; x <= cx + radius; x++) {
for (int y = cy - radius; y <= cy + radius; y++) {
int dx = x - cx;
int dy = y - cy;
if (dx * dx + dy * dy <= radius * radius) {
Painter.set(level, x, y, terrain);
}
}
}
}
public static void set( Level level, int cell, int value ) {
level.map[cell] = value;
}

View File

@ -25,6 +25,8 @@ import com.shatteredpixel.shatteredpixeldungeon.Conducts;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.ShatteredPixelDungeon;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.Room;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.standard.EyeRoom;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.standard.YinYangRoom;
import com.watabou.utils.Bundle;
import com.watabou.utils.Random;
import com.watabou.utils.Reflection;
@ -85,12 +87,13 @@ public abstract class SpecialRoom extends Room {
new ArrayList<>( Dungeon.isDLC(Conducts.Conduct.BOSSRUSH) ? Arrays.asList(
CryptRoom.class, PoolRoom.class, ArmoryRoom.class, SentryRoom.class,
StatueRoom.class, CrystalVaultRoom.class, CrystalPathRoom.class, CrystalChoiceRoom.class,
SacrificeRoom.class
YinYangRoom.class,
SacrificeRoom.class, EyeRoom.class
) :
Arrays.asList(
WeakFloorRoom.class, CryptRoom.class, PoolRoom.class, ArmoryRoom.class, SentryRoom.class,
StatueRoom.class, CrystalVaultRoom.class, CrystalPathRoom.class, CrystalChoiceRoom.class,
SacrificeRoom.class
StatueRoom.class, CrystalVaultRoom.class, CrystalPathRoom.class, CrystalChoiceRoom.class, YinYangRoom.class,
SacrificeRoom.class,EyeRoom.class
));
//9 special rooms which give consumables more often than equipment

View File

@ -0,0 +1,147 @@
package com.shatteredpixel.shatteredpixeldungeon.levels.rooms.standard;
import static com.shatteredpixel.shatteredpixeldungeon.Dungeon.depth;
import static com.shatteredpixel.shatteredpixeldungeon.levels.Terrain.EMPTY;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.BruteBot;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Crab;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.CrystalMimic;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.DM201;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Eye;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mimic;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.SRPDHBLR;
import com.shatteredpixel.shatteredpixeldungeon.items.Generator;
import com.shatteredpixel.shatteredpixeldungeon.items.Gold;
import com.shatteredpixel.shatteredpixeldungeon.items.Heap;
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain;
import com.shatteredpixel.shatteredpixeldungeon.levels.painters.Painter;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.special.SpecialRoom;
import com.watabou.utils.Point;
public class EyeRoom extends SpecialRoom {
@Override
public int minWidth() {
return 13;
}
@Override
public int minHeight() {
return 13;
}
@Override
public int maxWidth() {
return 13;
}
@Override
public int maxHeight() {
return 13;
}
@Override
public boolean canMerge(Level l, Point p, int mergeTerrain) {
return false;
}
@Override
public void paint(Level level) {
Point center = new Point((left + right) / 2, (top + bottom) / 2);
int eyeRadius = (right - left) / 4;
Painter.fill(level,this, EMPTY);
// 绘制外围墙壁
Painter.drawLine(level, new Point(left, top), new Point(right, top), Terrain.WALL);
Painter.drawLine(level, new Point(right, top), new Point(right, bottom), Terrain.WALL);
Painter.drawLine(level, new Point(right, bottom), new Point(left, bottom), Terrain.WALL);
Painter.drawLine(level, new Point(left, bottom), new Point(left, top), Terrain.WALL);
// 绘制眼睛外圈和门
Painter.drawCircle(level, center, eyeRadius, Terrain.EMPTY_SP);
Painter.drawCircle(level, center, eyeRadius + 1, Terrain.WALL);
int doorX = center.x;
int doorY = center.y + eyeRadius;
// 绘制眼睛中心和瞳孔
Painter.set(level, center, Terrain.EMPTY_SP);
int pupilRadius = eyeRadius / 2;
Point pupilPos = center.offset(0, pupilRadius / 2);
Painter.drawCircle(level, pupilPos, pupilRadius+1, Terrain.EMPTY_SP);
// 绘制眼睛眉毛
Point browStart = center.offset(-eyeRadius - 1, -3);
Point browEnd = center.offset(eyeRadius + 1, -3);
// 绘制眼瞳
Painter.set(level, doorX, doorY - 3, Terrain.PEDESTAL);
int chestPos = (top + 6) * level.width() + left + 6;
/** 套五个宝箱 */
level.drop( new Gold(),chestPos).type = Heap.Type.TELECRYSTL;
level.mobs.add(Mimic.spawnAt(chestPos,( Generator.randomUsingDefaults( Generator.Category.POTION ) ), CrystalMimic.class));
level.mobs.add(Mimic.spawnAt(chestPos,( Generator.randomUsingDefaults( Generator.Category.SCROLL ) ), CrystalMimic.class));
level.mobs.add(Mimic.spawnAt(chestPos,( Generator.randomUsingDefaults( Generator.Category.WEAPON ) ),
CrystalMimic.class));
level.mobs.add(Mimic.spawnAt(chestPos,( Generator.randomUsingDefaults( Generator.Category.ARMOR ) ), CrystalMimic.class));
//四大恶人
int[] MBTPOS = new int[]{
(top + 4) * level.width() + left + 6,
(top + 8) * level.width() + left + 6,
(top + 6) * level.width() + left + 4,
(top + 6) * level.width() + left + 8,
};
for (int i : MBTPOS) {
Mob n = new Crab();
if(depth >= 20){
n = new Eye();
} else if(depth >= 15) {
n = new BruteBot();
} else if(depth >= 10) {
n = new DM201();
} else if(depth >= 6){
n = new SRPDHBLR();
}
n.pos = i;
level.mobs.add(n);
}
int TopPos = (top + 1) * level.width() + left + 6;
int BotPos = (top + 11) * level.width() + left + 6;
int LeftPos = (top + 6) * level.width() + left + 1;
int RightPos = (top + 6) * level.width() + left + 11;
/** 小时候诋毁cocoa长大后质疑cocoa成年后认可cocoa现在成为cocoa
/** Watabou看看你的房间是多么的恶心
/** 由于房间类的特殊性质,无法直接从外部调用 */
level.drop( ( Generator.randomUsingDefaults( Generator.Category.ARTIFACT )),LeftPos).type = Heap.Type.WHITETOMB;
level.drop( ( Generator.randomUsingDefaults( Generator.Category.GOLD )),RightPos).type = Heap.Type.TOMB;
level.drop( ( Generator.randomUsingDefaults( Generator.Category.GOLD )),BotPos).type = Heap.Type.TOMB;
level.drop( ( Generator.randomUsingDefaults( Generator.Category.GOLD )),TopPos).type = Heap.Type.TOMB;
// 添加边界检查
browStart.x = Math.max(browStart.x, left + 1);
browStart.x = Math.min(browStart.x, right - 1);
browEnd.x = Math.max(browEnd.x, left + 1);
browEnd.x = Math.min(browEnd.x, right - 1);
Painter.drawLine(level, browStart, browEnd, Terrain.WALL);
for (Door door : connected.values()) {
door.set(Door.Type.HIDDEN);
}
}
}

View File

@ -0,0 +1,128 @@
package com.shatteredpixel.shatteredpixeldungeon.levels.rooms.standard;
import com.shatteredpixel.shatteredpixeldungeon.Challenges;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.CrystalMimic;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mimic;
import com.shatteredpixel.shatteredpixeldungeon.items.Generator;
import com.shatteredpixel.shatteredpixeldungeon.items.Heap;
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
import com.shatteredpixel.shatteredpixeldungeon.items.keys.CrystalKey;
import com.shatteredpixel.shatteredpixeldungeon.items.potions.PotionOfLevitation;
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain;
import com.shatteredpixel.shatteredpixeldungeon.levels.painters.Painter;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.special.SpecialRoom;
import com.watabou.utils.Point;
import com.watabou.utils.Random;
import com.watabou.utils.Rect;
import java.util.ArrayList;
import java.util.Arrays;
public class YinYangRoom extends SpecialRoom {
@Override
public int minWidth() { return 11; }
@Override
public int minHeight() {
return 11;
}
@Override
public int maxWidth() { return 11; }
@Override
public int maxHeight() {
return 11;
}
@Override
public boolean canMerge(Level l, Point p, int mergeTerrain) {
return false;
}
@Override
public Rect resize(int w, int h) {
super.resize(w, h);
return this;
}
private Item prize() {
Generator.Category cat = prizeClasses.remove(0);
prizeClasses.add(cat);
Item prize;
do {
prize = Generator.random(cat);
prize.level= Random.NormalIntRange(1,2);
prize.cursed = false;
} while (Challenges.isItemBlocked(prize));
return prize;
}
private Item Blackprize() {
Generator.Category cat = prizeClasses.remove(0);
prizeClasses.add(cat);
Item prize;
do {
prize = Generator.random(cat);
prize.level= Random.NormalIntRange(2,3);
prize.cursed = true;
} while (Challenges.isItemBlocked(prize));
return prize;
}
private ArrayList<Generator.Category> prizeClasses = new ArrayList<>(
Arrays.asList(Generator.Category.WAND,
Generator.Category.RING,
Generator.Category.ARTIFACT));
@Override
public void paint(Level level) {
Point a = new Point((left + right) / 2 + (right - left + 2) / 4 - 1,top + (right - left + 2) / 4 - 1);
Point b = new Point((left + right) / 2 - (right - left + 2) / 4 + 1,bottom - (right - left + 2) / 4 + 1);
Painter.fill(level,this,Terrain.WALL);
Painter.fill(level,left + 1,top + 1,width() - 2,height() - 2,Terrain.WATER);
for (int i = 1;i < right - left;i++) {
for (int j =1;j < bottom - top;j++) {
if (i + j < right - left + 1) {
Painter.set(level,left + i,top + j,Terrain.CHASM);
}
}
}
Painter.fill(level,a.x,top + 1,right - a.x,a.y - top + 1,Terrain.WATER);
Painter.fill(level,left + 1,b.y,b.x - left,bottom - b.y,Terrain.CHASM);
Painter.drawLine(level,new Point((left + right) / 2,top),a,Terrain.WALL);
Painter.drawLine(level,new Point((left + right) / 2,bottom),b,Terrain.WALL);
Painter.drawLine(level,a.offset(0,1),b.offset(0,-1),Terrain.WALL);
int chestPos = left + right - a.x + a.y * level.width();
int chestPos2 = left + right - b.x + b.y * level.width();
Painter.set(level,chestPos,Terrain.PEDESTAL);
level.drop(prize(), chestPos).type = Heap.Type.CRYSTAL_CHEST;
Painter.set(level,chestPos2,Terrain.EMPTY_SP);
if (Random.Int(10) == 0){
level.mobs.add(Mimic.spawnAt(chestPos2,Blackprize(), CrystalMimic.class));
} else {
level.drop(prize(), chestPos2).type = Heap.Type.CRYSTAL_CHEST;
}
Painter.set(level,left + 1,top + 1,Terrain.WALL);
Painter.set(level,right - 1,top + 1,Terrain.WALL);
Painter.set(level,left + 1,bottom - 1,Terrain.WALL);
Painter.set(level,right - 1,bottom - 1,Terrain.WALL);
for (Door door : connected.values()) {
door.set(Door.Type.HIDDEN);
}
level.addItemToSpawn( new CrystalKey( Dungeon.depth ) );
level.addItemToSpawn( new PotionOfLevitation());
}
}

View File

@ -1423,7 +1423,7 @@ public class GameScene extends PixelScene {
Buff.detach( ch, MagicGirlSayTimeLast.class );
}
/** Boss 出场的Logo显示 灵感:泰拉瑞亚灾厄炼狱 */
public static void bossReady() {
if (Dungeon.hero.isAlive()) {
Banner bossSlain = new Banner( BannerSprites.get( BannerSprites.Type.NULL ) );
@ -1438,10 +1438,10 @@ public class GameScene extends PixelScene {
scene.showBanner( bossSlain );
}
break;
case 5:
if(!Dungeon.isDLC(Conducts.Conduct.BOSSRUSH) ) {
bossSlain.texture(Assets.Interfaces.QliPhoth_Title);
bossSlain.show(0xFFFFFF, 0.3f, 5f);
case 0:
if(Dungeon.isDLC(Conducts.Conduct.BOSSRUSH) ) {
bossSlain.texture(Assets.Interfaces.SakaBJY_Title);
bossSlain.show( Window.CYELLOW, 0.3f, 5f);
scene.showBanner(bossSlain);
}
break;
@ -1472,10 +1472,10 @@ public class GameScene extends PixelScene {
scene.showBanner( bossSlain );
}
break;
case 5:
if(!Dungeon.isDLC(Conducts.Conduct.BOSSRUSH) ) {
bossSlain.texture(Assets.Interfaces.QliPhoth_Clear);
bossSlain.show(0xFFFFFF, 0.3f, 5f);
case 0:
if(Dungeon.isDLC(Conducts.Conduct.BOSSRUSH) ) {
bossSlain.texture(Assets.Interfaces.SakaBJY_Clear);
bossSlain.show( Window.CYELLOW, 0.3f, 5f);
scene.showBanner(bossSlain);
}
break;

View File

@ -73,7 +73,7 @@ public class InterlevelScene extends PixelScene {
public static int returnBranch;
public enum Mode {
DESCEND, ASCEND, CONTINUE, RESURRECT, RETURN, FALL, RESET, NONE,EXBOSS,GOBACK,FRGIRLBOSS,DR,
DESCEND, ASCEND, CONTINUE, RESURRECT, RETURN, FALL, RESET, NONE,EXBOSS,GOBACK,FRGIRLBOSS,ANCITYBOSS,DR,
}
public static Mode mode;
@ -285,6 +285,9 @@ public class InterlevelScene extends PixelScene {
case FRGIRLBOSS:
exboss(2);
break;
case ANCITYBOSS:
exboss(3);
break;
}
@ -563,6 +566,9 @@ public class InterlevelScene extends PixelScene {
case 2:
level=Dungeon.ColdFlowerCanyonDie();
break;
case 3:
level=Dungeon.AncityWaterLevel();
break;
default:
level = Dungeon.newLevel();
}

View File

@ -329,6 +329,13 @@ public class CharSprite extends MovieClip implements Tweener.Listener, MovieClip
jump( from, to, callback, distance * 2, distance * 0.1f );
}
public void dirtcar( int from, int to, Callback callback ) {
float distance = Dungeon.level.trueDistance( from, to );
jump( from, to, callback, 0, distance * 0.1f );
}
public void jump( int from, int to, Callback callback, float height, float duration ) {
jumpCallback = callback;

View File

@ -0,0 +1,31 @@
package com.shatteredpixel.shatteredpixeldungeon.sprites;
import com.shatteredpixel.shatteredpixeldungeon.Assets;
import com.watabou.noosa.TextureFilm;
public class DictFishSprites extends MobSprite {
public DictFishSprites() {
super();
texture( Assets.Sprites.DICT );
TextureFilm frames = new TextureFilm( texture, 24, 11 );
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,15 );
play( idle );
}
}

View File

@ -207,10 +207,12 @@ public class ItemSprite extends MovieClip {
return view( ItemSpriteSheet.CHEST, null );
case LOCKED_CHEST:
return view( ItemSpriteSheet.LOCKED_CHEST, null );
case CRYSTAL_CHEST:
case CRYSTAL_CHEST:case TELECRYSTL:
return view( ItemSpriteSheet.CRYSTAL_CHEST, null );
case TOMB:
return view( ItemSpriteSheet.TOMB, null );
case WHITETOMB:
return view( ItemSpriteSheet.GRAVE, null );
case SKELETON:
return view( ItemSpriteSheet.BONES, null );
case REMAINS:

View File

@ -0,0 +1,32 @@
package com.shatteredpixel.shatteredpixeldungeon.sprites;
import com.shatteredpixel.shatteredpixeldungeon.Assets;
import com.watabou.noosa.MovieClip;
import com.watabou.noosa.TextureFilm;
public class RoomStoneSprites extends MobSprite {
public RoomStoneSprites() {
super();
texture( Assets.Sprites.ROOMSTONE);
TextureFilm frames = new TextureFilm( texture, 18, 20 );
idle = new MovieClip.Animation( 2, true );
idle.frames( frames, 0, 0, 0, 1 );
run = new MovieClip.Animation( 10, true );
run.frames( frames, 6, 7, 8, 9, 10 );
attack = new MovieClip.Animation( 15, false );
attack.frames( frames, 2, 3, 4, 5, 0 );
die = new MovieClip.Animation( 10, false );
die.frames( frames, 11, 12, 13, 14 );
play( idle );
}
}

View File

@ -1,10 +1,24 @@
package com.shatteredpixel.shatteredpixeldungeon.sprites;
import com.shatteredpixel.shatteredpixeldungeon.Assets;
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.bosses.SakaFishBoss;
import com.shatteredpixel.shatteredpixeldungeon.effects.Beam;
import com.shatteredpixel.shatteredpixeldungeon.effects.MagicMissile;
import com.shatteredpixel.shatteredpixeldungeon.tiles.DungeonTilemap;
import com.watabou.noosa.TextureFilm;
import com.watabou.noosa.audio.Sample;
import com.watabou.noosa.particles.Emitter;
public class SakaFishBossSprites extends MobSprite {
private Animation leap;
private int zapPos;
private Animation activeIdle;
private Animation charging;
private Emitter chargeParticles;
public SakaFishBossSprites() {
super();
@ -15,17 +29,120 @@ public class SakaFishBossSprites extends MobSprite {
idle = new Animation( 4, true );
idle.frames( frames, 14,15,16,17 );
activeIdle = new Animation( 4, true );
activeIdle.frames( frames, 18,19,20,21);
run = new Animation( 10, true );
run.frames( frames, 2,3 );
attack = new Animation( 15, false );
attack.frames( frames, 4,5,6 );
zap = attack.clone();
die = new Animation( 10, false );
die.frames( frames, 1 );
leap = new Animation( 2, true );
leap.frames( frames, 52,53,54,55 );
charging = new Animation( 20, true);
charging.frames( frames, 28, 29,30,31,32,33,29,30,31,29,30,31,29,30,31,29,30,31,29,30,31,29,30,31,29,30,31,29,30,31,29,30,31,29,30,31,29,30,31,29,30,31,29,30,31,29,30,31,29,30,31,29,30,31,29,30,31,29,30,31,29,30,31,29,30,31,29,30,31,29,30,31,29,30,31 );
play( idle );
}
// 创死你
public void leapPrep( int cell ){
turnTo( ch.pos, cell );
play( leap );
}
public void activate(){
idle = activeIdle.clone();
idle();
}
@Override
public void zap( int pos ) {
zapPos = pos;
super.zap( pos );
}
//超级激光
public void charge( int pos ){
turnTo(ch.pos, pos);
play(charging);
if (visible) Sample.INSTANCE.play( Assets.Sounds.CHARGEUP );
}
@Override
public void link(Char ch) {
super.link(ch);
chargeParticles = centerEmitter();
chargeParticles.autoKill = false;
chargeParticles.pour(MagicMissile.MagicParticle.ATTRACTING, 0.05f);
chargeParticles.on = false;
if (((SakaFishBoss)ch).beamCharged) play(charging);
if (((SakaFishBoss) ch).state != ((SakaFishBoss) ch).SLEEPING){
activate();
}
renderShadow = false;
}
@Override
public void update() {
super.update();
if (chargeParticles != null){
chargeParticles.pos( center() );
chargeParticles.visible = visible;
}
}
@Override
public void die() {
super.die();
if (chargeParticles != null){
chargeParticles.on = false;
}
}
@Override
public void kill() {
super.kill();
if (chargeParticles != null){
chargeParticles.killAndErase();
}
}
@Override
public void play(Animation anim) {
if (chargeParticles != null) chargeParticles.on = anim == charging;
super.play(anim);
}
@Override
public void onComplete( Animation anim ) {
super.onComplete( anim );
if (anim == zap) {
idle();
if (Actor.findChar(zapPos) != null){
parent.add(new Beam.DeathRayS(center(), Actor.findChar(zapPos).sprite.center()));
} else {
parent.add(new Beam.DeathRayS(center(), DungeonTilemap.raisedTileCenterToWorld(zapPos)));
}
((SakaFishBoss)ch).deathGaze();
ch.next();
} else if (anim == die){
chargeParticles.killAndErase();
}
}
}

View File

@ -32,7 +32,7 @@ public class SalamanderSprites extends MobSprite {
cast = attack.clone();
die = new MovieClip.Animation( 12, false );
die.frames( frames, 7 );
die.frames( frames, 7,8,9 );
play( idle );
}

View File

@ -38,6 +38,7 @@ import com.shatteredpixel.shatteredpixeldungeon.sprites.RedSwarmSprite;
import com.shatteredpixel.shatteredpixeldungeon.sprites.SRPDHBLRTT;
import com.shatteredpixel.shatteredpixeldungeon.sprites.SalamanderSprites;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ShopkKingSprite;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ShopkeeperSprite;
import com.shatteredpixel.shatteredpixeldungeon.sprites.SlimeKingSprite;
import com.shatteredpixel.shatteredpixeldungeon.sprites.SnakeSprite;
import com.shatteredpixel.shatteredpixeldungeon.sprites.WFSprite;
@ -54,6 +55,7 @@ import java.util.ArrayList;
public class vM0_6_7_X_Changes {
public static void addAllChanges(ArrayList<ChangeInfo> changeInfos) {
add_v0_6_54_Changes(changeInfos);
add_v0_6_53_Changes(changeInfos);
add_v0_6_52_Changes(changeInfos);
add_v0_6_51_Changes(changeInfos);
@ -110,6 +112,34 @@ public class vM0_6_7_X_Changes {
add_v0_6_0_Changes(changeInfos);
}
public static void add_v0_6_54_Changes( ArrayList<ChangeInfo> changeInfos ) {
ChangeInfo changes = new ChangeInfo("v0.6.4.0-Beta1", true, "");
changes.hardlight(Window.TITLE_COLOR);
changeInfos.add(changes);
changes = new ChangeInfo("新内容", false, null);
changes.hardlight(Window.GREEN_COLOR);
changeInfos.add(changes);
changes.addButton( new ChangeButton(new Image(Assets.Environment.TILES_SEWERS, 48, 48, 16
, 16), "房间改动",
"全新房间:慧眼墓碑房/太极八卦房加入"));
changes.addButton(new ChangeButton(new ShopkeeperSprite(), ("回购系统"),
("商店追加回购系统,除了商人领主和奈亚子均可原价退回商品")));
changes = new ChangeInfo("改动", false, null);
changes.hardlight(Window.CYELLOW);
changeInfos.add(changes);
changes.addButton(new ChangeButton(new PinkLingSprite(), ("杂项改动"),
("优化地牢部分数据,并且为即将更新的每日狩猎等设好底层。")));
changes.addButton(new ChangeButton(new Image("sprites/spinner.png", 144, 0, 16, 16),
Messages.get(ChangesScene.class, "bugfixes"), Messages.get(vM0_6_7_X_Changes.class, "bug_06X81")));
}
public static void add_v0_6_53_Changes( ArrayList<ChangeInfo> changeInfos ) {
ChangeInfo changes = new ChangeInfo("v0.6.3.0-Beta5-5.1", true, "");
changes.hardlight(Window.TITLE_COLOR);

View File

@ -195,7 +195,7 @@ public class WndRedDragon extends Window {
@Override
protected void onClick() {
RewardWindow.this.hide();
if (rewardObtained == false) {
if (!rewardObtained) {
WndRedDragon.this.selectReward(item);
} else {
GLog.b(Messages.get(this, "why"));

View File

@ -26,6 +26,8 @@ import static com.shatteredpixel.shatteredpixeldungeon.Dungeon.shopOnLevel;
import com.shatteredpixel.shatteredpixeldungeon.Conducts;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.Statistics;
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.ShopGuardDead;
@ -61,13 +63,20 @@ public class WndTradeItem extends WndInfoItem {
this.owner = owner;
float pos = height;
Shopkeeper shop = null;
for (Char ch : Actor.chars()){
if (ch instanceof Shopkeeper){
shop = (Shopkeeper) ch;
break;
}
}
final Shopkeeper finalShop = shop;
if (item.quantity() == 1) {
RedButton btnSell = new RedButton( Messages.get(this, "sell", item.value()) ) {
@Override
protected void onClick() {
sell( item );
sell( item,finalShop );
hide();
}
};
@ -93,7 +102,7 @@ public class WndTradeItem extends WndInfoItem {
RedButton btnSellAll = new RedButton( Messages.get(this, "sell_all", priceAll ) ) {
@Override
protected void onClick() {
sell( item );
sell( item,finalShop );
hide();
}
};
@ -218,7 +227,7 @@ public class WndTradeItem extends WndInfoItem {
if (selling) Shopkeeper.sell();
}
public static void sell( Item item ) {
public static void sell( Item item, Shopkeeper shop ) {
Hero hero = Dungeon.hero;
@ -229,24 +238,42 @@ public class WndTradeItem extends WndInfoItem {
//selling items in the sell interface doesn't spend time
hero.spend(-hero.cooldown());
Statistics.totalScore += 400;
new Gold( item.value() ).doPickUp( hero );
if (shop != null){
shop.buybackItems.add(item);
while (shop.buybackItems.size() > Shopkeeper.MAX_BUYBACK_HISTORY){
shop.buybackItems.remove(0);
}
}
}
public static void sellOne( Item item ) {
sellOne( item, null );
}
public static void sellOne( Item item, Shopkeeper shop ) {
if (item.quantity() <= 1) {
sell( item );
sell( item, shop );
} else {
Hero hero = Dungeon.hero;
Statistics.totalScore += 100;
item = item.detach( hero.belongings.backpack );
//selling items in the sell interface doesn't spend time
hero.spend(-hero.cooldown());
new Gold( item.value() ).doPickUp( hero );
if (shop != null){
shop.buybackItems.add(item);
while (shop.buybackItems.size() > Shopkeeper.MAX_BUYBACK_HISTORY){
shop.buybackItems.remove(0);
}
}
}
}