From b6fc98f44e3411bea668f9d76ad25c9cd3e54222 Mon Sep 17 00:00:00 2001 From: dalyjame Date: Sat, 15 Jun 2019 14:07:28 -0400 Subject: [PATCH] Added fixed-damage moves --- FakeMon/src/fmon/Game.scala | 19 +-- FakeMon/src/fmon/stat/Move.scala | 50 +++--- FakeMon/src/fmon/stat/data/moves.yaml | 227 +++++++++++++++++++++++++- FakeMon/src/fmon/stat/package.scala | 1 + 4 files changed, 259 insertions(+), 38 deletions(-) diff --git a/FakeMon/src/fmon/Game.scala b/FakeMon/src/fmon/Game.scala index e940abc..e7d58f2 100644 --- a/FakeMon/src/fmon/Game.scala +++ b/FakeMon/src/fmon/Game.scala @@ -14,23 +14,6 @@ case class Prop(url : Seq[String]) object Game { 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: _*) } } @@ -46,7 +29,7 @@ class Game extends Application { implicit val rng = new scala.util.Random() val form1 = Form("Diabolo") 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("facade")) val movepool2 = IndexedSeq(Move("flail")) val p1 = TrainerID("Jaeda", Gender.Female, 0) val p2 = TrainerID("Wild Monster", Gender.Male, 0) diff --git a/FakeMon/src/fmon/stat/Move.scala b/FakeMon/src/fmon/stat/Move.scala index 3b253fc..8f0f077 100644 --- a/FakeMon/src/fmon/stat/Move.scala +++ b/FakeMon/src/fmon/stat/Move.scala @@ -53,7 +53,8 @@ abstract class Move extends MoveTurn { val desc: String val category: MoveType 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 accuracy: Int val pp: Int @@ -76,7 +77,7 @@ abstract class Move extends MoveTurn { override def useMove(user: Monster, target: Monster)(implicit reader: SignalConsumer, rng: Random) = { reader ! Message(s"$user used $name.") if (attackRoll(user, target)) { - if (pow > 0 || powCallback != null) { + if (pow > 0 || powCallback != null || damageCallback != null) { val dmg = damageRoll(user, target) val actualDmg = target.takeDamage(dmg) if (dmg == actualDmg) { @@ -133,21 +134,24 @@ abstract class Move extends MoveTurn { } def damageRoll(user: Monster, target: Monster)(implicit reader: SignalConsumer, rng: Random) = { - 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, this, target) else pow - val baseDmg = (2 * user.level / 5 + 2) * actualPow * user(atkStat) / (target(defStat) * 50) + 2 - val effectiveness = target.effectiveness(element) - val multiplier = effectiveness * critMultiplier(user, target) - if (effectiveness > 1.0) { - reader ! Message("It's super effective!") - } else if (effectiveness < 1.0) { - reader ! Message("It's not very effective.") + if (damageCallback != null) { + damageCallback(user, this, target, reader, rng) + } else { + val atkStat = if (category == MoveType.Physical) PAtk else MAtk + val defStat = if (category == MoveType.Physical) PDef else MDef + val actualPow = if (powCallback != null) powCallback(user, this, target, reader, rng) else pow + val baseDmg = (2 * user.level / 5 + 2) * actualPow * user(atkStat) / (target(defStat) * 50) + 2 + val effectiveness = target.effectiveness(element) + val multiplier = effectiveness * critMultiplier(user, target) + if (effectiveness > 1.0) { + 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) = { @@ -195,6 +199,7 @@ case class MoveToken( @JsonScalaEnumeration(classOf[MoveTypeType]) val category: MoveType, val basePower: Option[Int], val basePowerCallback: String, + val damage: String, val priority: Int, val accuracy: Option[Int], val pp: Int, @@ -219,6 +224,7 @@ case class MoveToken( val category = token.category val pow = token.basePower.getOrElse(0) val powCallback = Move.compilePowCallback(token.basePowerCallback) + val damageCallback = Move.compileDamageCallback(token.damage) val prior = token.priority val pp = token.pp val element = Element(token.`type`) @@ -247,14 +253,16 @@ object Move { moves(name) } - def compilePowCallback(code: String): (Monster, Move, Monster) => Int = { + def compilePowCallback(code: String): (Monster, Move, Monster, SignalConsumer, Random) => Int = { if (code != null) { val tb = runtimeMirror(getClass.getClassLoader).mkToolBox() val tree = tb.parse( s""" + |import scala.util.Random + |import fmon.battle.msg._ |import fmon.stat._ |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 |} |callback _ @@ -262,10 +270,14 @@ object Move { val f = tb.compile(tree) val wrapper = f() - wrapper.asInstanceOf[(Monster, Move, Monster) => Int] + wrapper.asInstanceOf[(Monster, Move, Monster, SignalConsumer, Random) => Int] } else { null } } + + def compileDamageCallback(code: String): (Monster, Move, Monster, SignalConsumer, Random) => Int = { + compilePowCallback(code) + } } \ No newline at end of file diff --git a/FakeMon/src/fmon/stat/data/moves.yaml b/FakeMon/src/fmon/stat/data/moves.yaml index 085a8c2..20c9cde 100644 --- a/FakeMon/src/fmon/stat/data/moves.yaml +++ b/FakeMon/src/fmon/stat/data/moves.yaml @@ -1621,6 +1621,25 @@ dragonpulse: target: Any type: Dragon 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: accuracy: 75 basePower: 100 @@ -2021,6 +2040,34 @@ extremespeed: target: Normal type: Normal 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: accuracy: 100 basePower: 40 @@ -4081,6 +4128,28 @@ nastyplot: target: Self type: Dark 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: accuracy: 100 basePower: 60 @@ -4125,6 +4194,27 @@ nightdaze: target: Normal type: Dark 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: accuracy: 100 basePower: 70 @@ -4799,7 +4889,27 @@ psychocut: target: Normal type: Psychic 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: accuracy: 100 basePower: 40 @@ -5244,6 +5354,29 @@ seedflare: target: Normal type: Grass 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: accuracy: 100 basePower: 80 @@ -5803,6 +5936,26 @@ snarl: target: AllAdjacentFoes type: Dark 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: accuracy: 95 basePower: 100 @@ -6140,6 +6293,30 @@ submission: target: Normal type: Fighting 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: accuracy: 100 basePower: 120 @@ -6763,6 +6940,34 @@ vitalthrow: target: Normal type: Fighting 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: accuracy: 100 basePower: 80 @@ -6985,6 +7190,26 @@ workup: type: Normal zMoveBoost: 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: accuracy: 50 basePower: 120 diff --git a/FakeMon/src/fmon/stat/package.scala b/FakeMon/src/fmon/stat/package.scala index be5b307..59141b6 100644 --- a/FakeMon/src/fmon/stat/package.scala +++ b/FakeMon/src/fmon/stat/package.scala @@ -18,4 +18,5 @@ package object stat { implicit def rngDice(rng : Random) = new Dice(rng) implicit def ptrToMonster(ptr : MonsterPtr) : Monster = ptr.mon implicit def templateToStatus(status: StatusTemplate): Status = status.build + } \ No newline at end of file