Update Beta XV

This commit is contained in:
LingASDJ 2022-07-28 22:32:59 +08:00
parent cc62ae4fe3
commit 1e1287937e
24 changed files with 925 additions and 178 deletions

View File

@ -5,11 +5,17 @@ text.herostat.duration = 总回合数
text.herostat.score = 分数
text.herostat.real_time = 总时间
text.herostat.seed_dungeon = 种子序列号
text.herostat.seed_custom_no = SD
text.herostat.seed_custom_no =
text.textchallenges.seed_custom_title = 种子
text.textchallenges.hint = 不输入即为随机种子
text.textchallenges.delete_seed_input = 清除
actors.mobs.bloodbat$bloodbatrecharge.name=血影充能
actors.mobs.bloodbat$bloodbatrecharge.desc=小血影正在充能,等待下一次和主人并肩作战的时候!
actors.mobs.bloodbat.name=血影蝙蝠
actors.mobs.bloodbat.desc=极影铃虹的随身伙伴,为了主人的安全将会让一切试图伤害主人的家伙万劫不复。\n\n它的能力和主人紧密相连主人的成长也会让小血影成长
actors.buffs.halomethaneburning.name=磷火缠身
actors.buffs.halomethaneburning.heromsg=磷火像恶魔一样缠在了你的身上!
actors.buffs.halomethaneburning.burnsup=%s被烧的渣都不剩了
@ -387,7 +393,7 @@ actors.mobs.npcs.slyl.message1=我叫冷群,这是我的真名。
actors.mobs.npcs.slyl.message2=地牢最深处的黑暗……似乎有点忘记了。但据说最近有冒险者在地牢新发现了一批特别的书籍,它们或多或少都沾染过魔法。
actors.mobs.npcs.slyl.def_verb=风暴将临
actors.mobs.npcs.slyl.desc=_冷群_是一位掌握冰系力量的魔人族是300年前_寒冰圣都_的管理者。\n由于地下异常的不断出现她来到这里调查异常的原因。\n看起来她似乎摸鱼。
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=看来你需要更加艰难的试炼了。

View File

@ -448,6 +448,7 @@ items.artifacts.cloakofshadows$cloakstealth.no_charge=你的斗篷耗尽了能
items.artifacts.cloakofshadows$cloakstealth.levelup=你的斗篷变得更强大了!
items.artifacts.cloakofshadows$cloakstealth.name=斗篷之下
items.artifacts.cloakofshadows$cloakstealth.desc=你身上的暗影斗篷正给予你隐形效果。\n\n当你在隐形时敌人无法追踪或攻击你。大部分物理攻击和魔法(比如卷轴和法杖)会不可避免地消除隐形效果。\n\n你会一直拥有该状态直到你自行取消或斗篷耗尽能量。
items.artifacts.cloakofshadows.ac_bloodbat=召唤伙伴
items.artifacts.driedrose.name=干枯玫瑰
items.artifacts.driedrose.ac_summon=召唤
@ -1951,10 +1952,10 @@ items.weapon.weapon$enchantment.enchant=附魔
###misc items
items.amulet.name=Yendor护身符
items.amulet.ac_end=结束游戏
items.amulet.rankings_desc=获得Yendor护身符
items.amulet.desc=Yendor护身符是人类与矮人所知的最强大的神器。其上镶嵌的闪闪发光的水晶蕴含着不可思议的神奇力量。\n\n护身符的来历不详。根据历史记载矮人国王夸口说他在矮人文明与外界切断一切联系之前不久就发现了这件神器。那他是怎么找到的古神又是怎么从他那里拿走的也许这些问题不需要现在解答真正重要的是护身符正属于你
items.amulet.name=水晶之心
items.amulet.ac_end=返回主城
items.amulet.rankings_desc=获得水晶之心,而危机仍在
items.amulet.desc=击败了古神后,你发现了水晶之心。但是,前面不再有前进的道路了。莫非,本次旅程已经宣告结束了吗?
items.ankh.name=重生十字架
items.ankh.ac_bless=祝福

View File

@ -450,5 +450,6 @@ ui.changelist.mlpd.vm0_5_x_changes.frlogs=尚待调查……
ui.changelist.mlpd.vm0_6_7_x_changes.bug_06x20=-1.支离破碎bug已修复\n2.部分符石文本缺失已修复\n3.0层饱食度问题已修复\n4.炼金移植有问题已修复\n5.药水文本缺失已修复\n6.钥匙材质有问题已修复\n7.怨灵血量异常已修复\n8.种子显示问题已修复\n9.快捷栏优化问题已修复\n10.初始升级卷轴,以及初始物品已修复\n12.奈亚子初始奖励异常已修复\n13.由于V1.2.3楼层名字导致部分BOSS超类闪退已修复\n14.精英强敌鬼磷文本缺失已修复\n15.炼金合成表已移植\n16.风行水上部分buff已经重做\n17.部分原始Java类已合并\n18.英雄类逻辑楼层应该为0已修复\n19.光Buff有问题已修复\n20.恶魔层贴图有问题已修复\n21.部分buff尚未定义在破碎123英雄类里面已修复\n22.尚方宝剑属性问题已修复
ui.changelist.mlpd.vm0_6_7_x_changes.bug_06x21=-1.修复了矮人国王的闪退问题\n-2.游戏性能优化\n-3.修复了钻石宝箱王的错误刷怪\n-去除了重生十字架的金色光环。
//ui.changelist.mlpd.vm0_5_x_changes.xxx//

View File

