Added the first charge-move, razorwind. Future moves incoming. Note that since there are no items or weather, insta-charge is not yet implemented
This commit is contained in:
@@ -36,6 +36,7 @@ trait MoveTurn extends Effect {
|
||||
|
||||
class SwitchOut(val party: Party, val replacement: Monster) extends MoveTurn {
|
||||
def name = "Swap"
|
||||
def id = "swap"
|
||||
def flags = Set()
|
||||
def prior = +6
|
||||
def target = Target.Self
|
||||
@@ -52,11 +53,13 @@ class SwitchOut(val party: Party, val replacement: Monster) extends MoveTurn {
|
||||
|
||||
abstract class Move extends MoveTurn {
|
||||
val name: String
|
||||
val id: String
|
||||
val desc: String
|
||||
val category: MoveType
|
||||
val pow: Int
|
||||
val powCallback: (Monster, Move, Monster, SignalConsumer, Random) => Int
|
||||
val damageCallback: (Monster, Move, Monster, SignalConsumer, Random) => Int
|
||||
val onTryMove: (Monster, Move, Monster, SignalConsumer, Random) => Boolean
|
||||
val prior: Int
|
||||
val accuracy: Int
|
||||
val pp: Int
|
||||
@@ -78,53 +81,56 @@ abstract class Move extends MoveTurn {
|
||||
|
||||
override def useMove(user: Monster, target: Monster)(implicit reader: SignalConsumer, rng: Random) = {
|
||||
reader ! Message(s"$user used $name.")
|
||||
if (attackRoll(user, target)) {
|
||||
if (pow > 0 || powCallback != null || damageCallback != null) {
|
||||
val dmg = damageRoll(user, target)
|
||||
val actualDmg = target.takeDamage(dmg)
|
||||
if (dmg == actualDmg) {
|
||||
reader ! Message(s"$target takes $actualDmg damage!")
|
||||
reader ! DamageMsg(dmg, target, element)
|
||||
} else {
|
||||
reader ! Message(s"$target takes $actualDmg (+${dmg - actualDmg} overkill) damage!")
|
||||
reader ! DamageMsg(dmg, target, element)
|
||||
if (onTryMove(user, this, target, reader, rng)) {
|
||||
if (attackRoll(user, target)) {
|
||||
if (pow > 0 || powCallback != null || damageCallback != null) {
|
||||
val dmg = damageRoll(user, target)
|
||||
val actualDmg = target.takeDamage(dmg)
|
||||
if (dmg == actualDmg) {
|
||||
reader ! Message(s"$target takes $actualDmg damage!")
|
||||
reader ! DamageMsg(dmg, target, element)
|
||||
} else {
|
||||
reader ! Message(s"$target takes $actualDmg (+${dmg - actualDmg} overkill) damage!")
|
||||
reader ! DamageMsg(dmg, target, element)
|
||||
}
|
||||
if (drain > 0.frac) {
|
||||
val healing = Math.max(drain * actualDmg, 1)
|
||||
user.recoverDamage(healing)
|
||||
reader ! Message(s"$user recovered $healing damage.")
|
||||
} else if (drain < 0.frac) {
|
||||
val recoil = Math.max(-drain * actualDmg, 1)
|
||||
user.takeDamage(recoil)
|
||||
reader ! Message(s"$user took $recoil damage from recoil!")
|
||||
reader ! DamageMsg(actualDmg, target, Element("None"))
|
||||
}
|
||||
|
||||
target.base.ability.onAfterDamage(user, this, target, actualDmg)
|
||||
|
||||
if (!user.isAlive) {
|
||||
reader ! Message(s"$user fainted!")
|
||||
}
|
||||
if (!target.isAlive) {
|
||||
reader ! Message(s"$target fainted!")
|
||||
}
|
||||
}
|
||||
if (drain > 0.frac) {
|
||||
val healing = Math.max(drain * actualDmg, 1)
|
||||
user.recoverDamage(healing)
|
||||
reader ! Message(s"$user recovered $healing damage.")
|
||||
} else if (drain < 0.frac) {
|
||||
val recoil = Math.max(-drain * actualDmg, 1)
|
||||
user.takeDamage(recoil)
|
||||
reader ! Message(s"$user took $recoil damage from recoil!")
|
||||
reader ! DamageMsg(actualDmg, target, Element("None"))
|
||||
applyBoosts(target, boosts, user)
|
||||
applyStatus(target, user, status)
|
||||
if (effect != null) {
|
||||
applyEffect(target, user, effect)
|
||||
}
|
||||
|
||||
target.base.ability.onAfterDamage(user, this, target, actualDmg)
|
||||
|
||||
if (!user.isAlive) {
|
||||
reader ! Message(s"$user fainted!")
|
||||
if (selfEffect != null) {
|
||||
applyEffect(user, user, selfEffect)
|
||||
}
|
||||
if (!target.isAlive) {
|
||||
reader ! Message(s"$target fainted!")
|
||||
if (secondary != null && rng.chance(secondary.chance.%%)) {
|
||||
applyEffect(target, user, secondary)
|
||||
}
|
||||
|
||||
// TODO : Multiparty
|
||||
} else {
|
||||
reader ! Message("Missed!")
|
||||
}
|
||||
applyBoosts(target, boosts, user)
|
||||
applyStatus(target, user, status)
|
||||
if (effect != null) {
|
||||
applyEffect(target, user, effect)
|
||||
}
|
||||
if (selfEffect != null) {
|
||||
applyEffect(user, user, selfEffect)
|
||||
}
|
||||
if (secondary != null && rng.chance(secondary.chance.%%)) {
|
||||
applyEffect(target, user, secondary)
|
||||
}
|
||||
|
||||
// TODO : Multiparty
|
||||
} else {
|
||||
reader ! Message("Missed!")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
def attackRoll(user: Monster, target: Monster)(implicit reader: SignalConsumer, rng: Random) = {
|
||||
@@ -208,10 +214,12 @@ abstract class Move extends MoveTurn {
|
||||
|
||||
case class MoveToken(
|
||||
val name: String,
|
||||
val id: String,
|
||||
val shortDesc: String,
|
||||
@JsonScalaEnumeration(classOf[MoveTypeType]) val category: MoveType,
|
||||
val basePower: Option[Int],
|
||||
val basePowerCallback: String,
|
||||
val onTryMove: String,
|
||||
val damage: String,
|
||||
val priority: Int,
|
||||
val accuracy: Option[Int],
|
||||
@@ -233,11 +241,13 @@ case class MoveToken(
|
||||
val effectToken = SecondaryToken(100, Map(), null, token.volatileStatus, null)
|
||||
new Move {
|
||||
val name = token.name
|
||||
val id = token.id
|
||||
val desc = token.shortDesc
|
||||
val category = token.category
|
||||
val pow = token.basePower.getOrElse(0)
|
||||
val powCallback = Move.compilePowCallback(token.basePowerCallback)
|
||||
val damageCallback = Move.compileDamageCallback(token.damage)
|
||||
val onTryMove = Move.compileOnTryMove(token.onTryMove)
|
||||
val prior = token.priority
|
||||
val pp = token.pp
|
||||
val element = Element(token.`type`)
|
||||
@@ -265,7 +275,15 @@ object Move {
|
||||
}
|
||||
moves(name)
|
||||
}
|
||||
|
||||
|
||||
private val helpers = """
|
||||
implicit val dice = rng
|
||||
implicit val consumer = reader
|
||||
def msg(text: String): Unit = {
|
||||
reader ! Message(text)
|
||||
}
|
||||
"""
|
||||
|
||||
def compilePowCallback(code: String): (Monster, Move, Monster, SignalConsumer, Random) => Int = {
|
||||
if (code != null) {
|
||||
val tb = runtimeMirror(getClass.getClassLoader).mkToolBox()
|
||||
@@ -294,4 +312,29 @@ object Move {
|
||||
def compileDamageCallback(code: String): (Monster, Move, Monster, SignalConsumer, Random) => Int = {
|
||||
compilePowCallback(code)
|
||||
}
|
||||
|
||||
def compileOnTryMove(code: String): (Monster, Move, Monster, SignalConsumer, Random) => Boolean = {
|
||||
if (code == null) {
|
||||
(_, _, _, _, _) => true
|
||||
} else {
|
||||
val tb = runtimeMirror(getClass.getClassLoader).mkToolBox()
|
||||
val tree = tb.parse(
|
||||
s"""
|
||||
|import scala.util.Random
|
||||
|import fmon._
|
||||
|import fmon.battle.msg._
|
||||
|import fmon.stat._
|
||||
|import fmon.stat.Statistic._
|
||||
|def callback(user : Monster, move: Move, target : Monster, reader: SignalConsumer, rng: Random): Boolean = {
|
||||
| $helpers
|
||||
| $code
|
||||
|}
|
||||
|callback _
|
||||
""".stripMargin)
|
||||
val f = tb.compile(tree)
|
||||
val wrapper = f()
|
||||
|
||||
wrapper.asInstanceOf[(Monster, Move, Monster, SignalConsumer, Random) => Boolean]
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user