Added support for abilities including a bunch of abilities that have effects the the monster is hit. Better monster generation support has been added.

This commit is contained in:
James Daly 2019-06-05 21:31:25 -04:00
parent ce81ab2079
commit ad6780362b
12 changed files with 351 additions and 73 deletions

View File

@ -18,13 +18,13 @@ object Game {
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("Confuse Ray")) val movepool1 = IndexedSeq(Move("electroball"), Move("thunderwave"))
val movepool2 = IndexedSeq(Move("Headbutt")) val movepool2 = IndexedSeq(Move("headbutt"))
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(new Monster(new StorageMon("Allied Mon", 500, Gene.randomGene(null, form1), form1, Statistic.emptyEvs, movepool1))), IndexedSeq()) val party1 = new Party(p1, new MonsterPtr(Monster.generate("Allied Mon", p1, 500, form1, movepool1)), IndexedSeq())
val party2 = new Party(p2, new MonsterPtr(new Monster(new StorageMon("Wild Mon", 500, Gene.randomGene(null, form2), form2, Statistic.emptyEvs, movepool2))), IndexedSeq( val party2 = new Party(p2, new MonsterPtr(Monster.generate("Wild Mon", p2, 500, form2, movepool2)), IndexedSeq(
new Monster(new StorageMon("Sideboard Mon", 500, Gene.randomGene(null, form2), form2, Statistic.emptyEvs, movepool2)) Monster.generate("Sideboard Mon", p2, 500, form2, movepool2)
)) ))
println(form1.xpCurve) println(form1.xpCurve)
val engine = new BattleEngine(party1, party2) val engine = new BattleEngine(party1, party2)

View File

@ -0,0 +1,76 @@
package fmon.stat
import scala.reflect.runtime.universe._
import scala.tools.reflect.ToolBox
import scala.io.Source
import scala.util.Random
import fmon.util._
abstract class Ability {
val name: String
val desc: String
def onAfterDamage(source: Monster, move: MoveTurn, mon: Monster, dmg: Int)(implicit rng: Random) = onAfterDamageImp(source, move, mon, dmg, rng)
protected val onAfterDamageImp: (Monster, MoveTurn, Monster, Int, Random) => Unit
override def toString = name
}
class AbilityToken(
val name: String,
val shortDesc: String,
val onAfterDamage: String
) {
def instantiate(): Ability = {
val self = this
new Ability {
val name = self.name
val desc = self.shortDesc
val onAfterDamageImp = Ability.compileOnAfterDamage(self.onAfterDamage)
}
}
}
object Ability {
private var abilities = Map[String, Ability]()
val tokens = YamlHelper.extractMap[AbilityToken](Source.fromInputStream(Ability.getClass.getResourceAsStream("data/abilities.yaml")))
private val tb = runtimeMirror(getClass.getClassLoader).mkToolBox()
def apply(name: String) = {
if (!abilities.contains(name)) {
abilities = abilities.updated(name, tokens(name).instantiate())
}
abilities(name)
}
private val header = """
|import scala.util.Random
|import fmon.stat._
|import fmon.stat.MoveType._
|import fmon.stat.Statistic._
|import fmon.util._
"""
def compileOnAfterDamage(code: String): (Monster, MoveTurn, Monster, Int, Random) => Unit = {
if (code == null) {
(_, _, _, _, _) => ()
} else {
val tree = tb.parse(
s"""
|$header
|def onAfterDamage(source: Monster, move: MoveTurn, mon: Monster, damage: Int, rng: Random): Unit = {
| implicit val gen = rng
| $code
|}
|onAfterDamage _
""".stripMargin)
val f = tb.compile(tree)
val wrapper = f()
implicit val c = code
wrapper.asInstanceOf[(Monster, MoveTurn, Monster, Int, Random) => Unit]
}
}
}

View File