@ -285,11 +285,50 @@ windows.wndsettings$langstab.credits=制作名单
windows.wndsettings$langstab.reviewers=审核员
windows.wndsettings$langstab.translators=翻译员
windows.wndstory.sewers=这片地牢位于城市的正下方,它的较上层其实是由城市的下水道系统组成的。\n\n由于下方不断渗透的黑暗能量这些本应无害的下水道生物变得越来越危险。城市向这里派出巡逻队并试图以此保护其上方的区域但他们的影响也在逐渐式微。\n\n这片区域已经具有一定的危险性不过至少邪恶魔法对这里的影响尚且是薄弱的。
windows.wndstory.prison=多年以前一座地下监狱为了收容危险的犯罪者而建立于此。由于其严格的监管和高安全性,地表各处的囚犯都被带到这里经受时间的折磨。 \n\n但不久之后下方充斥着黑暗的瘴气在这里弥漫开来扭曲了罪犯和狱卒的心智。\n\n监狱里充斥开来的混乱使其彻底失去了秩序于是城市封锁了整个监狱。现今已经没有人知道这些高墙之下经历过无数死亡的生物究竟会是什么样子...
windows.wndstory.caves=这座从废弃监狱延伸而下的洞穴,早已空无一人。矿产丰富的洞穴曾经是下方矮人国度的一个贸易与工业中心。然而随着矮人逐渐堕入黑暗魔法的深渊,这里也慢慢被废弃了。\n\n荒凉的洞穴中大抵只有地下生物与豺狼人居住偶尔能见到废弃的机械。与之前的区域类似这里的活物似乎也被同一种邪恶力量所扭曲。
windows.wndstory.city=矮人都市曾经是最宏伟的矮人城邦。在其鼎盛时期矮人制造了一批注入魔力的奇特机械,借此快速扩张矮人城邦。\n\n然而突然有一天城邦的大门被紧闭从此外界再也得不到矮人的消息。据几位侥幸逃脱的矮人讲有一位癫狂的矮人篡夺了王位并利用他掌控的黑暗魔法巩固统治的地位。
windows.wndstory.halls=这些遍布矮人王国深处的大厅已经被恶魔力量扭曲。在过去,这里由矮人王旗下的精英术士们做主,但他们似乎已经为某些更加邪恶强大的存在所取代...\n\n恶魔生物们盘踞着这些大厅。令人胆寒的黑暗意志主宰着它们。既然矮人王不是腐化的根源那真正的它一定就藏在这里\n\n路上要小心很少有冒险者能一路走到这里...
windows.wndstory.sewers=这里是荒废已久的地牢\n\n相传这地牢以前曾经繁荣昌盛过\n\n直到她的介入后这个地牢变得危机四伏\n\n现在这个地牢的居民都是被黑魔法感染的怪物\n\n你现在来到这里是为了寻找300年前的真相\n\n你必须一路走下去\n\n现在已经不可能再回头了。
windows.wndstory.sewersboss=这里人迹罕至,这里寒冷降至。\n\n但这里却被它的烈焰燃烧
windows.wndstory.prison=多年以前一座地下监狱为了收容危险的犯罪者而建立于此。由于其严格的监管和高安全性,地表各处的囚犯都被带到这里经受时间的折磨。 \n\n但不久之后下方充斥着黑暗的瘴气在这里弥漫开来扭曲了罪犯和狱卒的心智。\n\n监狱里充斥开来的混乱使其彻底失去了秩序于是城市封锁了整个监狱。现今已经没有人知道这些高墙之下经历过无数死亡的生物究竟会是什么样子...\n\n现在这里已经乱套你只能将所有东西全部杀掉。
windows.wndstory.prisonboss=如果你做了坏事,就会付出与之相匹配的代价。\n\n希望与绝望是一个相对量\n\n这是她曾经对天狗说过的话\n\n\
\n\n\n\n\n\n\
\n\n\n\n\n\n
windows.wndstory.caves=这座从废弃监狱延伸而下的洞穴,早已空无一人。这里对于城市而言过于深入且很难开发,其中极度匮乏的矿物也无法激起矮人的兴趣。曾经在这里有一个为两个势力建立的贸易站,但在矮人国度衰落之后,只有无所不在的豺狼人和地下生物还居住在这里。\n\n但这里早已经被邪恶的魔力控制\n\n这里已经十分危险了。
windows.wndstory.cavesboss=起源,发展,盛世,腐朽,危机,暴乱,谋权,灭亡\n\n这便是这个矮人王国的发展历程\n\n现在矮人王国的人似乎已经知道你正在前来的路上、\n\n\
他们为你准备了一份大礼,你是否看见了前面的那台机器?\n\n那是DM是矮人王国的中的一台巨型采矿机器。\n\n不过现在这个机器只是在守卫这里。\n\n它在等待什么\n\n我们又在这里干什么\n\n 按照你曾经在家看见的古书记载,这里过去就是曾经繁荣昌盛的矮人国度。\n\nDM似乎并没有发现你虽然这不是DM的错但你是想寻找到地牢的深处。\n\n为此你不得不得向这台机器进行殊死搏斗。\n\n记住要相信自己能够活下来
windows.wndstory.icedead=死亡不是我们的终点,而是我们的起点。\n\n-在堕落的那一瞬间,我就已经与世隔绝。现在,谁还能帮助我?
windows.wndstory.gamehappy=你已启用娱乐模式,玩的愉快!!!
windows.wndstory.city=矮人都市曾经是最宏伟的矮人城邦。在其鼎盛时期矮人的机械化部队曾成功击退过古神及其恶魔军队的入侵。但是也有传闻说,凯旋而归的战士同时带来了腐坏的种子,矮人王国的胜利正是其毁灭的开端。\n\n这里的魔力越来越强烈谁才是幕后主谋
windows.wndstory.cityboss=一路杀出重围\n\n一路直逼矮人国王议事厅\n\n你的心中一直明白“这里已经不是矮人王国这里是恶魔的乐园”\n\n矮人国度的幕后主谋应该知道你来了\n\n而你也知道这将是你第一次同时也是最后一次见到矮人国王\n\n你已经准备好了那么就请杀出一条血路吧
windows.wndstory.halls=很久以前这片区域曾是矮人都市的郊区。在与古神的战争中取得惨胜的矮人已经无力掌控并清理这片地区。于是存活的恶魔逐渐巩固了对这里的控制,现在,这里被称作恶魔大厅。\n\n很少有冒险者能够深入到这种地方...
windows.wndstory.hallsboss=这里空无一物\n\n这里了无生机\n\n这里是起始之初\n\n这里真的太安静了\n\n不过你明白这是试炼\n\n但你必须面对你准备好了吗
windows.wndstory.new=在击败了Yog古神后似乎一切变得平静下来了。\n\n但你总感觉这事情并不会这么快的结束。\n\n\
殿耀姿\n\n\n\n\
\n\
\nMLPD\
--\n\n-
windows.wndstory.forest=300年前一场大火让这个地牢不复存在。地牢的创始人翼绫也不见踪影。\n\n300年后随着地牢原住民对地牢的维修和重建地牢渐渐的有了生机。\n特别是和矮人他们共同从300年的灾难逃出来的古神YOG,是让地牢重新振兴的核心人员。\n随着时间的推移YOG他们有了一个疯狂的想法并将这个想法交给了地表三巨头。\n霜落女帝当即批准该建议并发布猎杀的悬赏令。\n然而人人都知道亵渎她的后果可仍然顶风作案。\n你也是参与的一员你现在来到了地牢的入口现在开始你的旅途了。
windows.wndtradeitem.stole=抢劫商店
windows.wndstory.dm920=Yog-Dzewa的陨落其实背后有太多的秘密。\nYog的后面是一个连Yog都害怕的一个DM终极实验品\n它是造成矮人国度堕落的元凶它是灾难的象征\n它是曾经的死灵军团的杀手锏它是死亡的代言词\n它是连Yog-Dzewa都要敬畏它三分的DM920,\n你需直面你不可逃避你的路途就是为此而来。\n已经没有退路唯有放手一搏无论它是真是假\n但你明白不击败他死的就只能是自己
windows.wndgoshop.szo=地牢商人
windows.wndgoshop.ary=哦,我注意到你对我的东西蠢蠢欲动。如果你想动什么歪心思,我劝你还是放弃吧!!!\n\n商人正在非常警惕的看见你如果你想抢劫商店本层恐怕会发生奇妙的变换。\n\n那么对于商人的警告你的选择是
windows.wndgoshop.yes=抢劫
windows.wndgoshop.no=放弃
windows.wndgoshop.notbad=好吧,我以为你想抢劫商店的……
windows.wndstory.drawfmaster=庄严的大厅,死寂的环境。\n\n这里曾经是矮人王国的最大议事厅而如今的死寂恐怖气氛却令这里显得十分诡异。\n\n并且这里似乎机关重重……\n有一个破旧不堪的石碑依稀的写着不要踏入这里裂缝会变为地板大将将会醒来……\n这在预示着什么
windows.wndsupportprompt.title=来自开发者的留言
windows.wndsupportprompt.intro=欢迎~希望您能在破碎的像素地牢中玩得开心!

Binary file not shown.

After

Width:  |  Height:  |  Size: 704 B

View File

