fakemon/FakeMon/src/mon/stat/Move.scala
2019-05-23 22:58:31 -04:00

116 lines
3.2 KiB
Scala

package mon.stat
import scala.reflect.runtime.universe._
import scala.tools.reflect.ToolBox
import com.fasterxml.jackson.module.scala.JsonScalaEnumeration
import scala.io.Source
import mon.util.{TypeReference, YamlHelper}
object MoveType extends Enumeration {
val Physical, Special, Status = Value
}
class MoveTypeType extends TypeReference[MoveType.type]
object Target extends Enumeration {
val Normal, Self, AllAdjacentFoes = Value
}
class TargetType extends TypeReference[Target.type]
abstract class Move {
val name : String
val desc : String
val mvType : MoveType
val pow : Int
val powCallback : (Monster, Monster) => Int
val prior : Int
val accuracy : Int
val pp : Int
val element : Element
val flags : Set[String]
val target : Target
val boosts : Map[Stat, Int]
val crit : Int
val selfEffect : Secondary
val secondary: Secondary
// boosts
// onHit
// onTryHit
// zPower, zMoveEffect, zMoveBoost
override def toString = {
name
}
}
case class MoveToken(
val name : String,
val shortDesc : String,
@JsonScalaEnumeration(classOf[MoveTypeType]) val category : MoveType,
val basePower : Option[Int],
val basePowerCallback : String,
val priority : Int,
val accuracy : Option[Int],
val pp : Int,
val `type` : String,
val flags : Map[String, Int],
val self : SecondaryToken,
val secondary : SecondaryToken,
@JsonScalaEnumeration(classOf[TargetType]) val target : Target = Target.Normal,
val boosts : Map[String, Int] = Map(),
val crit : Int = 0) {
def instantiate() = {
val token = this
new Move {
val name = token.name
val desc = token.shortDesc
val mvType = category
val pow = token.basePower.getOrElse(0)
val powCallback = Move.compilePowCallback(token.basePowerCallback)
val prior = token.priority
val pp = token.pp
val element = Element(token.`type`)
val accuracy = token.accuracy.getOrElse(100)
val flags = token.flags.keySet
val target = token.target
val boosts = if (token.boosts != null) token.boosts.map{case (s, i) => (Statistic(s), i)} else Map()
val crit = token.crit
val selfEffect = if (token.self != null) token.self.instantiate() else null
val secondary = if (token.secondary != null) token.secondary.instantiate() else null
}
}
}
object Move {
val tokens = YamlHelper.extractSeq[MoveToken](Source.fromInputStream(Move.getClass.getResourceAsStream("data/moves.yaml")))
val moves = tokens.map(_.instantiate())
val byName = moves.map(m => (m.name, m)).toMap
def apply(s : String) = byName(s)
def compilePowCallback(code: String): (Monster, Monster) => Int = {
if (code != null) {
val tb = runtimeMirror(getClass.getClassLoader).mkToolBox()
val tree = tb.parse(
s"""
|import mon.stat.Monster
|import mon.stat.Statistic._
|def callback(user : Monster, target : Monster): Int = {
| $code
|}
|callback _
""".stripMargin)
val f = tb.compile(tree)
val wrapper = f()
wrapper.asInstanceOf[(Monster, Monster) => Int]
} else {
null
}
}
}