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:
dalyjame 2019-06-18 16:48:54 -04:00
parent c244d36bd6
commit e008892c13
6 changed files with 147 additions and 47 deletions

View File

@ -30,7 +30,7 @@ class Game extends Application {
val form1 = Form("Diabolo")
val form2 = Form("Chanilla")
val movepool1 = IndexedSeq(Move("eruption"), Move("willowisp"), Move("thunderbolt"), Move("thunderwave"), Move("blastburn"))
val movepool2 = IndexedSeq(Move("blastburn"))
val movepool2 = IndexedSeq(Move("razorwind"))
val p1 = TrainerID("Jaeda", Gender.Female, 0)
val p2 = TrainerID("Wild Monster", Gender.Male, 0)
val party1 = new Party(p1, new MonsterPtr(Monster.generate("Allied Mon", p1, 500, form1, movepool1)), IndexedSeq())

View File

@ -24,6 +24,7 @@ abstract class Ability extends Effect {
class AbilityToken(
val name: String,
val id: String,
val shortDesc: String,
val onAfterDamage: String
) {
@ -32,6 +33,7 @@ class AbilityToken(
val self = this
new Ability {
val name = self.name
val id = self.id
val desc = self.shortDesc
val onAfterDamageImp = Ability.compileOnAfterDamage(self.onAfterDamage)
}

View File

@ -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)
}
if (selfEffect != null) {
applyEffect(user, user, selfEffect)
}
if (secondary != null && rng.chance(secondary.chance.%%)) {
applyEffect(target, user, secondary)
}
target.base.ability.onAfterDamage(user, this, target, actualDmg)
if (!user.isAlive) {
reader ! Message(s"$user fainted!")
}
if (!target.isAlive) {
reader ! Message(s"$target fainted!")
}
// 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`)
@ -266,6 +276,14 @@ 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]
}
}
}

View File

@ -29,6 +29,7 @@ object EffectType extends Enumeration {
trait Effect {
def name: String
def id: String
def effectType: EffectType
def isItem = effectType == EffectType.ItemEffect
@ -37,6 +38,9 @@ trait Effect {
}
case class EffectSource(mon: Monster, effect: Effect) {
def name = effect.name
def id = effect.id
def isItem = effect.isItem
def isMove = effect.isMove
def isAbility = effect.isAbility
@ -47,7 +51,7 @@ case class EffectSource(mon: Monster, effect: Effect) {
class Status(template: StatusTemplate) extends Effect {
def name = template.name
// val id
def id = template.id
def effectType = template.effectType
def onStart(mon: Monster, source: EffectSource)(implicit reader: SignalConsumer, rng: Random) = template.onStart(this, mon, source, reader, rng)
def onEnd(mon: Monster)(implicit reader: SignalConsumer, rng: Random) = template.onEnd(this, mon, reader, rng)
@ -62,14 +66,14 @@ class Status(template: StatusTemplate) extends Effect {
def onLockMove(mon: Monster)(implicit reader: SignalConsumer, rng: Random) = template.onLockMove(this, mon, reader, rng)
val intData: MutMap[String, Int] = MutMap[String, Int]()
val stringData = MutMap[String, String]()
val strData = MutMap[String, String]()
override def toString = name
}
abstract class StatusTemplate {
val name: String
// val id
val id: String
val effectType: EffectType
val onStart: (Status, Monster, EffectSource, SignalConsumer, Random) => Unit
val onEnd: (Status, Monster, SignalConsumer, Random) => Unit
@ -90,6 +94,7 @@ abstract class StatusTemplate {
case class StatusToken(
val name: String,
val id: String,
val effectType: String,
val onStart: String,
val onEnd: String,
@ -102,6 +107,7 @@ case class StatusToken(
val self = this
new StatusTemplate {
val name = self.name
val id = self.id
val effectType = EffectType.parse(self.effectType, Volatile)
val onStart = Status.compileOnStart(self.onStart)
val onEnd = Status.compileOnEnd(self.onEnd)

View File

@ -5139,6 +5139,42 @@ razorshell:
target: Normal
type: Water
zMovePower: 140
razorwind:
accuracy: 100
basePower: 80
category: Special
contestType: Cool
critRatio: 2
desc: Has a higher chance for a critical hit. This attack charges on the first turn
and executes on the second. If the user is holding a Power Herb, the move completes
in one turn.
flags:
charge: 1
mirror: 1
protect: 1
id: razorwind
name: Razor Wind
num: 13
onTryMove: |-
if (user.statuses.exists(_.id == "twoturnmove")) {
user -= Status("twoturnmove")
true
} else {
msg(s"${user} drew in power!")
/*if (!this.runEvent('ChargeMove', attacker, defender, move)) {
return;
}*/
user.addStatus(Status("twoturnmove"), EffectSource(user, move))
false
}
pp: 10
priority: 0
secondary: null
shortDesc: Charges, then hits foe(s) turn 2. High crit ratio.
target: AllAdjacentFoes
type: Normal
zMovePower: 160
recharge:
accuracy: 100
basePower: 0

View File

@ -180,3 +180,16 @@ tox:
}
mon.takeDamage(self.intData("stage") \\ 16 * mon(Hp));
msg(s"${mon} was damaged by poison!")
twoturnmove:
duration: 2
id: twoturnmove
name: twoturnmove
num: 0
onLockMove: self.strData("move")
onStart: |-
self.strData("move") = source.id
//target.addVolatile(effect.id, source)
//this.attrLastMove("[still]")
onMoveAborted: |-
mon -= self