Merged some conflicts with the new damage animations
This commit is contained in:
commit
c244d36bd6
21
FakeMon/src/fmon/Config.scala
Normal file
21
FakeMon/src/fmon/Config.scala
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
package fmon
|
||||||
|
|
||||||
|
import fmon.util.YamlHelper
|
||||||
|
|
||||||
|
case class Config(
|
||||||
|
val title: String,
|
||||||
|
val crit: Double,
|
||||||
|
val stab: Double,
|
||||||
|
val maxBoost: Int
|
||||||
|
) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
object Config {
|
||||||
|
val config = YamlHelper.extract[Config](getClass.getResourceAsStream("config.yaml"))
|
||||||
|
|
||||||
|
def title = config.title
|
||||||
|
def crit = config.crit
|
||||||
|
def stab = config.stab
|
||||||
|
def maxBoost = config.maxBoost
|
||||||
|
}
|
@ -14,23 +14,6 @@ case class Prop(url : Seq[String])
|
|||||||
|
|
||||||
object Game {
|
object Game {
|
||||||
def main(args : Array[String]): Unit = {
|
def main(args : Array[String]): Unit = {
|
||||||
/*
|
|
||||||
implicit val rng = new scala.util.Random()
|
|
||||||
val form1 = Form("Diabolo")
|
|
||||||
val form2 = Form("Chanilla")
|
|
||||||
val movepool1 = IndexedSeq(Move("eruption"))
|
|
||||||
val movepool2 = IndexedSeq(Move("flail"))
|
|
||||||
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())
|
|
||||||
val party2 = new Party(p2, new MonsterPtr(Monster.generate("Wild Mon", p2, 500, form2, movepool2)), IndexedSeq(
|
|
||||||
Monster.generate("Sideboard Mon", p2, 500, form2, movepool2)
|
|
||||||
))
|
|
||||||
println(form1.xpCurve)
|
|
||||||
val engine = new BattleEngine(party1, party2)
|
|
||||||
engine.play()
|
|
||||||
println(party1.lead.elements)
|
|
||||||
* */
|
|
||||||
Application.launch(classOf[Game], args: _*)
|
Application.launch(classOf[Game], args: _*)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -46,8 +29,8 @@ class Game extends Application {
|
|||||||
implicit val rng = new scala.util.Random()
|
implicit val rng = new scala.util.Random()
|
||||||
val form1 = Form("Diabolo")
|
val form1 = Form("Diabolo")
|
||||||
val form2 = Form("Chanilla")
|
val form2 = Form("Chanilla")
|
||||||
val movepool1 = IndexedSeq(Move("eruption"), Move("willowisp"), Move("thunderbolt"), Move("thunderwave"))
|
val movepool1 = IndexedSeq(Move("eruption"), Move("willowisp"), Move("thunderbolt"), Move("thunderwave"), Move("blastburn"))
|
||||||
val movepool2 = IndexedSeq(Move("flail"))
|
val movepool2 = IndexedSeq(Move("blastburn"))
|
||||||
val p1 = TrainerID("Jaeda", Gender.Female, 0)
|
val p1 = TrainerID("Jaeda", Gender.Female, 0)
|
||||||
val p2 = TrainerID("Wild Monster", Gender.Male, 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())
|
val party1 = new Party(p1, new MonsterPtr(Monster.generate("Allied Mon", p1, 500, form1, movepool1)), IndexedSeq())
|
||||||
@ -57,7 +40,7 @@ class Game extends Application {
|
|||||||
val engine = new BattleEngine(party1, party2)
|
val engine = new BattleEngine(party1, party2)
|
||||||
controller.setEngine(engine)
|
controller.setEngine(engine)
|
||||||
|
|
||||||
primaryStage.setTitle("FakeMon Battle Simulator")
|
primaryStage.setTitle(Config.title)
|
||||||
primaryStage.setScene(scene)
|
primaryStage.setScene(scene)
|
||||||
primaryStage.show()
|
primaryStage.show()
|
||||||
}
|
}
|
||||||
|
@ -18,10 +18,17 @@ class BattleEngine(val player: Party, val enemy: Party)(implicit val reader: Sig
|
|||||||
|
|
||||||
def playTurn(): Unit = {
|
def playTurn(): Unit = {
|
||||||
val playerAction = player.pollAction(enemy)
|
val playerAction = player.pollAction(enemy)
|
||||||
playTurn(playerAction)
|
playTurnImp(playerAction)
|
||||||
}
|
}
|
||||||
|
|
||||||
def playTurn(playerAction: Action): Unit = {
|
def playTurn(playerAction: Action): Unit = {
|
||||||
|
playTurnImp(playerAction)
|
||||||
|
while (player.lead.isLocked) {
|
||||||
|
playTurn()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def playTurnImp(playerAction: Action): Unit = {
|
||||||
val enemyAction = enemy.pollAction(player)
|
val enemyAction = enemy.pollAction(player)
|
||||||
|
|
||||||
val actions = Seq(playerAction, enemyAction)
|
val actions = Seq(playerAction, enemyAction)
|
||||||
|
@ -52,7 +52,9 @@ class BattleUI extends SignalConsumer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
def onMove(move: Move): Unit = {
|
def onMove(move: Move): Unit = {
|
||||||
val action = Action(engine.player.lead, move, engine.enemy.lead)
|
implicit val rng = engine.rng
|
||||||
|
implicit val reader = engine
|
||||||
|
val action = Action(engine.player.lead, move, engine.player.pollTarget(move, engine.player.lead, engine.enemy))
|
||||||
engine.playTurn(action)
|
engine.playTurn(action)
|
||||||
updateUI()
|
updateUI()
|
||||||
}
|
}
|
||||||
@ -68,7 +70,6 @@ class BattleUI extends SignalConsumer {
|
|||||||
val r = 25
|
val r = 25
|
||||||
val color = Color.AliceBlue
|
val color = Color.AliceBlue
|
||||||
val center = findCenter(target)
|
val center = findCenter(target)
|
||||||
print(center)
|
|
||||||
|
|
||||||
val circle = new Circle {
|
val circle = new Circle {
|
||||||
radius = r
|
radius = r
|
||||||
|
@ -6,6 +6,7 @@ import javafx.scene.{control => jfxsc}
|
|||||||
import scalafx.Includes._
|
import scalafx.Includes._
|
||||||
import scalafx.scene.control._
|
import scalafx.scene.control._
|
||||||
|
|
||||||
|
import fmon._
|
||||||
import fmon.stat.Monster
|
import fmon.stat.Monster
|
||||||
import fmon.stat._
|
import fmon.stat._
|
||||||
|
|
||||||
|
@ -1,12 +1,5 @@
|
|||||||
package fmon
|
package fmon
|
||||||
|
|
||||||
import scala.language.implicitConversions
|
|
||||||
import scala.util.Random
|
|
||||||
|
|
||||||
import fmon.util._
|
|
||||||
|
|
||||||
|
|
||||||
package object battle {
|
package object battle {
|
||||||
implicit def rngDice(rng : Random) = new Dice(rng)
|
|
||||||
implicit def int2Helper(x : Int) = new IntFraction(x)
|
|
||||||
}
|
}
|
5
FakeMon/src/fmon/config.yaml
Normal file
5
FakeMon/src/fmon/config.yaml
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
title: FakeMon Engine Demo
|
||||||
|
crit: 1.5
|
||||||
|
stab: 1.5
|
||||||
|
maxBoost: 6
|
||||||
|
newday: 02:00
|
13
FakeMon/src/fmon/package.scala
Normal file
13
FakeMon/src/fmon/package.scala
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
|
||||||
|
import scala.language.implicitConversions
|
||||||
|
import scala.util.Random
|
||||||
|
|
||||||
|
import fmon.stat._
|
||||||
|
import fmon.util.{Dice, IntFraction}
|
||||||
|
|
||||||
|
package object fmon {
|
||||||
|
|
||||||
|
implicit def rngDice(rng : Random) = new Dice(rng)
|
||||||
|
implicit def int2Helper(x : Int) = new IntFraction(x)
|
||||||
|
implicit def ptrToMonster(ptr : MonsterPtr) : Monster = ptr.mon
|
||||||
|
}
|
@ -53,10 +53,10 @@ object Ability {
|
|||||||
private val header = """
|
private val header = """
|
||||||
|import scala.util.Random
|
|import scala.util.Random
|
||||||
|import fmon.battle.msg._
|
|import fmon.battle.msg._
|
||||||
|
|import fmon._
|
||||||
|import fmon.stat._
|
|import fmon.stat._
|
||||||
|import fmon.stat.MoveType._
|
|import fmon.stat.MoveType._
|
||||||
|import fmon.stat.Statistic._
|
|import fmon.stat.Statistic._
|
||||||
|import fmon.util._
|
|
||||||
"""
|
"""
|
||||||
private val helper = """
|
private val helper = """
|
||||||
implicit val gen = rng
|
implicit val gen = rng
|
||||||
|
@ -2,6 +2,7 @@ package fmon.stat
|
|||||||
|
|
||||||
import scala.util._
|
import scala.util._
|
||||||
|
|
||||||
|
import fmon._
|
||||||
import fmon.battle.msg._
|
import fmon.battle.msg._
|
||||||
import fmon.util._
|
import fmon.util._
|
||||||
|
|
||||||
@ -69,7 +70,7 @@ class Monster(val base : StorageMon) {
|
|||||||
|
|
||||||
def applyBoost(s : Stat, boost : Int, effect: EffectSource)(implicit reader: SignalConsumer, rng: Random) {
|
def applyBoost(s : Stat, boost : Int, effect: EffectSource)(implicit reader: SignalConsumer, rng: Random) {
|
||||||
val modified = boosts.getOrElse(s, 0) + boost
|
val modified = boosts.getOrElse(s, 0) + boost
|
||||||
boosts = boosts.updated(s, Math.min(MaxBoost, Math.max(-MaxBoost, modified)))
|
boosts = boosts.updated(s, Math.min(Config.maxBoost, Math.max(-Config.maxBoost, modified)))
|
||||||
if (boost > 0) {
|
if (boost > 0) {
|
||||||
reader ! Message(s"$this's $s rose!")
|
reader ! Message(s"$this's $s rose!")
|
||||||
} else if (boost < 0) {
|
} else if (boost < 0) {
|
||||||
@ -81,6 +82,10 @@ class Monster(val base : StorageMon) {
|
|||||||
elements.foldLeft(1.0)((m, e) => m * (element --> e))
|
elements.foldLeft(1.0)((m, e) => m * (element --> e))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def isLocked(implicit reader: SignalConsumer, rng: Random): Boolean = {
|
||||||
|
statuses.exists(_.onLockMove(this).isDefined)
|
||||||
|
}
|
||||||
|
|
||||||
private def computeStat(s : Stat) : Int = {
|
private def computeStat(s : Stat) : Int = {
|
||||||
val num = 2 * base.form.baseStats(s) + base.gene.ivs(s) + base.evs(s) / 4
|
val num = 2 * base.form.baseStats(s) + base.gene.ivs(s) + base.evs(s) / 4
|
||||||
val frac = num * level / 100
|
val frac = num * level / 100
|
||||||
@ -93,8 +98,6 @@ class Monster(val base : StorageMon) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
object Monster {
|
object Monster {
|
||||||
final val MaxBoost = 6
|
|
||||||
|
|
||||||
def generate(nickname: String, ot: TrainerID, xp: Int, form: Form, moves: IndexedSeq[Move])(implicit rng: Random) = {
|
def generate(nickname: String, ot: TrainerID, xp: Int, form: Form, moves: IndexedSeq[Move])(implicit rng: Random) = {
|
||||||
new Monster(StorageMon.generate(nickname, ot, xp, form, moves))
|
new Monster(StorageMon.generate(nickname, ot, xp, form, moves))
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,8 @@ import scala.util.Random
|
|||||||
|
|
||||||
import Statistic._
|
import Statistic._
|
||||||
import fmon.battle.msg._
|
import fmon.battle.msg._
|
||||||
|
import fmon._
|
||||||
|
import fmon.battle.msg.{Message, SignalConsumer}
|
||||||
import fmon.util._
|
import fmon.util._
|
||||||
|
|
||||||
object MoveType extends Enumeration {
|
object MoveType extends Enumeration {
|
||||||
@ -53,7 +55,8 @@ abstract class Move extends MoveTurn {
|
|||||||
val desc: String
|
val desc: String
|
||||||
val category: MoveType
|
val category: MoveType
|
||||||
val pow: Int
|
val pow: Int
|
||||||
val powCallback: (Monster, Move, Monster) => Int
|
val powCallback: (Monster, Move, Monster, SignalConsumer, Random) => Int
|
||||||
|
val damageCallback: (Monster, Move, Monster, SignalConsumer, Random) => Int
|
||||||
val prior: Int
|
val prior: Int
|
||||||
val accuracy: Int
|
val accuracy: Int
|
||||||
val pp: Int
|
val pp: Int
|
||||||
@ -76,7 +79,7 @@ abstract class Move extends MoveTurn {
|
|||||||
override def useMove(user: Monster, target: Monster)(implicit reader: SignalConsumer, rng: Random) = {
|
override def useMove(user: Monster, target: Monster)(implicit reader: SignalConsumer, rng: Random) = {
|
||||||
reader ! Message(s"$user used $name.")
|
reader ! Message(s"$user used $name.")
|
||||||
if (attackRoll(user, target)) {
|
if (attackRoll(user, target)) {
|
||||||
if (pow > 0 || powCallback != null) {
|
if (pow > 0 || powCallback != null || damageCallback != null) {
|
||||||
val dmg = damageRoll(user, target)
|
val dmg = damageRoll(user, target)
|
||||||
val actualDmg = target.takeDamage(dmg)
|
val actualDmg = target.takeDamage(dmg)
|
||||||
if (dmg == actualDmg) {
|
if (dmg == actualDmg) {
|
||||||
@ -136,21 +139,24 @@ abstract class Move extends MoveTurn {
|
|||||||
}
|
}
|
||||||
|
|
||||||
def damageRoll(user: Monster, target: Monster)(implicit reader: SignalConsumer, rng: Random) = {
|
def damageRoll(user: Monster, target: Monster)(implicit reader: SignalConsumer, rng: Random) = {
|
||||||
val atkStat = if (category == MoveType.Physical) PAtk else MAtk
|
if (damageCallback != null) {
|
||||||
val defStat = if (category == MoveType.Physical) PDef else MDef
|
damageCallback(user, this, target, reader, rng)
|
||||||
// TODO : Fixed damage
|
} else {
|
||||||
val actualPow = if (powCallback != null) powCallback(user, this, target) else pow
|
val atkStat = if (category == MoveType.Physical) PAtk else MAtk
|
||||||
val baseDmg = (2 * user.level / 5 + 2) * actualPow * user(atkStat) / (target(defStat) * 50) + 2
|
val defStat = if (category == MoveType.Physical) PDef else MDef
|
||||||
val effectiveness = target.effectiveness(element)
|
val actualPow = if (powCallback != null) powCallback(user, this, target, reader, rng) else pow
|
||||||
val multiplier = effectiveness * critMultiplier(user, target)
|
val baseDmg = (2 * user.level / 5 + 2) * actualPow * user(atkStat) / (target(defStat) * 50) + 2
|
||||||
if (effectiveness > 1.0) {
|
val effectiveness = target.effectiveness(element)
|
||||||
reader ! Message("It's super effective!")
|
val multiplier = effectiveness * critMultiplier(user, target) * stabMultiplier(user)
|
||||||
} else if (effectiveness < 1.0) {
|
if (effectiveness > 1.0) {
|
||||||
reader ! Message("It's not very effective.")
|
reader ! Message("It's super effective!")
|
||||||
|
} else if (effectiveness < 1.0) {
|
||||||
|
reader ! Message("It's not very effective.")
|
||||||
|
}
|
||||||
|
val maxDmg = (baseDmg * multiplier).toInt
|
||||||
|
val minDmg = (17 \\ 20) * maxDmg
|
||||||
|
rng.nextInt(minDmg, maxDmg)
|
||||||
}
|
}
|
||||||
val maxDmg = (baseDmg * multiplier).toInt
|
|
||||||
val minDmg = (17 \\ 20) * maxDmg
|
|
||||||
rng.nextInt(minDmg, maxDmg)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def critMultiplier(user: Monster, target: Monster)(implicit reader: SignalConsumer, rng: Random) = {
|
def critMultiplier(user: Monster, target: Monster)(implicit reader: SignalConsumer, rng: Random) = {
|
||||||
@ -159,7 +165,15 @@ abstract class Move extends MoveTurn {
|
|||||||
val chance = (1 << stage) \\ 16 // Doubles per stage
|
val chance = (1 << stage) \\ 16 // Doubles per stage
|
||||||
if (rng.chance(chance)) {
|
if (rng.chance(chance)) {
|
||||||
reader ! Message("A critical hit!")
|
reader ! Message("A critical hit!")
|
||||||
1.5
|
Config.crit
|
||||||
|
} else {
|
||||||
|
1.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def stabMultiplier(user: Monster) = {
|
||||||
|
if (user.elements.contains(element)) {
|
||||||
|
Config.stab
|
||||||
} else {
|
} else {
|
||||||
1.0
|
1.0
|
||||||
}
|
}
|
||||||
@ -198,6 +212,7 @@ case class MoveToken(
|
|||||||
@JsonScalaEnumeration(classOf[MoveTypeType]) val category: MoveType,
|
@JsonScalaEnumeration(classOf[MoveTypeType]) val category: MoveType,
|
||||||
val basePower: Option[Int],
|
val basePower: Option[Int],
|
||||||
val basePowerCallback: String,
|
val basePowerCallback: String,
|
||||||
|
val damage: String,
|
||||||
val priority: Int,
|
val priority: Int,
|
||||||
val accuracy: Option[Int],
|
val accuracy: Option[Int],
|
||||||
val pp: Int,
|
val pp: Int,
|
||||||
@ -222,6 +237,7 @@ case class MoveToken(
|
|||||||
val category = token.category
|
val category = token.category
|
||||||
val pow = token.basePower.getOrElse(0)
|
val pow = token.basePower.getOrElse(0)
|
||||||
val powCallback = Move.compilePowCallback(token.basePowerCallback)
|
val powCallback = Move.compilePowCallback(token.basePowerCallback)
|
||||||
|
val damageCallback = Move.compileDamageCallback(token.damage)
|
||||||
val prior = token.priority
|
val prior = token.priority
|
||||||
val pp = token.pp
|
val pp = token.pp
|
||||||
val element = Element(token.`type`)
|
val element = Element(token.`type`)
|
||||||
@ -250,14 +266,17 @@ object Move {
|
|||||||
moves(name)
|
moves(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
def compilePowCallback(code: String): (Monster, Move, Monster) => Int = {
|
def compilePowCallback(code: String): (Monster, Move, Monster, SignalConsumer, Random) => Int = {
|
||||||
if (code != null) {
|
if (code != null) {
|
||||||
val tb = runtimeMirror(getClass.getClassLoader).mkToolBox()
|
val tb = runtimeMirror(getClass.getClassLoader).mkToolBox()
|
||||||
val tree = tb.parse(
|
val tree = tb.parse(
|
||||||
s"""
|
s"""
|
||||||
|
|import scala.util.Random
|
||||||
|
|import fmon._
|
||||||
|
|import fmon.battle.msg._
|
||||||
|import fmon.stat._
|
|import fmon.stat._
|
||||||
|import fmon.stat.Statistic._
|
|import fmon.stat.Statistic._
|
||||||
|def callback(user : Monster, move: Move, target : Monster): Int = {
|
|def callback(user : Monster, move: Move, target : Monster, reader: SignalConsumer, rng: Random): Int = {
|
||||||
| $code
|
| $code
|
||||||
|}
|
|}
|
||||||
|callback _
|
|callback _
|
||||||
@ -265,10 +284,14 @@ object Move {
|
|||||||
val f = tb.compile(tree)
|
val f = tb.compile(tree)
|
||||||
val wrapper = f()
|
val wrapper = f()
|
||||||
|
|
||||||
wrapper.asInstanceOf[(Monster, Move, Monster) => Int]
|
wrapper.asInstanceOf[(Monster, Move, Monster, SignalConsumer, Random) => Int]
|
||||||
} else {
|
} else {
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def compileDamageCallback(code: String): (Monster, Move, Monster, SignalConsumer, Random) => Int = {
|
||||||
|
compilePowCallback(code)
|
||||||
|
}
|
||||||
}
|
}
|
@ -2,6 +2,8 @@ package fmon.stat
|
|||||||
|
|
||||||
import scala.util.Random
|
import scala.util.Random
|
||||||
|
|
||||||
|
import fmon._
|
||||||
|
|
||||||
import Statistic._
|
import Statistic._
|
||||||
|
|
||||||
object Nature extends Enumeration {
|
object Nature extends Enumeration {
|
||||||
|
@ -2,16 +2,35 @@ package fmon.stat
|
|||||||
|
|
||||||
import scala.util.Random
|
import scala.util.Random
|
||||||
|
|
||||||
|
import fmon._
|
||||||
import fmon.battle.Action
|
import fmon.battle.Action
|
||||||
|
import fmon.battle.msg.SignalConsumer
|
||||||
import fmon.stat.Target._
|
import fmon.stat.Target._
|
||||||
|
|
||||||
class Party(val trainer: TrainerID, val lead: MonsterPtr, var sideboard: IndexedSeq[Monster]) {
|
class Party(val trainer: TrainerID, val lead: MonsterPtr, var sideboard: IndexedSeq[Monster]) {
|
||||||
def pollAction(them: Party)(implicit rng: Random): Action = {
|
def pollAction(them: Party)(implicit reader: SignalConsumer, rng: Random): Action = {
|
||||||
if (hasBackup && shouldSwitch(them)) {
|
if (lead.isLocked) {
|
||||||
|
val moveNames = lead.statuses.flatMap(s => s.onLockMove(lead)).distinct
|
||||||
|
moveNames match {
|
||||||
|
case Seq(moveName) => {
|
||||||
|
// Use locked move
|
||||||
|
val move = Move(moveName)
|
||||||
|
// TODO : remember target
|
||||||
|
val target = pollTarget(move, lead, them)
|
||||||
|
Action(lead, move, target)
|
||||||
|
}
|
||||||
|
case _ => {
|
||||||
|
// Struggle
|
||||||
|
val move = Move("struggle")
|
||||||
|
val target = pollTarget(move, lead, them)
|
||||||
|
Action(lead, move, target)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (hasBackup && shouldSwitch(them)) {
|
||||||
val sub = pollReplacement(them: Party)
|
val sub = pollReplacement(them: Party)
|
||||||
val move = new SwitchOut(this, sub)
|
val move = new SwitchOut(this, sub)
|
||||||
Action(lead, move, lead)
|
Action(lead, move, lead)
|
||||||
} else {
|
} else{
|
||||||
val move = pollMove
|
val move = pollMove
|
||||||
val target = pollTarget(move, lead, them)
|
val target = pollTarget(move, lead, them)
|
||||||
Action(lead, move, target)
|
Action(lead, move, target)
|
||||||
|
@ -7,6 +7,7 @@ import scala.util.Random
|
|||||||
|
|
||||||
import scala.io.Source
|
import scala.io.Source
|
||||||
|
|
||||||
|
import fmon._
|
||||||
import fmon.battle.msg._
|
import fmon.battle.msg._
|
||||||
import fmon.util._
|
import fmon.util._
|
||||||
import EffectType.Volatile
|
import EffectType.Volatile
|
||||||
@ -58,6 +59,7 @@ class Status(template: StatusTemplate) extends Effect {
|
|||||||
def onResidualOrder = template.onResidualOrder
|
def onResidualOrder = template.onResidualOrder
|
||||||
def onResidual(mon: Monster)(implicit reader: SignalConsumer, rng: Random) = template.onResidual(this, mon, reader, rng)
|
def onResidual(mon: Monster)(implicit reader: SignalConsumer, rng: Random) = template.onResidual(this, mon, reader, rng)
|
||||||
// val onSwitchIn
|
// val onSwitchIn
|
||||||
|
def onLockMove(mon: Monster)(implicit reader: SignalConsumer, rng: Random) = template.onLockMove(this, mon, reader, rng)
|
||||||
|
|
||||||
val intData: MutMap[String, Int] = MutMap[String, Int]()
|
val intData: MutMap[String, Int] = MutMap[String, Int]()
|
||||||
val stringData = MutMap[String, String]()
|
val stringData = MutMap[String, String]()
|
||||||
@ -79,6 +81,7 @@ abstract class StatusTemplate {
|
|||||||
val onResidualOrder: Int
|
val onResidualOrder: Int
|
||||||
val onResidual: (Status, Monster, SignalConsumer, Random) => Unit
|
val onResidual: (Status, Monster, SignalConsumer, Random) => Unit
|
||||||
// val onSwitchIn
|
// val onSwitchIn
|
||||||
|
val onLockMove: (Status, Monster, SignalConsumer, Random) => Option[String]
|
||||||
|
|
||||||
def build = new Status(this)
|
def build = new Status(this)
|
||||||
|
|
||||||
@ -93,7 +96,8 @@ case class StatusToken(
|
|||||||
val onBeforeMove: String,
|
val onBeforeMove: String,
|
||||||
val onModifyStat: String,
|
val onModifyStat: String,
|
||||||
val onResidualOrder: Int,
|
val onResidualOrder: Int,
|
||||||
val onResidual: String) {
|
val onResidual: String,
|
||||||
|
val onLockMove: String) {
|
||||||
def instantiate() = {
|
def instantiate() = {
|
||||||
val self = this
|
val self = this
|
||||||
new StatusTemplate {
|
new StatusTemplate {
|
||||||
@ -105,6 +109,7 @@ case class StatusToken(
|
|||||||
val onModifyStat = Status.compileOnModifyStat(self.onModifyStat)
|
val onModifyStat = Status.compileOnModifyStat(self.onModifyStat)
|
||||||
val onResidualOrder = self.onResidualOrder
|
val onResidualOrder = self.onResidualOrder
|
||||||
val onResidual = Status.compileOnResidual(self.onResidual)
|
val onResidual = Status.compileOnResidual(self.onResidual)
|
||||||
|
val onLockMove = Status.compileOnLockMove(self.onLockMove)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -124,12 +129,15 @@ object Status {
|
|||||||
private val header = """
|
private val header = """
|
||||||
import scala.util.Random
|
import scala.util.Random
|
||||||
import fmon.battle.msg._
|
import fmon.battle.msg._
|
||||||
|
import fmon._
|
||||||
import fmon.stat._
|
import fmon.stat._
|
||||||
import fmon.stat.MoveType._
|
import fmon.stat.MoveType._
|
||||||
import fmon.stat.Statistic._
|
import fmon.stat.Statistic._
|
||||||
import fmon.util._
|
import fmon.util.Fraction
|
||||||
"""
|
"""
|
||||||
private val helpers = """
|
private val helpers = """
|
||||||
|
implicit val dice = rng
|
||||||
|
implicit val consumer = reader
|
||||||
def msg(text: String): Unit = {
|
def msg(text: String): Unit = {
|
||||||
reader ! Message(text)
|
reader ! Message(text)
|
||||||
}
|
}
|
||||||
@ -230,4 +238,25 @@ object Status {
|
|||||||
wrapper.asInstanceOf[(Status, Monster, SignalConsumer, Random) => Unit]
|
wrapper.asInstanceOf[(Status, Monster, SignalConsumer, Random) => Unit]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def compileOnLockMove(code: String): (Status, Monster, SignalConsumer, Random) => Option[String] = {
|
||||||
|
if (code == null) {
|
||||||
|
(_, _, _, _) => None
|
||||||
|
} else {
|
||||||
|
val tree = tb.parse(
|
||||||
|
s"""
|
||||||
|
|$header
|
||||||
|
|def onLockMove(self: Status, mon: Monster, reader: SignalConsumer, rng: Random) = {
|
||||||
|
| $helpers
|
||||||
|
| val result = {$code}
|
||||||
|
| Some(result)
|
||||||
|
|}
|
||||||
|
|onLockMove _
|
||||||
|
""".stripMargin)
|
||||||
|
val f = tb.compile(tree)
|
||||||
|
val wrapper = f()
|
||||||
|
|
||||||
|
wrapper.asInstanceOf[(Status, Monster, SignalConsumer, Random) => Option[String]]
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -2,7 +2,7 @@ package fmon.stat
|
|||||||
|
|
||||||
import scala.util.Random
|
import scala.util.Random
|
||||||
|
|
||||||
import fmon.util._
|
import fmon._
|
||||||
|
|
||||||
class StorageMon(val nickname : String, val xp: Int, val gene : Gene, val form : Form, val evs : Map[Stat, Int], val moves : IndexedSeq[Move], val ability: Ability) {
|
class StorageMon(val nickname : String, val xp: Int, val gene : Gene, val form : Form, val evs : Map[Stat, Int], val moves : IndexedSeq[Move], val ability: Ability) {
|
||||||
def level = form.xpCurve(xp)
|
def level = form.xpCurve(xp)
|
||||||
|
@ -462,6 +462,29 @@ bite:
|
|||||||
target: Normal
|
target: Normal
|
||||||
type: Dark
|
type: Dark
|
||||||
zMovePower: 120
|
zMovePower: 120
|
||||||
|
blastburn:
|
||||||
|
accuracy: 90
|
||||||
|
basePower: 150
|
||||||
|
category: Special
|
||||||
|
contestType: Beautiful
|
||||||
|
desc: If this move is successful, the user must recharge on the following turn and
|
||||||
|
cannot make a move.
|
||||||
|
flags:
|
||||||
|
mirror: 1
|
||||||
|
protect: 1
|
||||||
|
recharge: 1
|
||||||
|
id: blastburn
|
||||||
|
name: Blast Burn
|
||||||
|
num: 307
|
||||||
|
pp: 5
|
||||||
|
priority: 0
|
||||||
|
secondary: null
|
||||||
|
self:
|
||||||
|
volatileStatus: mustrecharge
|
||||||
|
shortDesc: User cannot move next turn.
|
||||||
|
target: Normal
|
||||||
|
type: Fire
|
||||||
|
zMovePower: 200
|
||||||
blazekick:
|
blazekick:
|
||||||
accuracy: 90
|
accuracy: 90
|
||||||
basePower: 85
|
basePower: 85
|
||||||
@ -1621,6 +1644,25 @@ dragonpulse:
|
|||||||
target: Any
|
target: Any
|
||||||
type: Dragon
|
type: Dragon
|
||||||
zMovePower: 160
|
zMovePower: 160
|
||||||
|
dragonrage:
|
||||||
|
accuracy: 100
|
||||||
|
basePower: 0
|
||||||
|
category: Special
|
||||||
|
contestType: Cool
|
||||||
|
damage: 40
|
||||||
|
flags:
|
||||||
|
mirror: 1
|
||||||
|
protect: 1
|
||||||
|
id: dragonrage
|
||||||
|
name: Dragon Rage
|
||||||
|
num: 82
|
||||||
|
pp: 10
|
||||||
|
priority: 0
|
||||||
|
secondary: null
|
||||||
|
shortDesc: Deals 40 HP of damage to the target.
|
||||||
|
target: Normal
|
||||||
|
type: Dragon
|
||||||
|
zMovePower: 100
|
||||||
dragonrush:
|
dragonrush:
|
||||||
accuracy: 75
|
accuracy: 75
|
||||||
basePower: 100
|
basePower: 100
|
||||||
@ -2021,6 +2063,34 @@ extremespeed:
|
|||||||
target: Normal
|
target: Normal
|
||||||
type: Normal
|
type: Normal
|
||||||
zMovePower: 160
|
zMovePower: 160
|
||||||
|
facade:
|
||||||
|
accuracy: 100
|
||||||
|
basePower: 70
|
||||||
|
category: Physical
|
||||||
|
contestType: Cute
|
||||||
|
desc: Power doubles if the user is burned, paralyzed, or poisoned. The physical
|
||||||
|
damage halving effect from the user's burn is ignored.
|
||||||
|
flags:
|
||||||
|
contact: 1
|
||||||
|
mirror: 1
|
||||||
|
protect: 1
|
||||||
|
id: facade
|
||||||
|
isViable: true
|
||||||
|
name: Facade
|
||||||
|
num: 263
|
||||||
|
onBasePower: |-
|
||||||
|
if (user.status != null && user.status != Status("slp")) {
|
||||||
|
move.pow * 2
|
||||||
|
} else {
|
||||||
|
move.pow
|
||||||
|
}
|
||||||
|
pp: 20
|
||||||
|
priority: 0
|
||||||
|
secondary: null
|
||||||
|
shortDesc: Power doubles if user is burn/poison/paralyzed.
|
||||||
|
target: Normal
|
||||||
|
type: Normal
|
||||||
|
zMovePower: 140
|
||||||
fairywind:
|
fairywind:
|
||||||
accuracy: 100
|
accuracy: 100
|
||||||
basePower: 40
|
basePower: 40
|
||||||
@ -2481,6 +2551,30 @@ forcepalm:
|
|||||||
target: Normal
|
target: Normal
|
||||||
type: Fighting
|
type: Fighting
|
||||||
zMovePower: 120
|
zMovePower: 120
|
||||||
|
frenzyplant:
|
||||||
|
accuracy: 90
|
||||||
|
basePower: 150
|
||||||
|
category: Special
|
||||||
|
contestType: Cool
|
||||||
|
desc: If this move is successful, the user must recharge on the following turn and
|
||||||
|
cannot select a move.
|
||||||
|
flags:
|
||||||
|
mirror: 1
|
||||||
|
nonsky: 1
|
||||||
|
protect: 1
|
||||||
|
recharge: 1
|
||||||
|
id: frenzyplant
|
||||||
|
name: Frenzy Plant
|
||||||
|
num: 338
|
||||||
|
pp: 5
|
||||||
|
priority: 0
|
||||||
|
secondary: null
|
||||||
|
self:
|
||||||
|
volatileStatus: mustrecharge
|
||||||
|
shortDesc: User cannot move next turn.
|
||||||
|
target: Normal
|
||||||
|
type: Grass
|
||||||
|
zMovePower: 200
|
||||||
frostbreath:
|
frostbreath:
|
||||||
accuracy: 90
|
accuracy: 90
|
||||||
basePower: 60
|
basePower: 60
|
||||||
@ -2527,6 +2621,30 @@ gigadrain:
|
|||||||
target: Normal
|
target: Normal
|
||||||
type: Grass
|
type: Grass
|
||||||
zMovePower: 140
|
zMovePower: 140
|
||||||
|
gigaimpact:
|
||||||
|
accuracy: 90
|
||||||
|
basePower: 150
|
||||||
|
category: Physical
|
||||||
|
contestType: Tough
|
||||||
|
desc: If this move is successful, the user must recharge on the following turn and
|
||||||
|
cannot select a move.
|
||||||
|
flags:
|
||||||
|
contact: 1
|
||||||
|
mirror: 1
|
||||||
|
protect: 1
|
||||||
|
recharge: 1
|
||||||
|
id: gigaimpact
|
||||||
|
name: Giga Impact
|
||||||
|
num: 416
|
||||||
|
pp: 5
|
||||||
|
priority: 0
|
||||||
|
secondary: null
|
||||||
|
self:
|
||||||
|
volatileStatus: mustrecharge
|
||||||
|
shortDesc: User cannot move next turn.
|
||||||
|
target: Normal
|
||||||
|
type: Normal
|
||||||
|
zMovePower: 200
|
||||||
glaciate:
|
glaciate:
|
||||||
accuracy: 95
|
accuracy: 95
|
||||||
basePower: 65
|
basePower: 65
|
||||||
@ -2953,6 +3071,29 @@ howl:
|
|||||||
type: Normal
|
type: Normal
|
||||||
zMoveBoost:
|
zMoveBoost:
|
||||||
PAtk: 1
|
PAtk: 1
|
||||||
|
hydrocannon:
|
||||||
|
accuracy: 90
|
||||||
|
basePower: 150
|
||||||
|
category: Special
|
||||||
|
contestType: Beautiful
|
||||||
|
desc: If this move is successful, the user must recharge on the following turn and
|
||||||
|
cannot select a move.
|
||||||
|
flags:
|
||||||
|
mirror: 1
|
||||||
|
protect: 1
|
||||||
|
recharge: 1
|
||||||
|
id: hydrocannon
|
||||||
|
name: Hydro Cannon
|
||||||
|
num: 308
|
||||||
|
pp: 5
|
||||||
|
priority: 0
|
||||||
|
secondary: null
|
||||||
|
self:
|
||||||
|
volatileStatus: mustrecharge
|
||||||
|
shortDesc: User cannot move next turn.
|
||||||
|
target: Normal
|
||||||
|
type: Water
|
||||||
|
zMovePower: 200
|
||||||
hydropump:
|
hydropump:
|
||||||
accuracy: 80
|
accuracy: 80
|
||||||
basePower: 110
|
basePower: 110
|
||||||
@ -2972,6 +3113,29 @@ hydropump:
|
|||||||
target: Normal
|
target: Normal
|
||||||
type: Water
|
type: Water
|
||||||
zMovePower: 185
|
zMovePower: 185
|
||||||
|
hyperbeam:
|
||||||
|
accuracy: 90
|
||||||
|
basePower: 150
|
||||||
|
category: Special
|
||||||
|
contestType: Cool
|
||||||
|
desc: If this move is successful, the user must recharge on the following turn and
|
||||||
|
cannot select a move.
|
||||||
|
flags:
|
||||||
|
mirror: 1
|
||||||
|
protect: 1
|
||||||
|
recharge: 1
|
||||||
|
id: hyperbeam
|
||||||
|
name: Hyper Beam
|
||||||
|
num: 63
|
||||||
|
pp: 5
|
||||||
|
priority: 0
|
||||||
|
secondary: null
|
||||||
|
self:
|
||||||
|
volatileStatus: mustrecharge
|
||||||
|
shortDesc: User cannot move next turn.
|
||||||
|
target: Normal
|
||||||
|
type: Normal
|
||||||
|
zMovePower: 200
|
||||||
hyperfang:
|
hyperfang:
|
||||||
accuracy: 90
|
accuracy: 90
|
||||||
basePower: 80
|
basePower: 80
|
||||||
@ -4081,6 +4245,28 @@ nastyplot:
|
|||||||
target: Self
|
target: Self
|
||||||
type: Dark
|
type: Dark
|
||||||
zMoveEffect: clearnegativeboost
|
zMoveEffect: clearnegativeboost
|
||||||
|
naturesmadness:
|
||||||
|
accuracy: 90
|
||||||
|
basePower: 0
|
||||||
|
category: Special
|
||||||
|
contestType: Tough
|
||||||
|
damage: Math.max(target.hp / 2, 1);
|
||||||
|
desc: Deals damage to the target equal to half of its current HP, rounded down,
|
||||||
|
but not less than 1 HP.
|
||||||
|
flags:
|
||||||
|
mirror: 1
|
||||||
|
protect: 1
|
||||||
|
id: naturesmadness
|
||||||
|
isViable: true
|
||||||
|
name: Nature's Madness
|
||||||
|
num: 717
|
||||||
|
pp: 10
|
||||||
|
priority: 0
|
||||||
|
secondary: null
|
||||||
|
shortDesc: Does damage equal to 1/2 target's current HP.
|
||||||
|
target: Normal
|
||||||
|
type: Fairy
|
||||||
|
zMovePower: 100
|
||||||
needlearm:
|
needlearm:
|
||||||
accuracy: 100
|
accuracy: 100
|
||||||
basePower: 60
|
basePower: 60
|
||||||
@ -4125,6 +4311,27 @@ nightdaze:
|
|||||||
target: Normal
|
target: Normal
|
||||||
type: Dark
|
type: Dark
|
||||||
zMovePower: 160
|
zMovePower: 160
|
||||||
|
nightshade:
|
||||||
|
accuracy: 100
|
||||||
|
basePower: 0
|
||||||
|
category: Special
|
||||||
|
contestType: Clever
|
||||||
|
damage: user.level
|
||||||
|
desc: Deals damage to the target equal to the user's level.
|
||||||
|
flags:
|
||||||
|
mirror: 1
|
||||||
|
protect: 1
|
||||||
|
id: nightshade
|
||||||
|
isViable: true
|
||||||
|
name: Night Shade
|
||||||
|
num: 101
|
||||||
|
pp: 15
|
||||||
|
priority: 0
|
||||||
|
secondary: null
|
||||||
|
shortDesc: Does damage equal to the user's level.
|
||||||
|
target: Normal
|
||||||
|
type: Ghost
|
||||||
|
zMovePower: 100
|
||||||
nightslash:
|
nightslash:
|
||||||
accuracy: 100
|
accuracy: 100
|
||||||
basePower: 70
|
basePower: 70
|
||||||
@ -4711,6 +4918,29 @@ precipiceblades:
|
|||||||
target: AllAdjacentFoes
|
target: AllAdjacentFoes
|
||||||
type: Ground
|
type: Ground
|
||||||
zMovePower: 190
|
zMovePower: 190
|
||||||
|
prismaticlaser:
|
||||||
|
accuracy: 100
|
||||||
|
basePower: 160
|
||||||
|
category: Special
|
||||||
|
contestType: Cool
|
||||||
|
desc: If this move is successful, the user must recharge on the following turn and
|
||||||
|
cannot select a move.
|
||||||
|
flags:
|
||||||
|
mirror: 1
|
||||||
|
protect: 1
|
||||||
|
recharge: 1
|
||||||
|
id: prismaticlaser
|
||||||
|
name: Prismatic Laser
|
||||||
|
num: 711
|
||||||
|
pp: 10
|
||||||
|
priority: 0
|
||||||
|
secondary: null
|
||||||
|
self:
|
||||||
|
volatileStatus: mustrecharge
|
||||||
|
shortDesc: User cannot move next turn.
|
||||||
|
target: Normal
|
||||||
|
type: Psychic
|
||||||
|
zMovePower: 200
|
||||||
psybeam:
|
psybeam:
|
||||||
accuracy: 100
|
accuracy: 100
|
||||||
basePower: 65
|
basePower: 65
|
||||||
@ -4799,7 +5029,27 @@ psychocut:
|
|||||||
target: Normal
|
target: Normal
|
||||||
type: Psychic
|
type: Psychic
|
||||||
zMovePower: 140
|
zMovePower: 140
|
||||||
|
psywave:
|
||||||
|
accuracy: 100
|
||||||
|
basePower: 0
|
||||||
|
category: Special
|
||||||
|
contestType: Clever
|
||||||
|
damage: rng.nextInt(50, 151) * user.level / 100
|
||||||
|
desc: Deals damage to the target equal to (user's level) * (X + 50) / 100, where
|
||||||
|
X is a random number from 0 to 100, rounded down, but not less than 1 HP.
|
||||||
|
flags:
|
||||||
|
mirror: 1
|
||||||
|
protect: 1
|
||||||
|
id: psywave
|
||||||
|
name: Psywave
|
||||||
|
num: 149
|
||||||
|
pp: 15
|
||||||
|
priority: 0
|
||||||
|
secondary: null
|
||||||
|
shortDesc: Random damage equal to 0.5x-1.5x user's level.
|
||||||
|
target: Normal
|
||||||
|
type: Psychic
|
||||||
|
zMovePower: 100
|
||||||
quickattack:
|
quickattack:
|
||||||
accuracy: 100
|
accuracy: 100
|
||||||
basePower: 40
|
basePower: 40
|
||||||
@ -4889,6 +5139,48 @@ razorshell:
|
|||||||
target: Normal
|
target: Normal
|
||||||
type: Water
|
type: Water
|
||||||
zMovePower: 140
|
zMovePower: 140
|
||||||
|
recharge:
|
||||||
|
accuracy: 100
|
||||||
|
basePower: 0
|
||||||
|
category: Support
|
||||||
|
contestType: Tough
|
||||||
|
flags:
|
||||||
|
contact: 1
|
||||||
|
mirror: 1
|
||||||
|
protect: 1
|
||||||
|
id: recharge
|
||||||
|
name: Recharge
|
||||||
|
num: 10
|
||||||
|
pp: 40
|
||||||
|
priority: 0
|
||||||
|
secondary: null
|
||||||
|
shortDesc: Placeholder move for when recharging.
|
||||||
|
target: Normal
|
||||||
|
type: Normal
|
||||||
|
zMovePower: 100
|
||||||
|
roaroftime:
|
||||||
|
accuracy: 90
|
||||||
|
basePower: 150
|
||||||
|
category: Special
|
||||||
|
contestType: Beautiful
|
||||||
|
desc: If this move is successful, the user must recharge on the following turn and
|
||||||
|
cannot select a move.
|
||||||
|
flags:
|
||||||
|
mirror: 1
|
||||||
|
protect: 1
|
||||||
|
recharge: 1
|
||||||
|
id: roaroftime
|
||||||
|
name: Roar of Time
|
||||||
|
num: 459
|
||||||
|
pp: 5
|
||||||
|
priority: 0
|
||||||
|
secondary: null
|
||||||
|
self:
|
||||||
|
volatileStatus: mustrecharge
|
||||||
|
shortDesc: User cannot move next turn.
|
||||||
|
target: Normal
|
||||||
|
type: Dragon
|
||||||
|
zMovePower: 200
|
||||||
rockclimb:
|
rockclimb:
|
||||||
accuracy: 85
|
accuracy: 85
|
||||||
basePower: 90
|
basePower: 90
|
||||||
@ -5017,6 +5309,30 @@ rocktomb:
|
|||||||
target: Normal
|
target: Normal
|
||||||
type: Rock
|
type: Rock
|
||||||
zMovePower: 120
|
zMovePower: 120
|
||||||
|
rockwrecker:
|
||||||
|
accuracy: 90
|
||||||
|
basePower: 150
|
||||||
|
category: Physical
|
||||||
|
contestType: Tough
|
||||||
|
desc: If this move is successful, the user must recharge on the following turn and
|
||||||
|
cannot select a move.
|
||||||
|
flags:
|
||||||
|
bullet: 1
|
||||||
|
mirror: 1
|
||||||
|
protect: 1
|
||||||
|
recharge: 1
|
||||||
|
id: rockwrecker
|
||||||
|
name: Rock Wrecker
|
||||||
|
num: 439
|
||||||
|
pp: 5
|
||||||
|
priority: 0
|
||||||
|
secondary: null
|
||||||
|
self:
|
||||||
|
volatileStatus: mustrecharge
|
||||||
|
shortDesc: User cannot move next turn.
|
||||||
|
target: Normal
|
||||||
|
type: Rock
|
||||||
|
zMovePower: 200
|
||||||
rollingkick:
|
rollingkick:
|
||||||
accuracy: 85
|
accuracy: 85
|
||||||
basePower: 60
|
basePower: 60
|
||||||
@ -5244,6 +5560,29 @@ seedflare:
|
|||||||
target: Normal
|
target: Normal
|
||||||
type: Grass
|
type: Grass
|
||||||
zMovePower: 190
|
zMovePower: 190
|
||||||
|
seismictoss:
|
||||||
|
accuracy: 100
|
||||||
|
basePower: 0
|
||||||
|
category: Physical
|
||||||
|
contestType: Tough
|
||||||
|
damage: user.level
|
||||||
|
desc: Deals damage to the target equal to the user's level.
|
||||||
|
flags:
|
||||||
|
contact: 1
|
||||||
|
mirror: 1
|
||||||
|
nonsky: 1
|
||||||
|
protect: 1
|
||||||
|
id: seismictoss
|
||||||
|
isViable: true
|
||||||
|
name: Seismic Toss
|
||||||
|
num: 69
|
||||||
|
pp: 20
|
||||||
|
priority: 0
|
||||||
|
secondary: null
|
||||||
|
shortDesc: Does damage equal to the user's level.
|
||||||
|
target: Normal
|
||||||
|
type: Fighting
|
||||||
|
zMovePower: 100
|
||||||
shadowball:
|
shadowball:
|
||||||
accuracy: 100
|
accuracy: 100
|
||||||
basePower: 80
|
basePower: 80
|
||||||
@ -5803,6 +6142,26 @@ snarl:
|
|||||||
target: AllAdjacentFoes
|
target: AllAdjacentFoes
|
||||||
type: Dark
|
type: Dark
|
||||||
zMovePower: 100
|
zMovePower: 100
|
||||||
|
sonicboom:
|
||||||
|
accuracy: 90
|
||||||
|
basePower: 0
|
||||||
|
category: Special
|
||||||
|
contestType: Cool
|
||||||
|
damage: 20
|
||||||
|
desc: Deals 20 HP of damage to the target.
|
||||||
|
flags:
|
||||||
|
mirror: 1
|
||||||
|
protect: 1
|
||||||
|
id: sonicboom
|
||||||
|
name: Sonic Boom
|
||||||
|
num: 49
|
||||||
|
pp: 20
|
||||||
|
priority: 0
|
||||||
|
secondary: null
|
||||||
|
shortDesc: Always does 20 HP of damage.
|
||||||
|
target: Normal
|
||||||
|
type: Normal
|
||||||
|
zMovePower: 100
|
||||||
spacialrend:
|
spacialrend:
|
||||||
accuracy: 95
|
accuracy: 95
|
||||||
basePower: 100
|
basePower: 100
|
||||||
@ -6140,6 +6499,30 @@ submission:
|
|||||||
target: Normal
|
target: Normal
|
||||||
type: Fighting
|
type: Fighting
|
||||||
zMovePower: 160
|
zMovePower: 160
|
||||||
|
superfang:
|
||||||
|
accuracy: 90
|
||||||
|
basePower: 0
|
||||||
|
category: Physical
|
||||||
|
contestType: Tough
|
||||||
|
damage: Math.max(target.hp / 2, 1);
|
||||||
|
desc: Deals damage to the target equal to half of its current HP, rounded down,
|
||||||
|
but not less than 1 HP.
|
||||||
|
flags:
|
||||||
|
contact: 1
|
||||||
|
mirror: 1
|
||||||
|
protect: 1
|
||||||
|
id: superfang
|
||||||
|
isViable: true
|
||||||
|
name: Super Fang
|
||||||
|
num: 162
|
||||||
|
pp: 10
|
||||||
|
priority: 0
|
||||||
|
secondary: null
|
||||||
|
shortDesc: Does damage equal to 1/2 target's current HP.
|
||||||
|
target: Normal
|
||||||
|
type: Normal
|
||||||
|
zMovePower: 100
|
||||||
|
|
||||||
superpower:
|
superpower:
|
||||||
accuracy: 100
|
accuracy: 100
|
||||||
basePower: 120
|
basePower: 120
|
||||||
@ -6763,6 +7146,34 @@ vitalthrow:
|
|||||||
target: Normal
|
target: Normal
|
||||||
type: Fighting
|
type: Fighting
|
||||||
zMovePower: 140
|
zMovePower: 140
|
||||||
|
volttackle:
|
||||||
|
accuracy: 100
|
||||||
|
basePower: 120
|
||||||
|
category: Physical
|
||||||
|
contestType: Cool
|
||||||
|
desc: Has a 10% chance to paralyze the target. If the target lost HP, the user takes
|
||||||
|
recoil damage equal to 33% the HP lost by the target, rounded half up, but not
|
||||||
|
less than 1 HP.
|
||||||
|
flags:
|
||||||
|
contact: 1
|
||||||
|
mirror: 1
|
||||||
|
protect: 1
|
||||||
|
id: volttackle
|
||||||
|
isViable: true
|
||||||
|
name: Volt Tackle
|
||||||
|
num: 344
|
||||||
|
pp: 15
|
||||||
|
priority: 0
|
||||||
|
recoil:
|
||||||
|
denom: 100
|
||||||
|
num: 33
|
||||||
|
secondary:
|
||||||
|
chance: 10
|
||||||
|
status: par
|
||||||
|
shortDesc: Has 33% recoil. 10% chance to paralyze target.
|
||||||
|
target: Normal
|
||||||
|
type: Electric
|
||||||
|
zMovePower: 190
|
||||||
waterfall:
|
waterfall:
|
||||||
accuracy: 100
|
accuracy: 100
|
||||||
basePower: 80
|
basePower: 80
|
||||||
@ -6985,6 +7396,26 @@ workup:
|
|||||||
type: Normal
|
type: Normal
|
||||||
zMoveBoost:
|
zMoveBoost:
|
||||||
PAtk: 1
|
PAtk: 1
|
||||||
|
xscissor:
|
||||||
|
accuracy: 100
|
||||||
|
basePower: 80
|
||||||
|
category: Physical
|
||||||
|
contestType: Cool
|
||||||
|
flags:
|
||||||
|
contact: 1
|
||||||
|
mirror: 1
|
||||||
|
protect: 1
|
||||||
|
id: xscissor
|
||||||
|
isViable: true
|
||||||
|
name: X-Scissor
|
||||||
|
num: 404
|
||||||
|
pp: 15
|
||||||
|
priority: 0
|
||||||
|
secondary: null
|
||||||
|
shortDesc: No additional effect.
|
||||||
|
target: Normal
|
||||||
|
type: Bug
|
||||||
|
zMovePower: 160
|
||||||
zapcannon:
|
zapcannon:
|
||||||
accuracy: 50
|
accuracy: 50
|
||||||
basePower: 120
|
basePower: 120
|
||||||
|
@ -41,16 +41,6 @@ confusion:
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
this.activeTarget = mon;
|
|
||||||
let damage = this.getDamage(mon, mon, 40);
|
|
||||||
if (typeof damage !== 'number') throw new Error('Confusion damage not dealt');
|
|
||||||
mon.takeDamage(damage, mon, mon, /** @type {ActiveMove} */ ({
|
|
||||||
'id': 'confused',
|
|
||||||
'effectType': 'Move',
|
|
||||||
'type': '???'
|
|
||||||
}));
|
|
||||||
*/
|
|
||||||
onBeforeMovePriority: 3
|
onBeforeMovePriority: 3
|
||||||
onEnd: msg(s"${mon} snapped out of its confusion.")
|
onEnd: msg(s"${mon} snapped out of its confusion.")
|
||||||
onStart: |-
|
onStart: |-
|
||||||
@ -95,11 +85,6 @@ slp:
|
|||||||
msg(s"${mon} woke up!")
|
msg(s"${mon} woke up!")
|
||||||
onBeforeMovePriority: 10
|
onBeforeMovePriority: 10
|
||||||
onBeforeMove: |
|
onBeforeMove: |
|
||||||
/*
|
|
||||||
if (mon.hasAbility('earlybird')) {
|
|
||||||
this.intData.time--;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
self.intData("time") -= 1;
|
self.intData("time") -= 1;
|
||||||
if (self.intData("time") <= 0) {
|
if (self.intData("time") <= 0) {
|
||||||
mon.cureStatus();
|
mon.cureStatus();
|
||||||
@ -149,6 +134,21 @@ frz:
|
|||||||
mon.cureStatus()
|
mon.cureStatus()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mustrecharge:
|
||||||
|
duration: 2
|
||||||
|
id: mustrecharge
|
||||||
|
name: mustrecharge
|
||||||
|
num: 0
|
||||||
|
onBeforeMove: |-
|
||||||
|
msg(s"${mon} must recharge!")
|
||||||
|
mon -= self
|
||||||
|
//mon.removeVolatile('mustrecharge');
|
||||||
|
//mon.removeVolatile('truant');
|
||||||
|
false
|
||||||
|
onBeforeMovePriority: 11
|
||||||
|
onLockMove: |
|
||||||
|
"recharge"
|
||||||
|
|
||||||
psn:
|
psn:
|
||||||
name: 'psn'
|
name: 'psn'
|
||||||
id: 'psn'
|
id: 'psn'
|
||||||
|
@ -15,7 +15,6 @@ package object stat {
|
|||||||
type Target = Target.Value
|
type Target = Target.Value
|
||||||
type XpCurve = XpCurve.Val
|
type XpCurve = XpCurve.Val
|
||||||
|
|
||||||
implicit def rngDice(rng : Random) = new Dice(rng)
|
|
||||||
implicit def ptrToMonster(ptr : MonsterPtr) : Monster = ptr.mon
|
|
||||||
implicit def templateToStatus(status: StatusTemplate): Status = status.build
|
implicit def templateToStatus(status: StatusTemplate): Status = status.build
|
||||||
|
|
||||||
}
|
}
|
@ -42,5 +42,4 @@ package object util {
|
|||||||
new BufferedInputStream(new FileInputStream(filename))
|
new BufferedInputStream(new FileInputStream(filename))
|
||||||
}
|
}
|
||||||
|
|
||||||
implicit def int2Helper(x : Int) = new IntFraction(x)
|
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user