From 908069f2bc18ac8d09f018be9d54a37379915bdb Mon Sep 17 00:00:00 2001 From: dalyjame Date: Mon, 17 Jun 2019 14:41:15 -0400 Subject: [PATCH] Added moves with a cooldown --- FakeMon/src/fmon/Game.scala | 4 +- FakeMon/src/fmon/battle/BattleEngine.scala | 9 +- FakeMon/src/fmon/battle/BattleUI.scala | 4 +- FakeMon/src/fmon/config.yaml | 3 +- FakeMon/src/fmon/stat/Monster.scala | 4 + FakeMon/src/fmon/stat/Party.scala | 24 ++- FakeMon/src/fmon/stat/Status.scala | 29 ++- FakeMon/src/fmon/stat/data/moves.yaml | 206 +++++++++++++++++++++ FakeMon/src/fmon/stat/data/statuses.yaml | 30 +-- 9 files changed, 289 insertions(+), 24 deletions(-) diff --git a/FakeMon/src/fmon/Game.scala b/FakeMon/src/fmon/Game.scala index 1ab1fd1..7f25f75 100644 --- a/FakeMon/src/fmon/Game.scala +++ b/FakeMon/src/fmon/Game.scala @@ -29,8 +29,8 @@ 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"), Move("facade")) - val movepool2 = IndexedSeq(Move("flail")) + val movepool1 = IndexedSeq(Move("eruption"), Move("willowisp"), Move("thunderbolt"), Move("thunderwave"), Move("blastburn")) + val movepool2 = IndexedSeq(Move("blastburn")) 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()) diff --git a/FakeMon/src/fmon/battle/BattleEngine.scala b/FakeMon/src/fmon/battle/BattleEngine.scala index 454249b..e0a8b4e 100644 --- a/FakeMon/src/fmon/battle/BattleEngine.scala +++ b/FakeMon/src/fmon/battle/BattleEngine.scala @@ -18,10 +18,17 @@ class BattleEngine(val player: Party, val enemy: Party)(implicit val reader: Sig def playTurn(): Unit = { val playerAction = player.pollAction(enemy) - playTurn(playerAction) + playTurnImp(playerAction) } def playTurn(playerAction: Action): Unit = { + playTurnImp(playerAction) + while (player.lead.isLocked) { + playTurn() + } + } + + def playTurnImp(playerAction: Action): Unit = { val enemyAction = enemy.pollAction(player) val actions = Seq(playerAction, enemyAction) diff --git a/FakeMon/src/fmon/battle/BattleUI.scala b/FakeMon/src/fmon/battle/BattleUI.scala index 6aff388..b5bea60 100644 --- a/FakeMon/src/fmon/battle/BattleUI.scala +++ b/FakeMon/src/fmon/battle/BattleUI.scala @@ -39,7 +39,9 @@ class BattleUI extends SignalConsumer { } def onMove(move: Move): Unit = { - val action = Action(engine.player.lead, move, engine.enemy.lead) + implicit val rng = engine.rng + implicit val reader = engine + val action = Action(engine.player.lead, move, engine.player.pollTarget(move, engine.player.lead, engine.enemy)) engine.playTurn(action) updateUI() } diff --git a/FakeMon/src/fmon/config.yaml b/FakeMon/src/fmon/config.yaml index 7f77364..ee7a7af 100644 --- a/FakeMon/src/fmon/config.yaml +++ b/FakeMon/src/fmon/config.yaml @@ -1,4 +1,5 @@ title: FakeMon Engine Demo crit: 1.5 stab: 1.5 -maxBoost: 6 \ No newline at end of file +maxBoost: 6 +newday: 02:00 \ No newline at end of file diff --git a/FakeMon/src/fmon/stat/Monster.scala b/FakeMon/src/fmon/stat/Monster.scala index 7e094ed..676625e 100644 --- a/FakeMon/src/fmon/stat/Monster.scala +++ b/FakeMon/src/fmon/stat/Monster.scala @@ -82,6 +82,10 @@ class Monster(val base : StorageMon) { elements.foldLeft(1.0)((m, e) => m * (element --> e)) } + def isLocked(implicit reader: SignalConsumer, rng: Random): Boolean = { + statuses.exists(_.onLockMove(this).isDefined) + } + private def computeStat(s : Stat) : Int = { val num = 2 * base.form.baseStats(s) + base.gene.ivs(s) + base.evs(s) / 4 val frac = num * level / 100 diff --git a/FakeMon/src/fmon/stat/Party.scala b/FakeMon/src/fmon/stat/Party.scala index e424f1f..2c1eed3 100644 --- a/FakeMon/src/fmon/stat/Party.scala +++ b/FakeMon/src/fmon/stat/Party.scala @@ -4,15 +4,33 @@ import scala.util.Random import fmon._ import fmon.battle.Action +import fmon.battle.msg.SignalConsumer import fmon.stat.Target._ class Party(val trainer: TrainerID, val lead: MonsterPtr, var sideboard: IndexedSeq[Monster]) { - def pollAction(them: Party)(implicit rng: Random): Action = { - if (hasBackup && shouldSwitch(them)) { + def pollAction(them: Party)(implicit reader: SignalConsumer, rng: Random): Action = { + if (lead.isLocked) { + val moveNames = lead.statuses.flatMap(s => s.onLockMove(lead)).distinct + moveNames match { + case Seq(moveName) => { + // Use locked move + val move = Move(moveName) + // TODO : remember target + val target = pollTarget(move, lead, them) + Action(lead, move, target) + } + case _ => { + // Struggle + val move = Move("struggle") + val target = pollTarget(move, lead, them) + Action(lead, move, target) + } + } + } else if (hasBackup && shouldSwitch(them)) { val sub = pollReplacement(them: Party) val move = new SwitchOut(this, sub) Action(lead, move, lead) - } else { + } else{ val move = pollMove val target = pollTarget(move, lead, them) Action(lead, move, target) diff --git a/FakeMon/src/fmon/stat/Status.scala b/FakeMon/src/fmon/stat/Status.scala index 578fd55..1d89166 100644 --- a/FakeMon/src/fmon/stat/Status.scala +++ b/FakeMon/src/fmon/stat/Status.scala @@ -59,6 +59,7 @@ class Status(template: StatusTemplate) extends Effect { def onResidualOrder = template.onResidualOrder def onResidual(mon: Monster)(implicit reader: SignalConsumer, rng: Random) = template.onResidual(this, mon, reader, rng) // val onSwitchIn + def onLockMove(mon: Monster)(implicit reader: SignalConsumer, rng: Random) = template.onLockMove(this, mon, reader, rng) val intData: MutMap[String, Int] = MutMap[String, Int]() val stringData = MutMap[String, String]() @@ -80,6 +81,7 @@ abstract class StatusTemplate { val onResidualOrder: Int val onResidual: (Status, Monster, SignalConsumer, Random) => Unit // val onSwitchIn + val onLockMove: (Status, Monster, SignalConsumer, Random) => Option[String] def build = new Status(this) @@ -94,7 +96,8 @@ case class StatusToken( val onBeforeMove: String, val onModifyStat: String, val onResidualOrder: Int, - val onResidual: String) { + val onResidual: String, + val onLockMove: String) { def instantiate() = { val self = this new StatusTemplate { @@ -106,6 +109,7 @@ case class StatusToken( val onModifyStat = Status.compileOnModifyStat(self.onModifyStat) val onResidualOrder = self.onResidualOrder val onResidual = Status.compileOnResidual(self.onResidual) + val onLockMove = Status.compileOnLockMove(self.onLockMove) } } } @@ -132,6 +136,8 @@ object Status { import fmon.util.Fraction """ private val helpers = """ + implicit val dice = rng + implicit val consumer = reader def msg(text: String): Unit = { reader ! Message(text) } @@ -232,4 +238,25 @@ object Status { wrapper.asInstanceOf[(Status, Monster, SignalConsumer, Random) => Unit] } } + + def compileOnLockMove(code: String): (Status, Monster, SignalConsumer, Random) => Option[String] = { + if (code == null) { + (_, _, _, _) => None + } else { + val tree = tb.parse( + s""" + |$header + |def onLockMove(self: Status, mon: Monster, reader: SignalConsumer, rng: Random) = { + | $helpers + | val result = {$code} + | Some(result) + |} + |onLockMove _ + """.stripMargin) + val f = tb.compile(tree) + val wrapper = f() + + wrapper.asInstanceOf[(Status, Monster, SignalConsumer, Random) => Option[String]] + } + } } \ 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 20c9cde..8b1f6b7 100644 --- a/FakeMon/src/fmon/stat/data/moves.yaml +++ b/FakeMon/src/fmon/stat/data/moves.yaml @@ -462,6 +462,29 @@ bite: target: Normal type: Dark zMovePower: 120 +blastburn: + accuracy: 90 + basePower: 150 + category: Special + contestType: Beautiful + desc: If this move is successful, the user must recharge on the following turn and + cannot make a move. + flags: + mirror: 1 + protect: 1 + recharge: 1 + id: blastburn + name: Blast Burn + num: 307 + pp: 5 + priority: 0 + secondary: null + self: + volatileStatus: mustrecharge + shortDesc: User cannot move next turn. + target: Normal + type: Fire + zMovePower: 200 blazekick: accuracy: 90 basePower: 85 @@ -2528,6 +2551,30 @@ forcepalm: target: Normal type: Fighting zMovePower: 120 +frenzyplant: + accuracy: 90 + basePower: 150 + category: Special + contestType: Cool + desc: If this move is successful, the user must recharge on the following turn and + cannot select a move. + flags: + mirror: 1 + nonsky: 1 + protect: 1 + recharge: 1 + id: frenzyplant + name: Frenzy Plant + num: 338 + pp: 5 + priority: 0 + secondary: null + self: + volatileStatus: mustrecharge + shortDesc: User cannot move next turn. + target: Normal + type: Grass + zMovePower: 200 frostbreath: accuracy: 90 basePower: 60 @@ -2574,6 +2621,30 @@ gigadrain: target: Normal type: Grass zMovePower: 140 +gigaimpact: + accuracy: 90 + basePower: 150 + category: Physical + contestType: Tough + desc: If this move is successful, the user must recharge on the following turn and + cannot select a move. + flags: + contact: 1 + mirror: 1 + protect: 1 + recharge: 1 + id: gigaimpact + name: Giga Impact + num: 416 + pp: 5 + priority: 0 + secondary: null + self: + volatileStatus: mustrecharge + shortDesc: User cannot move next turn. + target: Normal + type: Normal + zMovePower: 200 glaciate: accuracy: 95 basePower: 65 @@ -3000,6 +3071,29 @@ howl: type: Normal zMoveBoost: PAtk: 1 +hydrocannon: + accuracy: 90 + basePower: 150 + category: Special + contestType: Beautiful + desc: If this move is successful, the user must recharge on the following turn and + cannot select a move. + flags: + mirror: 1 + protect: 1 + recharge: 1 + id: hydrocannon + name: Hydro Cannon + num: 308 + pp: 5 + priority: 0 + secondary: null + self: + volatileStatus: mustrecharge + shortDesc: User cannot move next turn. + target: Normal + type: Water + zMovePower: 200 hydropump: accuracy: 80 basePower: 110 @@ -3019,6 +3113,29 @@ hydropump: target: Normal type: Water zMovePower: 185 +hyperbeam: + accuracy: 90 + basePower: 150 + category: Special + contestType: Cool + desc: If this move is successful, the user must recharge on the following turn and + cannot select a move. + flags: + mirror: 1 + protect: 1 + recharge: 1 + id: hyperbeam + name: Hyper Beam + num: 63 + pp: 5 + priority: 0 + secondary: null + self: + volatileStatus: mustrecharge + shortDesc: User cannot move next turn. + target: Normal + type: Normal + zMovePower: 200 hyperfang: accuracy: 90 basePower: 80 @@ -4801,6 +4918,29 @@ precipiceblades: target: AllAdjacentFoes type: Ground zMovePower: 190 +prismaticlaser: + accuracy: 100 + basePower: 160 + category: Special + contestType: Cool + desc: If this move is successful, the user must recharge on the following turn and + cannot select a move. + flags: + mirror: 1 + protect: 1 + recharge: 1 + id: prismaticlaser + name: Prismatic Laser + num: 711 + pp: 10 + priority: 0 + secondary: null + self: + volatileStatus: mustrecharge + shortDesc: User cannot move next turn. + target: Normal + type: Psychic + zMovePower: 200 psybeam: accuracy: 100 basePower: 65 @@ -4999,6 +5139,48 @@ razorshell: target: Normal type: Water zMovePower: 140 +recharge: + accuracy: 100 + basePower: 0 + category: Support + contestType: Tough + flags: + contact: 1 + mirror: 1 + protect: 1 + id: recharge + name: Recharge + num: 10 + pp: 40 + priority: 0 + secondary: null + shortDesc: Placeholder move for when recharging. + target: Normal + type: Normal + zMovePower: 100 +roaroftime: + accuracy: 90 + basePower: 150 + category: Special + contestType: Beautiful + desc: If this move is successful, the user must recharge on the following turn and + cannot select a move. + flags: + mirror: 1 + protect: 1 + recharge: 1 + id: roaroftime + name: Roar of Time + num: 459 + pp: 5 + priority: 0 + secondary: null + self: + volatileStatus: mustrecharge + shortDesc: User cannot move next turn. + target: Normal + type: Dragon + zMovePower: 200 rockclimb: accuracy: 85 basePower: 90 @@ -5127,6 +5309,30 @@ rocktomb: target: Normal type: Rock zMovePower: 120 +rockwrecker: + accuracy: 90 + basePower: 150 + category: Physical + contestType: Tough + desc: If this move is successful, the user must recharge on the following turn and + cannot select a move. + flags: + bullet: 1 + mirror: 1 + protect: 1 + recharge: 1 + id: rockwrecker + name: Rock Wrecker + num: 439 + pp: 5 + priority: 0 + secondary: null + self: + volatileStatus: mustrecharge + shortDesc: User cannot move next turn. + target: Normal + type: Rock + zMovePower: 200 rollingkick: accuracy: 85 basePower: 60 diff --git a/FakeMon/src/fmon/stat/data/statuses.yaml b/FakeMon/src/fmon/stat/data/statuses.yaml index 346e28c..e888a39 100644 --- a/FakeMon/src/fmon/stat/data/statuses.yaml +++ b/FakeMon/src/fmon/stat/data/statuses.yaml @@ -41,16 +41,6 @@ confusion: true } } - /* - this.activeTarget = mon; - let damage = this.getDamage(mon, mon, 40); - if (typeof damage !== 'number') throw new Error('Confusion damage not dealt'); - mon.takeDamage(damage, mon, mon, /** @type {ActiveMove} */ ({ - 'id': 'confused', - 'effectType': 'Move', - 'type': '???' - })); - */ onBeforeMovePriority: 3 onEnd: msg(s"${mon} snapped out of its confusion.") onStart: |- @@ -95,11 +85,6 @@ slp: msg(s"${mon} woke up!") onBeforeMovePriority: 10 onBeforeMove: | - /* - if (mon.hasAbility('earlybird')) { - this.intData.time--; - } - */ self.intData("time") -= 1; if (self.intData("time") <= 0) { mon.cureStatus(); @@ -148,6 +133,21 @@ frz: if (move.flags("defrost")) { mon.cureStatus() } + +mustrecharge: + duration: 2 + id: mustrecharge + name: mustrecharge + num: 0 + onBeforeMove: |- + msg(s"${mon} must recharge!") + mon -= self + //mon.removeVolatile('mustrecharge'); + //mon.removeVolatile('truant'); + false + onBeforeMovePriority: 11 + onLockMove: | + "recharge" psn: name: 'psn'