v0.9.3: implemented the spirit hawk ability
This commit is contained in:
parent
4bf8ac0383
commit
e22b12c6d3
|
@ -387,13 +387,19 @@ actors.hero.abilities.huntress.spectralblades.name=spectral blades
|
|||
actors.hero.abilities.huntress.spectralblades.short_desc=The Huntress throws _Spectral Blades_ at a target, inflicting damage depending on her currently equipped melee weapon.
|
||||
actors.hero.abilities.huntress.spectralblades.desc=The Huntress throws out a spectral blade at an enemy, which acts like a ranged strike from her melee weapon. All of the normal effects of a melee weapon will activate, including enchantments.\n\nThis ability costs 25 charge.
|
||||
actors.hero.abilities.huntress.naturespower.name=nature's power
|
||||
actors.hero.abilities.huntress.naturespower$naturespowertracker.name=nature's power
|
||||
actors.hero.abilities.huntress.naturespower$naturespowertracker.desc=The Huntress is briefly empowered, increasing her movement speed and attack speed with her bow.\n\nTurns remaining: %s.
|
||||
actors.hero.abilities.huntress.naturespower.short_desc=The Huntress calls upon _Nature's Power_, increasing her movement speed and her bow's rate of fire for a short time.
|
||||
actors.hero.abilities.huntress.naturespower.desc=The Huntress temporarily empowers herself and her bow with the power of nature! This lasts for 8 turns.\n\nDuring this time, the huntress moves at 2x speed, and attacks 33% faster with her bow. The bonus bow effects do not trigger if the sniper is using her special attacks.\n\nThis ability costs 35 charge.
|
||||
actors.hero.abilities.huntress.naturespower$naturespowertracker.name=nature's power
|
||||
actors.hero.abilities.huntress.naturespower$naturespowertracker.desc=The Huntress is briefly empowered, increasing her movement speed and attack speed with her bow.\n\nTurns remaining: %s.
|
||||
actors.hero.abilities.huntress.spirithawk.name=spirit hawk
|
||||
actors.hero.abilities.huntress.spirithawk.no_space=There is no free space near you.
|
||||
actors.hero.abilities.huntress.spirithawk.short_desc=The Huntress summons a _Spirit Hawk_ familiar, which can help her scout locations and distract enemies.
|
||||
actors.hero.abilities.huntress.spirithawk.desc=TODO
|
||||
actors.hero.abilities.huntress.spirithawk.desc=The Huntress summons a spirit hawk familiar, which can be directed by using the ability again while it is summoned. The hawk lasts for 50 turns.\n\nThe hawk has minimal health and attacking power, but is fast, evasive, and accurate. It shares its entire field of vision with the huntress at all times. It is immune to all area-bound effects, such as fire and poison gas. It will not attack unless specifically directed to.\n\nSummoning the hawk costs 35 charge.
|
||||
actors.hero.abilities.huntress.spirithawk$hawkally.name=spirit hawk
|
||||
actors.hero.abilities.huntress.spirithawk$hawkally.direct_follow=Your hawk moves to follow you.
|
||||
actors.hero.abilities.huntress.spirithawk$hawkally.direct_attack=Your hawk moves to attack!
|
||||
actors.hero.abilities.huntress.spirithawk$hawkally.desc=A magical hawk, summoned by the Huntress.\n\nWhile it isn't much of a fighter its speed and vision make it excellent for scouting and distracting enemies.\n\nTurns remaining: %d.
|
||||
actors.hero.abilities.huntress.spirithawk$hawkally.desc_dodges=Guaranteed dodges remaining: %d.
|
||||
|
||||
actors.hero.abilities.ratmogrify.name=ratmogrify
|
||||
actors.hero.abilities.ratmogrify.cant_transform=You can't ratmogrify that!
|
||||
|
@ -706,12 +712,12 @@ actors.hero.talent.natures_wrath.desc=_+1:_ While nature's power is active, shot
|
|||
actors.hero.talent.wild_momentum.title=wild momentum
|
||||
actors.hero.talent.wild_momentum.desc=_+1:_ Killing an enemy with the spirit bow prolongs the duration of nature's power by _1 turn_. The duration can be extended by a max of _2 turns_.\n\n_+2:_ Killing an enemy with the spirit bow prolongs the duration of nature's power by _2 turns_. The duration can be extended by a max of _4 turns_.\n\n_+3:_ Killing an enemy with the spirit bow prolongs the duration of nature's power by _3 turns_. The duration can be extended by a max of _6 turns_.\n\n_+4:_ Killing an enemy with the spirit bow prolongs the duration of nature's power by _4 turns_. The duration can be extended by a max of _8 turns_.
|
||||
|
||||
actors.hero.talent.huntress_3_1.title=TODO NAME
|
||||
actors.hero.talent.huntress_3_1.desc=_+1:_ \n\n_+2:_ \n\n_+3:_ \n\n_+4:_
|
||||
actors.hero.talent.huntress_3_2.title=TODO NAME
|
||||
actors.hero.talent.huntress_3_2.desc=_+1:_ \n\n_+2:_ \n\n_+3:_ \n\n_+4:_
|
||||
actors.hero.talent.huntress_3_3.title=TODO NAME
|
||||
actors.hero.talent.huntress_3_3.desc=_+1:_ \n\n_+2:_ \n\n_+3:_ \n\n_+4:_
|
||||
actors.hero.talent.eagle_eye.title=eagle eye
|
||||
actors.hero.talent.eagle_eye.desc=_+1:_ The spirit hawk's vision range is increased to _7 tiles_ from 6.\n\n_+2:_ The spirit hawk's vision range is increased to _8 tiles_ from 6.\n\n_+3:_ The spirit hawk's vision range is increased to _8 tiles_ from 6, and it gets _2 tiles_ of mind vision.\n\n_+4:_ The spirit hawk's vision range is increased to _8 tiles_ from 6, and it gets _3 tiles_ of mind vision.
|
||||
actors.hero.talent.go_for_the_eyes.title=go for the eyes
|
||||
actors.hero.talent.go_for_the_eyes.desc=_+1:_ Attacks from the spirit hawk blind enemies for _2 turns_.\n\n_+2:_ Attacks from the spirit hawk blind enemies for _3 turns_.\n\n_+3:_ Attacks from the spirit hawk blind enemies for _4 turns_.\n\n_+4:_ Attacks from the spirit hawk blind enemies for _5 turns_.
|
||||
actors.hero.talent.swift_spirit.title=swift spirit
|
||||
actors.hero.talent.swift_spirit.desc=_+1:_ The spirit hawk's movement speed is increased to _2.5 tiles_ from 2, and it is guaranteed to dodge the first _1 attack_ made against it.\n\n_+2:_ The spirit hawk's movement speed is increased to _3 tiles_ from 2, and it is guaranteed to dodge the first _2 attacks_ made against it.\n\n_+3:_ The spirit hawk's movement speed is increased to _3.5 tiles_ from 2, and it is guaranteed to dodge the first _3 attacks_ made against it.\n\n_+4:_The spirit hawk's movement speed is increased to _4 tiles_ from 2, and it is guaranteed to dodge the first _4 attacks_ made against it.
|
||||
|
||||
#universal
|
||||
actors.hero.talent.heroic_energy.title=heroic energy
|
||||
|
|
|
@ -30,6 +30,7 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.MindVision;
|
|||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.RevealedArea;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Talent;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.abilities.huntress.SpiritHawk;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.Blacksmith;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.Ghost;
|
||||
|
@ -43,6 +44,8 @@ import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.TalismanOfForesi
|
|||
import com.shatteredpixel.shatteredpixeldungeon.items.potions.Potion;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.rings.Ring;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.Scroll;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfRegrowth;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfWarding;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.journal.Notes;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.CavesLevel;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.CityLevel;
|
||||
|
@ -764,6 +767,33 @@ public class Dungeon {
|
|||
GameScene.updateFog(a.pos, 2);
|
||||
}
|
||||
|
||||
for (Char ch : Actor.chars()){
|
||||
if (ch instanceof WandOfWarding.Ward
|
||||
|| ch instanceof WandOfRegrowth.Lotus
|
||||
|| ch instanceof SpiritHawk.HawkAlly){
|
||||
x = ch.pos % level.width();
|
||||
y = ch.pos / level.width();
|
||||
|
||||
//left, right, top, bottom
|
||||
dist = ch.viewDistance+1;
|
||||
l = Math.max( 0, x - dist );
|
||||
r = Math.min( x + dist, level.width() - 1 );
|
||||
t = Math.max( 0, y - dist );
|
||||
b = Math.min( y + dist, level.height() - 1 );
|
||||
|
||||
width = r - l + 1;
|
||||
height = b - t + 1;
|
||||
|
||||
pos = l + t * level.width();
|
||||
|
||||
for (int i = t; i <= b; i++) {
|
||||
BArray.or( level.visited, level.heroFOV, pos, width, level.visited );
|
||||
pos+=level.width();
|
||||
}
|
||||
GameScene.updateFog(ch.pos, dist);
|
||||
}
|
||||
}
|
||||
|
||||
GameScene.afterObserve();
|
||||
}
|
||||
|
||||
|
|
|
@ -136,8 +136,8 @@ public enum Talent {
|
|||
FAN_OF_BLADES(113, 4), PROJECTING_BLADES(114, 4), SPIRIT_BLADES(115, 4),
|
||||
//Natures Power T4
|
||||
GROWING_POWER(116, 4), NATURES_WRATH(117, 4), WILD_MOMENTUM(118, 4),
|
||||
//??? T4
|
||||
HUNTRESS_3_1(119, 4), HUNTRESS_3_2(120, 4), HUNTRESS_3_3(121, 4),
|
||||
//Spirit Hawk T4
|
||||
EAGLE_EYE(119, 4), GO_FOR_THE_EYES(120, 4), SWIFT_SPIRIT(121, 4),
|
||||
|
||||
//universal T4
|
||||
HEROIC_ENERGY(123, 4),
|
||||
|
|
|
@ -21,20 +21,234 @@
|
|||
|
||||
package com.shatteredpixel.shatteredpixeldungeon.actors.hero.abilities.huntress;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.Electricity;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.Freezing;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Bleeding;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Blindness;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.BlobImmunity;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Invisibility;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Talent;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.abilities.ArmorAbility;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.DirectableAlly;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.armor.ClassArmor;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.BatSprite;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
|
||||
import com.watabou.utils.Bundle;
|
||||
import com.watabou.utils.GameMath;
|
||||
import com.watabou.utils.PathFinder;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class SpiritHawk extends ArmorAbility {
|
||||
|
||||
@Override
|
||||
public String targetingPrompt() {
|
||||
if (getHawk() == null) {
|
||||
return super.targetingPrompt();
|
||||
} else {
|
||||
return Messages.get(this, "prompt");
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
baseChargeUse = 35f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float chargeUse(Hero hero) {
|
||||
if (getHawk() == null) {
|
||||
return super.chargeUse(hero);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void activate(ClassArmor armor, Hero hero, Integer target) {
|
||||
//TODO
|
||||
HawkAlly ally = getHawk();
|
||||
|
||||
if (ally != null){
|
||||
if (target == null){
|
||||
return;
|
||||
} else {
|
||||
ally.directTocell(target);
|
||||
}
|
||||
} else {
|
||||
ArrayList<Integer> spawnPoints = new ArrayList<>();
|
||||
for (int i = 0; i < PathFinder.NEIGHBOURS8.length; i++) {
|
||||
int p = hero.pos + PathFinder.NEIGHBOURS8[i];
|
||||
if (Actor.findChar(p) == null && (Dungeon.level.passable[p] || Dungeon.level.avoid[p])) {
|
||||
spawnPoints.add(p);
|
||||
}
|
||||
}
|
||||
|
||||
if (!spawnPoints.isEmpty()){
|
||||
ally = new HawkAlly();
|
||||
|
||||
ally.pos = Random.element(spawnPoints);
|
||||
|
||||
GameScene.add(ally);
|
||||
Dungeon.level.occupyCell(ally);
|
||||
Dungeon.observe();
|
||||
|
||||
armor.charge -= chargeUse(hero);
|
||||
armor.updateQuickslot();
|
||||
Invisibility.dispel();
|
||||
hero.spendAndNext(Actor.TICK);
|
||||
|
||||
} else {
|
||||
GLog.w(Messages.get(this, "no_space"));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Talent[] talents() {
|
||||
return new Talent[]{Talent.HUNTRESS_3_1, Talent.HUNTRESS_3_2, Talent.HUNTRESS_3_3, Talent.HEROIC_ENERGY};
|
||||
return new Talent[]{Talent.EAGLE_EYE, Talent.GO_FOR_THE_EYES, Talent.SWIFT_SPIRIT, Talent.HEROIC_ENERGY};
|
||||
}
|
||||
|
||||
private static HawkAlly getHawk(){
|
||||
for (Char ch : Actor.chars()){
|
||||
if (ch instanceof HawkAlly){
|
||||
return (HawkAlly) ch;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static class HawkAlly extends DirectableAlly {
|
||||
|
||||
{
|
||||
spriteClass = HawkSprite.class;
|
||||
|
||||
HP = HT = 10;
|
||||
defenseSkill = 50;
|
||||
|
||||
flying = true;
|
||||
viewDistance = (int)GameMath.gate(6, 6+Dungeon.hero.pointsInTalent(Talent.EAGLE_EYE), 8);
|
||||
attacksAutomatically = false;
|
||||
|
||||
immunities.addAll(new BlobImmunity().immunities());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int attackSkill(Char target) {
|
||||
return 50;
|
||||
}
|
||||
|
||||
private int dodgesUsed = 0;
|
||||
private float timeRemaining = 50f;
|
||||
|
||||
@Override
|
||||
public int defenseSkill(Char enemy) {
|
||||
if (dodgesUsed < Dungeon.hero.pointsInTalent(Talent.SWIFT_SPIRIT)){
|
||||
dodgesUsed++;
|
||||
return Char.INFINITE_EVASION;
|
||||
}
|
||||
return super.defenseSkill(enemy);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int damageRoll() {
|
||||
return Random.NormalIntRange(5, 10);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int attackProc(Char enemy, int damage) {
|
||||
damage = super.attackProc( enemy, damage );
|
||||
if (Dungeon.hero.hasTalent(Talent.GO_FOR_THE_EYES)) {
|
||||
Buff.prolong( enemy, Blindness.class, 1 + Dungeon.hero.pointsInTalent(Talent.GO_FOR_THE_EYES) );
|
||||
}
|
||||
|
||||
return damage;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean act() {
|
||||
viewDistance = (int)GameMath.gate(6, 6+Dungeon.hero.pointsInTalent(Talent.EAGLE_EYE), 8);
|
||||
boolean result = super.act();
|
||||
Dungeon.level.updateFieldOfView( this, fieldOfView );
|
||||
GameScene.updateFog(pos, viewDistance+(int)Math.ceil(speed()));
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float speed() {
|
||||
return 2f + Dungeon.hero.pointsInTalent(Talent.SWIFT_SPIRIT)/2f;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void spend(float time) {
|
||||
super.spend(time);
|
||||
timeRemaining -= time;
|
||||
if (timeRemaining <= 0){
|
||||
die(null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
super.destroy();
|
||||
Dungeon.observe();
|
||||
GameScene.updateFog();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void followHero() {
|
||||
GLog.i(Messages.get(this, "direct_follow"));
|
||||
super.followHero();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void targetChar(Char ch) {
|
||||
GLog.i(Messages.get(this, "direct_attack"));
|
||||
super.targetChar(ch);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String description() {
|
||||
String message = Messages.get(this, "desc", (int)timeRemaining);
|
||||
if (dodgesUsed < Dungeon.hero.pointsInTalent(Talent.SWIFT_SPIRIT)){
|
||||
message += "\n" + Messages.get(this, "desc_dodges", (Dungeon.hero.pointsInTalent(Talent.SWIFT_SPIRIT) - dodgesUsed));
|
||||
}
|
||||
return message;
|
||||
}
|
||||
|
||||
private static final String DODGES_USED = "dodges_used";
|
||||
private static final String TIME_REMAINING = "time_remaining";
|
||||
|
||||
@Override
|
||||
public void storeInBundle(Bundle bundle) {
|
||||
super.storeInBundle(bundle);
|
||||
bundle.put(DODGES_USED, dodgesUsed);
|
||||
bundle.put(TIME_REMAINING, timeRemaining);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreFromBundle(Bundle bundle) {
|
||||
super.restoreFromBundle(bundle);
|
||||
dodgesUsed = bundle.getInt(DODGES_USED);
|
||||
timeRemaining = bundle.getFloat(TIME_REMAINING);
|
||||
}
|
||||
}
|
||||
|
||||
//TODO real sprite
|
||||
public static class HawkSprite extends BatSprite {
|
||||
|
||||
@Override
|
||||
public void resetColor() {
|
||||
super.resetColor();
|
||||
tint(0, 1f, 1f, 1f);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,6 +44,7 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Shadows;
|
|||
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.hero.abilities.huntress.SpiritHawk;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Bestiary;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mimic;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob;
|
||||
|
@ -1120,6 +1121,18 @@ public abstract class Level implements Bundlable {
|
|||
}
|
||||
}
|
||||
|
||||
if (c instanceof SpiritHawk.HawkAlly && Dungeon.hero.pointsInTalent(Talent.EAGLE_EYE) >= 3){
|
||||
int range = 1+(Dungeon.hero.pointsInTalent(Talent.EAGLE_EYE)-2);
|
||||
for (Mob mob : mobs) {
|
||||
int p = mob.pos;
|
||||
if (!fieldOfView[p] && distance(c.pos, p) <= range) {
|
||||
for (int i : PathFinder.NEIGHBOURS9) {
|
||||
fieldOfView[mob.pos + i] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Currently only the hero can get mind vision or awareness
|
||||
if (c.isAlive() && c == Dungeon.hero) {
|
||||
|
||||
|
@ -1171,7 +1184,9 @@ public abstract class Level implements Bundlable {
|
|||
}
|
||||
|
||||
for (Mob m : mobs){
|
||||
if (m instanceof WandOfWarding.Ward || m instanceof WandOfRegrowth.Lotus){
|
||||
if (m instanceof WandOfWarding.Ward
|
||||
|| m instanceof WandOfRegrowth.Lotus
|
||||
|| m instanceof SpiritHawk.HawkAlly){
|
||||
if (m.fieldOfView == null || m.fieldOfView.length != length()){
|
||||
m.fieldOfView = new boolean[length()];
|
||||
Dungeon.level.updateFieldOfView( m, m.fieldOfView );
|
||||
|
|
Loading…
Reference in New Issue
Block a user