Add Beta21-p1.8
All Commit
This commit is contained in:
parent
4709a3dbed
commit
9654542d1f
Binary file not shown.
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
|
@ -1,3 +1,11 @@
|
||||||
|
###SPD1.3
|
||||||
|
text.herostat.item_wnd_depth = 层数:
|
||||||
|
text.herostat.item_wnd_mimic = 宝箱怪:
|
||||||
|
text.herostat.item_wnd_reward = 任务:
|
||||||
|
text.herostat.item_wnd_cursed = 诅咒的
|
||||||
|
text.herostat.item_basic = 常规:
|
||||||
|
text.herostat.item_enter = 查看物品生成
|
||||||
|
|
||||||
###MLPD
|
###MLPD
|
||||||
actors.mobs.bosses.crossdiedtower.dead=控制目标已丢失,已自动摧毁……
|
actors.mobs.bosses.crossdiedtower.dead=控制目标已丢失,已自动摧毁……
|
||||||
actors.mobs.bosses.crossdiedtower.name=激光十字晶柱
|
actors.mobs.bosses.crossdiedtower.name=激光十字晶柱
|
||||||
|
|
|
@ -6,10 +6,6 @@ items.bombs.laserpython.name=激光十字晶柱召唤器
|
||||||
items.bombs.laserpython.desc=这枚召唤器会在爆炸后立刻生成一个十字晶柱。
|
items.bombs.laserpython.desc=这枚召唤器会在爆炸后立刻生成一个十字晶柱。
|
||||||
items.bombs.laserpython.didnot_pick=你无法拾取该物品……
|
items.bombs.laserpython.didnot_pick=你无法拾取该物品……
|
||||||
|
|
||||||
items.weapon.melee.endingblade.ac_lastcrystal=Γ激光晶柱Γ
|
|
||||||
items.weapon.melee.endingblade.ac_diedghost=✦死亡宣告✦
|
|
||||||
items.weapon.melee.endingblade.ac_healreset=_亡者归来_
|
|
||||||
|
|
||||||
items.artifacts.wraithamulet.name=暗金宝石护符
|
items.artifacts.wraithamulet.name=暗金宝石护符
|
||||||
items.artifacts.wraithamulet.desc=来自于异世界的产物,能使自己进入虚无化。当护符能量足够多的时候,你还可以对敌人实行一次暗夜袭击,护符能量将会随着时间自动恢复。\n\n这个护符是证明给强者之人用的,冰雪魔女已经输的心服口服,现在她将此护身符给予给你。
|
items.artifacts.wraithamulet.desc=来自于异世界的产物,能使自己进入虚无化。当护符能量足够多的时候,你还可以对敌人实行一次暗夜袭击,护符能量将会随着时间自动恢复。\n\n这个护符是证明给强者之人用的,冰雪魔女已经输的心服口服,现在她将此护身符给予给你。
|
||||||
items.artifacts.wraithamulet.ac_ghost=遁入虚无
|
items.artifacts.wraithamulet.ac_ghost=遁入虚无
|
||||||
|
@ -95,9 +91,14 @@ items.quest.skeletongold.wow=染血金币发出诡异的光芒,你感到下层
|
||||||
|
|
||||||
items.weapon.melee.endingblade.name=终焉
|
items.weapon.melee.endingblade.name=终焉
|
||||||
items.weapon.melee.endingblade.desc=不知道从哪来的一个拆开的场记板,貌似沾染了焰之诅咒,会随机产生_一种诅咒_,有着强大的侵蚀能力,一旦装备了它就无法脱身了……\n\n这个武器在攻击敌人的时候能吸收一定的浊焰能量,在汲取一定的浊焰能量后会产生新的能力以及自我升级。\n\n当前的浊焰能量:
|
items.weapon.melee.endingblade.desc=不知道从哪来的一个拆开的场记板,貌似沾染了焰之诅咒,会随机产生_一种诅咒_,有着强大的侵蚀能力,一旦装备了它就无法脱身了……\n\n这个武器在攻击敌人的时候能吸收一定的浊焰能量,在汲取一定的浊焰能量后会产生新的能力以及自我升级。\n\n当前的浊焰能量:
|
||||||
|
items.weapon.melee.endingblade.desc_2=\n\n死亡宣告当前冷却值为:
|
||||||
items.weapon.melee.endingblade.cursed=当你装备上这个武器后,一股无形的力量将你束缚住……
|
items.weapon.melee.endingblade.cursed=当你装备上这个武器后,一股无形的力量将你束缚住……
|
||||||
items.weapon.melee.endingblade.donot_eqip=终焉的诅咒已经浸染你的身体,你无力脱下它。
|
items.weapon.melee.endingblade.donot_eqip=终焉的诅咒已经浸染你的身体,你无力脱下它。
|
||||||
|
|
||||||
|
items.weapon.melee.endingblade.ac_lastcrystal=Γ激光晶柱Γ
|
||||||
|
items.weapon.melee.endingblade.ac_diedghost=✦死亡宣告✦
|
||||||
|
items.weapon.melee.endingblade.ac_healreset=_亡者归来_
|
||||||
|
|
||||||
#MLPDSTOREYBOOKS
|
#MLPDSTOREYBOOKS
|
||||||
|
|
||||||
items.books.bookslist.hellfirebooks.name=《浊焰事件》
|
items.books.bookslist.hellfirebooks.name=《浊焰事件》
|
||||||
|
|
|
@ -67,6 +67,10 @@ badges$badge.games_played_3=进行250场游戏
|
||||||
badges$badge.games_played_4=进行1000场游戏
|
badges$badge.games_played_4=进行1000场游戏
|
||||||
badges$badge.godd_make=老人与海\n累计完成老杖匠的全部任务\n\n_奖励:0层随机戒指(四大基座上)_
|
badges$badge.godd_make=老人与海\n累计完成老杖匠的全部任务\n\n_奖励:0层随机戒指(四大基座上)_
|
||||||
badges$badge.clear_water=净化大师\n完成挑战:污泥浊水\n\n_奖励:敬请期待_
|
badges$badge.clear_water=净化大师\n完成挑战:污泥浊水\n\n_奖励:敬请期待_
|
||||||
|
|
||||||
|
badges$badge.ghostdage=幽灵大哥\n_在幽灵处获得一次+4品质武器或护甲\n\n_(镀层需求:+5品质武器)
|
||||||
|
//badges$badge.ghostdage=幽灵大哥\n在幽灵处获得一次_+5_品质武器或护甲\n\nΞ你已成功镀层Ξ
|
||||||
|
|
||||||
badges$badge.halofire_died=死于磷火烈焰
|
badges$badge.halofire_died=死于磷火烈焰
|
||||||
badges$badge.happy_end=幸福结局
|
badges$badge.happy_end=幸福结局
|
||||||
badges$badge.champion_1x=开启1项挑战通关
|
badges$badge.champion_1x=开启1项挑战通关
|
||||||
|
|
|
@ -2,6 +2,9 @@ windows.textchallenges.seed_custom_title = 种子
|
||||||
windows.textchallenges.hint = 不输入即为随机种子
|
windows.textchallenges.hint = 不输入即为随机种子
|
||||||
windows.textchallenges.delete_seed_input = 清除
|
windows.textchallenges.delete_seed_input = 清除
|
||||||
|
|
||||||
|
windows.wndsettings$helptab.title=辅助功能
|
||||||
|
windows.wndsettings$helptab.helpsettings=启用物品生成查询器
|
||||||
|
|
||||||
windows.wndkingshop.buy=购买
|
windows.wndkingshop.buy=购买
|
||||||
windows.wndkingshop.cancel=取消
|
windows.wndkingshop.cancel=取消
|
||||||
windows.wndkingshop.king=商人领主
|
windows.wndkingshop.king=商人领主
|
||||||
|
|
|
@ -109,6 +109,7 @@ public class Badges {
|
||||||
GAMES_PLAYED_1 ( 54, true ),
|
GAMES_PLAYED_1 ( 54, true ),
|
||||||
GODD_MAKE ( 82 ),
|
GODD_MAKE ( 82 ),
|
||||||
CLEAR_WATER ( 83 ),
|
CLEAR_WATER ( 83 ),
|
||||||
|
GHOSTDAGE ( 84 ),
|
||||||
//gold
|
//gold
|
||||||
PIRANHAS ( 64 ),
|
PIRANHAS ( 64 ),
|
||||||
//these names are a bit outdated, but it doesn't really matter.
|
//these names are a bit outdated, but it doesn't really matter.
|
||||||
|
|
|
@ -686,6 +686,9 @@ public class Dungeon {
|
||||||
|
|
||||||
hero.curAction = hero.lastAction = null;
|
hero.curAction = hero.lastAction = null;
|
||||||
|
|
||||||
|
//SPD
|
||||||
|
LevelSwitchListener.onLevelSwitch();
|
||||||
|
|
||||||
observe();
|
observe();
|
||||||
try {
|
try {
|
||||||
saveAll();
|
saveAll();
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
package com.shatteredpixel.shatteredpixeldungeon;
|
||||||
|
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.custom.ch.GameTracker;
|
||||||
|
|
||||||
|
public class LevelSwitchListener {
|
||||||
|
public static void onLevelSwitch(){
|
||||||
|
GameTracker gmt = Dungeon.hero.buff(GameTracker.class);
|
||||||
|
if(gmt != null){
|
||||||
|
gmt.onNewLevel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -109,9 +109,7 @@ public class SPDSettings extends GameSettings {
|
||||||
|
|
||||||
private static final String KEY_PAGE = "page_ui";
|
private static final String KEY_PAGE = "page_ui";
|
||||||
|
|
||||||
private static final String KEY_PCUI = "pc_ui";
|
private static final String HelpSettings = "helpsettings";
|
||||||
|
|
||||||
private static final String KEY_SWAP = "quickswap";
|
|
||||||
|
|
||||||
public static void fullscreen( boolean value ) {
|
public static void fullscreen( boolean value ) {
|
||||||
put( KEY_FULLSCREEN, value );
|
put( KEY_FULLSCREEN, value );
|
||||||
|
@ -447,6 +445,14 @@ public class SPDSettings extends GameSettings {
|
||||||
return getBoolean(KEY_DARK, false);
|
return getBoolean(KEY_DARK, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void HelpSettings(boolean value) {
|
||||||
|
put( HelpSettings, value );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean HelpSettings() {
|
||||||
|
return getBoolean(HelpSettings, false);
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean ClassSkin() {
|
public static boolean ClassSkin() {
|
||||||
return getBoolean(KEY_SKIN, false);
|
return getBoolean(KEY_SKIN, false);
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
package com.shatteredpixel.shatteredpixeldungeon;
|
package com.shatteredpixel.shatteredpixeldungeon;
|
||||||
|
|
||||||
import com.watabou.utils.Bundle;
|
import com.watabou.utils.Bundle;
|
||||||
|
import com.watabou.utils.SparseArray;
|
||||||
|
|
||||||
public class Statistics {
|
public class Statistics {
|
||||||
public static int realdeepestFloor;
|
public static int realdeepestFloor;
|
||||||
|
@ -53,6 +54,15 @@ public class Statistics {
|
||||||
public static boolean fireGirlnoshopping = false;
|
public static boolean fireGirlnoshopping = false;
|
||||||
|
|
||||||
public static boolean deadshoppingdied = false;
|
public static boolean deadshoppingdied = false;
|
||||||
|
|
||||||
|
//Directly add float time will cause accuracy lose and stop timing if time is long enough
|
||||||
|
//so use long to record seconds, float to count sub-seconds.
|
||||||
|
//SPD-V1.3.2-ITEM SPAWN CODE
|
||||||
|
public static long real_seconds = 0;
|
||||||
|
public static float second_elapsed = 0;
|
||||||
|
public static float turnsPassed = 0f;
|
||||||
|
|
||||||
|
public static SparseArray<Boolean> floorsExplored = new SparseArray<>();
|
||||||
|
|
||||||
public static void reset() {
|
public static void reset() {
|
||||||
|
|
||||||
|
@ -79,6 +89,10 @@ public class Statistics {
|
||||||
fireGirlnoshopping = false;
|
fireGirlnoshopping = false;
|
||||||
|
|
||||||
deadshoppingdied = false;
|
deadshoppingdied = false;
|
||||||
|
|
||||||
|
second_elapsed = 0f;
|
||||||
|
real_seconds = 0;
|
||||||
|
turnsPassed = 0f;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,7 +122,7 @@ public class Statistics {
|
||||||
private static final String SHOPPINGDIED = "deadshoppingdied";
|
private static final String SHOPPINGDIED = "deadshoppingdied";
|
||||||
|
|
||||||
private static final String EXLEVEL = "Exlevel";
|
private static final String EXLEVEL = "Exlevel";
|
||||||
|
|
||||||
public static void storeInBundle( Bundle bundle ) {
|
public static void storeInBundle( Bundle bundle ) {
|
||||||
bundle.put( GOLD, goldCollected );
|
bundle.put( GOLD, goldCollected );
|
||||||
bundle.put( DEEPEST, deepestFloor );
|
bundle.put( DEEPEST, deepestFloor );
|
||||||
|
@ -133,6 +147,11 @@ public class Statistics {
|
||||||
bundle.put( NOSHOPPING, fireGirlnoshopping );
|
bundle.put( NOSHOPPING, fireGirlnoshopping );
|
||||||
|
|
||||||
bundle.put( SHOPPINGDIED, deadshoppingdied );
|
bundle.put( SHOPPINGDIED, deadshoppingdied );
|
||||||
|
|
||||||
|
//SPD
|
||||||
|
bundle.put("real_time_passed", second_elapsed);
|
||||||
|
bundle.put("real_seconds_passed", real_seconds);
|
||||||
|
bundle.put("turns_passed", turnsPassed);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void restoreFromBundle( Bundle bundle ) {
|
public static void restoreFromBundle( Bundle bundle ) {
|
||||||
|
@ -158,6 +177,11 @@ public class Statistics {
|
||||||
|
|
||||||
fireGirlnoshopping = bundle.getBoolean( NOSHOPPING );
|
fireGirlnoshopping = bundle.getBoolean( NOSHOPPING );
|
||||||
deadshoppingdied = bundle.getBoolean( SHOPPINGDIED );
|
deadshoppingdied = bundle.getBoolean( SHOPPINGDIED );
|
||||||
|
|
||||||
|
//SPD
|
||||||
|
second_elapsed = bundle.getFloat("real_time_passed");
|
||||||
|
real_seconds = bundle.getLong("real_seconds_passed");
|
||||||
|
turnsPassed = bundle.getFloat("turns_passed");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void preview( GamesInProgress.Info info, Bundle bundle ){
|
public static void preview( GamesInProgress.Info info, Bundle bundle ){
|
||||||
|
|
|
@ -79,6 +79,7 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Monk;
|
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Monk;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Snake;
|
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Snake;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.lb.BlackSoul;
|
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.lb.BlackSoul;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.custom.ch.GameTracker;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.effects.CellEmitter;
|
import com.shatteredpixel.shatteredpixeldungeon.effects.CellEmitter;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.effects.CheckedCell;
|
import com.shatteredpixel.shatteredpixeldungeon.effects.CheckedCell;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.effects.Speck;
|
import com.shatteredpixel.shatteredpixeldungeon.effects.Speck;
|
||||||
|
@ -494,6 +495,7 @@ public class Hero extends Char {
|
||||||
}
|
}
|
||||||
Buff.affect( this, Regeneration.class );
|
Buff.affect( this, Regeneration.class );
|
||||||
Buff.affect( this, Hunger.class );
|
Buff.affect( this, Hunger.class );
|
||||||
|
Buff.affect(this, GameTracker.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int tier() {
|
public int tier() {
|
||||||
|
|
|
@ -313,10 +313,10 @@ public class Ghost extends NPC {
|
||||||
Generator.Category c = Generator.wepTiers[wepTier - 1];
|
Generator.Category c = Generator.wepTiers[wepTier - 1];
|
||||||
weapon = (MeleeWeapon) Reflection.newInstance(c.classes[Random.chances(c.probs)]);
|
weapon = (MeleeWeapon) Reflection.newInstance(c.classes[Random.chances(c.probs)]);
|
||||||
|
|
||||||
//30%:+0, 25%:+1, 15%:+2, 10%:+3, 15%:+4, 5%+5
|
//26%:+0, 25%:+1, 15%:+2, 10%:+3, 5%:+4, 5%+5
|
||||||
float itemLevelRoll = Random.Float();
|
float itemLevelRoll = Random.Float();
|
||||||
int itemLevel;
|
int itemLevel;
|
||||||
if (itemLevelRoll < 0.1f){
|
if (itemLevelRoll < 0.74f){
|
||||||
itemLevel = 0;
|
itemLevel = 0;
|
||||||
} else if (itemLevelRoll < 0.75f){
|
} else if (itemLevelRoll < 0.75f){
|
||||||
itemLevel = 1;
|
itemLevel = 1;
|
||||||
|
|
|
@ -0,0 +1,87 @@
|
||||||
|
package com.shatteredpixel.shatteredpixeldungeon.custom.buffs;
|
||||||
|
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.custom.messages.M;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIndicator;
|
||||||
|
import com.watabou.noosa.Image;
|
||||||
|
import com.watabou.utils.Bundle;
|
||||||
|
|
||||||
|
public class AbsoluteBlindness extends Buff {
|
||||||
|
{
|
||||||
|
actPriority = VFX_PRIO;
|
||||||
|
announced = true;
|
||||||
|
type=buffType.NEGATIVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected float left=0f;
|
||||||
|
private int storedViewDistance;
|
||||||
|
@Override
|
||||||
|
public boolean act(){
|
||||||
|
spend(TICK);
|
||||||
|
if(target.viewDistance>0 && storedViewDistance != target.viewDistance){
|
||||||
|
storedViewDistance = target.viewDistance;
|
||||||
|
}
|
||||||
|
target.viewDistance = 0;
|
||||||
|
left-=1f;
|
||||||
|
if(left<0) detach();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void storeInBundle(Bundle b){
|
||||||
|
super.storeInBundle(b);
|
||||||
|
b.put("stroedVD", storedViewDistance);
|
||||||
|
b.put("blindLeft", left);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void restoreFromBundle(Bundle b){
|
||||||
|
super.restoreFromBundle(b);
|
||||||
|
storedViewDistance = b.getInt("stroedVD");
|
||||||
|
left = b.getFloat("blindLeft") + 1f;
|
||||||
|
}
|
||||||
|
//deprecate
|
||||||
|
public AbsoluteBlindness storeVD(int vd){
|
||||||
|
if(vd>0) {
|
||||||
|
storedViewDistance = vd;
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AbsoluteBlindness addLeft(float left){
|
||||||
|
this.left += left;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void detach(){
|
||||||
|
//target.viewDistance = storedViewDistance;
|
||||||
|
target.viewDistance = Dungeon.level.viewDistance;
|
||||||
|
Dungeon.observe();
|
||||||
|
super.detach();
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public int icon(){
|
||||||
|
return BuffIndicator.BLINDNESS;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void tintIcon(Image icon){
|
||||||
|
icon.hardlight(0x3366D4);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return M.L(this, "name");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String heroMessage() {
|
||||||
|
return M.L(this, "heromsg");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String desc() {
|
||||||
|
return M.L(this, "desc");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,215 @@
|
||||||
|
package com.shatteredpixel.shatteredpixeldungeon.custom.buffs;
|
||||||
|
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.FlavourBuff;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.custom.utils.GME;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIndicator;
|
||||||
|
import com.watabou.utils.Bundle;
|
||||||
|
|
||||||
|
public class AttributeModifier extends FlavourBuff {
|
||||||
|
{
|
||||||
|
type = buffType.NEUTRAL;
|
||||||
|
announced = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float atk_m = 1f;
|
||||||
|
public float def_m = 1f;
|
||||||
|
public float acc_m = 1f;
|
||||||
|
public float eva_m = 1f;
|
||||||
|
public float dmg_m = 1f;
|
||||||
|
public float hp_m = 1f;
|
||||||
|
public float atk_l = 0f;
|
||||||
|
public float def_l = 0f;
|
||||||
|
public float acc_l = 0f;
|
||||||
|
public float eva_l = 0f;
|
||||||
|
public float dmg_l = 0f;
|
||||||
|
public float hp_l = 0f;
|
||||||
|
public int orig_HT = -1;
|
||||||
|
|
||||||
|
public void merge(AttributeModifier another){
|
||||||
|
atk_m *= another.atk_m;
|
||||||
|
def_m *= another.def_m;
|
||||||
|
acc_m *= another.acc_m;
|
||||||
|
eva_m *= another.eva_m;
|
||||||
|
dmg_m *= another.dmg_m;
|
||||||
|
hp_m *= another.hp_m;
|
||||||
|
atk_l += another.atk_l;
|
||||||
|
def_l += another.def_l;
|
||||||
|
acc_l += another.acc_l;
|
||||||
|
eva_l += another.eva_l;
|
||||||
|
dmg_l += another.dmg_l;
|
||||||
|
hp_l += another.hp_l;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int affectAtk(float attackPower){
|
||||||
|
return GME.accurateRound(attackPower * atk_m + atk_l);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int affectDef(float defensePower){
|
||||||
|
return GME.accurateRound(defensePower * def_m + def_l);
|
||||||
|
}
|
||||||
|
|
||||||
|
public float affectAcc(float accuracy){
|
||||||
|
return accuracy * acc_m + acc_l;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float affectEva(float evasion){
|
||||||
|
return evasion * eva_m + eva_l;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int affectDmg(float damage){
|
||||||
|
return GME.accurateRound(damage * dmg_m + dmg_l);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void affectHp(Char ch){
|
||||||
|
float percent = (float) ch.HP / ch.HT;
|
||||||
|
//HT of Char is bundled, need to roll back first
|
||||||
|
if(orig_HT < 0) {
|
||||||
|
orig_HT = ch.HT;
|
||||||
|
}else{
|
||||||
|
ch.HT = orig_HT;
|
||||||
|
}
|
||||||
|
ch.HT = (int)(ch.HT * hp_m + hp_l);
|
||||||
|
if(ch.HT <= 0){
|
||||||
|
ch.HT = 1;
|
||||||
|
}
|
||||||
|
ch.HP = GME.accurateRound(ch.HT * percent);
|
||||||
|
if(ch.HP <= 0){
|
||||||
|
ch.HP = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHPBack(Char ch){
|
||||||
|
float percent = (float) ch.HP / ch.HT;
|
||||||
|
ch.HT = orig_HT;
|
||||||
|
boolean alive = ch.isAlive();
|
||||||
|
ch.HP = GME.accurateRound(ch.HT * percent);
|
||||||
|
if(ch.HP <= 0 && alive) ch.HP = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AttributeModifier setAtk(float m, float l){
|
||||||
|
atk_m = m; atk_l = l;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AttributeModifier setDef(float m, float l){
|
||||||
|
def_m = m; def_l = l;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AttributeModifier setAcc(float m, float l){
|
||||||
|
acc_m = m; acc_l = l;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AttributeModifier setEva(float m, float l){
|
||||||
|
eva_m = m; eva_l = l;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AttributeModifier setDmg(float m, float l){
|
||||||
|
dmg_m = m; dmg_l = l;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AttributeModifier setHP(float m, float l){
|
||||||
|
hp_m = m; hp_l = l;
|
||||||
|
if(target != null){
|
||||||
|
affectHp(target);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AttributeModifier setAll(float[] mul, float[] add){
|
||||||
|
atk_m = mul[0];
|
||||||
|
def_m = mul[1];
|
||||||
|
acc_m = mul[2];
|
||||||
|
eva_m = mul[3];
|
||||||
|
dmg_m = mul[4];
|
||||||
|
hp_m = mul[5];
|
||||||
|
atk_l = add[0];
|
||||||
|
def_l = add[1];
|
||||||
|
acc_l = add[2];
|
||||||
|
eva_l = add[3];
|
||||||
|
dmg_l = add[4];
|
||||||
|
hp_l = add[5];
|
||||||
|
if(target != null){
|
||||||
|
affectHp(target);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean attachTo(Char target) {
|
||||||
|
for(Buff b: target.buffs()){
|
||||||
|
if(b instanceof AttributeModifier){
|
||||||
|
merge((AttributeModifier) b);
|
||||||
|
b.detach();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
boolean ret_val = super.attachTo(target);
|
||||||
|
if(ret_val){
|
||||||
|
affectHp(target);
|
||||||
|
}
|
||||||
|
return ret_val;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void detach() {
|
||||||
|
setHPBack(target);
|
||||||
|
super.detach();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int icon() {
|
||||||
|
return BuffIndicator.COMBO;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return Messages.get(this, "name");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String desc() {
|
||||||
|
return Messages.get(this, "desc", atk_m, atk_l, def_m, def_l, acc_m, acc_l, eva_m, eva_l, dmg_m, dmg_l, hp_m, hp_l, target.HP, target.HT);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void storeInBundle(Bundle bundle) {
|
||||||
|
super.storeInBundle(bundle);
|
||||||
|
bundle.put("atk_mul", atk_m);
|
||||||
|
bundle.put("def_mul", def_m);
|
||||||
|
bundle.put("acc_mul", acc_m);
|
||||||
|
bundle.put("eva_mul", eva_m);
|
||||||
|
bundle.put("dmg_mul", dmg_m);
|
||||||
|
bundle.put("hp_mul", hp_m);
|
||||||
|
bundle.put("atk_lin", atk_l);
|
||||||
|
bundle.put("def_lin", def_l);
|
||||||
|
bundle.put("acc_lin", acc_l);
|
||||||
|
bundle.put("eva_lin", eva_l);
|
||||||
|
bundle.put("dmg_lin", dmg_l);
|
||||||
|
bundle.put("hp_lin", hp_l);
|
||||||
|
bundle.put("orig_hp", orig_HT);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void restoreFromBundle(Bundle bundle) {
|
||||||
|
super.restoreFromBundle(bundle);
|
||||||
|
atk_m = bundle.getFloat("atk_mul");
|
||||||
|
def_m = bundle.getFloat("def_mul");
|
||||||
|
acc_m = bundle.getFloat("acc_mul");
|
||||||
|
eva_m = bundle.getFloat("eva_mul");
|
||||||
|
dmg_m = bundle.getFloat("dmg_mul");
|
||||||
|
hp_m = bundle.getFloat("hp_mul");
|
||||||
|
atk_l = bundle.getFloat("atk_lin");
|
||||||
|
def_l = bundle.getFloat("def_lin");
|
||||||
|
acc_l = bundle.getFloat("acc_lin");
|
||||||
|
eva_l = bundle.getFloat("eva_lin");
|
||||||
|
dmg_l = bundle.getFloat("dmg_lin");
|
||||||
|
hp_l = bundle.getFloat("hp_lin");
|
||||||
|
orig_HT = bundle.getInt("orig_hp");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,151 @@
|
||||||
|
package com.shatteredpixel.shatteredpixeldungeon.custom.buffs;
|
||||||
|
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.custom.messages.M;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.effects.Splash;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.effects.Wound;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.sprites.CharSprite;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIndicator;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
|
||||||
|
import com.watabou.utils.Bundle;
|
||||||
|
import com.watabou.utils.PointF;
|
||||||
|
import com.watabou.utils.Random;
|
||||||
|
|
||||||
|
public class ConsistBleeding extends Buff{
|
||||||
|
protected float[] lasting;
|
||||||
|
protected float[] dmg;
|
||||||
|
protected float percentDamage=0;
|
||||||
|
|
||||||
|
public ConsistBleeding(){
|
||||||
|
lasting = new float[5];
|
||||||
|
dmg = new float[5];
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean newLayer(float time, float damagePerAct){
|
||||||
|
for(int i=0;i<5;++i){
|
||||||
|
if(lasting[i]<=0f){
|
||||||
|
lasting[i]=time;
|
||||||
|
dmg[i]=damagePerAct;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void burst(){
|
||||||
|
float damage = 0;
|
||||||
|
for(int i = 0; i<5; ++i){
|
||||||
|
damage += Math.max(0, dmg[i])*lasting[i];
|
||||||
|
}
|
||||||
|
target.sprite.showStatus(CharSprite.NEGATIVE, "!!!");
|
||||||
|
if (target.sprite.visible) {
|
||||||
|
Splash.at( target.sprite.center(), -PointF.PI / 2, PointF.PI / 6,
|
||||||
|
target.sprite.blood(), 30 );
|
||||||
|
}
|
||||||
|
Wound.hit(target);
|
||||||
|
|
||||||
|
damage *= Random.Float(1.7f, 2.1f);
|
||||||
|
target.damage((int)damage, this);
|
||||||
|
if(target == Dungeon.hero && !target.isAlive()){
|
||||||
|
Dungeon.fail(getClass());
|
||||||
|
GLog.n(M.L(this, "burst_die"));
|
||||||
|
}
|
||||||
|
detach();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void resetList(){
|
||||||
|
for(int i=0; i<5; ++i){
|
||||||
|
lasting[i]=0;
|
||||||
|
dmg[i]=0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void decreaseTime(){
|
||||||
|
for(int i=0; i<5; ++i){
|
||||||
|
lasting[i]-=1f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public float oneDamage(){
|
||||||
|
float damage = 0;
|
||||||
|
for(int i=0; i<5; ++i){
|
||||||
|
damage += dmg[i];
|
||||||
|
}
|
||||||
|
return damage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getLayer(){
|
||||||
|
int layer = 0;
|
||||||
|
for(int i=0;i<5;++i){
|
||||||
|
layer += lasting[i]>0f?1:0;
|
||||||
|
}
|
||||||
|
return layer;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean act(){
|
||||||
|
spend(TICK);
|
||||||
|
percentDamage += oneDamage();
|
||||||
|
target.damage((int)percentDamage, this);
|
||||||
|
|
||||||
|
if (target.sprite.visible) {
|
||||||
|
Splash.at( target.sprite.center(), -PointF.PI / 2, PointF.PI / 6,
|
||||||
|
target.sprite.blood(), Math.min( 10 *(int)percentDamage / target.HT, 10 ) );
|
||||||
|
}
|
||||||
|
if(target == Dungeon.hero && !target.isAlive()){
|
||||||
|
Dungeon.fail(getClass());
|
||||||
|
GLog.n(M.L(this, "bleed_die"));
|
||||||
|
}
|
||||||
|
|
||||||
|
percentDamage -= (int)percentDamage;
|
||||||
|
|
||||||
|
decreaseTime();
|
||||||
|
|
||||||
|
if(getLayer()==0) detach();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void storeInBundle(Bundle b){
|
||||||
|
super.storeInBundle(b);
|
||||||
|
b.put("leftTime", lasting);
|
||||||
|
b.put("damageLeft", dmg);
|
||||||
|
b.put("percentDamage", percentDamage);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void restoreFromBundle(Bundle b){
|
||||||
|
super.restoreFromBundle(b);
|
||||||
|
lasting = b.getFloatArray("leftTime");
|
||||||
|
dmg = b.getFloatArray("damageLeft");
|
||||||
|
percentDamage = b.getFloat("percentDamage");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int icon(){
|
||||||
|
return BuffIndicator.BLEEDING;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String desc() {
|
||||||
|
return M.L(this, "desc", getLayer(), oneDamage());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return M.L(this, "name");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String heroMessage() {
|
||||||
|
return M.L(this, "heromsg");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float iconFadePercent() {
|
||||||
|
return Math.max(0, (5 - getLayer()) / 5f);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
package com.shatteredpixel.shatteredpixeldungeon.custom.buffs;
|
||||||
|
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
|
||||||
|
import com.watabou.utils.Bundle;
|
||||||
|
|
||||||
|
public class CountBuff extends Buff {
|
||||||
|
|
||||||
|
private float count = 0;
|
||||||
|
|
||||||
|
public void countUp( float inc ){
|
||||||
|
count += inc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void countDown( float inc ){
|
||||||
|
count -= inc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float count(){
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final String COUNT = "count";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void storeInBundle(Bundle bundle) {
|
||||||
|
super.storeInBundle(bundle);
|
||||||
|
bundle.put(COUNT, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void restoreFromBundle(Bundle bundle) {
|
||||||
|
super.restoreFromBundle(bundle);
|
||||||
|
count = bundle.getFloat(COUNT);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,71 @@
|
||||||
|
package com.shatteredpixel.shatteredpixeldungeon.custom.buffs;
|
||||||
|
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||||
|
import com.watabou.utils.Callback;
|
||||||
|
|
||||||
|
//It's called char, but it serves for buffs, not chars.
|
||||||
|
|
||||||
|
//Currently DummyChar is only used to hold "level buffs".
|
||||||
|
//Level buffs are buffs that not affected by chars.
|
||||||
|
//This kind of buff should be attached to a "static" char that is sealed in level, not existing chars.
|
||||||
|
//Or it would be problematic if the holder dies, or leaves the level.
|
||||||
|
|
||||||
|
//might be better to maintain a dummyChar array. Use id to distinguish between dcs.
|
||||||
|
public final class DummyChar extends Char {
|
||||||
|
|
||||||
|
{
|
||||||
|
alignment = Alignment.NEUTRAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean act() {
|
||||||
|
spend(TICK);
|
||||||
|
if(buffs().isEmpty()){
|
||||||
|
killDummyChar();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void damage(int dmg, Object src) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canInteract(Char c) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//return the first DummyChar,
|
||||||
|
public static DummyChar findDummyChar(){
|
||||||
|
for(Char ch: Actor.chars()){
|
||||||
|
if(ch instanceof DummyChar){
|
||||||
|
return (DummyChar) ch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
//return existing dummyChar, or create a new dummyChar
|
||||||
|
public static DummyChar getDC(){
|
||||||
|
for(Char ch: Actor.chars()){
|
||||||
|
if(ch instanceof DummyChar){
|
||||||
|
return (DummyChar) ch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DummyChar dc = new DummyChar();
|
||||||
|
Actor.add(dc);
|
||||||
|
return dc;
|
||||||
|
}
|
||||||
|
|
||||||
|
//remove existing dummyChar
|
||||||
|
public static boolean killDummyChar() {
|
||||||
|
DummyChar dc = findDummyChar();
|
||||||
|
if (dc == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Actor.remove(dc);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
package com.shatteredpixel.shatteredpixeldungeon.custom.buffs;
|
||||||
|
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.FlavourBuff;
|
||||||
|
|
||||||
|
public class FlavourBuffOpen extends FlavourBuff {
|
||||||
|
public void setDuration(float time){
|
||||||
|
spend(time);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
package com.shatteredpixel.shatteredpixeldungeon.custom.buffs;
|
||||||
|
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.FlavourBuff;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIndicator;
|
||||||
|
import com.watabou.noosa.Image;
|
||||||
|
|
||||||
|
public class IgnoreArmor extends FlavourBuff {
|
||||||
|
{
|
||||||
|
type = buffType.NEUTRAL;
|
||||||
|
announced = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int icon() {
|
||||||
|
return BuffIndicator.VULNERABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void tintIcon(Image icon) {
|
||||||
|
super.tintIcon(icon);
|
||||||
|
icon.hardlight(0.8f, 0f, 0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return Messages.get(this, "name");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String desc() {
|
||||||
|
return Messages.get(this, "desc", dispTurns());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
package com.shatteredpixel.shatteredpixeldungeon.custom.buffs;
|
||||||
|
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.FlavourBuff;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIndicator;
|
||||||
|
import com.watabou.noosa.Image;
|
||||||
|
|
||||||
|
public class PositiveBuffProhibition extends FlavourBuff {
|
||||||
|
{
|
||||||
|
type = buffType.NEUTRAL;
|
||||||
|
announced = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int icon() {
|
||||||
|
return BuffIndicator.DEGRADE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void tintIcon(Image icon) {
|
||||||
|
super.tintIcon(icon);
|
||||||
|
icon.hardlight(0f, 1f, 0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return Messages.get(this, "name");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String desc() {
|
||||||
|
return Messages.get(this, "desc", dispTurns());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean attachTo(Char target) {
|
||||||
|
for(Buff b: target.buffs()){
|
||||||
|
if(b.type == buffType.POSITIVE && !b.revivePersists){
|
||||||
|
b.detach();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return super.attachTo(target);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
package com.shatteredpixel.shatteredpixeldungeon.custom.buffs;
|
||||||
|
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.FlavourBuff;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIndicator;
|
||||||
|
import com.watabou.noosa.Image;
|
||||||
|
|
||||||
|
public class ZeroAttack extends FlavourBuff {
|
||||||
|
{
|
||||||
|
type = buffType.NEUTRAL;
|
||||||
|
announced = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int icon() {
|
||||||
|
return BuffIndicator.WEAKNESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void tintIcon(Image icon) {
|
||||||
|
icon.hardlight(.5f, .5f, .5f);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return Messages.get(this, "name");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String desc() {
|
||||||
|
return Messages.get(this, "desc", dispTurns());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
package com.shatteredpixel.shatteredpixeldungeon.custom.buffs;
|
||||||
|
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.FlavourBuff;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIndicator;
|
||||||
|
import com.watabou.noosa.Image;
|
||||||
|
|
||||||
|
public class ZeroDefense extends FlavourBuff {
|
||||||
|
{
|
||||||
|
type = buffType.NEUTRAL;
|
||||||
|
announced = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int icon() {
|
||||||
|
return BuffIndicator.VULNERABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void tintIcon(Image icon) {
|
||||||
|
icon.hardlight(.5f, .5f, .5f);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return Messages.get(this, "name");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String desc() {
|
||||||
|
return Messages.get(this, "desc", dispTurns());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,154 @@
|
||||||
|
package com.shatteredpixel.shatteredpixeldungeon.custom.ch;
|
||||||
|
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.Statistics;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mimic;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.Ghost;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.Imp;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.RedDragon;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.Wandmaker;
|
||||||
|
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.Artifact;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.items.rings.Ring;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.items.wands.Wand;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.Weapon;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.levels.RegularLevel;
|
||||||
|
import com.watabou.noosa.Game;
|
||||||
|
import com.watabou.noosa.Visual;
|
||||||
|
import com.watabou.utils.Bundle;
|
||||||
|
|
||||||
|
public class GameTracker extends Buff {
|
||||||
|
{
|
||||||
|
actPriority = VFX_PRIO - 1;
|
||||||
|
revivePersists = true;
|
||||||
|
}
|
||||||
|
private VirtualVisualTimer vvt;
|
||||||
|
private int maxDepth = -1;
|
||||||
|
private String allItemInfo = "";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean act() {
|
||||||
|
spend(TICK/2f);
|
||||||
|
if(vvt==null) {
|
||||||
|
vvt = new VirtualVisualTimer();
|
||||||
|
Dungeon.hero.sprite.parent.add(vvt);
|
||||||
|
}
|
||||||
|
if(!vvt.alive || !vvt.active || vvt.parent == null){
|
||||||
|
vvt.revive();
|
||||||
|
vvt.active = true;
|
||||||
|
Dungeon.hero.sprite.parent.add(vvt);
|
||||||
|
vvt.parent = Dungeon.hero.sprite.parent;
|
||||||
|
}
|
||||||
|
if(maxDepth < Dungeon.depth){
|
||||||
|
spend(-TICK);
|
||||||
|
maxDepth = Dungeon.depth;
|
||||||
|
updateItemInfo();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onNewLevel(){
|
||||||
|
if(maxDepth < Dungeon.depth){
|
||||||
|
spend(-TICK);
|
||||||
|
maxDepth = Dungeon.depth;
|
||||||
|
updateItemInfo();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateItemInfo(){
|
||||||
|
if(Dungeon.level instanceof RegularLevel){
|
||||||
|
StringBuilder info = new StringBuilder("");
|
||||||
|
info.append("dungeon_depth: ").append(maxDepth).append("\n");
|
||||||
|
for(Heap heap: Dungeon.level.heaps.valueList()){
|
||||||
|
if((!heap.autoExplored) || heap.type == Heap.Type.CHEST || heap.type == Heap.Type.LOCKED_CHEST || heap.type == Heap.Type.CRYSTAL_CHEST){
|
||||||
|
for(Item item : heap.items){
|
||||||
|
appendDesc(item, info, "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(Mob m : Dungeon.level.mobs.toArray(new Mob[0])){
|
||||||
|
if(m instanceof Mimic){
|
||||||
|
for(Item item: ((Mimic) m).items){
|
||||||
|
appendDesc(item, info, "MIMIC_HOLD");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(m instanceof Ghost){
|
||||||
|
appendDesc(Ghost.Quest.weapon, info, "QUEST_REWARD");
|
||||||
|
appendDesc(Ghost.Quest.armor, info, "QUEST_REWARD");
|
||||||
|
}
|
||||||
|
if(m instanceof Wandmaker){
|
||||||
|
appendDesc(Wandmaker.Quest.wand1, info, "QUEST_REWARD");
|
||||||
|
appendDesc(Wandmaker.Quest.wand2, info, "QUEST_REWARD");
|
||||||
|
}
|
||||||
|
if(m instanceof RedDragon){
|
||||||
|
appendDesc(RedDragon.Quest.weapon, info, "QUEST_REWARD");
|
||||||
|
appendDesc(RedDragon.Quest.armor, info, "QUEST_REWARD");
|
||||||
|
}
|
||||||
|
if(m instanceof Imp){
|
||||||
|
appendDesc(Imp.Quest.reward, info, "QUEST_REWARD");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
allItemInfo += info.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void appendDesc(Item item, StringBuilder info, String prefix){
|
||||||
|
if(item != null) {
|
||||||
|
if (
|
||||||
|
((item instanceof Weapon || item instanceof Armor) && item.level() > 0)
|
||||||
|
|| (item instanceof Ring || item instanceof Wand || item instanceof Artifact)
|
||||||
|
) {
|
||||||
|
String name = item.trueName();
|
||||||
|
int index = name.indexOf('+');
|
||||||
|
if(index > 0){
|
||||||
|
name = name.substring(0, index - 3);
|
||||||
|
}
|
||||||
|
info.append(prefix).append(name).append('+').append(item.level()).append(item.cursed ? " CURSED\n" : "\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String itemInfo(){
|
||||||
|
return allItemInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void storeInBundle(Bundle bundle) {
|
||||||
|
super.storeInBundle(bundle);
|
||||||
|
bundle.put("allItemInfo", allItemInfo);
|
||||||
|
bundle.put("recordedMaxDepth", maxDepth);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void restoreFromBundle(Bundle bundle) {
|
||||||
|
super.restoreFromBundle(bundle);
|
||||||
|
allItemInfo = bundle.getString("allItemInfo");
|
||||||
|
maxDepth = bundle.getInt("recordedMaxDepth");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class VirtualVisualTimer extends Visual {
|
||||||
|
public VirtualVisualTimer(){
|
||||||
|
super(0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update() {
|
||||||
|
super.update();
|
||||||
|
Statistics.second_elapsed += Game.elapsed;
|
||||||
|
if(Statistics.second_elapsed > 1f){
|
||||||
|
Statistics.real_seconds += Math.floor(Statistics.second_elapsed);
|
||||||
|
Statistics.second_elapsed -= Math.floor(Statistics.second_elapsed);
|
||||||
|
}
|
||||||
|
if(Statistics.turnsPassed < Statistics.duration){
|
||||||
|
Statistics.turnsPassed = Statistics.duration;
|
||||||
|
}else{
|
||||||
|
Statistics.turnsPassed = Statistics.duration + Actor.now();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
package com.shatteredpixel.shatteredpixeldungeon.custom.testmode;
|
||||||
|
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.sprites.CharSprite;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
public class ImmortalShieldAffecter extends TestItem {
|
||||||
|
{
|
||||||
|
image = ItemSpriteSheet.ROUND_SHIELD;
|
||||||
|
defaultAction = AC_SWITCH;
|
||||||
|
}
|
||||||
|
private static final String AC_SWITCH = "switch";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ArrayList<String> actions(Hero hero ) {
|
||||||
|
ArrayList<String> actions = super.actions(hero);
|
||||||
|
actions.add(AC_SWITCH);
|
||||||
|
return actions;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(Hero hero, String action ) {
|
||||||
|
super.execute(hero, action);
|
||||||
|
if(action.equals(AC_SWITCH)){
|
||||||
|
if(isImmortal(hero)){
|
||||||
|
Buff.detach(hero, ImmortalShield.class);
|
||||||
|
}else{
|
||||||
|
Buff.affect(hero, ImmortalShield.class);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isImmortal(Char target){
|
||||||
|
return target.buff(ImmortalShield.class)!=null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ImmortalShield extends Buff{
|
||||||
|
{
|
||||||
|
type = buffType.NEUTRAL;
|
||||||
|
announced = false;
|
||||||
|
revivePersists = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean act(){
|
||||||
|
spend(TICK);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fx(boolean on) {
|
||||||
|
if (on) target.sprite.add(CharSprite.State.SHIELDED);
|
||||||
|
else target.sprite.remove(CharSprite.State.SHIELDED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -74,6 +74,8 @@ public class Heap implements Bundlable {
|
||||||
public ItemSprite sprite;
|
public ItemSprite sprite;
|
||||||
public boolean seen = false;
|
public boolean seen = false;
|
||||||
public boolean haunted = false;
|
public boolean haunted = false;
|
||||||
|
|
||||||
|
public boolean autoExplored = false; //used to determine if this heap should count for exploration bonus
|
||||||
|
|
||||||
public LinkedList<Item> items = new LinkedList<>();
|
public LinkedList<Item> items = new LinkedList<>();
|
||||||
|
|
||||||
|
@ -407,6 +409,8 @@ public class Heap implements Bundlable {
|
||||||
private static final String TYPE = "type";
|
private static final String TYPE = "type";
|
||||||
private static final String ITEMS = "items";
|
private static final String ITEMS = "items";
|
||||||
private static final String HAUNTED = "haunted";
|
private static final String HAUNTED = "haunted";
|
||||||
|
|
||||||
|
private static final String AUTO_EXPLORED = "auto_explored";
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Override
|
@Override
|
||||||
|
@ -431,6 +435,9 @@ public class Heap implements Bundlable {
|
||||||
}
|
}
|
||||||
|
|
||||||
haunted = bundle.getBoolean( HAUNTED );
|
haunted = bundle.getBoolean( HAUNTED );
|
||||||
|
|
||||||
|
//SPD
|
||||||
|
autoExplored = bundle.getBoolean( AUTO_EXPLORED );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -441,6 +448,9 @@ public class Heap implements Bundlable {
|
||||||
bundle.put( TYPE, type.toString() );
|
bundle.put( TYPE, type.toString() );
|
||||||
bundle.put( ITEMS, items );
|
bundle.put( ITEMS, items );
|
||||||
bundle.put( HAUNTED, haunted );
|
bundle.put( HAUNTED, haunted );
|
||||||
|
|
||||||
|
//SPD
|
||||||
|
bundle.put( AUTO_EXPLORED, autoExplored );
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,18 +26,51 @@ import com.shatteredpixel.shatteredpixeldungeon.Badges;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
|
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.AllyBuff;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Amok;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Barrier;
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Barrier;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Bleeding;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Blindness;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Burning;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Charm;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Chill;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Corrosion;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Corruption;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Cripple;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Doom;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Dread;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Drowsy;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.FlavourBuff;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Frost;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Hex;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Invisibility;
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Invisibility;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.LockedFloor;
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.LockedFloor;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.MagicImmune;
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.MagicImmune;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.MagicalSleep;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Ooze;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Paralysis;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Poison;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Recharging;
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Recharging;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Roots;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.ScrollEmpower;
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.ScrollEmpower;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Slow;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.SoulMark;
|
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.Vulnerable;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Weakness;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
|
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.HeroSubClass;
|
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.HeroSubClass;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Talent;
|
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Talent;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.abilities.mage.WildMagic;
|
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.abilities.mage.WildMagic;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Bee;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mimic;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Piranha;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Statue;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Swarm;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Wraith;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.effects.MagicMissile;
|
import com.shatteredpixel.shatteredpixeldungeon.effects.MagicMissile;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
|
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.TalismanOfForesight;
|
import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.TalismanOfForesight;
|
||||||
|
@ -61,6 +94,7 @@ import com.watabou.utils.PointF;
|
||||||
import com.watabou.utils.Random;
|
import com.watabou.utils.Random;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
public abstract class Wand extends Item {
|
public abstract class Wand extends Item {
|
||||||
public static final String AC_ZAP = "ZAP";
|
public static final String AC_ZAP = "ZAP";
|
||||||
|
@ -72,7 +106,7 @@ public abstract class Wand extends Item {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final float TIME_TO_ZAP = 1f;
|
private static final float TIME_TO_ZAP = 1f;
|
||||||
|
|
||||||
public int maxCharges = initialCharges();
|
public int maxCharges = initialCharges();
|
||||||
public int curCharges = maxCharges;
|
public int curCharges = maxCharges;
|
||||||
public float partialCharge = 0f;
|
public float partialCharge = 0f;
|
||||||
|
@ -381,7 +415,7 @@ public abstract class Wand extends Item {
|
||||||
particle.radiateXY(0.5f);
|
particle.radiateXY(0.5f);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void wandUsed() {
|
public void wandUsed() {
|
||||||
if (!isIdentified()) {
|
if (!isIdentified()) {
|
||||||
float uses = Math.min( availableUsesToID, Talent.itemIDSpeedFactor(Dungeon.hero, this) );
|
float uses = Math.min( availableUsesToID, Talent.itemIDSpeedFactor(Dungeon.hero, this) );
|
||||||
availableUsesToID -= uses;
|
availableUsesToID -= uses;
|
||||||
|
@ -531,6 +565,150 @@ public abstract class Wand extends Item {
|
||||||
return collisionProperties;
|
return collisionProperties;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//浊焰
|
||||||
|
|
||||||
|
private static final float MINOR_DEBUFF_WEAKEN = 1/4f;
|
||||||
|
private static final HashMap<Class<? extends Buff>, Float> MINOR_DEBUFFS = new HashMap<>();
|
||||||
|
static{
|
||||||
|
MINOR_DEBUFFS.put(Weakness.class, 2f);
|
||||||
|
MINOR_DEBUFFS.put(Vulnerable.class, 2f);
|
||||||
|
MINOR_DEBUFFS.put(Cripple.class, 1f);
|
||||||
|
MINOR_DEBUFFS.put(Blindness.class, 1f);
|
||||||
|
MINOR_DEBUFFS.put(Terror.class, 1f);
|
||||||
|
|
||||||
|
MINOR_DEBUFFS.put(Chill.class, 0f);
|
||||||
|
MINOR_DEBUFFS.put(Ooze.class, 0f);
|
||||||
|
MINOR_DEBUFFS.put(Roots.class, 0f);
|
||||||
|
MINOR_DEBUFFS.put(Vertigo.class, 0f);
|
||||||
|
MINOR_DEBUFFS.put(Drowsy.class, 0f);
|
||||||
|
MINOR_DEBUFFS.put(Bleeding.class, 0f);
|
||||||
|
MINOR_DEBUFFS.put(Burning.class, 0f);
|
||||||
|
MINOR_DEBUFFS.put(Poison.class, 0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final float MAJOR_DEBUFF_WEAKEN = 1/2f;
|
||||||
|
private static final HashMap<Class<? extends Buff>, Float> MAJOR_DEBUFFS = new HashMap<>();
|
||||||
|
static{
|
||||||
|
MAJOR_DEBUFFS.put(Amok.class, 3f);
|
||||||
|
MAJOR_DEBUFFS.put(Slow.class, 2f);
|
||||||
|
MAJOR_DEBUFFS.put(Hex.class, 2f);
|
||||||
|
MAJOR_DEBUFFS.put(Paralysis.class, 1f);
|
||||||
|
|
||||||
|
MAJOR_DEBUFFS.put(Dread.class, 0f);
|
||||||
|
MAJOR_DEBUFFS.put(Charm.class, 0f);
|
||||||
|
MAJOR_DEBUFFS.put(MagicalSleep.class, 0f);
|
||||||
|
MAJOR_DEBUFFS.put(SoulMark.class, 0f);
|
||||||
|
MAJOR_DEBUFFS.put(Corrosion.class, 0f);
|
||||||
|
MAJOR_DEBUFFS.put(Frost.class, 0f);
|
||||||
|
MAJOR_DEBUFFS.put(Doom.class, 0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onZapX(Ballistica bolt) {
|
||||||
|
Char ch = Actor.findChar(bolt.collisionPos);
|
||||||
|
|
||||||
|
if (ch != null){
|
||||||
|
|
||||||
|
if (!(ch instanceof Mob)){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Mob enemy = (Mob) ch;
|
||||||
|
|
||||||
|
float corruptingPower = 3 + buffedLvl()/2f;
|
||||||
|
|
||||||
|
//base enemy resistance is usually based on their exp, but in special cases it is based on other criteria
|
||||||
|
float enemyResist = 1 + enemy.EXP;
|
||||||
|
if (ch instanceof Mimic || ch instanceof Statue){
|
||||||
|
enemyResist = 1 + Dungeon.depth;
|
||||||
|
} else if (ch instanceof Piranha || ch instanceof Bee) {
|
||||||
|
enemyResist = 1 + Dungeon.depth/2f;
|
||||||
|
} else if (ch instanceof Wraith) {
|
||||||
|
//divide by 5 as wraiths are always at full HP and are therefore ~5x harder to corrupt
|
||||||
|
enemyResist = (1f + Dungeon.depth/3f) / 5f;
|
||||||
|
} else if (ch instanceof Swarm){
|
||||||
|
//child swarms don't give exp, so we force this here.
|
||||||
|
enemyResist = 1 + 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
//100% health: 5x resist 75%: 3.25x resist 50%: 2x resist 25%: 1.25x resist
|
||||||
|
enemyResist *= 1 + 4*Math.pow(enemy.HP/(float)enemy.HT, 2);
|
||||||
|
|
||||||
|
//debuffs placed on the enemy reduce their resistance
|
||||||
|
for (Buff buff : enemy.buffs()){
|
||||||
|
if (MAJOR_DEBUFFS.containsKey(buff.getClass())) enemyResist *= (1f-MAJOR_DEBUFF_WEAKEN);
|
||||||
|
else if (MINOR_DEBUFFS.containsKey(buff.getClass())) enemyResist *= (1f-MINOR_DEBUFF_WEAKEN);
|
||||||
|
else if (buff.type == Buff.buffType.NEGATIVE) enemyResist *= (1f-MINOR_DEBUFF_WEAKEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
//cannot re-corrupt or doom an enemy, so give them a major debuff instead
|
||||||
|
if(enemy.buff(Corruption.class) != null || enemy.buff(Doom.class) != null){
|
||||||
|
corruptingPower = enemyResist - 0.001f;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (corruptingPower > enemyResist){
|
||||||
|
corruptEnemy( enemy );
|
||||||
|
} else {
|
||||||
|
float debuffChance = corruptingPower / enemyResist;
|
||||||
|
if (Random.Float() < debuffChance){
|
||||||
|
debuffEnemy( enemy, MAJOR_DEBUFFS);
|
||||||
|
} else {
|
||||||
|
debuffEnemy( enemy, MINOR_DEBUFFS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wandProc(ch, chargesPerCast());
|
||||||
|
Sample.INSTANCE.play( Assets.Sounds.HIT_MAGIC, 1, 0.8f * Random.Float(0.87f, 1.15f) );
|
||||||
|
|
||||||
|
} else {
|
||||||
|
Dungeon.level.pressCell(bolt.collisionPos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void debuffEnemy( Mob enemy, HashMap<Class<? extends Buff>, Float> category ){
|
||||||
|
|
||||||
|
//do not consider buffs which are already assigned, or that the enemy is immune to.
|
||||||
|
HashMap<Class<? extends Buff>, Float> debuffs = new HashMap<>(category);
|
||||||
|
for (Buff existing : enemy.buffs()){
|
||||||
|
if (debuffs.containsKey(existing.getClass())) {
|
||||||
|
debuffs.put(existing.getClass(), 0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (Class<?extends Buff> toAssign : debuffs.keySet()){
|
||||||
|
if (debuffs.get(toAssign) > 0 && enemy.isImmune(toAssign)){
|
||||||
|
debuffs.put(toAssign, 0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//all buffs with a > 0 chance are flavor buffs
|
||||||
|
Class<?extends FlavourBuff> debuffCls = (Class<? extends FlavourBuff>) Random.chances(debuffs);
|
||||||
|
|
||||||
|
if (debuffCls != null){
|
||||||
|
Buff.append(enemy, debuffCls, 6 + buffedLvl()*3);
|
||||||
|
} else {
|
||||||
|
//if no debuff can be applied (all are present), then go up one tier
|
||||||
|
if (category == MINOR_DEBUFFS) debuffEnemy( enemy, MAJOR_DEBUFFS);
|
||||||
|
else if (category == MAJOR_DEBUFFS) corruptEnemy( enemy );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void corruptEnemy( Mob enemy ){
|
||||||
|
//cannot re-corrupt or doom an enemy, so give them a major debuff instead
|
||||||
|
if(enemy.buff(Corruption.class) != null || enemy.buff(Doom.class) != null){
|
||||||
|
GLog.w( Messages.get(this, "already_corrupted") );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!enemy.isImmune(Corruption.class)){
|
||||||
|
Corruption.corruptionHeal(enemy);
|
||||||
|
|
||||||
|
AllyBuff.affectAndLoot(enemy, curUser, Corruption.class);
|
||||||
|
} else {
|
||||||
|
Buff.affect(enemy, Doom.class);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static class PlaceHolder extends Wand {
|
public static class PlaceHolder extends Wand {
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
|
@ -28,6 +28,7 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.FlavourBuff;
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.FlavourBuff;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.effects.SpellSprite;
|
import com.shatteredpixel.shatteredpixeldungeon.effects.SpellSprite;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.EndingBlade;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.MagesStaff;
|
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.MagesStaff;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.mechanics.Ballistica;
|
import com.shatteredpixel.shatteredpixeldungeon.mechanics.Ballistica;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
|
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
|
||||||
|
@ -103,6 +104,7 @@ public class WandOfMagicMissile extends DamageWand {
|
||||||
|
|
||||||
private int level = 0;
|
private int level = 0;
|
||||||
private Wand wandJustApplied; //we don't bundle this as it's only used right as the buff is applied
|
private Wand wandJustApplied; //we don't bundle this as it's only used right as the buff is applied
|
||||||
|
private EndingBlade wandJustAppliedX; //we don't bundle this as it's only used right as the buff is applied
|
||||||
|
|
||||||
public void setup(Wand wand){
|
public void setup(Wand wand){
|
||||||
if (level < wand.buffedLvl()){
|
if (level < wand.buffedLvl()){
|
||||||
|
@ -128,6 +130,12 @@ public class WandOfMagicMissile extends DamageWand {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public EndingBlade wandJustAppliedX(){
|
||||||
|
EndingBlade result = this.wandJustAppliedX;
|
||||||
|
this.wandJustAppliedX = null;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int icon() {
|
public int icon() {
|
||||||
return BuffIndicator.UPGRADE;
|
return BuffIndicator.UPGRADE;
|
||||||
|
|
|
@ -1,23 +1,81 @@
|
||||||
package com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee;
|
package com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee;
|
||||||
|
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.Assets;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.Badges;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.AllyBuff;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Barrier;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Blindness;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Burning;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Chill;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Corrosion;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Corruption;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Cripple;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Doom;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Drowsy;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.FlavourBuff;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Frost;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Hex;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Invisibility;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.MagicImmune;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.MagicalSleep;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Ooze;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Paralysis;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Poison;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.ScrollEmpower;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Slow;
|
||||||
|
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.hero.Hero;
|
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.Bee;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mimic;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Piranha;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Statue;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Swarm;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Wraith;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.custom.utils.BallisticaReal;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.effects.Beam;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.effects.CellEmitter;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.effects.MagicMissile;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.effects.particles.PurpleParticle;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.TalismanOfForesight;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.bombs.LaserPython;
|
import com.shatteredpixel.shatteredpixeldungeon.items.bombs.LaserPython;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfRecharging;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.items.wands.Wand;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfMagicMissile;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.Weapon;
|
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.Weapon;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.enchantments.Blazing;
|
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.enchantments.Blazing;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.enchantments.Grim;
|
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.enchantments.Grim;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.enchantments.Kinetic;
|
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.enchantments.Kinetic;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.enchantments.Shocking;
|
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.enchantments.Shocking;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.enchantments.Unstable;
|
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.enchantments.Unstable;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.mechanics.Ballistica;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
|
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.scenes.CellSelector;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
|
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.ui.QuickSlotButton;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
|
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
|
||||||
|
import com.watabou.noosa.audio.Sample;
|
||||||
import com.watabou.utils.Bundle;
|
import com.watabou.utils.Bundle;
|
||||||
|
import com.watabou.utils.Callback;
|
||||||
|
import com.watabou.utils.Point;
|
||||||
|
import com.watabou.utils.PointF;
|
||||||
|
import com.watabou.utils.Random;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
public class EndingBlade extends Weapon {
|
public class EndingBlade extends Weapon {
|
||||||
|
|
||||||
{
|
{
|
||||||
image = ItemSpriteSheet.ENDDIED;
|
image = ItemSpriteSheet.ENDDIED;
|
||||||
tier = 4;
|
tier = 4;
|
||||||
|
@ -51,12 +109,14 @@ public class EndingBlade extends Weapon {
|
||||||
|
|
||||||
private static final String FIRST = "first";
|
private static final String FIRST = "first";
|
||||||
private static final String INTRPS = "intrps";
|
private static final String INTRPS = "intrps";
|
||||||
|
private static final String TDM = "shocking_ordinals";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void storeInBundle(Bundle bundle) {
|
public void storeInBundle(Bundle bundle) {
|
||||||
super.storeInBundle(bundle);
|
super.storeInBundle(bundle);
|
||||||
bundle.put(FIRST, firstx);
|
bundle.put(FIRST, firstx);
|
||||||
bundle.put(INTRPS, fireenergy);
|
bundle.put(INTRPS, fireenergy);
|
||||||
|
bundle.put(TDM, TIME_TO_DIED);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -64,10 +124,11 @@ public class EndingBlade extends Weapon {
|
||||||
super.restoreFromBundle(bundle);
|
super.restoreFromBundle(bundle);
|
||||||
firstx = bundle.getBoolean(FIRST);
|
firstx = bundle.getBoolean(FIRST);
|
||||||
fireenergy = bundle.getInt(INTRPS);
|
fireenergy = bundle.getInt(INTRPS);
|
||||||
|
TIME_TO_DIED = bundle.getInt(TDM);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String desc() {
|
public String desc() {
|
||||||
return Messages.get(this, "desc")+"_"+fireenergy+"_";
|
return Messages.get(this, "desc")+"_"+fireenergy+"_"+Messages.get(this, "desc_2")+"_"+TIME_TO_DIED+"_";
|
||||||
}
|
}
|
||||||
|
|
||||||
//每100点浊焰能量自动升级
|
//每100点浊焰能量自动升级
|
||||||
|
@ -75,7 +136,7 @@ public class EndingBlade extends Weapon {
|
||||||
public int level() {
|
public int level() {
|
||||||
return fireenergy/100;
|
return fireenergy/100;
|
||||||
}
|
}
|
||||||
|
private int TIME_TO_DIED = 0;
|
||||||
public void execute( Hero hero, String action ) {
|
public void execute( Hero hero, String action ) {
|
||||||
super.execute( hero, action );
|
super.execute( hero, action );
|
||||||
|
|
||||||
|
@ -92,7 +153,16 @@ public class EndingBlade extends Weapon {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case AC_DIEDGHOST:
|
case AC_DIEDGHOST:
|
||||||
GLog.p("2");
|
if(level >= 5 && TIME_TO_DIED == 0) {
|
||||||
|
curUser = hero;
|
||||||
|
curItem = this;
|
||||||
|
GameScene.selectCell(zapper);
|
||||||
|
TIME_TO_DIED = 20;
|
||||||
|
} else if (TIME_TO_DIED != 0) {
|
||||||
|
GLog.n("道具正在冷却");
|
||||||
|
} else {
|
||||||
|
GLog.n("等级不足");
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case AC_HEALRESET:
|
case AC_HEALRESET:
|
||||||
GLog.w("3");
|
GLog.w("3");
|
||||||
|
@ -100,8 +170,508 @@ public class EndingBlade extends Weapon {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int maxCharges = initialCharges();
|
||||||
|
public int curCharges = maxCharges;
|
||||||
|
public int collisionProperties(int target){
|
||||||
|
return collisionProperties;
|
||||||
|
}
|
||||||
|
protected int collisionProperties = Ballistica.MAGIC_BOLT;
|
||||||
|
protected int initialCharges() {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static CellSelector.Listener zapper = new CellSelector.Listener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSelect( Integer target ) {
|
||||||
|
|
||||||
|
if (target != null) {
|
||||||
|
|
||||||
|
//FIXME this safety check shouldn't be necessary
|
||||||
|
//it would be better to eliminate the curItem static variable.
|
||||||
|
final EndingBlade curWand;
|
||||||
|
if (curItem instanceof EndingBlade) {
|
||||||
|
curWand = (EndingBlade) EndingBlade.curItem;
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Ballistica shot = new Ballistica( curUser.pos, target, curWand.collisionProperties(target));
|
||||||
|
int cell = shot.collisionPos;
|
||||||
|
|
||||||
|
if (target == curUser.pos || cell == curUser.pos) {
|
||||||
|
if (target == curUser.pos && curUser.hasTalent(Talent.SHIELD_BATTERY)){
|
||||||
|
float shield = curUser.HT * (0.04f*curWand.curCharges);
|
||||||
|
if (curUser.pointsInTalent(Talent.SHIELD_BATTERY) == 2) shield *= 1.5f;
|
||||||
|
Buff.affect(curUser, Barrier.class).setShield(Math.round(shield));
|
||||||
|
curWand.curCharges = 0;
|
||||||
|
curUser.sprite.operate(curUser.pos);
|
||||||
|
Sample.INSTANCE.play(Assets.Sounds.CHARGEUP);
|
||||||
|
ScrollOfRecharging.charge(curUser);
|
||||||
|
updateQuickslot();
|
||||||
|
curUser.spend(Actor.TICK);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
GLog.i( Messages.get(Wand.class, "self_target") );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
curUser.sprite.zap(cell);
|
||||||
|
|
||||||
|
//attempts to target the cell aimed at if something is there, otherwise targets the collision pos.
|
||||||
|
if (Actor.findChar(target) != null)
|
||||||
|
QuickSlotButton.target(Actor.findChar(target));
|
||||||
|
else
|
||||||
|
QuickSlotButton.target(Actor.findChar(cell));
|
||||||
|
|
||||||
|
if (curWand.tryToZap(curUser, target)) {
|
||||||
|
|
||||||
|
curUser.busy();
|
||||||
|
curWand.fxs(shot, new Callback() {
|
||||||
|
public void call() {
|
||||||
|
curWand.onZap(shot);
|
||||||
|
curWand.wandUsed();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
curWand.cursedKnown = true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String prompt() {
|
||||||
|
return Messages.get(Wand.class, "prompt");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public boolean tryToZap( Hero owner, int target ){
|
||||||
|
|
||||||
|
if (owner.buff(MagicImmune.class) != null){
|
||||||
|
GLog.w( Messages.get(Wand.class, "no_magic") );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Wand.Charger charger;
|
||||||
|
|
||||||
|
private static final int USES_TO_ID = 10;
|
||||||
|
private float usesLeftToID = USES_TO_ID;
|
||||||
|
private float availableUsesToID = USES_TO_ID/2f;
|
||||||
|
private static final float TIME_TO_ZAP = 1f;
|
||||||
|
|
||||||
|
public void wandUsed() {
|
||||||
|
if (!isIdentified()) {
|
||||||
|
float uses = Math.min( availableUsesToID, Talent.itemIDSpeedFactor(Dungeon.hero, this) );
|
||||||
|
availableUsesToID -= uses;
|
||||||
|
usesLeftToID -= uses;
|
||||||
|
if (usesLeftToID <= 0 || Dungeon.hero.pointsInTalent(Talent.SCHOLARS_INTUITION) == 2) {
|
||||||
|
identify();
|
||||||
|
GLog.p( Messages.get(Wand.class, "identify") );
|
||||||
|
Badges.validateItemLevelAquired( this );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
curCharges -= cursed ? 1 : chargesPerCast();
|
||||||
|
|
||||||
|
//remove magic charge at a higher priority, if we are benefiting from it are and not the
|
||||||
|
//wand that just applied it
|
||||||
|
WandOfMagicMissile.MagicCharge buff = curUser.buff(WandOfMagicMissile.MagicCharge.class);
|
||||||
|
if (buff != null
|
||||||
|
&& buff.wandJustAppliedX() != this
|
||||||
|
&& buff.level() == buffedLvl()
|
||||||
|
&& buffedLvl() > super.buffedLvl()){
|
||||||
|
buff.detach();
|
||||||
|
} else {
|
||||||
|
ScrollEmpower empower = curUser.buff(ScrollEmpower.class);
|
||||||
|
if (empower != null){
|
||||||
|
empower.use();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//if the wand is owned by the hero, but not in their inventory, it must be in the staff
|
||||||
|
if (charger != null
|
||||||
|
&& charger.target == Dungeon.hero
|
||||||
|
&& !Dungeon.hero.belongings.contains(this)) {
|
||||||
|
if (curCharges == 0 && Dungeon.hero.hasTalent(Talent.BACKUP_BARRIER)) {
|
||||||
|
//grants 3/5 shielding
|
||||||
|
Buff.affect(Dungeon.hero, Barrier.class).setShield(1 + 2 * Dungeon.hero.pointsInTalent(Talent.BACKUP_BARRIER));
|
||||||
|
}
|
||||||
|
if (Dungeon.hero.hasTalent(Talent.EMPOWERED_STRIKE)){
|
||||||
|
Buff.prolong(Dungeon.hero, Talent.EmpoweredStrikeTracker.class, 10f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Invisibility.dispel();
|
||||||
|
updateQuickslot();
|
||||||
|
|
||||||
|
curUser.spendAndNext( TIME_TO_ZAP );
|
||||||
|
}
|
||||||
|
|
||||||
|
protected int nReflections(int level){
|
||||||
|
//return Math.min(2+level/3, 5);
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected float reflectionDamageFactor(int reflections){
|
||||||
|
return 1f+0.1f*reflections*reflections;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onZap( Ballistica beam ) {
|
||||||
|
int count = 0;
|
||||||
|
for(BallisticaReal b: beams){
|
||||||
|
onZapX(b, count);
|
||||||
|
++count;
|
||||||
|
}
|
||||||
|
Char ch = Actor.findChar(beam.collisionPos);
|
||||||
|
|
||||||
|
if (ch != null){
|
||||||
|
|
||||||
|
if (!(ch instanceof Mob)){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Mob enemy = (Mob) ch;
|
||||||
|
|
||||||
|
float corruptingPower = 3 + buffedLvl()/2f;
|
||||||
|
|
||||||
|
//base enemy resistance is usually based on their exp, but in special cases it is based on other criteria
|
||||||
|
float enemyResist = 1 + enemy.EXP;
|
||||||
|
if (ch instanceof Mimic || ch instanceof Statue){
|
||||||
|
enemyResist = 1 + Dungeon.depth;
|
||||||
|
} else if (ch instanceof Piranha || ch instanceof Bee) {
|
||||||
|
enemyResist = 1 + Dungeon.depth/2f;
|
||||||
|
} else if (ch instanceof Wraith) {
|
||||||
|
//divide by 5 as wraiths are always at full HP and are therefore ~5x harder to corrupt
|
||||||
|
enemyResist = (1f + Dungeon.depth/3f) / 5f;
|
||||||
|
} else if (ch instanceof Swarm){
|
||||||
|
//child swarms don't give exp, so we force this here.
|
||||||
|
enemyResist = 1 + 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
//100% health: 5x resist 75%: 3.25x resist 50%: 2x resist 25%: 1.25x resist
|
||||||
|
enemyResist *= 1 + 4*Math.pow(enemy.HP/(float)enemy.HT, 2);
|
||||||
|
|
||||||
|
//debuffs placed on the enemy reduce their resistance
|
||||||
|
for (Buff buff : enemy.buffs()){
|
||||||
|
if (MAJOR_DEBUFFS.containsKey(buff.getClass())) enemyResist *= (1f-MAJOR_DEBUFF_WEAKEN);
|
||||||
|
else if (MINOR_DEBUFFS.containsKey(buff.getClass())) enemyResist *= (1f-MINOR_DEBUFF_WEAKEN);
|
||||||
|
else if (buff.type == Buff.buffType.NEGATIVE) enemyResist *= (1f-MINOR_DEBUFF_WEAKEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
//cannot re-corrupt or doom an enemy, so give them a major debuff instead
|
||||||
|
if(enemy.buff(Corruption.class) != null || enemy.buff(Doom.class) != null){
|
||||||
|
corruptingPower = enemyResist - 0.001f;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (corruptingPower > enemyResist){
|
||||||
|
corruptEnemy( enemy );
|
||||||
|
} else {
|
||||||
|
float debuffChance = corruptingPower / enemyResist;
|
||||||
|
if (Random.Float() < debuffChance){
|
||||||
|
debuffEnemy( enemy, MAJOR_DEBUFFS);
|
||||||
|
} else {
|
||||||
|
debuffEnemy( enemy, MINOR_DEBUFFS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wandProc(ch, chargesPerCast());
|
||||||
|
Sample.INSTANCE.play( Assets.Sounds.HIT_MAGIC, 1, 0.8f * Random.Float(0.87f, 1.15f) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onZapX(BallisticaReal beam,int reflection) {
|
||||||
|
int level = buffedLvl();
|
||||||
|
|
||||||
|
int maxDistance = beam.dist;
|
||||||
|
|
||||||
|
ArrayList<Char> chars = new ArrayList<>();
|
||||||
|
|
||||||
|
for (int c : beam.subPath((reflection>0?0:1), maxDistance)) {
|
||||||
|
//prevent self_damage
|
||||||
|
if(c==beam.sourceI && c==curUser.pos) continue;
|
||||||
|
|
||||||
|
Char ch;
|
||||||
|
if ((ch = Actor.findChar( c )) != null) {
|
||||||
|
|
||||||
|
chars.add( ch );
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Dungeon.level.flamable[c]) {
|
||||||
|
Dungeon.level.destroy( c );
|
||||||
|
GameScene.updateMap( c );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
CellEmitter.center( c ).burst( PurpleParticle.BURST, Random.IntRange( 1, 2 ) );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Dungeon.observe();
|
||||||
|
|
||||||
|
boolean alive = curUser.isAlive();
|
||||||
|
|
||||||
|
int lvl = level;
|
||||||
|
for (Char ch : chars) {
|
||||||
|
wandProc(ch, chargesPerCast());
|
||||||
|
int damage = Math.round(2*reflectionDamageFactor(reflection));
|
||||||
|
if(!ch.equals(curUser)) {
|
||||||
|
ch.damage(damage, this);
|
||||||
|
}else{
|
||||||
|
ch.damage(damage/6, this);
|
||||||
|
}
|
||||||
|
ch.sprite.centerEmitter().burst( PurpleParticle.BURST, Random.IntRange( 1, 2 ) );
|
||||||
|
ch.sprite.flash();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!curUser.isAlive() && alive) {
|
||||||
|
Dungeon.fail( getClass() );
|
||||||
|
GLog.n(Messages.get(this, "ondeath"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected int chargesPerCast() {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void wandProc(Char target, int chargesUsed){
|
||||||
|
wandProc(target, buffedLvl(), chargesUsed);
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO Consider externalizing char awareness buff
|
||||||
|
protected static void wandProc(Char target, int wandLevel, int chargesUsed){
|
||||||
|
if (Dungeon.hero.hasTalent(Talent.ARCANE_VISION)) {
|
||||||
|
int dur = 5 + 5*Dungeon.hero.pointsInTalent(Talent.ARCANE_VISION);
|
||||||
|
Buff.append(Dungeon.hero, TalismanOfForesight.CharAwareness.class, dur).charID = target.id();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (target != Dungeon.hero &&
|
||||||
|
Dungeon.hero.subClass == HeroSubClass.WARLOCK &&
|
||||||
|
//standard 1 - 0.92^x chance, plus 7%. Starts at 15%
|
||||||
|
Random.Float() > (Math.pow(0.92f, (wandLevel*chargesUsed)+1) - 0.07f)){
|
||||||
|
SoulMark.prolong(target, SoulMark.class, SoulMark.DURATION + wandLevel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final float MINOR_DEBUFF_WEAKEN = 1/4f;
|
||||||
|
private static final HashMap<Class<? extends Buff>, Float> MINOR_DEBUFFS = new HashMap<>();
|
||||||
|
static{
|
||||||
|
MINOR_DEBUFFS.put(Weakness.class, 2f);
|
||||||
|
MINOR_DEBUFFS.put(Corruption.class, 2f);
|
||||||
|
MINOR_DEBUFFS.put(Cripple.class, 1f);
|
||||||
|
MINOR_DEBUFFS.put(Blindness.class, 1f);
|
||||||
|
MINOR_DEBUFFS.put(Terror.class, 1f);
|
||||||
|
|
||||||
|
MINOR_DEBUFFS.put(Chill.class, 0f);
|
||||||
|
MINOR_DEBUFFS.put(Ooze.class, 0f);
|
||||||
|
MINOR_DEBUFFS.put(Corruption.class, 4f);
|
||||||
|
MINOR_DEBUFFS.put(Vertigo.class, 0f);
|
||||||
|
MINOR_DEBUFFS.put(Drowsy.class, 0f);
|
||||||
|
MINOR_DEBUFFS.put(Corruption.class, 10f);
|
||||||
|
MINOR_DEBUFFS.put(Burning.class, 0f);
|
||||||
|
MINOR_DEBUFFS.put(Poison.class, 0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final float MAJOR_DEBUFF_WEAKEN = 1/2f;
|
||||||
|
private static final HashMap<Class<? extends Buff>, Float> MAJOR_DEBUFFS = new HashMap<>();
|
||||||
|
static{
|
||||||
|
MAJOR_DEBUFFS.put(Corruption.class, 3f);
|
||||||
|
MAJOR_DEBUFFS.put(Slow.class, 2f);
|
||||||
|
MAJOR_DEBUFFS.put(Hex.class, 2f);
|
||||||
|
MAJOR_DEBUFFS.put(Paralysis.class, 1f);
|
||||||
|
|
||||||
|
MAJOR_DEBUFFS.put(Corruption.class, 0f);
|
||||||
|
MAJOR_DEBUFFS.put(Corruption.class, 0f);
|
||||||
|
MAJOR_DEBUFFS.put(MagicalSleep.class, 0f);
|
||||||
|
MAJOR_DEBUFFS.put(SoulMark.class, 0f);
|
||||||
|
MAJOR_DEBUFFS.put(Corrosion.class, 0f);
|
||||||
|
MAJOR_DEBUFFS.put(Frost.class, 0f);
|
||||||
|
MAJOR_DEBUFFS.put(Doom.class, 0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private void debuffEnemy( Mob enemy, HashMap<Class<? extends Buff>, Float> category ){
|
||||||
|
|
||||||
|
//do not consider buffs which are already assigned, or that the enemy is immune to.
|
||||||
|
HashMap<Class<? extends Buff>, Float> debuffs = new HashMap<>(category);
|
||||||
|
for (Buff existing : enemy.buffs()){
|
||||||
|
if (debuffs.containsKey(existing.getClass())) {
|
||||||
|
debuffs.put(existing.getClass(), 0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (Class<?extends Buff> toAssign : debuffs.keySet()){
|
||||||
|
if (debuffs.get(toAssign) > 0 && enemy.isImmune(toAssign)){
|
||||||
|
debuffs.put(toAssign, 0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//all buffs with a > 0 chance are flavor buffs
|
||||||
|
Class<?extends FlavourBuff> debuffCls = (Class<? extends FlavourBuff>) Random.chances(debuffs);
|
||||||
|
|
||||||
|
if (debuffCls != null){
|
||||||
|
Buff.append(enemy, debuffCls, 6 + buffedLvl()*3);
|
||||||
|
} else {
|
||||||
|
//if no debuff can be applied (all are present), then go up one tier
|
||||||
|
if (category == MINOR_DEBUFFS) debuffEnemy( enemy, MAJOR_DEBUFFS);
|
||||||
|
else if (category == MAJOR_DEBUFFS) corruptEnemy( enemy );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void corruptEnemy( Mob enemy ){
|
||||||
|
//cannot re-corrupt or doom an enemy, so give them a major debuff instead
|
||||||
|
if(enemy.buff(Corruption.class) != null || enemy.buff(Doom.class) != null){
|
||||||
|
GLog.w( Messages.get(this, "already_corrupted") );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!enemy.isImmune(Corruption.class)){
|
||||||
|
Corruption.corruptionHeal(enemy);
|
||||||
|
|
||||||
|
AllyBuff.affectAndLoot(enemy, curUser, Corruption.class);
|
||||||
|
} else {
|
||||||
|
Buff.affect(enemy, Doom.class);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static ArrayList<PointF> fxS = new ArrayList<>();
|
||||||
|
protected static ArrayList<PointF> fxE = new ArrayList<>();
|
||||||
|
|
||||||
|
public void fxs(Ballistica beam, Callback callback) {
|
||||||
|
MagicMissile.boltFromChar( curUser.sprite.parent,
|
||||||
|
MagicMissile.SHADOW,
|
||||||
|
curUser.sprite,
|
||||||
|
beam.collisionPos,
|
||||||
|
callback);
|
||||||
|
Sample.INSTANCE.play( Assets.Sounds.ZAP );
|
||||||
|
buildBeams(beam);
|
||||||
|
int size = fxE.size();
|
||||||
|
for(int i=0;i<size;++i){
|
||||||
|
//Point p = Dungeon.level.cellToPoint(fxE.get(i));
|
||||||
|
//GLog.i("(%d, %d)", p.x, p.y);
|
||||||
|
curUser.sprite.parent.add(new Beam.DeathRayS(BallisticaReal.raisedPointToScreen(fxS.get(i)),
|
||||||
|
BallisticaReal.raisedPointToScreen(fxE.get(i)) ));
|
||||||
|
}
|
||||||
|
callback.call();
|
||||||
|
}
|
||||||
|
protected static ArrayList<BallisticaReal> beams = new ArrayList<>();
|
||||||
|
protected static ArrayList<Float> offset_1 = new ArrayList<>();
|
||||||
|
protected void buildOffsetArray(int level){
|
||||||
|
offset_1.clear();
|
||||||
|
float offPerStep = 45f* (1.9f+level) / (1.9f+level*3f);
|
||||||
|
int maxDSB;
|
||||||
|
if(level>7){maxDSB = 0;}
|
||||||
|
else if(level>3){maxDSB = 0;}
|
||||||
|
else{maxDSB = 0;}
|
||||||
|
//offset_1.add(0f);
|
||||||
|
if(maxDSB>0) {
|
||||||
|
for (int i = -maxDSB; i < maxDSB + 1; ++i) {
|
||||||
|
offset_1.add(i * offPerStep / maxDSB);
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
offset_1.add(0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if(level<9) return base_3;
|
||||||
|
//else return base_4;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected PointF pointToF(Point p){
|
||||||
|
return new PointF(p.x, p.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void addBeam(BallisticaReal beam){
|
||||||
|
beams.add(beam);
|
||||||
|
fxS.add(beam.sourceF);
|
||||||
|
fxE.add(beam.collisionF);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void buildBeams(Ballistica beam){
|
||||||
|
fxS.clear();
|
||||||
|
fxE.clear();
|
||||||
|
beams.clear();
|
||||||
|
buildOffsetArray(this.level());
|
||||||
|
//addBeam(new Ballistica(beam.sourcePos, beam.collisionPos, Ballistica.STOP_SOLID | Ballistica.IGNORE_SOFT_SOLID));
|
||||||
|
float angle = PointF.angle(new PointF(pointToF(Dungeon.level.cellToPoint(beam.sourcePos))),
|
||||||
|
new PointF(pointToF(Dungeon.level.cellToPoint(beam.collisionPos))));
|
||||||
|
angle /= PointF.G2R;
|
||||||
|
if(angle<0f) angle += 360f;
|
||||||
|
//GLog.i("%f,", angle);
|
||||||
|
int scatter = offset_1.size();
|
||||||
|
for(int i=0;i<scatter;++i){
|
||||||
|
addBeam(new BallisticaReal(beam.sourcePos, angle + offset_1.get(i), 20, BallisticaReal.STOP_SOLID | BallisticaReal.IGNORE_SOFT_SOLID));
|
||||||
|
}
|
||||||
|
int maxRf = nReflections(this.level());
|
||||||
|
for(int ref = 0; ref < maxRf; ++ref) {
|
||||||
|
for (int i = 0; i < scatter; ++i) {
|
||||||
|
BallisticaReal br = new BallisticaReal(fxE.get(i+ref*scatter), reflectAngle(fxS.get(i+ref*scatter), fxE.get(i+ref*scatter)), 20, BallisticaReal.STOP_SOLID | BallisticaReal.IGNORE_SOFT_SOLID);
|
||||||
|
addBeam(br);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected float horizontalReflectAngle(float angle){
|
||||||
|
angle = angle%360f;
|
||||||
|
return 360f-angle;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected float verticalReflectAngle(float angle){
|
||||||
|
angle = angle%360f;
|
||||||
|
if(angle<180f) angle=180f-angle;
|
||||||
|
else angle = 540f-angle;
|
||||||
|
return angle;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected float reflectAngle(PointF s, PointF e){
|
||||||
|
//PointF realPoint = nextPF(s,e);
|
||||||
|
float angle = PointF.angle(s,e)/PointF.G2R;
|
||||||
|
if(angle<0f) angle+= 360f;
|
||||||
|
float dx = e.x - s.x;
|
||||||
|
float dy = e.y - s.y;
|
||||||
|
boolean up = dy>0;
|
||||||
|
boolean right = dx>0;
|
||||||
|
boolean horizontalWall = false;
|
||||||
|
boolean verticalWall = false;
|
||||||
|
|
||||||
|
int xTile=(int)e.x;
|
||||||
|
if(e.x-(int)e.x<1e-5 && right){
|
||||||
|
xTile-=1;
|
||||||
|
}
|
||||||
|
int yTile=(int)e.y;
|
||||||
|
if(e.y-(int)e.y<1e-5 && up){
|
||||||
|
yTile-=1;
|
||||||
|
}
|
||||||
|
final int[] neigh = new int[]{-1, 1, -Dungeon.level.width(), Dungeon.level.width()};
|
||||||
|
boolean[] isWall = new boolean[4];
|
||||||
|
for(int i=0; i<4; ++i){
|
||||||
|
isWall[i]=Dungeon.level.solid[xTile+yTile*Dungeon.level.width()+neigh[i]];
|
||||||
|
}
|
||||||
|
if(e.x-(int)e.x<1e-5){
|
||||||
|
verticalWall = (right && isWall[1]) || (!right && isWall[0]);
|
||||||
|
}
|
||||||
|
if(e.y-(int)e.y<1e-5){
|
||||||
|
horizontalWall = (up && isWall[3]) || (!up && isWall[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(horizontalWall != verticalWall){
|
||||||
|
if(horizontalWall) return horizontalReflectAngle(angle);
|
||||||
|
else return verticalReflectAngle(angle);
|
||||||
|
}else if(horizontalWall && verticalWall){
|
||||||
|
if(Math.abs(dx)<Math.abs(dy)){
|
||||||
|
return horizontalReflectAngle(angle);
|
||||||
|
}else{
|
||||||
|
return verticalReflectAngle(angle);
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
return angle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int STRReq(int C) {
|
public int STRReq(int C) {
|
||||||
|
@ -112,6 +682,12 @@ public class EndingBlade extends Weapon {
|
||||||
//常规加+1浊焰能量
|
//常规加+1浊焰能量
|
||||||
++fireenergy;
|
++fireenergy;
|
||||||
int dmg;
|
int dmg;
|
||||||
|
tier+= fireenergy/100;
|
||||||
|
|
||||||
|
if(TIME_TO_DIED != 0){
|
||||||
|
TIME_TO_DIED--;
|
||||||
|
}
|
||||||
|
|
||||||
if(level >= 10){
|
if(level >= 10){
|
||||||
fireenergy += 0;
|
fireenergy += 0;
|
||||||
//武器最高级
|
//武器最高级
|
||||||
|
@ -168,14 +744,16 @@ public class EndingBlade extends Weapon {
|
||||||
String info = desc();
|
String info = desc();
|
||||||
|
|
||||||
if (levelKnown) {
|
if (levelKnown) {
|
||||||
info += "\n\n" + Messages.get(MeleeWeapon.class, "stats_known", tier, augment.damageFactor(min()), augment.damageFactor(max()), STRReq());
|
info += "\n\n" + Messages.get(MeleeWeapon.class, "stats_known", 4+fireenergy/100,
|
||||||
|
augment.damageFactor(min()),
|
||||||
|
augment.damageFactor(max()), STRReq());
|
||||||
if (STRReq() > Dungeon.hero.STR()) {
|
if (STRReq() > Dungeon.hero.STR()) {
|
||||||
info += " " + Messages.get(Weapon.class, "too_heavy");
|
info += " " + Messages.get(Weapon.class, "too_heavy");
|
||||||
} else if (Dungeon.hero.STR() > STRReq()){
|
} else if (Dungeon.hero.STR() > STRReq()){
|
||||||
info += " " + Messages.get(Weapon.class, "excess_str", Dungeon.hero.STR() - STRReq());
|
info += " " + Messages.get(Weapon.class, "excess_str", Dungeon.hero.STR() - STRReq());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
info += "\n\n" + Messages.get(MeleeWeapon.class, "stats_unknown", tier, min(0), max(0), STRReq(0));
|
info += "\n\n" + Messages.get(MeleeWeapon.class, "stats_unknown", 4+fireenergy/100, min(0), max(0), STRReq(0));
|
||||||
if (STRReq(0) > Dungeon.hero.STR()) {
|
if (STRReq(0) > Dungeon.hero.STR()) {
|
||||||
info += " " + Messages.get(MeleeWeapon.class, "probably_too_heavy");
|
info += " " + Messages.get(MeleeWeapon.class, "probably_too_heavy");
|
||||||
}
|
}
|
||||||
|
|
|
@ -110,6 +110,10 @@ public abstract class Level implements Bundlable {
|
||||||
SECRETS
|
SECRETS
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isLevelExplored( int depth ){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
protected int width;
|
protected int width;
|
||||||
protected int height;
|
protected int height;
|
||||||
protected int length;
|
protected int length;
|
||||||
|
|
|
@ -29,12 +29,15 @@ import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.Statistics;
|
import com.shatteredpixel.shatteredpixeldungeon.Statistics;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
|
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.Blob;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.SacrificialFire;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.RandomBuff;
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.RandomBuff;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Talent;
|
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Talent;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.GoldenMimic;
|
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.GoldenMimic;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mimic;
|
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mimic;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob;
|
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Statue;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.Generator;
|
import com.shatteredpixel.shatteredpixeldungeon.items.Generator;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.Heap;
|
import com.shatteredpixel.shatteredpixeldungeon.items.Heap;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
|
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
|
||||||
|
@ -43,13 +46,16 @@ import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.DriedRose;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.food.SmallRation;
|
import com.shatteredpixel.shatteredpixeldungeon.items.food.SmallRation;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.journal.GuidePage;
|
import com.shatteredpixel.shatteredpixeldungeon.items.journal.GuidePage;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.keys.GoldenKey;
|
import com.shatteredpixel.shatteredpixeldungeon.items.keys.GoldenKey;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.items.keys.Key;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.journal.Document;
|
import com.shatteredpixel.shatteredpixeldungeon.journal.Document;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.journal.Notes;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.levels.builders.Builder;
|
import com.shatteredpixel.shatteredpixeldungeon.levels.builders.Builder;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.levels.builders.FigureEightBuilder;
|
import com.shatteredpixel.shatteredpixeldungeon.levels.builders.FigureEightBuilder;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.levels.builders.LoopBuilder;
|
import com.shatteredpixel.shatteredpixeldungeon.levels.builders.LoopBuilder;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.levels.painters.Painter;
|
import com.shatteredpixel.shatteredpixeldungeon.levels.painters.Painter;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.Room;
|
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.Room;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.secret.SecretRoom;
|
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.secret.SecretRoom;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.special.MagicalFireRoom;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.special.NxhyShopRoom;
|
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.special.NxhyShopRoom;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.special.NyzBombAndBooksRoom;
|
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.special.NyzBombAndBooksRoom;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.special.PitRoom;
|
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.special.PitRoom;
|
||||||
|
@ -83,6 +89,57 @@ public abstract class RegularLevel extends Level {
|
||||||
|
|
||||||
protected Room roomEntrance;
|
protected Room roomEntrance;
|
||||||
protected Room roomExit;
|
protected Room roomExit;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isLevelExplored( int depth ) {
|
||||||
|
//A level is considered fully explored if:
|
||||||
|
|
||||||
|
//There are no levelgen heaps which are undiscovered, in an openable container, or which contain keys
|
||||||
|
for (Heap h : heaps.valueList()){
|
||||||
|
if (h.autoExplored) continue;
|
||||||
|
|
||||||
|
if (!h.seen || (h.type != Heap.Type.HEAP && h.type != Heap.Type.FOR_SALE && h.type != Heap.Type.CRYSTAL_CHEST)){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (Item i : h.items){
|
||||||
|
if (i instanceof Key){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//There is no magical fire or sacrificial fire
|
||||||
|
for (Blob b : blobs.values()){
|
||||||
|
if (b.volume > 0 && (b instanceof MagicalFireRoom.EternalFire || b instanceof SacrificialFire)){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//There are no statues or mimics (unless they were made allies)
|
||||||
|
for (Mob m : mobs.toArray(new Mob[0])){
|
||||||
|
if (m.alignment != Char.Alignment.ALLY && (m instanceof Statue || m instanceof Mimic)){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//There are no barricades, locked doors, or hidden doors
|
||||||
|
for (int i = 0; i < length; i++){
|
||||||
|
if (map[i] == Terrain.BARRICADE || map[i] == Terrain.LOCKED_DOOR || map[i] == Terrain.SECRET_DOOR){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//There are no unused keys for this depth in the journal
|
||||||
|
for (Notes.KeyRecord rec : Notes.getRecords(Notes.KeyRecord.class)){
|
||||||
|
if (rec.depth() == depth){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Note that it is NOT required for the player to see every tile or discover every trap.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean build() {
|
protected boolean build() {
|
||||||
|
|
|
@ -0,0 +1,329 @@
|
||||||
|
package com.shatteredpixel.shatteredpixeldungeon.mechanics;
|
||||||
|
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.ShatteredPixelDungeon;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.tiles.DungeonTilemap;
|
||||||
|
import com.watabou.utils.Point;
|
||||||
|
import com.watabou.utils.PointF;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
//REAL ballistica means works like real;
|
||||||
|
//Normally ballistica in game can go through corners when the beam go through a wall
|
||||||
|
//but the tile of wall is not built in trace. (Because there is only one tile for each tile in main direction)
|
||||||
|
//However, REAL ballistica can't go through corners.
|
||||||
|
//It considers all the points the beam cross with each x and y integer
|
||||||
|
//So complex actions like reflection can work correctly.
|
||||||
|
//Walls, target cells, chars are considered as a whole tile. Even 0.001 tile collision would stop.
|
||||||
|
//Yeah it would be quite odd when this happens, but it works for now.
|
||||||
|
//Integer pos is considered at the center of tile.
|
||||||
|
public class BallisticaReal {
|
||||||
|
//Why here we do NOT record FULL path?
|
||||||
|
//first, introduction of range makes real collision quite messy if we add end point to path.
|
||||||
|
//second, real beam collides with boundary, which means it has already considered the next cell.
|
||||||
|
//if we want to control the full path, just build a never-stop one and go by tiles.
|
||||||
|
//third, it would cost much more if go through full path. There are cases when it updates each flash.
|
||||||
|
public ArrayList<Integer> pathI = new ArrayList<>();
|
||||||
|
public Integer sourceI = null;
|
||||||
|
public Integer collisionI = null;
|
||||||
|
public Integer dist = 0;
|
||||||
|
|
||||||
|
public ArrayList<PointF> pathF = new ArrayList<>();
|
||||||
|
public PointF sourceF = null;
|
||||||
|
public PointF collisionF = null;
|
||||||
|
|
||||||
|
public static final int STOP_TARGET = 1; //ballistica will stop at the target cell
|
||||||
|
public static final int STOP_CHARS = 2; //ballistica will stop on first char hit
|
||||||
|
public static final int STOP_SOLID = 4; //ballistica will stop on solid terrain
|
||||||
|
public static final int IGNORE_SOFT_SOLID = 8; //ballistica will ignore soft solid terrain, such as doors and webs
|
||||||
|
|
||||||
|
public static final int PROJECTILE = STOP_TARGET | STOP_CHARS | STOP_SOLID;
|
||||||
|
|
||||||
|
public static final int MAGIC_BOLT = STOP_CHARS | STOP_SOLID;
|
||||||
|
|
||||||
|
public static final int WONT_STOP = 0;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public BallisticaReal(PointF from, PointF to, int params) {
|
||||||
|
//sourcepos need to offset a bit to judge cases the from is on the line
|
||||||
|
//for example, from = "30, 20.5", to = "20, 0.5", x>=30 is wall
|
||||||
|
//if we do not offset, the source will be 30, 20, and when it collides with y=20,
|
||||||
|
//the wall judgement is centered at (30, 20), not (29, 20). First judgement will look at (30, 19) instead of (29,19)
|
||||||
|
//When it collides, it regards the upper ceil, wall, not empty. And the ballistica will end here.
|
||||||
|
|
||||||
|
//if the point is on the edge of cell, give it a tiny offset.
|
||||||
|
if(from.x-(int)from.x==0f || from.y-(int)from.y==0f) {
|
||||||
|
sourceI = pointToCell(pointFloatToInt(from.clone().offset(to.x - from.x > 0 ? 0.001f : -0.001f, to.y - from.y > 0 ? 0.001f : -0.001f), false));
|
||||||
|
}else{
|
||||||
|
sourceI = pointToCell(pointFloatToInt(from.clone(), false));
|
||||||
|
}
|
||||||
|
sourceF = from;
|
||||||
|
buildTrace(sourceF, to,
|
||||||
|
(params & STOP_TARGET) > 0,
|
||||||
|
(params & STOP_CHARS) > 0,
|
||||||
|
(params & STOP_SOLID) > 0,
|
||||||
|
(params & IGNORE_SOFT_SOLID) > 0);
|
||||||
|
|
||||||
|
if (collisionI != null) {
|
||||||
|
dist = pathI.indexOf(collisionI);
|
||||||
|
} else if (!pathI.isEmpty()) {
|
||||||
|
collisionI = pathI.get(dist = pathI.size() - 1);
|
||||||
|
collisionF = pathF.get(pathF.size()-1);
|
||||||
|
} else {
|
||||||
|
dist = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public BallisticaReal(int from, int to, int params){
|
||||||
|
this(pointIntToFloat(cellToPoint(from)).offset(0.5f, 0.45f),
|
||||||
|
pointIntToFloat(cellToPoint(to)).offset(0.5f, 0.45f),
|
||||||
|
params);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BallisticaReal(PointF from, float angle, float range, int params){
|
||||||
|
this(from, new PointF(from.x, from.y).offset(poleToPointF(angle, range)), params);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BallisticaReal(int from, float angle, float range, int params){
|
||||||
|
this(pointIntToFloat(cellToPoint(from)).offset(0.5f, 0.45f),angle,range,params);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void buildTrace(PointF from, PointF to, boolean stopTarget, boolean stopChars, boolean stopTerrain, boolean ignoreSoftSolid){
|
||||||
|
PointF vector = new PointF(to.x - from.x, to.y - from.y);
|
||||||
|
|
||||||
|
float dx;
|
||||||
|
float dy;
|
||||||
|
float movX = Math.abs(vector.x);
|
||||||
|
float movY = Math.abs(vector.y);
|
||||||
|
//too short move ,return
|
||||||
|
if(movX < 0.001f && movY < 0.001f){
|
||||||
|
int end = pointToCell(pointFloatToInt(from, false));
|
||||||
|
pathI.add(end);
|
||||||
|
pathF.add(from);
|
||||||
|
cld(end);
|
||||||
|
cldF(from);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//actually it is abandoned
|
||||||
|
if(movX>movY){
|
||||||
|
dx = (vector.x>0?1f:-1f);
|
||||||
|
dy = movY/movX*(vector.y>0?1f:-1f);
|
||||||
|
}else{
|
||||||
|
dy = (vector.y>0?1f:-1f);
|
||||||
|
dx = movX/movY*(vector.x>0?1f:-1f);
|
||||||
|
}
|
||||||
|
//which direction?
|
||||||
|
boolean up = dy>0;
|
||||||
|
boolean right = dx>0;
|
||||||
|
boolean vertical = Math.abs(dx)<0.001f;
|
||||||
|
boolean horizontal = Math.abs(dy)<0.001f;
|
||||||
|
//record current point
|
||||||
|
PointF curPosF = new PointF(from.x, from.y);
|
||||||
|
Point curPos = cellToPoint(sourceI);//pointFloatToInt(from, false);
|
||||||
|
//we shot into one tile, and meet one border. passable caches whether beam can pass this border.
|
||||||
|
boolean[] canPass = new boolean[4];
|
||||||
|
final int[] neigh = new int[]{-1, 1, Dungeon.level.width(), -Dungeon.level.width()};
|
||||||
|
|
||||||
|
pathI.add(sourceI);
|
||||||
|
pathF.add(sourceF);
|
||||||
|
/*
|
||||||
|
if (stopTerrain && Dungeon.level.solid[sourceI]) {
|
||||||
|
if (ignoreSoftSolid && (Dungeon.level.passable[sourceI] || Dungeon.level.avoid[sourceI])) {
|
||||||
|
//do nothing
|
||||||
|
} else {
|
||||||
|
cld(sourceI);
|
||||||
|
cldF(sourceF);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else if (stopChars && Actor.findChar( sourceI ) != null) {
|
||||||
|
cld(sourceI);
|
||||||
|
cldF(sourceF);
|
||||||
|
return;
|
||||||
|
} else if (sourceF.equals(pointFloatToInt(to, false)) && stopTarget){
|
||||||
|
cld(sourceI);
|
||||||
|
cldF(sourceF);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
while(isInsideMap(curPosF)){
|
||||||
|
int cell= pointToCell(curPos);
|
||||||
|
boolean passable;
|
||||||
|
//build passable
|
||||||
|
for(int i=0;i<4;++i){
|
||||||
|
int target = cell + neigh[i];
|
||||||
|
passable = true;
|
||||||
|
if (stopTerrain && Dungeon.level.solid[target]) {
|
||||||
|
if (ignoreSoftSolid && (Dungeon.level.passable[target] || Dungeon.level.avoid[target])) {
|
||||||
|
//do nothing
|
||||||
|
} else {
|
||||||
|
passable = false;
|
||||||
|
}
|
||||||
|
} else if (stopChars && Actor.findChar( target ) != null) {
|
||||||
|
passable = false;
|
||||||
|
} else if (curPos.equals(pointFloatToInt(to, false)) && stopTarget){
|
||||||
|
passable = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
canPass[i]=passable;
|
||||||
|
}
|
||||||
|
//will meet which border
|
||||||
|
boolean xOnLine = curPosF.x-(int)curPosF.x==0;
|
||||||
|
boolean yOnLine = curPosF.y-(int)curPosF.y==0;
|
||||||
|
float tx = (float) (xOnLine?(Math.floor(curPosF.x) + (right?1f:-1f)):(Math.floor(curPosF.x) + (right?1f:0f)));
|
||||||
|
float ty = (float) (yOnLine?(Math.floor(curPosF.y) + (up?1f:-1f)):(Math.floor(curPosF.y) + (up?1f:0f)));
|
||||||
|
//meet x border, y border, or both? And where?
|
||||||
|
PointF nx, ny;
|
||||||
|
if(vertical){
|
||||||
|
ny = new PointF(curPosF.x, ty);
|
||||||
|
nx = null;
|
||||||
|
}else if(horizontal){
|
||||||
|
nx = new PointF(tx, curPosF.y);
|
||||||
|
ny = null;
|
||||||
|
}else{
|
||||||
|
nx = new PointF(tx, (tx-curPosF.x)*dy/dx+curPosF.y);
|
||||||
|
ny = new PointF((ty-curPosF.y)*dx/dy+curPosF.x, ty);
|
||||||
|
|
||||||
|
if(nx.y==ny.y){
|
||||||
|
//nx==ny means reaching xy cross
|
||||||
|
//do nothing
|
||||||
|
}else if((up && nx.y>ny.y) || (!up && nx.y<ny.y)){
|
||||||
|
nx = null;
|
||||||
|
}else{
|
||||||
|
ny = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//out of range, stop
|
||||||
|
if(stopTarget){
|
||||||
|
if((nx != null && Math.abs(nx.x - from.x)>=movX) ||
|
||||||
|
(ny != null && Math.abs(ny.y - from.y)>=movY))
|
||||||
|
{
|
||||||
|
cldF(to);
|
||||||
|
cld(pointToCell(pointFloatToInt(to, false)));
|
||||||
|
pathI.add(collisionI);
|
||||||
|
pathF.add(collisionF);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//next cell, next pointF. Handle xy logic first.
|
||||||
|
int nextCell=cell;
|
||||||
|
if(ny==null){
|
||||||
|
nextCell += dx>0? 1:-1;
|
||||||
|
}else if(nx==null){
|
||||||
|
nextCell += dy>0?Dungeon.level.width():-Dungeon.level.width();
|
||||||
|
}else{
|
||||||
|
//if reach the xy cross, judge x and y
|
||||||
|
nextCell += dx>0? 1:-1;
|
||||||
|
for(int i=0; i<4; ++i){
|
||||||
|
if(neigh[i]+cell!=nextCell) continue;
|
||||||
|
if(!canPass[i]){
|
||||||
|
cld(nextCell+dy>0?Dungeon.level.width():-Dungeon.level.width());
|
||||||
|
cldF(nx);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
nextCell += dy>0?Dungeon.level.width():-Dungeon.level.width();
|
||||||
|
for(int i=0; i<4; ++i){
|
||||||
|
if(neigh[i]+cell!=nextCell) continue;
|
||||||
|
if(!canPass[i]){
|
||||||
|
cld(nextCell);
|
||||||
|
cldF(ny);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//if x and y let it pass, the go on
|
||||||
|
}
|
||||||
|
|
||||||
|
//judge whether can pass, and collide. For x or y logic
|
||||||
|
pathI.add(nextCell);
|
||||||
|
pathF.add(ny==null?nx.clone():ny.clone());
|
||||||
|
//has judged xy cross
|
||||||
|
if(nx == null || ny == null) {
|
||||||
|
for (int i = 0; i < 4; ++i) {
|
||||||
|
if (neigh[i] + cell != nextCell) continue;
|
||||||
|
if (!canPass[i]) {
|
||||||
|
cld(nextCell);
|
||||||
|
cldF(ny == null ? nx : ny);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//go on one point, and continue
|
||||||
|
curPosF=(ny==null?nx.clone():ny.clone());
|
||||||
|
curPos=cellToPoint(nextCell);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void cld(int cell){
|
||||||
|
if (collisionI == null)
|
||||||
|
collisionI = cell;
|
||||||
|
}
|
||||||
|
|
||||||
|
//using with new pointF
|
||||||
|
private void cldF(PointF cell){
|
||||||
|
if (collisionF == null) {
|
||||||
|
collisionF = cell.clone();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Integer> subPath(int start, int end){
|
||||||
|
try {
|
||||||
|
end = Math.min( end, pathI.size()-1);
|
||||||
|
return pathI.subList(start, end+1);
|
||||||
|
} catch (Exception e){
|
||||||
|
ShatteredPixelDungeon.reportException(e);
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PointF pointToScreen(PointF p){
|
||||||
|
return p.clone().scale(DungeonTilemap.SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PointF raisedPointToScreen(PointF p){
|
||||||
|
return p.clone().scale(DungeonTilemap.SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private static final float A2P = 0.0174533f;
|
||||||
|
|
||||||
|
//We assume up is positive y but in game it is opposite.
|
||||||
|
private static PointF poleToPointF(float angle, float range){
|
||||||
|
return new PointF((float)(range*Math.cos(angle*A2P)), (float)(range*Math.sin(angle*A2P)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isInsideMap(PointF posF){
|
||||||
|
return !(posF.x<1f || posF.x> Dungeon.level.width()-1f || posF.y<1f || posF.y>Dungeon.level.height()-1f);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Point cellToPoint(int cell ){
|
||||||
|
return new Point(cell % Dungeon.level.width(), cell / Dungeon.level.width());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int pointToCell( Point p ){
|
||||||
|
return p.x + p.y*Dungeon.level.width();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Point pointFloatToInt(PointF p, boolean round){
|
||||||
|
if(round){
|
||||||
|
return new Point(Math.round(p.x), Math.round(p.y));
|
||||||
|
}
|
||||||
|
return new Point((int)p.x, (int)p.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static PointF pointIntToFloat(Point p){
|
||||||
|
return new PointF(p.x, p.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PointF coordToScreen(PointF p){
|
||||||
|
return p.clone().offset(0.5f, 0.5f).scale(DungeonTilemap.SIZE);
|
||||||
|
}
|
||||||
|
}
|
|
@ -337,4 +337,7 @@ public class RenderedTextBlock extends Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void hardlight(float r, float g, float b) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,11 +21,15 @@
|
||||||
|
|
||||||
package com.shatteredpixel.shatteredpixeldungeon.windows;
|
package com.shatteredpixel.shatteredpixeldungeon.windows;
|
||||||
|
|
||||||
|
import static com.shatteredpixel.shatteredpixeldungeon.SPDSettings.HelpSettings;
|
||||||
|
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.ShatteredPixelDungeon;
|
import com.shatteredpixel.shatteredpixeldungeon.ShatteredPixelDungeon;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.Statistics;
|
import com.shatteredpixel.shatteredpixeldungeon.Statistics;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Hunger;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
|
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.custom.ch.GameTracker;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.custom.messages.M;
|
import com.shatteredpixel.shatteredpixeldungeon.custom.messages.M;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
|
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
|
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
|
||||||
|
@ -36,6 +40,7 @@ import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIcon;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIndicator;
|
import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIndicator;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.ui.IconButton;
|
import com.shatteredpixel.shatteredpixeldungeon.ui.IconButton;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.ui.Icons;
|
import com.shatteredpixel.shatteredpixeldungeon.ui.Icons;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.ui.RedButton;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.ui.RenderedTextBlock;
|
import com.shatteredpixel.shatteredpixeldungeon.ui.RenderedTextBlock;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.ui.ScrollPane;
|
import com.shatteredpixel.shatteredpixeldungeon.ui.ScrollPane;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.ui.StatusPane;
|
import com.shatteredpixel.shatteredpixeldungeon.ui.StatusPane;
|
||||||
|
@ -50,12 +55,13 @@ import com.watabou.noosa.ui.Component;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
public class WndHero extends WndTabbed {
|
public class WndHero extends WndTabbed {
|
||||||
|
|
||||||
private static final int WIDTH = 130;
|
private static final int WIDTH = 130;
|
||||||
private static final int HEIGHT = 120;
|
private static final int HEIGHT = 120;
|
||||||
|
|
||||||
private StatsTab stats;
|
private StatsTab stats;
|
||||||
private TalentsTab talents;
|
private TalentsTab talents;
|
||||||
private BuffsTab buffs;
|
private BuffsTab buffs;
|
||||||
|
@ -63,11 +69,11 @@ public class WndHero extends WndTabbed {
|
||||||
public static int lastIdx = 0;
|
public static int lastIdx = 0;
|
||||||
|
|
||||||
public WndHero() {
|
public WndHero() {
|
||||||
|
|
||||||
super();
|
super();
|
||||||
|
|
||||||
resize( WIDTH, HEIGHT );
|
resize( WIDTH, HEIGHT );
|
||||||
|
|
||||||
stats = new StatsTab();
|
stats = new StatsTab();
|
||||||
add( stats );
|
add( stats );
|
||||||
|
|
||||||
|
@ -79,7 +85,7 @@ public class WndHero extends WndTabbed {
|
||||||
add( buffs );
|
add( buffs );
|
||||||
buffs.setRect(0, 0, WIDTH, HEIGHT);
|
buffs.setRect(0, 0, WIDTH, HEIGHT);
|
||||||
buffs.setupList();
|
buffs.setupList();
|
||||||
|
|
||||||
add( new IconTab( Icons.get(Icons.RANKINGS) ) {
|
add( new IconTab( Icons.get(Icons.RANKINGS) ) {
|
||||||
protected void select( boolean value ) {
|
protected void select( boolean value ) {
|
||||||
super.select( value );
|
super.select( value );
|
||||||
|
@ -125,11 +131,11 @@ public class WndHero extends WndTabbed {
|
||||||
}
|
}
|
||||||
|
|
||||||
private class StatsTab extends Group {
|
private class StatsTab extends Group {
|
||||||
|
|
||||||
private static final int GAP = 6;
|
private static final int GAP = 4;
|
||||||
|
|
||||||
private float pos;
|
private float pos;
|
||||||
|
|
||||||
public StatsTab() {
|
public StatsTab() {
|
||||||
initialize();
|
initialize();
|
||||||
}
|
}
|
||||||
|
@ -140,18 +146,15 @@ public class WndHero extends WndTabbed {
|
||||||
if (g != null) g.destroy();
|
if (g != null) g.destroy();
|
||||||
}
|
}
|
||||||
clear();
|
clear();
|
||||||
|
|
||||||
Hero hero = Dungeon.hero;
|
Hero hero = Dungeon.hero;
|
||||||
|
|
||||||
IconTitle title = new IconTitle();
|
IconTitle title = new IconTitle();
|
||||||
title.icon( HeroSprite.avatar(hero.heroClass, hero.tier()) );
|
title.icon( HeroSprite.avatar(hero.heroClass, hero.tier()) );
|
||||||
if (hero.name().equals(hero.className())) {
|
if (hero.name().equals(hero.className()))
|
||||||
title.label(Messages.get(this, "title", Integer.valueOf(hero.lvl), hero.className()).toUpperCase(Locale.ENGLISH));
|
title.label( Messages.get(this, "title", hero.lvl, hero.className() ).toUpperCase( Locale.ENGLISH ) );
|
||||||
} else {
|
else
|
||||||
title.label((hero.name() + "\n" + Messages.get(this, "title", Integer.valueOf(hero.lvl),
|
title.label((hero.name() + "\n" + Messages.get(this, "title", hero.lvl, hero.className())).toUpperCase(Locale.ENGLISH));
|
||||||
hero.className())).toUpperCase(Locale.ENGLISH));
|
|
||||||
}
|
|
||||||
|
|
||||||
title.color(Window.TITLE_COLOR);
|
title.color(Window.TITLE_COLOR);
|
||||||
title.setRect( 0, 0, WIDTH-16, 0 );
|
title.setRect( 0, 0, WIDTH-16, 0 );
|
||||||
add(title);
|
add(title);
|
||||||
|
@ -176,7 +179,7 @@ public class WndHero extends WndTabbed {
|
||||||
infoButton.setRect(title.right(), 0, 16, 16);
|
infoButton.setRect(title.right(), 0, 16, 16);
|
||||||
add(infoButton);
|
add(infoButton);
|
||||||
|
|
||||||
pos = title.bottom() + 2*GAP;
|
pos = title.bottom() + GAP;
|
||||||
|
|
||||||
int strBonus = hero.STR() - hero.STR;
|
int strBonus = hero.STR() - hero.STR;
|
||||||
if (strBonus > 0) statSlot( Messages.get(this, "str"), hero.STR + " + " + strBonus );
|
if (strBonus > 0) statSlot( Messages.get(this, "str"), hero.STR + " + " + strBonus );
|
||||||
|
@ -190,33 +193,119 @@ public class WndHero extends WndTabbed {
|
||||||
|
|
||||||
statSlot( Messages.get(this, "gold"), Statistics.goldCollected );
|
statSlot( Messages.get(this, "gold"), Statistics.goldCollected );
|
||||||
statSlot( Messages.get(this, "depth"), Statistics.deepestFloor );
|
statSlot( Messages.get(this, "depth"), Statistics.deepestFloor );
|
||||||
|
statSlot( Messages.get(HeroStat.class, "seed_dungeon"), DungeonSeed.convertToCode(Dungeon.seed) );
|
||||||
statSlot( M.L(HeroStat.class,"seed_dungeon"), DungeonSeed.convertToCode(Dungeon.seed).toUpperCase());
|
|
||||||
|
|
||||||
pos += GAP;
|
pos += GAP;
|
||||||
|
|
||||||
|
Hunger hunger = Dungeon.hero.buff(Hunger.class);
|
||||||
|
String hunger_str = "null";
|
||||||
|
if(hunger != null){
|
||||||
|
hunger_str = hunger.hunger() + "/" + Hunger.STARVING;
|
||||||
|
}
|
||||||
|
statSlot( M.L(HeroStat.class, "hunger"), hunger_str);
|
||||||
|
|
||||||
|
pos += GAP;
|
||||||
|
|
||||||
|
RedButton buttonItem = new RedButton(M.L(HeroStat.class, "item_enter"), 8){
|
||||||
|
@Override
|
||||||
|
protected void onClick() {
|
||||||
|
super.onClick();
|
||||||
|
GameScene.show(new StatsTab.WndTreasureGenerated());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
add(buttonItem);
|
||||||
|
buttonItem.setRect(2, pos, WIDTH - 4, 16);
|
||||||
|
if(HelpSettings()){
|
||||||
|
buttonItem.active = true;
|
||||||
|
} else {
|
||||||
|
buttonItem.active = false;
|
||||||
|
buttonItem.visible = false;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void statSlot( String label, String value ) {
|
private void statSlot( String label, String value ) {
|
||||||
|
|
||||||
RenderedTextBlock txt = PixelScene.renderTextBlock( label, 8 );
|
RenderedTextBlock txt = PixelScene.renderTextBlock( label, 7 );
|
||||||
txt.setPos(0, pos);
|
txt.setPos(0, pos);
|
||||||
add( txt );
|
add( txt );
|
||||||
|
|
||||||
txt = PixelScene.renderTextBlock( value, 8 );
|
txt = PixelScene.renderTextBlock( value, 7 );
|
||||||
txt.setPos(WIDTH * 0.6f, pos);
|
txt.setPos(WIDTH * 0.5f, pos);
|
||||||
PixelScene.align(txt);
|
PixelScene.align(txt);
|
||||||
add( txt );
|
add( txt );
|
||||||
|
|
||||||
pos += GAP + txt.height();
|
pos += GAP + txt.height();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void statSlot( String label, int value ) {
|
private void statSlot( String label, int value ) {
|
||||||
statSlot( label, Integer.toString( value ) );
|
statSlot( label, Integer.toString( value ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
public float height() {
|
public float height() {
|
||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class WndTreasureGenerated extends Window{
|
||||||
|
private static final int WIDTH = 120;
|
||||||
|
private static final int HEIGHT = 144;
|
||||||
|
|
||||||
|
public WndTreasureGenerated(){
|
||||||
|
super();
|
||||||
|
resize(WIDTH, HEIGHT);
|
||||||
|
ScrollPane pane = new ScrollPane(new Component());
|
||||||
|
Component content = pane.content();
|
||||||
|
this.add(pane);
|
||||||
|
pane.setRect(0,0,WIDTH, HEIGHT);
|
||||||
|
|
||||||
|
GameTracker gmt = Dungeon.hero.buff(GameTracker.class);
|
||||||
|
if(gmt != null){
|
||||||
|
String allInfo = gmt.itemInfo();
|
||||||
|
String[] result = allInfo.split("\n");
|
||||||
|
float pos = 2;
|
||||||
|
for(String info: result){
|
||||||
|
if(info.contains("dungeon_depth")){
|
||||||
|
pos += 4;
|
||||||
|
RenderedTextBlock depthText = PixelScene.renderTextBlock(info.replace("dungeon_depth: ", M.L(HeroStat.class, "item_wnd_depth")), 8);
|
||||||
|
depthText.maxWidth(WIDTH);
|
||||||
|
depthText.hardlight(0xFFFF00);
|
||||||
|
content.add(depthText);
|
||||||
|
depthText.setPos(0, pos);
|
||||||
|
pos += 8;
|
||||||
|
}else{
|
||||||
|
pos += 1;
|
||||||
|
info = info.replace("MIMIC_HOLD", M.L(HeroStat.class, "item_wnd_mimic"));
|
||||||
|
info = info.replace("QUEST_REWARD", M.L(HeroStat.class, "item_wnd_reward"));
|
||||||
|
info = info.replace("CURSED", M.L(HeroStat.class, "item_wnd_cursed"));
|
||||||
|
RenderedTextBlock itemText = PixelScene.renderTextBlock(info, 6);
|
||||||
|
itemText.maxWidth(WIDTH);
|
||||||
|
content.add(itemText);
|
||||||
|
itemText.setPos(0, pos);
|
||||||
|
pos += 6;
|
||||||
|
String level = Pattern.compile("[^0-9]").matcher(info).replaceAll("").trim();
|
||||||
|
try{
|
||||||
|
int lvl = Integer.parseInt(level);
|
||||||
|
if(lvl == 1){
|
||||||
|
itemText.hardlight(0x57FAFF);
|
||||||
|
}else if(lvl == 2){
|
||||||
|
itemText.hardlight(0xA000A0);
|
||||||
|
}else if(lvl == 3){
|
||||||
|
itemText.hardlight(0xFFB700);
|
||||||
|
}else if(lvl >= 4) {
|
||||||
|
itemText.hardlight(Window.Pink_COLOR);
|
||||||
|
}
|
||||||
|
}catch (Exception e){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
content.setSize(WIDTH, pos + 2);
|
||||||
|
}
|
||||||
|
pane.scrollTo(0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class TalentsTab extends Component {
|
public class TalentsTab extends Component {
|
||||||
|
|
|
@ -32,6 +32,7 @@ import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.scenes.PixelScene;
|
import com.shatteredpixel.shatteredpixeldungeon.scenes.PixelScene;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.services.news.News;
|
import com.shatteredpixel.shatteredpixeldungeon.services.news.News;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.CharSprite;
|
import com.shatteredpixel.shatteredpixeldungeon.sprites.CharSprite;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.sprites.CrossDiedSprites;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.ui.CheckBox;
|
import com.shatteredpixel.shatteredpixeldungeon.ui.CheckBox;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.ui.GameLog;
|
import com.shatteredpixel.shatteredpixeldungeon.ui.GameLog;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.ui.Icons;
|
import com.shatteredpixel.shatteredpixeldungeon.ui.Icons;
|
||||||
|
@ -66,6 +67,7 @@ public class WndSettings extends WndTabbed {
|
||||||
private AudioTab audio;
|
private AudioTab audio;
|
||||||
private LangsTab langs;
|
private LangsTab langs;
|
||||||
private ExtendTab extabs;
|
private ExtendTab extabs;
|
||||||
|
private HelpTab helps;
|
||||||
|
|
||||||
public static int last_index = 0;
|
public static int last_index = 0;
|
||||||
|
|
||||||
|
@ -176,6 +178,20 @@ public class WndSettings extends WndTabbed {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
helps = new HelpTab();
|
||||||
|
helps.setSize(width, 0);
|
||||||
|
height = Math.max(height, audio.height());
|
||||||
|
add( helps );
|
||||||
|
|
||||||
|
add( new IconTab(new CrossDiedSprites()){
|
||||||
|
@Override
|
||||||
|
protected void select(boolean value) {
|
||||||
|
super.select(value);
|
||||||
|
helps.visible = helps.active = value;
|
||||||
|
if (value) last_index = 6;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
resize(width, (int)Math.ceil(height));
|
resize(width, (int)Math.ceil(height));
|
||||||
|
|
||||||
layoutTabs();
|
layoutTabs();
|
||||||
|
@ -663,6 +679,54 @@ public class WndSettings extends WndTabbed {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class HelpTab extends Component {
|
||||||
|
|
||||||
|
RenderedTextBlock title;
|
||||||
|
ColorBlock sep1;
|
||||||
|
CheckBox LockFing;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void createChildren() {
|
||||||
|
title = PixelScene.renderTextBlock(Messages.get(this, "title"), 9);
|
||||||
|
title.hardlight(TITLE_COLOR);
|
||||||
|
add(title);
|
||||||
|
|
||||||
|
sep1 = new ColorBlock(1, 1, 0xFF000000);
|
||||||
|
add(sep1);
|
||||||
|
|
||||||
|
LockFing = new CheckBox( Messages.get(this, "helpsettings") ) {
|
||||||
|
@Override
|
||||||
|
protected void onClick() {
|
||||||
|
super.onClick();
|
||||||
|
SPDSettings.HelpSettings(checked());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
LockFing.checked(SPDSettings.HelpSettings());
|
||||||
|
add(LockFing);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void layout() {
|
||||||
|
|
||||||
|
float bottom = y;
|
||||||
|
|
||||||
|
title.setPos((width - title.width())/2, bottom + GAP);
|
||||||
|
sep1.size(width, 1);
|
||||||
|
sep1.y = title.bottom() + 2*GAP;
|
||||||
|
|
||||||
|
bottom = sep1.y + 1;
|
||||||
|
|
||||||
|
if (width > 200){
|
||||||
|
LockFing.setRect(0, bottom, width, SLIDER_HEIGHT);
|
||||||
|
} else {
|
||||||
|
LockFing.setRect(0, bottom + GAP, width, SLIDER_HEIGHT);
|
||||||
|
}
|
||||||
|
|
||||||
|
height = LockFing.bottom();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
private static class DataTab extends Component{
|
private static class DataTab extends Component{
|
||||||
|
|
||||||
RenderedTextBlock title;
|
RenderedTextBlock title;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user