v3.0.0: added 'quick cast' functionality for cleric spells
This commit is contained in:
Binary file not shown.
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.6 KiB |
@@ -343,6 +343,7 @@ items.artifacts.etherealchains$chainsrecharge.levelup=Your chains grow stronger!
|
||||
items.artifacts.holytome.name=holy tome
|
||||
items.artifacts.holytome.ac_cast=CAST
|
||||
items.artifacts.holytome.no_charge=Your tome is out of charge. Gain exp to recharge it.
|
||||
items.artifacts.holytome.no_spell=You're not able to cast that spell right now.
|
||||
items.artifacts.holytome.levelup=Your tome grows stronger!
|
||||
items.artifacts.holytome.desc=A holy tome that acts as a focus for the Cleric's divine magic. Using the tome lets the Cleric cast a variety of magical spells.\n\nThe tome will steadily get more powerful as the Cleric uses it, and it will recharge as the Cleric gains experience points when defeating enemies.
|
||||
|
||||
|
||||
@@ -41,8 +41,12 @@ windows.wndclass.mastery=Mastery
|
||||
|
||||
windows.wndclericspells.cast_title=cast a spell
|
||||
windows.wndclericspells.info_title=spell info
|
||||
windows.wndclericspells.cast_desc=Select a spell to cast it, or press the info button to switch to info mode.
|
||||
windows.wndclericspells.cast_desc_desktop=Select a spell to cast it, right click for info or to set a spell to quick cast.
|
||||
windows.wndclericspells.cast_desc_mobile=Select a spell to cast it, long press to set a spell to quick cast, or press the info button to switch to info mode.
|
||||
windows.wndclericspells.info_desc=Select a spell to learn about it, or press the info button to switch to cast mode.
|
||||
windows.wndclericspells.cast=Cast
|
||||
windows.wndclericspells.info=Info
|
||||
windows.wndclericspells.quick_cast=Quick Cast
|
||||
|
||||
windows.wndcombo.title=choose a combo move
|
||||
windows.wndcombo.combo_req=(%d combo)
|
||||
|
||||
@@ -119,6 +119,19 @@ public abstract class ClericSpell {
|
||||
}
|
||||
|
||||
return spells;
|
||||
};
|
||||
}
|
||||
|
||||
public static ArrayList<ClericSpell> getAllSpells() {
|
||||
ArrayList<ClericSpell> spells = new ArrayList<>();
|
||||
spells.add(GuidingLight.INSTANCE);
|
||||
spells.add(HolyWeapon.INSTANCE);
|
||||
spells.add(HolyWard.INSTANCE);
|
||||
spells.add(ShieldOfLight.INSTANCE);
|
||||
spells.add(DetectCurse.INSTANCE);
|
||||
spells.add(Sunray.INSTANCE);
|
||||
spells.add(RecallGlyph.INSTANCE);
|
||||
spells.add(DivineSense.INSTANCE);
|
||||
spells.add(HolyLance.INSTANCE);
|
||||
return spells;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,7 +86,9 @@ public class GuidingLight extends TargetedClericSpell {
|
||||
hero.next();
|
||||
|
||||
onSpellCast(tome, hero);
|
||||
Buff.affect(hero, GuidingLightPriestCooldown.class, 100f);
|
||||
if (hero.subClass == HeroSubClass.PRIEST) {
|
||||
Buff.affect(hero, GuidingLightPriestCooldown.class, 100f);
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
@@ -26,6 +26,8 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.MagicImmune;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Talent;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.spells.ClericSpell;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.spells.DetectCurse;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.spells.TargetedClericSpell;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.bags.Bag;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.rings.RingOfEnergy;
|
||||
@@ -33,8 +35,12 @@ import com.shatteredpixel.shatteredpixeldungeon.journal.Catalog;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.ui.ActionIndicator;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.ui.HeroIcon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.ui.QuickSlotButton;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.windows.WndClericSpells;
|
||||
import com.watabou.utils.Bundle;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
@@ -203,7 +209,45 @@ public class HolyTome extends Artifact {
|
||||
}
|
||||
}
|
||||
|
||||
public class TomeRecharge extends ArtifactBuff {
|
||||
private ClericSpell quickSpell = null;
|
||||
|
||||
public void setQuickSpell(ClericSpell spell){
|
||||
quickSpell = spell;
|
||||
if (passiveBuff != null){
|
||||
ActionIndicator.setAction((ActionIndicator.Action) passiveBuff);
|
||||
}
|
||||
}
|
||||
|
||||
private static final String QUICK_CLS = "quick_cls";
|
||||
|
||||
@Override
|
||||
public void storeInBundle(Bundle bundle) {
|
||||
super.storeInBundle(bundle);
|
||||
if (quickSpell != null) {
|
||||
bundle.put(QUICK_CLS, quickSpell.getClass());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreFromBundle(Bundle bundle) {
|
||||
super.restoreFromBundle(bundle);
|
||||
if (bundle.contains(QUICK_CLS)){
|
||||
Class quickCls = bundle.getClass(QUICK_CLS);
|
||||
for (ClericSpell spell : ClericSpell.getAllSpells()){
|
||||
if (spell.getClass() == quickCls){
|
||||
quickSpell = spell;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class TomeRecharge extends ArtifactBuff implements ActionIndicator.Action {
|
||||
|
||||
@Override
|
||||
public void fx(boolean on) {
|
||||
if (on && quickSpell != null) ActionIndicator.setAction(this);
|
||||
else ActionIndicator.clearAction(this);
|
||||
}
|
||||
|
||||
public void gainCharge(float levelPortion) {
|
||||
if (cursed || target.buff(MagicImmune.class) != null) return;
|
||||
@@ -242,6 +286,51 @@ public class HolyTome extends Artifact {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String actionName() {
|
||||
return quickSpell.name();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int actionIcon() {
|
||||
return quickSpell.icon() + HeroIcon.SPELL_ACTION_OFFSET;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int indicatorColor() {
|
||||
if (quickSpell == DetectCurse.INSTANCE){
|
||||
return 0x00A0FF;
|
||||
} else {
|
||||
return 0x002157;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doAction() {
|
||||
if (!canCast(Dungeon.hero, quickSpell)){
|
||||
GLog.w(Messages.get(HolyTome.this, "no_spell"));
|
||||
return;
|
||||
}
|
||||
|
||||
//TODO this is all pretty akward, might be better to just add autotarget functionality to the indicator
|
||||
if (QuickSlotButton.targetingSlot != -1 &&
|
||||
Dungeon.quickslot.getItem(QuickSlotButton.targetingSlot) == HolyTome.this) {
|
||||
int cell = QuickSlotButton.autoAim(QuickSlotButton.lastTarget, HolyTome.this);
|
||||
|
||||
if (cell != -1){
|
||||
GameScene.handleCell(cell);
|
||||
} else {
|
||||
//couldn't auto-aim, just target the position and hope for the best.
|
||||
GameScene.handleCell( QuickSlotButton.lastTarget.pos );
|
||||
}
|
||||
} else {
|
||||
quickSpell.onCast(HolyTome.this, Dungeon.hero);
|
||||
|
||||
if (quickSpell instanceof TargetedClericSpell && Dungeon.quickslot.contains(HolyTome.this)){
|
||||
QuickSlotButton.useTargeting(Dungeon.quickslot.getSlot(HolyTome.this));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -83,15 +83,17 @@ public class HeroIcon extends Image {
|
||||
public static final int RECALL_GLYPH = 47;
|
||||
public static final int HOLY_LANCE = 48;
|
||||
|
||||
//action indicator visuals
|
||||
public static final int BERSERK = 80;
|
||||
public static final int COMBO = 81;
|
||||
public static final int PREPARATION = 82;
|
||||
public static final int MOMENTUM = 83;
|
||||
public static final int SNIPERS_MARK = 84;
|
||||
public static final int WEAPON_SWAP = 85;
|
||||
public static final int MONK_ABILITIES = 86;
|
||||
//all cleric spells have a separate icon with no background for the action indicator
|
||||
public static final int SPELL_ACTION_OFFSET = 32;
|
||||
|
||||
//action indicator visuals
|
||||
public static final int BERSERK = 104;
|
||||
public static final int COMBO = 105;
|
||||
public static final int PREPARATION = 106;
|
||||
public static final int MOMENTUM = 107;
|
||||
public static final int SNIPERS_MARK = 108;
|
||||
public static final int WEAPON_SWAP = 109;
|
||||
public static final int MONK_ABILITIES = 110;
|
||||
|
||||
public HeroIcon(HeroSubClass subCls){
|
||||
super( Assets.Interfaces.HERO_ICONS );
|
||||
|
||||
@@ -38,9 +38,15 @@ import com.shatteredpixel.shatteredpixeldungeon.ui.IconButton;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.ui.Icons;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.ui.QuickSlotButton;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.ui.RenderedTextBlock;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.ui.RightClickMenu;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.ui.Window;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
|
||||
import com.watabou.input.PointerEvent;
|
||||
import com.watabou.noosa.ColorBlock;
|
||||
import com.watabou.noosa.Image;
|
||||
import com.watabou.noosa.NinePatch;
|
||||
import com.watabou.utils.DeviceCompat;
|
||||
import com.watabou.utils.PointF;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
@@ -67,8 +73,14 @@ public class WndClericSpells extends Window {
|
||||
btnInfo.setRect(WIDTH-16, 0, 16, 16);
|
||||
add(btnInfo);
|
||||
|
||||
//TODO we might want to intercept quickslot hotkeys and auto-cast the last spell if relevant
|
||||
RenderedTextBlock msg = PixelScene.renderTextBlock( Messages.get( this, info ? "info_desc" : "cast_desc"), 6);
|
||||
RenderedTextBlock msg;
|
||||
if (info){
|
||||
msg = PixelScene.renderTextBlock( Messages.get( this, "info_desc"), 6);
|
||||
} else if (DeviceCompat.isDesktop()){
|
||||
msg = PixelScene.renderTextBlock( Messages.get( this, "cast_desc_desktop"), 6);
|
||||
} else {
|
||||
msg = PixelScene.renderTextBlock( Messages.get( this, "cast_desc_mobile"), 6);
|
||||
}
|
||||
msg.maxWidth(WIDTH);
|
||||
msg.setPos(0, title.bottom()+4);
|
||||
add(msg);
|
||||
@@ -127,8 +139,8 @@ public class WndClericSpells extends Window {
|
||||
this.tome = tome;
|
||||
this.info = info;
|
||||
|
||||
if (!info && !tome.canCast(Dungeon.hero, spell)){
|
||||
enable(false);
|
||||
if (!tome.canCast(Dungeon.hero, spell)){
|
||||
icon.alpha( 0.3f );
|
||||
}
|
||||
|
||||
bg = Chrome.get(Chrome.Type.TOAST);
|
||||
@@ -152,15 +164,73 @@ public class WndClericSpells extends Window {
|
||||
GameScene.show(new WndTitledMessage(new HeroIcon(spell), Messages.titleCase(spell.name()), spell.desc()));
|
||||
} else {
|
||||
hide();
|
||||
spell.onCast(tome, Dungeon.hero);
|
||||
|
||||
//TODO, probably need targeting logic here
|
||||
if (spell instanceof TargetedClericSpell && Dungeon.quickslot.contains(tome)){
|
||||
QuickSlotButton.useTargeting(Dungeon.quickslot.getSlot(tome));
|
||||
|
||||
if(!spell.canCast(Dungeon.hero)){
|
||||
GLog.w(Messages.get(HolyTome.class, "no_spell"));
|
||||
} else {
|
||||
spell.onCast(tome, Dungeon.hero);
|
||||
|
||||
//TODO, probably need targeting logic here
|
||||
if (spell instanceof TargetedClericSpell && Dungeon.quickslot.contains(tome)){
|
||||
QuickSlotButton.useTargeting(Dungeon.quickslot.getSlot(tome));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean onLongClick() {
|
||||
hide();
|
||||
tome.setQuickSpell(spell);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRightClick() {
|
||||
super.onRightClick();
|
||||
RightClickMenu r = new RightClickMenu(new Image(icon),
|
||||
Messages.titleCase(spell.name()),
|
||||
Messages.get(WndClericSpells.class, "cast"),
|
||||
Messages.get(WndClericSpells.class, "info"),
|
||||
Messages.get(WndClericSpells.class, "quick_cast")){
|
||||
@Override
|
||||
public void onSelect(int index) {
|
||||
switch (index){
|
||||
default:
|
||||
//do nothing
|
||||
break;
|
||||
case 0:
|
||||
hide();
|
||||
if(!spell.canCast(Dungeon.hero)){
|
||||
GLog.w(Messages.get(HolyTome.class, "no_spell"));
|
||||
} else {
|
||||
spell.onCast(tome, Dungeon.hero);
|
||||
|
||||
//TODO, probably need targeting logic here
|
||||
if (spell instanceof TargetedClericSpell && Dungeon.quickslot.contains(tome)){
|
||||
QuickSlotButton.useTargeting(Dungeon.quickslot.getSlot(tome));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
GameScene.show(new WndTitledMessage(new HeroIcon(spell), Messages.titleCase(spell.name()), spell.desc()));
|
||||
break;
|
||||
case 2:
|
||||
hide();
|
||||
tome.setQuickSpell(spell);
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
parent.addToFront(r);
|
||||
r.camera = camera();
|
||||
PointF mousePos = PointerEvent.currentHoverPos();
|
||||
mousePos = camera.screenToCamera((int)mousePos.x, (int)mousePos.y);
|
||||
r.setPos(mousePos.x-3, mousePos.y-3);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String hoverText() {
|
||||
return "_" + Messages.titleCase(spell.name()) + "_\n" + spell.shortDesc();
|
||||
|
||||
Reference in New Issue
Block a user