From ad6780362baa4815b925414509ede25715269052 Mon Sep 17 00:00:00 2001 From: James Daly Date: Wed, 5 Jun 2019 21:31:25 -0400 Subject: [PATCH] Added support for abilities including a bunch of abilities that have effects the the monster is hit. Better monster generation support has been added. --- FakeMon/src/fmon/Game.scala | 10 +- FakeMon/src/fmon/stat/Ability.scala | 76 ++++++++++ FakeMon/src/fmon/stat/Form.scala | 4 +- FakeMon/src/fmon/stat/Monster.scala | 13 +- FakeMon/src/fmon/stat/MonsterPtr.scala | 6 - FakeMon/src/fmon/stat/Move.scala | 27 ++-- FakeMon/src/fmon/stat/Status.scala | 32 ++--- FakeMon/src/fmon/stat/StorageMon.scala | 13 +- FakeMon/src/fmon/stat/data/abilities.yaml | 164 ++++++++++++++++++++++ FakeMon/src/fmon/stat/data/forms.yaml | 5 + FakeMon/src/fmon/stat/data/moves.yaml | 71 ++++++---- FakeMon/src/fmon/stat/package.scala | 3 +- 12 files changed, 351 insertions(+), 73 deletions(-) create mode 100644 FakeMon/src/fmon/stat/Ability.scala delete mode 100644 FakeMon/src/fmon/stat/MonsterPtr.scala create mode 100644 FakeMon/src/fmon/stat/data/abilities.yaml diff --git a/FakeMon/src/fmon/Game.scala b/FakeMon/src/fmon/Game.scala index f2cac0c..10faac6 100644 --- a/FakeMon/src/fmon/Game.scala +++ b/FakeMon/src/fmon/Game.scala @@ -18,13 +18,13 @@ object Game { implicit val rng = new scala.util.Random() val form1 = Form("Diabolo") val form2 = Form("Chanilla") - val movepool1 = IndexedSeq(Move("Confuse Ray")) - val movepool2 = IndexedSeq(Move("Headbutt")) + val movepool1 = IndexedSeq(Move("electroball"), Move("thunderwave")) + val movepool2 = IndexedSeq(Move("headbutt")) val p1 = TrainerID("Jaeda", Gender.Female, 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 party2 = new Party(p2, new MonsterPtr(new Monster(new StorageMon("Wild Mon", 500, Gene.randomGene(null, form2), form2, Statistic.emptyEvs, movepool2))), IndexedSeq( - new Monster(new StorageMon("Sideboard Mon", 500, Gene.randomGene(null, form2), form2, Statistic.emptyEvs, movepool2)) + 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) diff --git a/FakeMon/src/fmon/stat/Ability.scala b/FakeMon/src/fmon/stat/Ability.scala new file mode 100644 index 0000000..ea321d3 --- /dev/null +++ b/FakeMon/src/fmon/stat/Ability.scala @@ -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] + } + } +} \ No newline at end of file diff --git a/FakeMon/src/fmon/stat/Form.scala b/FakeMon/src/fmon/stat/Form.scala index a167929..1b0694c 100644 --- a/FakeMon/src/fmon/stat/Form.scala +++ b/FakeMon/src/fmon/stat/Form.scala @@ -17,7 +17,7 @@ abstract class Form { val baseStats : Map[Stat, Int] // val appearance // animation // moves - // abilities + val abilities : IndexedSeq[Ability] val xpCurve : XpCurve val catchRate : Int // val color @@ -30,6 +30,7 @@ abstract class Form { case class FormToken( val name : String, val desc : String, + val abilities : IndexedSeq[String], val elements : IndexedSeq[String], val baseStats : Map[String, Int], @JsonScalaEnumeration(classOf[XpCurveType]) val xpCurve : XpCurve, @@ -43,6 +44,7 @@ case class FormToken( val desc = self.desc val elements = self.elements.map(Element(_)) val baseStats = self.baseStats.map{ case (s, i) => (Statistic(s), i)} + val abilities = self.abilities.map(Ability(_)) val xpCurve = self.xpCurve val catchRate = self.catchRate } diff --git a/FakeMon/src/fmon/stat/Monster.scala b/FakeMon/src/fmon/stat/Monster.scala index 494f45b..9ab429e 100644 --- a/FakeMon/src/fmon/stat/Monster.scala +++ b/FakeMon/src/fmon/stat/Monster.scala @@ -68,6 +68,11 @@ class Monster(val base : StorageMon) { def applyBoost(s : Stat, boost : Int) { val modified = boosts.getOrElse(s, 0) + boost 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 = { @@ -88,7 +93,11 @@ class Monster(val base : StorageMon) { object Monster { 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() } \ No newline at end of file diff --git a/FakeMon/src/fmon/stat/MonsterPtr.scala b/FakeMon/src/fmon/stat/MonsterPtr.scala deleted file mode 100644 index c555429..0000000 --- a/FakeMon/src/fmon/stat/MonsterPtr.scala +++ /dev/null @@ -1,6 +0,0 @@ -package fmon.stat - -class MonsterPtr(var mon : Monster) { - - override def toString : String = mon.toString() -} \ No newline at end of file diff --git a/FakeMon/src/fmon/stat/Move.scala b/FakeMon/src/fmon/stat/Move.scala index 7bc1da7..4f61754 100644 --- a/FakeMon/src/fmon/stat/Move.scala +++ b/FakeMon/src/fmon/stat/Move.scala @@ -12,7 +12,7 @@ import Statistic._ import fmon.util._ object MoveType extends Enumeration { - val Physical, Special, Status = Value + val Physical, Special, Support, Other = Value } class MoveTypeType extends TypeReference[MoveType.type] @@ -26,6 +26,7 @@ trait MoveTurn { def flags: Set[String] def prior: Int def target: Target + def category: MoveType 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 prior = +6 def target = Target.Self + def category = MoveType.Other def useMove(user: Monster, target: Monster)(implicit rng: Random): Unit = { 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 { val name: String val desc: String - val mvType: MoveType + val category: MoveType val pow: Int val powCallback: (Monster, Monster) => Int val prior: Int @@ -89,6 +91,9 @@ abstract class Move extends MoveTurn { user.takeDamage(recoil) println(s"$user took $recoil damage from recoil!") } + + target.base.ability.onAfterDamage(user, this, target, actualDmg) + if (!user.isAlive) { println(s"$user fainted!") } @@ -126,8 +131,8 @@ abstract class Move extends MoveTurn { } def damageRoll(user: Monster, target: Monster)(implicit rng: Random) = { - val atkStat = if (mvType == MoveType.Physical) PAtk else MAtk - val defStat = if (mvType == MoveType.Physical) PDef else MDef + val atkStat = if (category == MoveType.Physical) PAtk else MAtk + val defStat = if (category == MoveType.Physical) PDef else MDef // TODO : Fixed damage val actualPow = if (powCallback != null) powCallback(user, target) else pow 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 { case (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 { val name = token.name val desc = token.shortDesc - val mvType = category + val category = token.category val pow = token.basePower.getOrElse(0) val powCallback = Move.compilePowCallback(token.basePowerCallback) val prior = token.priority @@ -236,7 +237,7 @@ case class MoveToken( object 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 = { if (!moves.contains(name)) { @@ -250,8 +251,8 @@ object Move { val tb = runtimeMirror(getClass.getClassLoader).mkToolBox() val tree = tb.parse( s""" - |import mon.stat.Monster - |import mon.stat.Statistic._ + |import fmon.stat.Monster + |import fmon.stat.Statistic._ |def callback(user : Monster, target : Monster): Int = { | $code |} diff --git a/FakeMon/src/fmon/stat/Status.scala b/FakeMon/src/fmon/stat/Status.scala index ffcd61d..16bccfd 100644 --- a/FakeMon/src/fmon/stat/Status.scala +++ b/FakeMon/src/fmon/stat/Status.scala @@ -99,6 +99,13 @@ object Status { } 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 = { if (code == null) { @@ -106,10 +113,7 @@ object Status { } else { val tree = tb.parse( s""" - |import scala.util.Random - |import fmon.stat._ - |import fmon.stat.Statistic._ - |import fmon.util._ + |$header |def onStart(self:Status, mon: Monster, rng: Random) = { | $code |} @@ -127,13 +131,11 @@ object Status { } else { val tree = tb.parse( s""" - |import fmon.stat._ - |import fmon.stat.Statistic._ - |import fmon.util._ + |$header |def onStart(self:Status, mon: Monster) = { | $code |} - |onStart _ + onStart _ """.stripMargin) val f = tb.compile(tree) val wrapper = f() @@ -147,15 +149,13 @@ object Status { } else { val tree = tb.parse( s""" - import scala.util.Random - import fmon.stat._ - import fmon.stat.Statistic._ - import fmon.util._ + $header def onBeforeMove(self: Status, mon: Monster, move: MoveTurn, target: Monster, rng: Random): Boolean = { $code } onBeforeMove _ """) + val f = tb.compile(tree) val wrapper = f() wrapper.asInstanceOf[(Status, Monster, MoveTurn, Monster, Random) => Boolean] @@ -168,9 +168,7 @@ object Status { } else { val tree = tb.parse( s""" - import fmon.stat._ - import fmon.stat.Statistic._ - import fmon.util._ + $header def onModifyStat(self: Status, mon: Monster, stat: Stat): Fraction = { $code } @@ -188,9 +186,7 @@ object Status { } else { val tree = tb.parse( s""" - |import fmon.stat._ - |import fmon.stat.Statistic._ - |import fmon.util._ + |$header |def onResidual(self: Status, mon: Monster) = { | $code |} diff --git a/FakeMon/src/fmon/stat/StorageMon.scala b/FakeMon/src/fmon/stat/StorageMon.scala index 4993173..3397b5e 100644 --- a/FakeMon/src/fmon/stat/StorageMon.scala +++ b/FakeMon/src/fmon/stat/StorageMon.scala @@ -1,5 +1,16 @@ 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) +} + +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)) + } } \ No newline at end of file diff --git a/FakeMon/src/fmon/stat/data/abilities.yaml b/FakeMon/src/fmon/stat/data/abilities.yaml new file mode 100644 index 0000000..2f39846 --- /dev/null +++ b/FakeMon/src/fmon/stat/data/abilities.yaml @@ -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. \ No newline at end of file diff --git a/FakeMon/src/fmon/stat/data/forms.yaml b/FakeMon/src/fmon/stat/data/forms.yaml index f8e5fab..a6aaba1 100644 --- a/FakeMon/src/fmon/stat/data/forms.yaml +++ b/FakeMon/src/fmon/stat/data/forms.yaml @@ -2,6 +2,8 @@ desc: A vanilla chameleon. elements: - Normal + abilities: + - noability baseStats: hp: 60 patk: 70 @@ -16,6 +18,9 @@ elements: - Electric - Fire + abilities: + - flamebody + - static baseStats: hp: 40 patk: 110 diff --git a/FakeMon/src/fmon/stat/data/moves.yaml b/FakeMon/src/fmon/stat/data/moves.yaml index df2361d..80f79b6 100644 --- a/FakeMon/src/fmon/stat/data/moves.yaml +++ b/FakeMon/src/fmon/stat/data/moves.yaml @@ -1,4 +1,5 @@ -- name: "Absorb" +absorb: + name: "Absorb" num: 71 accuracy: 100 basePower: 20 @@ -19,7 +20,8 @@ zMovePower: 100 contestType: "Clever" -- name: Aqua Jet +aquajet: + name: Aqua Jet num: 453 accuracy: 100 basePower: 40 @@ -41,11 +43,12 @@ zMovePower: 100 contestType: Cool -- name: "Bulk Up" +bulkup: + name: "Bulk Up" num: 339 accuracy: 0 basePower: 0 - category: "Status" + category: Support desc: "Raises the user's Attack and Defense by 1 stage." shortDesc: "Raises the user's Attack and Defense by 1." id: "bulkup" @@ -64,11 +67,12 @@ patk: 1 contestType: "Cool" -- name: Charm +charm: + name: Charm num: 204 accuracy: 100 basePower: 0 - category: Status + category: Support desc: Lowers the target's Attack by 2 stages. shortDesc: Lowers the target's Attack by 2. id: charm @@ -88,7 +92,8 @@ pdef: 1 contestType: Cute -- name: "Close Combat" +closecombat: + name: "Close Combat" num: 370 accuracy: 100 basePower: 120 @@ -113,10 +118,11 @@ zMovePower: 190 contestType: "Tough" -- name: Confuse Ray +confuseray: + name: Confuse Ray accuracy: 100 basePower: 0 - category: Status + category: Support contestType: Clever desc: Causes the target to become confused. flags: @@ -135,7 +141,8 @@ zMoveBoost: MAtk: 1 -- name: Electro Ball +electroball: + name: Electro Ball num: 486 accuracy: 100 basePower: 0 @@ -169,7 +176,8 @@ zMovePower: 160 contestType: "Cool" -- name: "Frost Breath" +frostbreath: + name: "Frost Breath" num: 524 accuracy: 90 basePower: 60 @@ -187,7 +195,8 @@ zMovePower: 120 contestType: "Beautiful" -- name: Headbutt +headbutt: + name: Headbutt accuracy: 100 basePower: 70 category: Physical @@ -209,7 +218,8 @@ type: Normal zMovePower: 140 -- name: Ice Beam +icebeam: + name: Ice Beam accuracy: 100 basePower: 90 category: Special @@ -231,11 +241,12 @@ type: Ice zMovePower: 175 -- name: "Poison Gas" +poisongas: + name: "Poison Gas" num: 139 accuracy: 90 basePower: 0 - category: "Status" + category: Support desc: "Poisons the target." shortDesc: "Poisons the foe(s)." id: "poisongas" @@ -253,7 +264,8 @@ def: 1 contestType: "Clever" -- name: "Poison Sting" +poisonsting: + name: "Poison Sting" num: 40 accuracy: 100 basePower: 15 @@ -274,7 +286,8 @@ zMovePower: 100 contestType: "Clever" -- name: Scald +scald: + name: Scald accuracy: 100 basePower: 80 category: Special @@ -298,7 +311,8 @@ type: Water zMovePower: 160 -- name: "Snarl" +snarl: + name: "Snarl" num: 555 accuracy: 95 basePower: 55 @@ -322,10 +336,11 @@ zMovePower: 100 contestType: "Tough" -- name: Spore +spore: + name: Spore accuracy: 100 basePower: 0 - category: Status + category: Support contestType: Beautiful flags: mirror: 1 @@ -344,7 +359,8 @@ type: Grass zMoveEffect: clearnegativeboost -- name: Tackle +tackle: + name: Tackle num: 33 accuracy: 100 basePower: 40 @@ -363,10 +379,11 @@ zMovePower: 100 contestType: Tough -- name: Thunder Wave +thunderwave: + name: Thunder Wave accuracy: 90 basePower: 0 - category: Status + category: Support contestType: Cool desc: Paralyzes the target. This move does not ignore type immunity. flags: @@ -387,7 +404,8 @@ zMoveBoost: MDef: 1 -- name: "Volt Tackle" +volttackle: + name: "Volt Tackle" num: 344 accuracy: 100 basePower: 120 @@ -408,10 +426,11 @@ zMovePower: 190 contestType: "Cool" -- name: Will-O-Wisp +willowisp: + name: Will-O-Wisp accuracy: 85 basePower: 0 - category: Status + category: Support contestType: Beautiful desc: Burns the target. flags: diff --git a/FakeMon/src/fmon/stat/package.scala b/FakeMon/src/fmon/stat/package.scala index 03900c6..491e3a6 100644 --- a/FakeMon/src/fmon/stat/package.scala +++ b/FakeMon/src/fmon/stat/package.scala @@ -20,5 +20,6 @@ package object stat { implicit val formats = DefaultFormats + new EnumNameSerializer(MoveType) + new EnumNameSerializer(Gender) 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 } \ No newline at end of file