@ -294,6 +294,7 @@ public class Assets {
public static final String REDSWARM = "sprites/RedSearm.png";
public static final String REN = "Ren/ren.png";
public static final String WHITE = "Npcs/White.png";
public static final String BBAT = "sprites/bloodbat.png";
public static final String RAT = "sprites/rat.png";
public static final String BRUTE = "sprites/brute.png";

View File

@ -23,6 +23,7 @@ package com.shatteredpixel.shatteredpixeldungeon;
import static com.shatteredpixel.shatteredpixeldungeon.Challenges.ALLBOSS;
import static com.shatteredpixel.shatteredpixeldungeon.Challenges.RLPT;
import static com.shatteredpixel.shatteredpixeldungeon.actors.hero.HeroClass.ROGUE;
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
@ -35,6 +36,7 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.RevealedArea;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Talent;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.abilities.huntress.SpiritHawk;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.BloodBat;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.Blacksmith;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.Ghost;
@ -123,6 +125,7 @@ public class Dungeon {
STRENGTH_POTIONS,
UPGRADE_SCROLLS,
ARCANE_STYLI,
BBAT,
//Health potion sources
//enemies
@ -217,7 +220,7 @@ public class Dungeon {
Actor.resetNextID();
Random.pushGenerator(seed);
BloodBat.level = 1;
Scroll.initLabels();
Potion.initColors();
Ring.initGems();
@ -551,6 +554,25 @@ public class Dungeon {
Mob.restoreAllies( level, pos );
Actor.init();
if (!LimitedDrops.BBAT.dropped() && hero.isClass(ROGUE)){
LimitedDrops.BBAT.drop();
ArrayList<Integer> respawnPoints = new ArrayList<>();
for (int i = 0; i < PathFinder.NEIGHBOURS8.length; i++) {
int p = 0;
if (Actor.findChar( p ) == null && Dungeon.level.passable[p]) {
respawnPoints.add( p );
}
}
if (respawnPoints.size() > 0) {
BloodBat bat = new BloodBat();
bat.pos = respawnPoints.get(Random.index(respawnPoints));
bat.state = bat.WANDERING;
Dungeon.level.mobs.add( bat );
Actor.add( bat );
}
}
level.addRespawner();
hero.pos = pos;
@ -707,7 +729,7 @@ public class Dungeon {
Bundle badges = new Bundle();
Badges.saveLocal( badges );
bundle.put( BADGES, badges );
BloodBat.saveLevel(bundle);
FileUtils.bundleToFile( GamesInProgress.gameFile(save), bundle);
} catch (IOException e) {
@ -762,7 +784,7 @@ public class Dungeon {
Scroll.restore( bundle );
Potion.restore( bundle );
Ring.restore( bundle );
BloodBat.loadLevel(bundle);
quickslot.restorePlaceholders( bundle );
if (fullLoad) {

View File

@ -390,7 +390,7 @@ public abstract class Char extends Actor {
if (buff(FireImbue.class) != null) buff(FireImbue.class).proc(enemy);
if (buff(FrostImbue.class) != null) buff(FrostImbue.class).proc(enemy);
if (buff(FrostImbueEX.class) != null) buff(FrostImbue.class).proc(enemy);
if (buff(FrostImbueEX.class) != null) buff(FrostImbueEX.class).proc(enemy);
if (enemy.isAlive() && enemy.alignment != alignment && prep != null && prep.canKO(enemy)){
enemy.HP = 0;

View File

@ -34,8 +34,7 @@ public class AnkhInvulnerability extends FlavourBuff {
@Override
public void fx(boolean on) {
if (on) target.sprite.aura( 0xFFFF00 );
else target.sprite.clearAura();
//
}
@Override

View File

@ -0,0 +1,210 @@
package com.shatteredpixel.shatteredpixeldungeon.actors.buffs;
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.HeroAction;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.BloodBat;
import com.shatteredpixel.shatteredpixeldungeon.effects.CellEmitter;
import com.shatteredpixel.shatteredpixeldungeon.effects.Speck;
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
import com.shatteredpixel.shatteredpixeldungeon.scenes.CellSelector;
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
import com.shatteredpixel.shatteredpixeldungeon.ui.ActionIndicator;
import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIndicator;
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
import com.watabou.noosa.Image;
import com.watabou.noosa.audio.Sample;
import com.watabou.utils.Bundle;
import com.watabou.utils.PathFinder;
import java.text.DecimalFormat;
public class Marked extends Buff implements ActionIndicator.Action {
{
type = buffType.NEGATIVE;
announced = true;
}
public int stack = 0;
@Override
public void storeInBundle(Bundle bundle) {
super.storeInBundle(bundle);
bundle.put("stack", stack);
}
@Override
public void restoreFromBundle(Bundle bundle) {
super.restoreFromBundle(bundle);
stack = bundle.getInt("stack");
if (stack > 0) ActionIndicator.setAction(this);
}
public float bonusDamage(){
return (float) Math.pow(1.085f, stack);
}
@Override
public int icon() {
return BuffIndicator.PREPARATION;
}
@Override
public void tintIcon(Image icon) {
switch (stack){
case 1: case 2: case 3:
icon.hardlight(0f, 1f, 0f);
break;
case 4: case 5: case 6:
icon.hardlight(1f, 1f, 0f);
break;
case 7: case 8: case 9:
icon.hardlight(1f, 0.6f, 0f);
break;
case 10: case 11: default:
icon.hardlight(1f, 0f, 0f);
break;
}
}
@Override
public boolean act() {
if (stack > 0){
ActionIndicator.setAction(this);
}
spend(TICK);
return true;
}
@Override
public void detach() {
super.detach();
ActionIndicator.clearAction(this);
}
@Override
public String toString() {
return Messages.get(this, "name");
}
@Override
public String desc() {
String desc = Messages.get(this, "desc");
desc += "\n\n" + Messages.get(this, "desc_dmg", new DecimalFormat("#.##").format(100f * Math.pow(1.085f, stack) - 100f));
if (stack >= 2) desc += "\n\n" + Messages.get(this, "desc_poison");
if (stack >= 3) desc += "\n" + Messages.get(this, "desc_cripple");
if (stack >= 4) desc += "\n" + Messages.get(this, "desc_blinding");
if (stack >= 5) desc += "\n" + Messages.get(this, "desc_bleeding");
if (stack >= 6) desc += "\n" + Messages.get(this, "desc_vulnerable");
if (stack >= 7) desc += "\n" + Messages.get(this, "desc_hexed");
if (stack >= 8) desc += "\n" + Messages.get(this, "desc_slow");
if (stack >= 9) desc += "\n" + Messages.get(this, "desc_ooze");
if (stack >= 10) desc += "\n" + Messages.get(this, "desc_paralysis");
if (stack >= 11) desc += "\n" + Messages.get(this, "desc_doom");
return desc;
}
@Override
public String actionName() {
return null;
}
@Override
public Image actionIcon() {
return null;
}
@Override
public void doAction() {
GameScene.selectCell(attack);
}
private CellSelector.Listener attack = new CellSelector.Listener() {
@Override
public void onSelect(Integer cell) {
if (cell == null) return;
final Char enemy = Actor.findChar( cell );
if (enemy == null || enemy.buff(Marked.class) == null){
GLog.w(Messages.get(Marked.class, "no_target"));
} else {
if (Dungeon.hero.canAttack(enemy)){
effect(enemy);
Dungeon.hero.curAction = new HeroAction.Attack( enemy );
Dungeon.hero.next();
return;
}
boolean[] passable = Dungeon.level.passable.clone();
//need to consider enemy cell as passable in case they are on a trap or chasm
passable[cell] = true;
PathFinder.buildDistanceMap(Dungeon.hero.pos, passable, 100_000_000);
if (PathFinder.distance[cell] == Integer.MAX_VALUE){
GLog.w(Messages.get(Preparation.class, "out_of_reach"));
return;
}
//we can move through enemies when determining blink distance,
// but not when actually jumping to a location
for (Char ch : Actor.chars()){
if (ch != Dungeon.hero) passable[ch.pos] = false;
}
PathFinder.Path path = PathFinder.find(Dungeon.hero.pos, cell, passable);
int attackPos = path == null ? -1 : path.get(path.size()-2);
if (attackPos == -1 ||
Dungeon.level.distance(attackPos, Dungeon.hero.pos) > 100_000_000){
GLog.w(Messages.get(Preparation.class, "out_of_reach"));
return;
}
Dungeon.hero.pos = attackPos;
Dungeon.level.occupyCell(Dungeon.hero);
//prevents the hero from being interrupted by seeing new enemies
Dungeon.observe();
Dungeon.hero.checkVisibleMobs();
Dungeon.hero.sprite.place( Dungeon.hero.pos );
Dungeon.hero.sprite.turnTo( Dungeon.hero.pos, cell);
CellEmitter.get( Dungeon.hero.pos ).burst( Speck.factory( Speck.WOOL ), 6 );
Sample.INSTANCE.play( Assets.Sounds.PUFF );
effect(enemy);
Dungeon.hero.curAction = new HeroAction.Attack( enemy );
Dungeon.hero.next();
}
}
@Override
public String prompt() {
return Messages.get(Marked.class, "prompt");
}
};
public static void effect(Char enemy){
Marked mark = enemy.buff(Marked.class);
if (mark.stack >= 2) Buff.affect(enemy, Poison.class).set(Dungeon.escalatingDepth());
if (mark.stack >= 3) Buff.affect(enemy, Cripple.class, 4f);
if (mark.stack >= 4) Buff.affect(enemy, Blindness.class, 4f);
if (mark.stack >= 5) Buff.affect(enemy, Bleeding.class).level = Dungeon.escalatingDepth();
if (mark.stack >= 6) Buff.affect(enemy, Vulnerable.class, 4f);
if (mark.stack >= 7) Buff.affect(enemy, Hex.class, 4f);
if (mark.stack >= 8) Buff.affect(enemy, Slow.class, 4f);
if (mark.stack >= 9) Buff.affect(enemy, Ooze.class).set(20f);
if (mark.stack >= 10) Buff.affect(enemy, Paralysis.class, 5f);
if (mark.stack >= 11) Buff.affect(enemy, Doom.class);
for (Char ch : Actor.chars()){
if (ch instanceof BloodBat){
ch.sprite.emitter().burst(Speck.factory(Speck.SMOKE), 10);
ch.HP = Math.min(ch.HT, ch.HP + ch.HT / 5 * mark.stack);
}
}
enemy.buff(Marked.class).detach();
}
}

View File

@ -65,6 +65,7 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Vertigo;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.abilities.ArmorAbility;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.abilities.huntress.NaturesPower;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.abilities.warrior.Endure;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.BloodBat;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Monk;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Snake;
@ -164,13 +165,23 @@ import java.util.Collections;
import java.util.LinkedHashMap;
public class Hero extends Char {
public int shadeID;
{
actPriority = HERO_PRIO;
alignment = Alignment.ALLY;
}
public boolean isClass(HeroClass clazz){
if (heroClass == HeroClass.ROGUE) return true;
return clazz == this.heroClass;
}
public boolean isSubclass(HeroSubClass subClass) {
if (this.subClass == HeroSubClass.ASSASSIN || this.subClass == HeroSubClass.FREERUNNER) return true;
return subClass == this.subClass;
}
public ArrayList<Mob> visibleEnemiesList() {
return visibleEnemies;
}
@ -1596,6 +1607,8 @@ public class Hero extends Char {
WndHero.lastIdx = 1;
}
}
BloodBat.updateHP();
Item.updateQuickslot();

View File

@ -98,9 +98,11 @@ import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.exotic.ScrollOfRos
import com.shatteredpixel.shatteredpixeldungeon.items.spells.AquaBlast;
import com.shatteredpixel.shatteredpixeldungeon.items.spells.BeaconOfReturning;
import com.shatteredpixel.shatteredpixeldungeon.items.spells.MagicalInfusion;
import com.shatteredpixel.shatteredpixeldungeon.items.spells.SummonElemental;
import com.shatteredpixel.shatteredpixeldungeon.items.stones.StoneOfFlock;
import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfBlueFuck;
import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfCorruption;
import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfFireblast;
import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfFrost;
import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfGodIce;
import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfMagicMissile;
@ -129,6 +131,7 @@ import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
import com.shatteredpixel.shatteredpixeldungeon.plants.AikeLaier;
import com.shatteredpixel.shatteredpixeldungeon.plants.Blindweed;
import com.shatteredpixel.shatteredpixeldungeon.plants.Firebloom;
import com.watabou.utils.Random;
public enum HeroClass {
@ -319,7 +322,7 @@ public enum HeroClass {
ThrowingStone stones = new ThrowingStone();
stones.quantity(3).collect();
Dungeon.quickslot.setSlot(0, stones);
new SummonElemental().quantity(2).identify().collect();
if (hero.belongings.armor != null){
hero.belongings.armor.affixSeal(new BrokenSeal());
}
@ -336,7 +339,17 @@ public enum HeroClass {
(hero.belongings.weapon = staff).identify();
hero.belongings.weapon.activate(hero);
WandOfFireblast woc = new WandOfFireblast();
woc.level(Random.NormalIntRange(0,2));
woc.identify().quantity(1);
WandOfFrost wox = new WandOfFrost();
wox.level(Random.NormalIntRange(0,2));
wox.identify().quantity(1);
Dungeon.quickslot.setSlot(0, staff);
Dungeon.quickslot.setSlot(1, wox);
Dungeon.quickslot.setSlot(2, woc);
new ScrollOfUpgrade().identify();
new PotionOfLiquidFlame().identify();

View File

@ -58,10 +58,8 @@ import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.MeleeWeapon;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.missiles.MissileWeapon;
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain;
import com.shatteredpixel.shatteredpixeldungeon.messages.Languages;
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
import com.shatteredpixel.shatteredpixeldungeon.scenes.HeroSelectScene;
import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIndicator;
import com.watabou.noosa.Image;
import com.watabou.noosa.audio.Sample;
@ -399,6 +397,8 @@ public enum Talent {
}
}
public static void onArtifactUsed( Hero hero ){
if (hero.hasTalent(ENHANCED_RINGS)){
Buff.prolong(hero, EnhancedRings.class, 3f*hero.pointsInTalent(ENHANCED_RINGS));

View File

@ -0,0 +1,240 @@
package com.shatteredpixel.shatteredpixeldungeon.actors.mobs;
import com.shatteredpixel.shatteredpixeldungeon.Assets;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.ArtifactRecharge;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Blindness;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Degrade;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.FlavourBuff;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Marked;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.HeroSubClass;
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
import com.shatteredpixel.shatteredpixeldungeon.sprites.BlueBatSprite;
import com.shatteredpixel.shatteredpixeldungeon.sprites.CharSprite;
import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIndicator;
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
import com.watabou.noosa.Image;
import com.watabou.noosa.audio.Sample;
import com.watabou.utils.Bundle;
import com.watabou.utils.Callback;
import com.watabou.utils.Random;
public class BloodBat extends Mob implements Callback {
{
HP = HT = 20;
defenseSkill = 7;
baseSpeed = 1.5f;
spriteClass = BlueBatSprite.class;
alignment = Alignment.ALLY;
WANDERING = new Wandering();
intelligentAlly = true;
maxLvl = -30;
}
public void onZapComplete() {
zap();
next();
}
@Override
public void call() {
next();
}
public static class DarkBolt{}
public static int level = 1;
private static final float TIME_TO_ZAP = 2f;
private void zap() {
spend( TIME_TO_ZAP );
if (hit( this, enemy, true )) {
//TODO would be nice for this to work on ghost/statues too
if (enemy == Dungeon.hero && Random.Int( 2 ) == 0) {
Buff.prolong( enemy, Blindness.class, Degrade.DURATION );
Sample.INSTANCE.play( Assets.Sounds.DEBUFF );
}
int dmg = Random.NormalIntRange( 2, 4 );
enemy.damage( dmg, new BloodBat.DarkBolt() );
if (enemy == Dungeon.hero && !enemy.isAlive()) {
Dungeon.fail( getClass() );
GLog.n( Messages.get(this, "frost_kill") );
}
} else {
enemy.sprite.showStatus( CharSprite.NEUTRAL, enemy.defenseVerb() );
}
}
public static void saveLevel(Bundle bundle){
bundle.put("BloodBatLevel", level);
}
public static void loadLevel(Bundle bundle){
level = bundle.getInt("BloodBatLevel");
}
@Override
public int damageRoll() {
if (Dungeon.hero.isSubclass(HeroSubClass.ASSASSIN)){
int i = Random.NormalIntRange(0, level * 2);
if (enemy.buff(Marked.class) != null) i *= enemy.buff(Marked.class).bonusDamage();
return i;
}
return Random.NormalIntRange( level, 1 + level * 2 );
}
@Override
public float attackDelay() {
return super.attackDelay() * (Dungeon.hero.isSubclass(HeroSubClass.ASSASSIN) ? 0.33f : 0.5f);
}
@Override
public int attackSkill(Char target) {
return 4 + level * 2;
}
@Override
public int attackProc(Char enemy, int damage) {
if(level >= 2){
zap();
} else {
if (Dungeon.hero.isSubclass(HeroSubClass.ASSASSIN)) Buff.affect(enemy, Marked.class).stack++;
}
return super.attackProc(enemy, damage);
}
@Override
protected Char chooseEnemy() {
Char enemy = super.chooseEnemy();
int targetPos = Dungeon.hero.pos;
int distance = Dungeon.hero.isSubclass(HeroSubClass.ASSASSIN) ? 99999 : 8;
//will never attack something far from their target
if (enemy != null
&& Dungeon.level.mobs.contains(enemy)
&& (Dungeon.level.distance(enemy.pos, targetPos) <= distance)){
((Mob)enemy).aggro(this);
return enemy;
}
return null;
}
public static void updateHP(){
level += 1;
if (Dungeon.level != null) {
for (Mob mob : Dungeon.level.mobs.toArray(new Mob[0])) {
if (mob instanceof BloodBat) {
mob.HP = mob.HT = 18 + level * 2;
((BloodBat) mob).defenseSkill = 3 + level * 2;
}
}
}
}
@Override
public void damage(int dmg, Object src) {
super.damage(dmg, src);
Buff.affect(Dungeon.hero, ArtifactRecharge.class).prolong(dmg*2);
}
@Override
public void die(Object cause) {
super.die(cause);
Buff.affect(Dungeon.hero, BloodBatRecharge.class, 800f);
}
private class Wandering extends Mob.Wandering {
@Override
public boolean act( boolean enemyInFOV, boolean justAlerted ) {
if ( enemyInFOV ) {
enemySeen = true;
notice();
alerted = true;
state = HUNTING;
target = enemy.pos;
} else {
enemySeen = false;
int oldPos = pos;
target = Dungeon.hero.pos;
//always move towards the hero when wandering
if (getCloser( target )) {
spend( 1 / speed() );
return moveSprite( oldPos, pos );
} else {
spend( TICK );
}
}
return true;
}
}
protected boolean doAttack( Char enemy ) {
if (Dungeon.level.adjacent( pos, enemy.pos )) {
return super.doAttack( enemy );
} else {
if (sprite != null && (sprite.visible || enemy.sprite.visible)) {
sprite.zap( enemy.pos );
return false;
} else {
zap();
return true;
}
}
}
public static class BloodBatRecharge extends FlavourBuff {
public static final float DURATION = 800f;
{
type = buffType.NEGATIVE;
announced = true;
}
@Override
public int icon() {
return BuffIndicator.TIME;
}
@Override
public void tintIcon(Image icon) {
icon.tint(0, 0, 0, 0.05f);
}
@Override
public float iconFadePercent() {
return Math.max(0, (DURATION - visualcooldown()) / DURATION);
}
@Override
public String toString() {
return Messages.get(this, "name");
}
@Override
public String desc() {
return Messages.get(this, "desc", dispTurns());
}
}
}

View File

@ -570,7 +570,7 @@ public class DimandKing extends Boss {
}
}
public static class DKWarlock extends DimandMimic {
public static class DKWarlock extends SRPDHBLR {
{
state = HUNTING;
immunities.add(Corruption.class);

View File

@ -47,7 +47,7 @@ import com.shatteredpixel.shatteredpixeldungeon.items.armor.glyphs.Viscosity;
import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.DriedRose;
import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.LloydsBeacon;
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfTeleportation;
import com.shatteredpixel.shatteredpixeldungeon.levels.CityBossLevel;
import com.shatteredpixel.shatteredpixeldungeon.levels.NewCityBossLevel;
import com.shatteredpixel.shatteredpixeldungeon.mechanics.Ballistica;
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
@ -55,7 +55,6 @@ import com.shatteredpixel.shatteredpixeldungeon.sprites.CharSprite;
import com.shatteredpixel.shatteredpixeldungeon.sprites.KingSprite;
import com.shatteredpixel.shatteredpixeldungeon.ui.BossHealthBar;
import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIndicator;
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
import com.watabou.noosa.audio.Sample;
import com.watabou.noosa.particles.Emitter;
import com.watabou.utils.Bundle;
@ -138,7 +137,7 @@ public class DwarfKing extends Mob {
@Override
protected boolean act() {
if (pos == CityBossLevel.throne){
if (pos == NewCityBossLevel.throne){
throwItems();
}
@ -312,7 +311,7 @@ public class DwarfKing extends Mob {
private boolean summonSubject( int delay, Class<?extends Mob> type ){
Summoning s = new Summoning();
s.pos = ((CityBossLevel)Dungeon.level).getSummoningPos();
s.pos = ((NewCityBossLevel)Dungeon.level).getSummoningPos();
if (s.pos == -1) return false;
s.summon = type;
s.delay = delay;
@ -460,7 +459,7 @@ public class DwarfKing extends Mob {
if (HP <= (Dungeon.isChallenged(Challenges.STRONGER_BOSSES) ? 100 : 50)) {
HP = (Dungeon.isChallenged(Challenges.STRONGER_BOSSES) ? 100 : 50);
sprite.showStatus(CharSprite.POSITIVE, Messages.get(this, "invulnerable"));
ScrollOfTeleportation.appear(this, CityBossLevel.throne);
ScrollOfTeleportation.appear(this, NewCityBossLevel.throne);
properties.add(Property.IMMOVABLE);
phase = 2;
summonsMade = 0;

View File

@ -3,7 +3,7 @@
* Copyright (C) 2012-2015 Oleg Dolya
*
* Shattered Pixel Dungeon
* Copyright (C) 2014-2022 Evan Debenham
* Copyright (C) 2014-2019 Evan Debenham
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -24,24 +24,28 @@ package com.shatteredpixel.shatteredpixeldungeon.items.artifacts;
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.buffs.Barrier;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.LockedFloor;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Preparation;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.HeroSubClass;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Talent;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.BloodBat;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob;
import com.shatteredpixel.shatteredpixeldungeon.effects.Speck;
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
import com.shatteredpixel.shatteredpixeldungeon.items.bags.Bag;
import com.shatteredpixel.shatteredpixeldungeon.items.rings.RingOfEnergy;
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
import com.shatteredpixel.shatteredpixeldungeon.sprites.CharSprite;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIndicator;
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
import com.watabou.noosa.audio.Sample;
import com.watabou.noosa.tweeners.AlphaTweener;
import com.watabou.utils.Bundle;
import com.watabou.utils.Callback;
import com.watabou.utils.PathFinder;
import com.watabou.utils.Random;
import java.util.ArrayList;
@ -53,9 +57,9 @@ public class CloakOfShadows extends Artifact {
exp = 0;
levelCap = 10;
charge = Math.min(level()+3, 10);
charge = level()+3;
partialCharge = 0;
chargeCap = Math.min(level()+3, 10);
chargeCap = level()+3;
defaultAction = AC_STEALTH;
@ -63,15 +67,27 @@ public class CloakOfShadows extends Artifact {
bones = false;
}
private boolean stealthed = false;
public static final String AC_STEALTH = "STEALTH";
public static final String AC_BloodBat = "BloodBat";
@Override
public ArrayList<String> actions( Hero hero ) {
ArrayList<String> actions = super.actions( hero );
if ((isEquipped( hero ) || hero.hasTalent(Talent.LIGHT_CLOAK))
&& !cursed && (charge > 0 || activeBuff != null)) {
if (isEquipped( hero ) && !cursed && (charge > 0 || stealthed))
actions.add(AC_STEALTH);
boolean needToSpawn = true;
for (Mob mob : Dungeon.level.mobs.toArray( new Mob[0] )) {
if (mob instanceof BloodBat) {
needToSpawn = false;
break;
}
}
if (needToSpawn) {
if (hero.buff(BloodBat.BloodBatRecharge.class) != null) needToSpawn = false;
}
if (needToSpawn) actions.add(AC_BloodBat);
return actions;
}
@ -82,35 +98,65 @@ public class CloakOfShadows extends Artifact {
if (action.equals( AC_STEALTH )) {
if (activeBuff == null){
if (!isEquipped(hero) && !hero.hasTalent(Talent.LIGHT_CLOAK)) GLog.i( Messages.get(Artifact.class, "need_to_equip") );
if (!stealthed){
if (!isEquipped(hero)) GLog.i( Messages.get(Artifact.class, "need_to_equip") );
else if (cursed) GLog.i( Messages.get(this, "cursed") );
else if (charge <= 0) GLog.i( Messages.get(this, "no_charge") );
else {
stealthed = true;
hero.spend( 1f );
hero.busy();
Sample.INSTANCE.play(Assets.Sounds.MELD);
activeBuff = activeBuff();
activeBuff.attachTo(hero);
Talent.onArtifactUsed(Dungeon.hero);
if (hero.sprite.parent != null) {
hero.sprite.parent.add(new AlphaTweener(hero.sprite, 0.4f, 0.4f));
} else {
hero.sprite.alpha(0.4f);
}
hero.sprite.operate(hero.pos);
}
} else {
stealthed = false;
activeBuff.detach();
activeBuff = null;
if (hero.invisible <= 0 && hero.buff(Preparation.class) != null){
hero.buff(Preparation.class).detach();
}
hero.spend( 1f );
hero.sprite.operate( hero.pos );
}
} else if (action.equals(AC_BloodBat)){
hero.sprite.operate(hero.pos, new Callback() {
@Override
public void call() {
ArrayList<Integer> respawnPoints = new ArrayList<>();
for (int i = 0; i < PathFinder.NEIGHBOURS8.length; i++) {
int p = hero.pos + PathFinder.NEIGHBOURS8[i];
if (Actor.findChar( p ) == null && Dungeon.level.passable[p]) {
respawnPoints.add( p );
}
}
if (respawnPoints.size() > 0){
BloodBat bat = new BloodBat();
bat.pos = respawnPoints.get(Random.index( respawnPoints ));
bat.HP = bat.HT = 18 + BloodBat.level * 2;
((BloodBat) bat).defenseSkill = 4 + BloodBat.level*2;
bat.state = bat.WANDERING;
GameScene.add(bat);
bat.sprite.emitter().burst(Speck.factory(Speck.STAR), 10);
hero.sprite.idle();
}
}
});
}
}
@Override
public void activate(Char ch){
super.activate(ch);
if (activeBuff != null && activeBuff.target == null){
if (stealthed){
activeBuff = activeBuff();
activeBuff.attachTo(ch);
}
}
@ -118,46 +164,12 @@ public class CloakOfShadows extends Artifact {
@Override
public boolean doUnequip(Hero hero, boolean collect, boolean single) {
if (super.doUnequip(hero, collect, single)){
if (!collect || !hero.hasTalent(Talent.LIGHT_CLOAK)){
if (activeBuff != null){
activeBuff.detach();
activeBuff = null;
}
} else {
activate(hero);
}
stealthed = false;
return true;
} else
return false;
}
@Override
public boolean collect( Bag container ) {
if (super.collect(container)){
if (container.owner instanceof Hero
&& passiveBuff == null
&& ((Hero) container.owner).hasTalent(Talent.LIGHT_CLOAK)){
activate((Hero) container.owner);
}
return true;
} else{
return false;
}
}
@Override
protected void onDetach() {
if (passiveBuff != null){
passiveBuff.detach();
passiveBuff = null;
}
if (activeBuff != null && !isEquipped((Hero) activeBuff.target)){
activeBuff.detach();
activeBuff = null;
}
}
@Override
protected ArtifactBuff passiveBuff() {
return new cloakRecharge();
@ -167,7 +179,7 @@ public class CloakOfShadows extends Artifact {
protected ArtifactBuff activeBuff( ) {
return new cloakStealth();
}
@Override
public void charge(Hero target, float amount) {
if (charge < chargeCap) {
@ -181,55 +193,52 @@ public class CloakOfShadows extends Artifact {
}
}
@Override
public int value() {
return 0;
}
public void overCharge(int amount){
charge = Math.min(charge+amount, chargeCap+amount);
updateQuickslot();
}
@Override
public Item upgrade() {
chargeCap = Math.min(chargeCap + 1, 10);
chargeCap = chargeCap+1;
return super.upgrade();
}
private static final String STEALTHED = "stealthed";
private static final String BUFF = "buff";
@Override
public void storeInBundle( Bundle bundle ) {
super.storeInBundle(bundle);
if (activeBuff != null) bundle.put(BUFF, activeBuff);
bundle.put( STEALTHED, stealthed );
}
@Override
public void restoreFromBundle( Bundle bundle ) {
super.restoreFromBundle(bundle);
if (bundle.contains(BUFF)){
activeBuff = new cloakStealth();
activeBuff.restoreFromBundle(bundle.getBundle(BUFF));
}
stealthed = bundle.getBoolean( STEALTHED );
}
@Override
public int value() {
return 0;
}
public class cloakRecharge extends ArtifactBuff{
@Override
public boolean act() {
if (charge < chargeCap) {
LockedFloor lock = target.buff(LockedFloor.class);
if (activeBuff == null && (lock == null || lock.regenOn())) {
if (!stealthed && (lock == null || lock.regenOn())) {
float missing = (chargeCap - charge);
if (level() > 7) missing += 5*(level() - 7)/3f;
float turnsToCharge = (45 - missing);
turnsToCharge /= RingOfEnergy.artifactChargeMultiplier(target);
float chargeToGain = (1f / turnsToCharge);
if (!isEquipped(Dungeon.hero)){
chargeToGain *= 0.75f*Dungeon.hero.pointsInTalent(Talent.LIGHT_CLOAK)/3f;
if (turnsToCharge <= 0) {
turnsToCharge = 1 / (missing - 44);
}
partialCharge += chargeToGain;
turnsToCharge /= RingOfEnergy.artifactChargeMultiplier(target);
if (turnsToCharge <= 0) turnsToCharge = 1;
partialCharge += (1f / turnsToCharge);
}
if (partialCharge >= 1) {
@ -256,11 +265,11 @@ public class CloakOfShadows extends Artifact {
}
public class cloakStealth extends ArtifactBuff{
{
type = buffType.POSITIVE;
}
int turnsToCost = 0;
@Override
@ -270,45 +279,23 @@ public class CloakOfShadows extends Artifact {
@Override
public float iconFadePercent() {
return (4f - turnsToCost) / 4f;
}
@Override
public String iconTextDisplay() {
return Integer.toString(turnsToCost);
return (5f - turnsToCost) / 5f;
}
@Override
public boolean attachTo( Char target ) {
if (super.attachTo( target )) {
target.invisible++;
if (target instanceof Hero && ((Hero) target).subClass == HeroSubClass.ASSASSIN){
Buff.affect(target, Preparation.class);
}
return true;
} else {
return false;
}
}
float barrierInc = 0.5f;
@Override
public boolean act(){
turnsToCost--;
//barrier every 2/1 turns, to a max of 3/5
if (((Hero)target).hasTalent(Talent.PROTECTIVE_SHADOWS)){
Barrier barrier = Buff.affect(target, Barrier.class);
if (barrier.shielding() < 1 + 2*((Hero)target).pointsInTalent(Talent.PROTECTIVE_SHADOWS)) {
barrierInc += 0.5f * ((Hero) target).pointsInTalent(Talent.PROTECTIVE_SHADOWS);
}
if (barrierInc >= 1 ){
barrierInc = 0;
barrier.incShield(1);
}
}
if (turnsToCost <= 0){
charge--;
if (charge < 0) {
@ -328,14 +315,14 @@ public class CloakOfShadows extends Artifact {
} else {
exp += Math.round(10f * Math.pow(0.75f, -lvlDiffFromTarget));
}
if (exp >= (level() + 1) * 50 && level() < levelCap) {
upgrade();
exp -= level() * 50;
GLog.p(Messages.get(this, "levelup"));
}
turnsToCost = 4;
turnsToCost = 5;
}
updateQuickslot();
}
@ -350,6 +337,11 @@ public class CloakOfShadows extends Artifact {
detach();
}
public void dispelAssassin(){
updateQuickslot();
charge = Math.min(0, charge - 2);
}
@Override
public void fx(boolean on) {
if (on) target.sprite.add( CharSprite.State.INVISIBLE );
@ -368,31 +360,28 @@ public class CloakOfShadows extends Artifact {
@Override
public void detach() {
activeBuff = null;
if (target.invisible > 0) target.invisible--;
if (target.invisible > 0)
target.invisible--;
stealthed = false;
updateQuickslot();
super.detach();
}
private static final String TURNSTOCOST = "turnsToCost";
private static final String BARRIER_INC = "barrier_inc";
@Override
public void storeInBundle(Bundle bundle) {
super.storeInBundle(bundle);
bundle.put( TURNSTOCOST , turnsToCost);
bundle.put( BARRIER_INC, barrierInc);
}
@Override
public void restoreFromBundle(Bundle bundle) {
super.restoreFromBundle(bundle);
turnsToCost = bundle.getInt( TURNSTOCOST );
barrierInc = bundle.getFloat( BARRIER_INC );
}
}
}

View File

@ -109,7 +109,7 @@ public class SummonElemental extends Spell {
GameScene.add( elemental );
Buff.affect(elemental, InvisAlly.class);
elemental.setSummonedALly();
elemental.HP = elemental.HT;
elemental.HP = elemental.HT = 20;
ScrollOfTeleportation.appear( elemental, Random.element(spawnPoints) );
curUser.spendAndNext(Actor.TICK);

View File

@ -184,7 +184,7 @@ public class SpiritBow extends Weapon {
@Override
public int min(int lvl) {
int dmg = 1 + Dungeon.hero.lvl/5
int dmg = 4 + Dungeon.hero.lvl/5
+ RingOfSharpshooting.levelDamageBonus(Dungeon.hero)
+ (curseInfusionBonus ? 1 + Dungeon.hero.lvl/30 : 0);
return Math.max(0, dmg);
@ -192,7 +192,7 @@ public class SpiritBow extends Weapon {
@Override
public int max(int lvl) {
int dmg = 6 + (int)(Dungeon.hero.lvl/2.5f)
int dmg = 9 + (int)(Dungeon.hero.lvl/2.5f)
+ 2*RingOfSharpshooting.levelDamageBonus(Dungeon.hero)
+ (curseInfusionBonus ? 2 + Dungeon.hero.lvl/15 : 0);
return Math.max(0, dmg);

View File

@ -21,6 +21,8 @@
package com.shatteredpixel.shatteredpixeldungeon.scenes;
import static com.shatteredpixel.shatteredpixeldungeon.Challenges.ALLBOSS;
import com.shatteredpixel.shatteredpixeldungeon.Assets;
import com.shatteredpixel.shatteredpixeldungeon.BGMPlayer;
import com.shatteredpixel.shatteredpixeldungeon.Badges;
@ -407,24 +409,49 @@ public class GameScene extends PixelScene {
case RETURN:
ScrollOfTeleportation.appear( Dungeon.hero, Dungeon.hero.pos );
break;
case DESCEND:
case FALL:
switch (Dungeon.depth) {
case 1:
WndStory.showChapter( WndStory.ID_SEWERS );
break;
case 6:
WndStory.showChapter( WndStory.ID_PRISON );
break;
case 11:
WndStory.showChapter( WndStory.ID_CAVES );
break;
case 16:
WndStory.showChapter( WndStory.ID_CITY );
break;
case 21:
WndStory.showChapter( WndStory.ID_HALLS );
break;
case DESCEND:
if (Dungeon.isChallenged(ALLBOSS)){
switch (Dungeon.depth) {
case 0:
WndStory.showChapter( WndStory.ID_GAME );
case 3:
WndStory.showChapter( WndStory.ID_DM920 );
}
} else {
switch (Dungeon.depth) {
case 0:
WndStory.showChapter( WndStory.ID_FOREST );
break;
case 1:
WndStory.showChapter( WndStory.ID_SEWERS );
break;
case 5:
WndStory.showChapter( WndStory.ID_SEWERSBOSS );
break;
case 6:
WndStory.showChapter( WndStory.ID_PRISON );
break;
case 11:
WndStory.showChapter( WndStory.ID_CAVES );
break;
case 16:
WndStory.showChapter( WndStory.ID_CITY );
break;
case 20:
if((Statistics.boss_enhance & 0x8) != 0) WndStory.showChapter( WndStory.ID_DWADA );
else WndStory.showChapter( WndStory.ID_CITYSBOSS );
break;
case 21:
WndStory.showChapter( WndStory.ID_HALLS );
break;
case 25:
WndStory.showChapter( WndStory.ID_HALLSBOOS );
break;
case 26:
WndStory.showChapter( WndStory.ID_CHAPTONEEND );
break;
}
}
if (Dungeon.hero.isAlive()) {
Badges.validateNoKilling();

View File

@ -0,0 +1,97 @@
/*
* 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.sprites;
import com.shatteredpixel.shatteredpixeldungeon.Assets;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.BloodBat;
import com.shatteredpixel.shatteredpixeldungeon.effects.MagicMissile;
import com.watabou.noosa.TextureFilm;
import com.watabou.noosa.audio.Sample;
import com.watabou.utils.Callback;
public class BlueBatSprite extends MobSprite {
public void zap( int cell ) {
turnTo( ch.pos , cell );
play( zap );
MagicMissile.boltFromChar( parent,
MagicMissile.FROST,
this,
cell,
new Callback() {
@Override
public void call() {
((BloodBat)ch).onZapComplete();
}
} );
Sample.INSTANCE.play( Assets.Sounds.ZAP );
}
public BlueBatSprite() {
super();
texture( Assets.Sprites.BBAT );
TextureFilm frames = new TextureFilm( texture, 15, 15 );
idle = new Animation( 8, true );
idle.frames( frames, 0, 1 );
run = new Animation( 12, true );
run.frames( frames, 0, 1 );
attack = new Animation( 12, false );
attack.frames( frames, 2, 3, 0, 1 );
die = new Animation( 12, false );
die.frames( frames, 4, 5, 6 );
play( idle );
}
public static class BatEDSprite extends MobSprite {
public BatEDSprite() {
super();
texture(Assets.Sprites.BATEX);
TextureFilm frames = new TextureFilm(texture, 15, 15);
idle = new Animation(8, true);
idle.frames(frames, 0, 1);
run = new Animation(12, true);
run.frames(frames, 0, 1);
attack = new Animation(12, false);
attack.frames(frames, 2, 3, 0, 1);
die = new Animation(12, false);
die.frames(frames, 4, 5, 6);
play(idle);
}
}
}

View File

@ -3,6 +3,7 @@ package com.shatteredpixel.shatteredpixeldungeon.ui.changelist.mlpd;
import com.shatteredpixel.shatteredpixeldungeon.Assets;
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
import com.shatteredpixel.shatteredpixeldungeon.scenes.ChangesScene;
import com.shatteredpixel.shatteredpixeldungeon.sprites.BlueBatSprite;
import com.shatteredpixel.shatteredpixeldungeon.sprites.FlameBoiSprite;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSprite;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
@ -17,9 +18,48 @@ import java.util.ArrayList;
public class vM0_6_7_X_Changes {
public static void addAllChanges(ArrayList<ChangeInfo> changeInfos) {
add_v0_6_1_Changes(changeInfos);
add_v0_6_0_Changes(changeInfos);
}
public static void add_v0_6_1_Changes( ArrayList<ChangeInfo> changeInfos ) {
ChangeInfo changes = new ChangeInfo("v0.6.0.0-BetaXV", 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 BlueBatSprite(), ("血影蝙蝠"),
("极影铃虹的宠物,为主人而战")));
changes = new ChangeInfo("改动", false, null);
changes.hardlight(Window.SKYBULE_COLOR);
changeInfos.add(changes);
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_06X21")));
changes = new ChangeInfo("调整", false, null);
changes.hardlight(Window.CYELLOW);
changeInfos.add(changes);
changes.addButton(new ChangeButton(new ItemSprite(ItemSpriteSheet.SPIRIT_ARROW), ("女猎初始改动"),
("灵能短弓伤害面板从1-6提升到4-9,成长系数不变")));
changes.addButton(new ChangeButton(new ItemSprite(ItemSpriteSheet.WAND_FROST), ("法师初始改动"),
("茉莉伊洛是双属性的魔法少女拥有强大的魔力她将会把烈焰法杖和冰雪法杖幻化到快捷栏里这两个法杖不能升级不能灌注但是开局随机0-2级。\n\n且一旦替换幻化的快捷栏将消失。\n\n" +
"低语:错误的选择将让你万劫不复的,茉莉!")));
changes.addButton(new ChangeButton(new ItemSprite(ItemSpriteSheet.SUMMON_ELE), ("战士初始改动"),
("蕾零安洁虽然本身没有魔力,但家族世世代代都在研究一种高超的技术,这项技术足以让她在地牢里面有冒险的资本。\n\n使用战士将追加2个唤魔晶柱")));
changes.addButton(new ChangeButton(new BlueBatSprite(), ("盗贼初始改动"),
("极影铃虹的潜能非常强大,她的小蝙蝠经常与她为伴。\n\n盗贼将在开局追加一个小蝙蝠。")));
}
public static void add_v0_6_0_Changes( ArrayList<ChangeInfo> changeInfos ) {
ChangeInfo changes = new ChangeInfo("v0.6.0.0-BetaX", true, "");
changes.hardlight(Window.TITLE_COLOR);

View File

@ -3,7 +3,7 @@
* Copyright (C) 2012-2015 Oleg Dolya
*
* Shattered Pixel Dungeon
* Copyright (C) 2014-2022 Evan Debenham
* Copyright (C) 2014-2021 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
@ -35,39 +35,63 @@ import com.watabou.utils.SparseArray;
public class WndStory extends Window {
private static final int WIDTH_P = 125;
private static final int WIDTH_L = 160;
private static final int MARGIN = 2;
private static final float bgR = 0.77f;
private static final float bgG = 0.73f;
private static final float bgB = 0.62f;
public static final int ID_FOREST = -1;
public static final int ID_SEWERS = 0;
public static final int ID_PRISON = 1;
public static final int ID_CAVES = 2;
public static final int ID_CITY = 3;
public static final int ID_HALLS = 4;
public static final int ID_SEWERSBOSS = 5;
public static final int ID_PRISONBOSS = 6;
public static final int ID_CAVESBOSS = 7;
public static final int ID_CITYSBOSS = 8;
public static final int ID_HALLSBOOS = 9;
public static final int ID_CHAPTONEEND = 10;
public static final int ID_ICEBOSS = 11;
public static final int ID_GAME = 12;
public static final int ID_DM920 = 12;
public static final int ID_DWADA = 13;
private static final SparseArray<String> CHAPTERS = new SparseArray<>();
static {
CHAPTERS.put( ID_FOREST, "forest" );
CHAPTERS.put( ID_SEWERS, "sewers" );
CHAPTERS.put( ID_PRISON, "prison" );
CHAPTERS.put( ID_CAVES, "caves" );
CHAPTERS.put( ID_CITY, "city" );
CHAPTERS.put( ID_HALLS, "halls" );
CHAPTERS.put( ID_SEWERSBOSS, "sewersboss" );
CHAPTERS.put( ID_PRISONBOSS, "prisonboss" );
CHAPTERS.put( ID_CAVESBOSS, "cavesboss" );
CHAPTERS.put( ID_CITYSBOSS, "cityboss" );
CHAPTERS.put( ID_HALLSBOOS, "hallsboss" );
CHAPTERS.put( ID_CHAPTONEEND, "new" );
CHAPTERS.put( ID_ICEBOSS, "icedead" );
CHAPTERS.put( ID_GAME, "gamehappy" );
CHAPTERS.put( ID_DM920, "dm920" );
CHAPTERS.put( ID_DWADA, "drawfmaster" );
}
private IconTitle ttl;
private RenderedTextBlock tf;
private float delay;
public WndStory( String text ) {
this( null, null, text );
}
public WndStory(Image icon, String title, String text ) {
super( 0, 0, Chrome.get( Chrome.Type.SCROLL ) );
@ -81,41 +105,39 @@ public class WndStory extends Window {
add(ttl);
ttl.tfLabel.invert();
}
tf = PixelScene.renderTextBlock( text, 6 );
tf.maxWidth(width);
tf.invert();
tf.setPos(MARGIN, y);
add( tf );
PointerArea blocker = new PointerArea( 0, 0, PixelScene.uiCamera.width, PixelScene.uiCamera.height ) {
add( new PointerArea( chrome ) {
@Override
protected void onClick( PointerEvent event ) {
onBackPressed();
hide();
}
};
blocker.camera = PixelScene.uiCamera;
add(blocker);
} );
resize( (int)(tf.width() + MARGIN * 2), (int)Math.min( tf.bottom()+MARGIN, 180 ) );
}
@Override
public void update() {
super.update();
if (delay > 0 && (delay -= Game.elapsed) <= 0) {
shadow.visible = chrome.visible = tf.visible = true;
if (ttl != null) ttl.visible = true;
}
}
public static void showChapter( int id ) {
if (Dungeon.chapters.contains( id )) {
return;
}
String text = Messages.get(WndStory.class, CHAPTERS.get( id ));
if (text != null) {
WndStory wnd = new WndStory( text );
@ -123,9 +145,9 @@ public class WndStory extends Window {
wnd.shadow.visible = wnd.chrome.visible = wnd.tf.visible = false;
if (wnd.ttl != null) wnd.ttl.visible = false;
}
Game.scene().add( wnd );
Dungeon.chapters.add( id );
}
}

View File

@ -24,6 +24,9 @@ package com.shatteredpixel.shatteredpixeldungeon.windows;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.ShopGuardDead;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.ImpShopkeeper;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.Nxhy;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.Shopkeeper;
import com.shatteredpixel.shatteredpixeldungeon.items.EquipableItem;
import com.shatteredpixel.shatteredpixeldungeon.items.Gold;
@ -31,6 +34,7 @@ import com.shatteredpixel.shatteredpixeldungeon.items.Heap;
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.MasterThievesArmband;
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSprite;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
import com.shatteredpixel.shatteredpixeldungeon.ui.RedButton;
@ -128,6 +132,30 @@ public class WndTradeItem extends WndInfoItem {
pos = btnBuy.bottom();
RedButton btnStole = new RedButton( Messages.get(this, "stole", price) ) {
@Override
protected void onClick() {
hide();
for (Mob mob : Dungeon.level.mobs) {
if (mob instanceof Shopkeeper) {
GameScene.show(new WndGoShop(this));
break;
} else if (mob instanceof Nxhy) {
mob.yell(Messages.get(mob, "why"));
break;
}else if (mob instanceof ImpShopkeeper) {
mob.yell(Messages.get(mob, "why"));
break;
}
}
}
};
btnStole.setRect( 0, pos + GAP, width, BTN_HEIGHT );
btnStole.icon(new ShopGuardDead.ShopGuardianRedSprite());
add( btnStole );
pos = btnStole.bottom();
final MasterThievesArmband.Thievery thievery = Dungeon.hero.buff(MasterThievesArmband.Thievery.class);
if (thievery != null && !thievery.isCursed() && thievery.chargesToUse(item) > 0) {
final float chance = thievery.stealChance(item);