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:
parent
ce81ab2079
commit
ad6780362b
@ -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)
|
||||||
|
76
FakeMon/src/fmon/stat/Ability.scala
Normal file
76
FakeMon/src/fmon/stat/Ability.scala
Normal 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]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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()
|
||||||
}
|
}
|
@ -1,6 +0,0 @@
|
|||||||
package fmon.stat
|
|
||||||
|
|
||||||
class MonsterPtr(var mon : Monster) {
|
|
||||||
|
|
||||||
override def toString : String = mon.toString()
|
|
||||||
}
|
|
@ -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
|
||||||
|}
|
|}
|
||||||
|
@ -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
|
||||||
|}
|
|}
|
||||||
|
@ -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))
|
||||||
|
}
|
||||||
|
}
|
164
FakeMon/src/fmon/stat/data/abilities.yaml
Normal file
164
FakeMon/src/fmon/stat/data/abilities.yaml
Normal 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.
|
@ -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
|
||||||
|
@ -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:
|
||||||
|
@ -21,4 +21,5 @@ 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
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user