@ -17,7 +17,7 @@ abstract class Form {
val baseStats : Map[Stat, Int] val baseStats : Map[Stat, Int]
// val appearance // animation // val appearance // animation
// moves // moves
// abilities val abilities : IndexedSeq[Ability]
val xpCurve : XpCurve val xpCurve : XpCurve
val catchRate : Int val catchRate : Int
// val color // val color
@ -30,6 +30,7 @@ abstract class Form {
case class FormToken( case class FormToken(
val name : String, val name : String,
val desc : String, val desc : String,
val abilities : IndexedSeq[String],
val elements : IndexedSeq[String], val elements : IndexedSeq[String],
val baseStats : Map[String, Int], val baseStats : Map[String, Int],
@JsonScalaEnumeration(classOf[XpCurveType]) val xpCurve : XpCurve, @JsonScalaEnumeration(classOf[XpCurveType]) val xpCurve : XpCurve,
@ -43,6 +44,7 @@ case class FormToken(
val desc = self.desc val desc = self.desc
val elements = self.elements.map(Element(_)) val elements = self.elements.map(Element(_))
val baseStats = self.baseStats.map{ case (s, i) => (Statistic(s), i)} val baseStats = self.baseStats.map{ case (s, i) => (Statistic(s), i)}
val abilities = self.abilities.map(Ability(_))
val xpCurve = self.xpCurve val xpCurve = self.xpCurve
val catchRate = self.catchRate val catchRate = self.catchRate
} }

View File

@ -68,6 +68,11 @@ class Monster(val base : StorageMon) {
def applyBoost(s : Stat, boost : Int) { def applyBoost(s : Stat, boost : Int) {
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(MaxBoost, Math.max(-MaxBoost, modified)))
if (boost > 0) {
println(s"$this's $s rose!")
} else if (boost < 0) {
println(s"$this's $s fell!")
}
} }
def effectiveness(element : Element) : Double = { def effectiveness(element : Element) : Double = {
@ -88,7 +93,11 @@ class Monster(val base : StorageMon) {
object Monster { object Monster {
final val MaxBoost = 6 final val MaxBoost = 6
def build(trainer : TrainerID, form : Form)(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))
} }
}
class MonsterPtr(var mon : Monster) {
override def toString : String = mon.toString()
} }

View File

@ -1,6 +0,0 @@
package fmon.stat
class MonsterPtr(var mon : Monster) {
override def toString : String = mon.toString()
}

View File

@ -12,7 +12,7 @@ import Statistic._
import fmon.util._ import fmon.util._
object MoveType extends Enumeration { object MoveType extends Enumeration {
val Physical, Special, Status = Value val Physical, Special, Support, Other = Value
} }
class MoveTypeType extends TypeReference[MoveType.type] class MoveTypeType extends TypeReference[MoveType.type]
@ -26,6 +26,7 @@ trait MoveTurn {
def flags: Set[String] def flags: Set[String]
def prior: Int def prior: Int
def target: Target def target: Target
def category: MoveType
def useMove(user: Monster, target: Monster)(implicit rng: Random): Unit def useMove(user: Monster, target: Monster)(implicit rng: Random): Unit
} }
@ -34,6 +35,7 @@ class SwitchOut(val party: Party, val replacement: Monster) extends MoveTurn {
def flags = Set() def flags = Set()
def prior = +6 def prior = +6
def target = Target.Self def target = Target.Self
def category = MoveType.Other
def useMove(user: Monster, target: Monster)(implicit rng: Random): Unit = { def useMove(user: Monster, target: Monster)(implicit rng: Random): Unit = {
println(s"${party.trainer} withdrew $user!") println(s"${party.trainer} withdrew $user!")
@ -47,7 +49,7 @@ class SwitchOut(val party: Party, val replacement: Monster) extends MoveTurn {
abstract class Move extends MoveTurn { abstract class Move extends MoveTurn {
val name: String val name: String
val desc: String val desc: String
val mvType: MoveType val category: MoveType
val pow: Int val pow: Int
val powCallback: (Monster, Monster) => Int val powCallback: (Monster, Monster) => Int
val prior: Int val prior: Int
@ -89,6 +91,9 @@ abstract class Move extends MoveTurn {
user.takeDamage(recoil) user.takeDamage(recoil)
println(s"$user took $recoil damage from recoil!") println(s"$user took $recoil damage from recoil!")
} }
target.base.ability.onAfterDamage(user, this, target, actualDmg)
if (!user.isAlive) { if (!user.isAlive) {
println(s"$user fainted!") println(s"$user fainted!")
} }
@ -126,8 +131,8 @@ abstract class Move extends MoveTurn {
} }
def damageRoll(user: Monster, target: Monster)(implicit rng: Random) = { def damageRoll(user: Monster, target: Monster)(implicit rng: Random) = {
val atkStat = if (mvType == MoveType.Physical) PAtk else MAtk val atkStat = if (category == MoveType.Physical) PAtk else MAtk
val defStat = if (mvType == MoveType.Physical) PDef else MDef val defStat = if (category == MoveType.Physical) PDef else MDef
// TODO : Fixed damage // TODO : Fixed damage
val actualPow = if (powCallback != null) powCallback(user, target) else pow val actualPow = if (powCallback != null) powCallback(user, target) else pow
val baseDmg = (2 * user.level / 5 + 2) * actualPow * user(atkStat) / (target(defStat) * 50) + 2 val baseDmg = (2 * user.level / 5 + 2) * actualPow * user(atkStat) / (target(defStat) * 50) + 2
@ -172,11 +177,7 @@ abstract class Move extends MoveTurn {
boosts.foreach { boosts.foreach {
case (s, b) => { case (s, b) => {
target.applyBoost(s, b) target.applyBoost(s, b)
if (b > 0) {
println(s"$target's $s rose!")
} else if (b < 0) {
println(s"$target's $s fell!")
}
} }
} }
} }
@ -214,7 +215,7 @@ case class MoveToken(
new Move { new Move {
val name = token.name val name = token.name
val desc = token.shortDesc val desc = token.shortDesc
val mvType = 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 prior = token.priority val prior = token.priority
@ -236,7 +237,7 @@ case class MoveToken(
object Move { object Move {
private var moves = Map[String, Move]() private var moves = Map[String, Move]()
val tokens = YamlHelper.extractSeq[MoveToken](Source.fromInputStream(Move.getClass.getResourceAsStream("data/moves.yaml"))).map(t => (t.name, t)).toMap val tokens = YamlHelper.extractMap[MoveToken](Source.fromInputStream(Move.getClass.getResourceAsStream("data/moves.yaml")))
def apply(name: String): Move = { def apply(name: String): Move = {
if (!moves.contains(name)) { if (!moves.contains(name)) {
@ -250,8 +251,8 @@ object Move {
val tb = runtimeMirror(getClass.getClassLoader).mkToolBox() val tb = runtimeMirror(getClass.getClassLoader).mkToolBox()
val tree = tb.parse( val tree = tb.parse(
s""" s"""
|import mon.stat.Monster |import fmon.stat.Monster
|import mon.stat.Statistic._ |import fmon.stat.Statistic._
|def callback(user : Monster, target : Monster): Int = { |def callback(user : Monster, target : Monster): Int = {
| $code | $code
|} |}

View File

@ -99,6 +99,13 @@ object Status {
} }
private val tb = runtimeMirror(getClass.getClassLoader).mkToolBox() private val tb = runtimeMirror(getClass.getClassLoader).mkToolBox()
private val header = """
import scala.util.Random
import fmon.stat._
import fmon.stat.MoveType._
import fmon.stat.Statistic._
import fmon.util._
"""
def compileOnStart(code: String): (Status, Monster /*, source, source effect */, Random ) => Unit = { def compileOnStart(code: String): (Status, Monster /*, source, source effect */, Random ) => Unit = {
if (code == null) { if (code == null) {
@ -106,10 +113,7 @@ object Status {
} else { } else {
val tree = tb.parse( val tree = tb.parse(
s""" s"""
|import scala.util.Random |$header
|import fmon.stat._
|import fmon.stat.Statistic._
|import fmon.util._
|def onStart(self:Status, mon: Monster, rng: Random) = { |def onStart(self:Status, mon: Monster, rng: Random) = {
| $code | $code
|} |}
@ -127,13 +131,11 @@ object Status {
} else { } else {
val tree = tb.parse( val tree = tb.parse(
s""" s"""
|import fmon.stat._ |$header
|import fmon.stat.Statistic._
|import fmon.util._
|def onStart(self:Status, mon: Monster) = { |def onStart(self:Status, mon: Monster) = {
| $code | $code
|} |}
|onStart _ onStart _
""".stripMargin) """.stripMargin)
val f = tb.compile(tree) val f = tb.compile(tree)
val wrapper = f() val wrapper = f()
@ -147,15 +149,13 @@ object Status {
} else { } else {
val tree = tb.parse( val tree = tb.parse(
s""" s"""
import scala.util.Random $header
import fmon.stat._
import fmon.stat.Statistic._
import fmon.util._
def onBeforeMove(self: Status, mon: Monster, move: MoveTurn, target: Monster, rng: Random): Boolean = { def onBeforeMove(self: Status, mon: Monster, move: MoveTurn, target: Monster, rng: Random): Boolean = {
$code $code
} }
onBeforeMove _ onBeforeMove _
""") """)
val f = tb.compile(tree) val f = tb.compile(tree)
val wrapper = f() val wrapper = f()
wrapper.asInstanceOf[(Status, Monster, MoveTurn, Monster, Random) => Boolean] wrapper.asInstanceOf[(Status, Monster, MoveTurn, Monster, Random) => Boolean]
@ -168,9 +168,7 @@ object Status {
} else { } else {
val tree = tb.parse( val tree = tb.parse(
s""" s"""
import fmon.stat._ $header
import fmon.stat.Statistic._
import fmon.util._
def onModifyStat(self: Status, mon: Monster, stat: Stat): Fraction = { def onModifyStat(self: Status, mon: Monster, stat: Stat): Fraction = {
$code $code
} }
@ -188,9 +186,7 @@ object Status {
} else { } else {
val tree = tb.parse( val tree = tb.parse(
s""" s"""
|import fmon.stat._ |$header
|import fmon.stat.Statistic._
|import fmon.util._
|def onResidual(self: Status, mon: Monster) = { |def onResidual(self: Status, mon: Monster) = {
| $code | $code
|} |}

View File

@ -1,5 +1,16 @@
package fmon.stat package fmon.stat
class StorageMon(val nickname : String, val xp: Int, val gene : Gene, val form : Form, val evs : Map[Stat, Int], val moves : IndexedSeq[Move]) { import scala.util.Random
import fmon.util._
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)
}
object StorageMon {
def generate(nickname: String, ot: TrainerID, xp: Int, form: Form, moves: IndexedSeq[Move])(implicit rng: Random) = {
val gene = Gene.randomGene(ot, form)
new StorageMon(nickname, xp, gene, form, Statistic.emptyEvs, moves, rng.pick(form.abilities))
}
} }

View File

@ -0,0 +1,164 @@
noability:
id: noability
isNonstandard: Past
name: No Ability
num: 0
rating: 0.1
shortDesc: Does nothing.
aftermath:
desc: If this Pokemon is knocked out with a contact move, that move's user loses
1/4 of its maximum HP, rounded down. If any active Pokemon has the Damp Ability,
this effect is prevented.
id: aftermath
name: Aftermath
num: 106
onAfterDamage: |-
if ((source != null) && (source != mon) && (move != null) && move.flags("contact") && !mon.isAlive) {
println(s"$source is damaged in the aftermath!")
source.takeDamage(source(Hp) / 4);
}
onAfterDamageOrder: 1
rating: 2.5
shortDesc: If this Pokemon is KOed with a contact move, that move's user loses 1/4
its max HP.
flamebody:
id: flamebody
name: Flame Body
num: 49
onAfterDamage: |-
if (move != null && move.flags("contact")) {
if (rng.chance(3, 10)) {
source += Status("brn");
}
}
rating: 2
shortDesc: 30% chance a Pokemon making contact with this Pokemon will be burned.
gooey:
id: gooey
name: Gooey
num: 183
onAfterDamage: |-
if (move != null && move.flags("contact")) {
//this.add('-ability', target, 'Gooey');
source.applyBoost(Speed, -1)
//this.boost({'spe': -1}, source, target, null, true);
}
rating: 2.5
shortDesc: Pokemon making contact with this Pokemon have their Speed lowered by
1 stage.
innardsout:
desc: If this Pokemon is knocked out with a move, that move's user loses HP equal
to the amount of damage inflicted on this Pokemon.
id: innardsout
name: Innards Out
num: 215
onAfterDamage: |-
if (source != null && source != mon && move != null /* && move.effectType === 'Move'*/ && !mon.isAlive) {
println(s"$source is damaged in the aftermath!")
source.takeDamage(damage)//, source, target);
}
onAfterDamageOrder: 1
rating: 2.5
shortDesc: If this Pokemon is KOed with a move, that move's user loses an equal
amount of HP.
ironbarbs:
desc: Pokemon making contact with this Pokemon lose 1/8 of their maximum HP, rounded
down.
id: ironbarbs
name: Iron Barbs
num: 160
onAfterDamage: |-
if (source != null && source != mon && move != null && move.flags("contact")) {
println(s"Pointed barbs dug into $source!")
source.takeDamage(source(Hp) / 8)//, source, target)
}
onAfterDamageOrder: 1
rating: 3
shortDesc: Pokemon making contact with this Pokemon lose 1/8 of their max HP.
poisonpoint:
id: poisonpoint
name: Poison Point
num: 38
onAfterDamage: |-
if (move != null && move.flags("contact")) {
if (rng.chance(3, 10)) {
source += Status("psn")
}
}
rating: 2
shortDesc: 30% chance a Pokemon making contact with this Pokemon will be poisoned.
roughskin:
desc: Pokemon making contact with this Pokemon lose 1/8 of their maximum HP, rounded
down.
id: roughskin
name: Rough Skin
num: 24
onAfterDamage: |-
if (source != null && source != mon && move != null && move.flags("contact")) {
println(s"$source is damaged by rough skin!")
source.takeDamage(source(Hp) / 8)//, source, target)
}
onAfterDamageOrder: 1
rating: 3
shortDesc: Pokemon making contact with this Pokemon lose 1/8 of their max HP.
stamina:
id: stamina
name: Stamina
num: 192
onAfterDamage: |-
if (move != null /*&& effect.effectType == 'Move' && effect.id != 'confused'*/) {
mon.applyBoost(PDef, +1)
}
rating: 3
shortDesc: This Pokemon's Defense is raised by 1 stage after it is damaged by a move.
static:
id: static
name: Static
num: 9
onAfterDamage: |-
if (move != null && move.flags("contact")) {
if (rng.chance(3, 10)) {
source += Status("par");
}
}
rating: 2
shortDesc: 30% chance a Pokemon making contact with this Pokemon will be paralyzed.
tanglinghair:
id: tanglinghair
name: Tangling Hair
num: 221
onAfterDamage: |-
if (move != null && move.flags("contact")) {
this.add('-ability', target, 'Tangling Hair');
source.applyBoost(Speed, -1)
//this.boost({'spe': -1}, source, target, null, true);
}
rating: 2.5
shortDesc: Pokemon making contact with this Pokemon have their Speed lowered by
1 stage.
weakarmor:
desc: If a physical attack hits this Pokemon, its Defense is lowered by 1 stage
and its Speed is raised by 2 stages.
id: weakarmor
name: Weak Armor
num: 133
onAfterDamage: |-
if (move.category == Physical) {
//this.boost({'def': -1, 'spe': 2}, target, target);
mon.applyBoost(PDef, -1)
mon.applyBoost(Speed, +2)
}
rating: 1
shortDesc: If a physical attack hits this Pokemon, Defense is lowered by 1, Speed
is raised by 2.

View File

@ -2,6 +2,8 @@
desc: A vanilla chameleon. desc: A vanilla chameleon.
elements: elements:
- Normal - Normal
abilities:
- noability
baseStats: baseStats:
hp: 60 hp: 60
patk: 70 patk: 70
@ -16,6 +18,9 @@
elements: elements:
- Electric - Electric
- Fire - Fire
abilities:
- flamebody
- static
baseStats: baseStats:
hp: 40 hp: 40
patk: 110 patk: 110

View File

@ -1,4 +1,5 @@
- name: "Absorb" absorb:
name: "Absorb"
num: 71 num: 71
accuracy: 100 accuracy: 100
basePower: 20 basePower: 20
@ -19,7 +20,8 @@
zMovePower: 100 zMovePower: 100
contestType: "Clever" contestType: "Clever"
- name: Aqua Jet aquajet:
name: Aqua Jet
num: 453 num: 453
accuracy: 100 accuracy: 100
basePower: 40 basePower: 40
@ -41,11 +43,12 @@
zMovePower: 100 zMovePower: 100
contestType: Cool contestType: Cool
- name: "Bulk Up" bulkup:
name: "Bulk Up"
num: 339 num: 339
accuracy: 0 accuracy: 0
basePower: 0 basePower: 0
category: "Status" category: Support
desc: "Raises the user's Attack and Defense by 1 stage." desc: "Raises the user's Attack and Defense by 1 stage."
shortDesc: "Raises the user's Attack and Defense by 1." shortDesc: "Raises the user's Attack and Defense by 1."
id: "bulkup" id: "bulkup"
@ -64,11 +67,12 @@
patk: 1 patk: 1
contestType: "Cool" contestType: "Cool"
- name: Charm charm:
name: Charm
num: 204 num: 204
accuracy: 100 accuracy: 100
basePower: 0 basePower: 0
category: Status category: Support
desc: Lowers the target's Attack by 2 stages. desc: Lowers the target's Attack by 2 stages.
shortDesc: Lowers the target's Attack by 2. shortDesc: Lowers the target's Attack by 2.
id: charm id: charm
@ -88,7 +92,8 @@
pdef: 1 pdef: 1
contestType: Cute contestType: Cute
- name: "Close Combat" closecombat:
name: "Close Combat"
num: 370 num: 370
accuracy: 100 accuracy: 100
basePower: 120 basePower: 120
@ -113,10 +118,11 @@
zMovePower: 190 zMovePower: 190
contestType: "Tough" contestType: "Tough"
- name: Confuse Ray confuseray:
name: Confuse Ray
accuracy: 100 accuracy: 100
basePower: 0 basePower: 0
category: Status category: Support
contestType: Clever contestType: Clever
desc: Causes the target to become confused. desc: Causes the target to become confused.
flags: flags:
@ -135,7 +141,8 @@
zMoveBoost: zMoveBoost:
MAtk: 1 MAtk: 1
- name: Electro Ball electroball:
name: Electro Ball
num: 486 num: 486
accuracy: 100 accuracy: 100
basePower: 0 basePower: 0
@ -169,7 +176,8 @@
zMovePower: 160 zMovePower: 160
contestType: "Cool" contestType: "Cool"
- name: "Frost Breath" frostbreath:
name: "Frost Breath"
num: 524 num: 524
accuracy: 90 accuracy: 90
basePower: 60 basePower: 60
@ -187,7 +195,8 @@
zMovePower: 120 zMovePower: 120
contestType: "Beautiful" contestType: "Beautiful"
- name: Headbutt headbutt:
name: Headbutt
accuracy: 100 accuracy: 100
basePower: 70 basePower: 70
category: Physical category: Physical
@ -209,7 +218,8 @@
type: Normal type: Normal
zMovePower: 140 zMovePower: 140
- name: Ice Beam icebeam:
name: Ice Beam
accuracy: 100 accuracy: 100
basePower: 90 basePower: 90
category: Special category: Special
@ -231,11 +241,12 @@
type: Ice type: Ice
zMovePower: 175 zMovePower: 175
- name: "Poison Gas" poisongas:
name: "Poison Gas"
num: 139 num: 139
accuracy: 90 accuracy: 90
basePower: 0 basePower: 0
category: "Status" category: Support
desc: "Poisons the target." desc: "Poisons the target."
shortDesc: "Poisons the foe(s)." shortDesc: "Poisons the foe(s)."
id: "poisongas" id: "poisongas"
@ -253,7 +264,8 @@
def: 1 def: 1
contestType: "Clever" contestType: "Clever"
- name: "Poison Sting" poisonsting:
name: "Poison Sting"
num: 40 num: 40
accuracy: 100 accuracy: 100
basePower: 15 basePower: 15
@ -274,7 +286,8 @@
zMovePower: 100 zMovePower: 100
contestType: "Clever" contestType: "Clever"
- name: Scald scald:
name: Scald
accuracy: 100 accuracy: 100
basePower: 80 basePower: 80
category: Special category: Special
@ -298,7 +311,8 @@
type: Water type: Water
zMovePower: 160 zMovePower: 160
- name: "Snarl" snarl:
name: "Snarl"
num: 555 num: 555
accuracy: 95 accuracy: 95
basePower: 55 basePower: 55
@ -322,10 +336,11 @@
zMovePower: 100 zMovePower: 100
contestType: "Tough" contestType: "Tough"
- name: Spore spore:
name: Spore
accuracy: 100 accuracy: 100
basePower: 0 basePower: 0
category: Status category: Support
contestType: Beautiful contestType: Beautiful
flags: flags:
mirror: 1 mirror: 1
@ -344,7 +359,8 @@
type: Grass type: Grass
zMoveEffect: clearnegativeboost zMoveEffect: clearnegativeboost
- name: Tackle tackle:
name: Tackle
num: 33 num: 33
accuracy: 100 accuracy: 100
basePower: 40 basePower: 40
@ -363,10 +379,11 @@
zMovePower: 100 zMovePower: 100
contestType: Tough contestType: Tough
- name: Thunder Wave thunderwave:
name: Thunder Wave
accuracy: 90 accuracy: 90
basePower: 0 basePower: 0
category: Status category: Support
contestType: Cool contestType: Cool
desc: Paralyzes the target. This move does not ignore type immunity. desc: Paralyzes the target. This move does not ignore type immunity.
flags: flags:
@ -387,7 +404,8 @@
zMoveBoost: zMoveBoost:
MDef: 1 MDef: 1
- name: "Volt Tackle" volttackle:
name: "Volt Tackle"
num: 344 num: 344
accuracy: 100 accuracy: 100
basePower: 120 basePower: 120
@ -408,10 +426,11 @@
zMovePower: 190 zMovePower: 190
contestType: "Cool" contestType: "Cool"
- name: Will-O-Wisp willowisp:
name: Will-O-Wisp
accuracy: 85 accuracy: 85
basePower: 0 basePower: 0
category: Status category: Support
contestType: Beautiful contestType: Beautiful
desc: Burns the target. desc: Burns the target.
flags: flags:

View File

@ -20,5 +20,6 @@ package object stat {
implicit val formats = DefaultFormats + new EnumNameSerializer(MoveType) + new EnumNameSerializer(Gender) implicit val formats = DefaultFormats + new EnumNameSerializer(MoveType) + new EnumNameSerializer(Gender)
implicit def rngDice(rng : Random) = new Dice(rng) implicit def rngDice(rng : Random) = new Dice(rng)
implicit def ptrToMonster(ptr : MonsterPtr) : Monster = ptr.mon implicit def ptrToMonster(ptr : MonsterPtr) : Monster = ptr.mon
implicit def templateToStatus(status: StatusTemplate): Status = status.build
} }