Messages will now play when an ability triggers

This commit is contained in:
James Daly 2019-06-06 17:37:32 -04:00
parent d2ee6debf8
commit bebbf469db
6 changed files with 87 additions and 44 deletions

View File

@ -7,13 +7,15 @@ import scala.util.Random
import fmon.util._ import fmon.util._
abstract class Ability { abstract class Ability extends Effect {
val name: String val name: String
val desc: String val desc: String
def onAfterDamage(source: Monster, move: MoveTurn, mon: Monster, dmg: Int)(implicit rng: Random) = onAfterDamageImp(source, move, mon, dmg, rng) def effectType = EffectType.AbilityEffect
protected val onAfterDamageImp: (Monster, MoveTurn, Monster, Int, Random) => Unit def onAfterDamage(source: Monster, move: MoveTurn, mon: Monster, dmg: Int)(implicit rng: Random) = onAfterDamageImp(this, source, move, mon, dmg, rng)
protected val onAfterDamageImp: (Ability, Monster, MoveTurn, Monster, Int, Random) => Unit
override def toString = name override def toString = name
} }
@ -53,16 +55,23 @@ object Ability {
|import fmon.stat.Statistic._ |import fmon.stat.Statistic._
|import fmon.util._ |import fmon.util._
""" """
private val helper = """
implicit val gen = rng
def trigger {
print(s"[${mon}'s ${self}]")
}
def effect = EffectSource(mon, self)
"""
def compileOnAfterDamage(code: String): (Monster, MoveTurn, Monster, Int, Random) => Unit = { def compileOnAfterDamage(code: String): (Ability, Monster, MoveTurn, Monster, Int, Random) => Unit = {
if (code == null) { if (code == null) {
(_, _, _, _, _) => () (_, _, _, _, _, _) => ()
} else { } else {
val tree = tb.parse( val tree = tb.parse(
s""" s"""
|$header |$header
|def onAfterDamage(source: Monster, move: MoveTurn, mon: Monster, damage: Int, rng: Random): Unit = { |def onAfterDamage(self: Ability, source: Monster, move: MoveTurn, mon: Monster, damage: Int, rng: Random): Unit = {
| implicit val gen = rng | $helper
| $code | $code
|} |}
|onAfterDamage _ |onAfterDamage _
@ -70,7 +79,7 @@ object Ability {
val f = tb.compile(tree) val f = tb.compile(tree)
val wrapper = f() val wrapper = f()
implicit val c = code implicit val c = code
wrapper.asInstanceOf[(Monster, MoveTurn, Monster, Int, Random) => Unit] wrapper.asInstanceOf[(Ability, Monster, MoveTurn, Monster, Int, Random) => Unit]
} }
} }
} }

View File

@ -44,13 +44,13 @@ class Monster(val base : StorageMon) {
status = None status = None
} }
def +=(s : Status)(implicit rng: Random) = { def addStatus(s : Status, source: EffectSource)(implicit rng: Random) = {
if (s.effectType == EffectType.Volatile && !volatile.exists(_.name == s.name)) { if (s.effectType == EffectType.Volatile && !volatile.exists(_.name == s.name)) {
volatile +:= s volatile +:= s
s.onStart(this) s.onStart(this, source)
} else if (s.effectType == EffectType.NonVolatile && status == None) { } else if (s.effectType == EffectType.NonVolatile && status == None) {
status = Some(s) status = Some(s)
s.onStart(this) s.onStart(this, source)
} else { } else {
println("But it failed!") println("But it failed!")
} }
@ -65,7 +65,7 @@ class Monster(val base : StorageMon) {
} }
} }
def applyBoost(s : Stat, boost : Int) { def applyBoost(s : Stat, boost : Int, effect: EffectSource) {
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) { if (boost > 0) {

View File

@ -21,8 +21,9 @@ object Target extends Enumeration {
} }
class TargetType extends TypeReference[Target.type] class TargetType extends TypeReference[Target.type]
trait MoveTurn { trait MoveTurn extends Effect {
def name: String def name: String
def effectType = EffectType.MoveEffect
def flags: Set[String] def flags: Set[String]
def prior: Int def prior: Int
def target: Target def target: Target
@ -101,16 +102,16 @@ abstract class Move extends MoveTurn {
println(s"$target fainted!") println(s"$target fainted!")
} }
} }
applyBoosts(target, boosts) applyBoosts(target, boosts, user)
applyStatus(target, status) applyStatus(target, user, status)
if (effect != null) { if (effect != null) {
applyEffect(target, effect) applyEffect(target, user, effect)
} }
if (selfEffect != null) { if (selfEffect != null) {
applyEffect(user, selfEffect) applyEffect(user, user, selfEffect)
} }
if (secondary != null && rng.chance(secondary.chance.%%)) { if (secondary != null && rng.chance(secondary.chance.%%)) {
applyEffect(target, secondary) applyEffect(target, user, secondary)
} }
// TODO : Multiparty // TODO : Multiparty
@ -160,24 +161,23 @@ abstract class Move extends MoveTurn {
} }
} }
def applyEffect(target: Monster, effect: Secondary)(implicit rng: Random) { def applyEffect(target: Monster, source: Monster, effect: Secondary)(implicit rng: Random) {
applyBoosts(target, effect.boosts) applyBoosts(target, effect.boosts, source)
applyStatus(target, effect.status) applyStatus(target, source, effect.status)
applyStatus(target, effect.volatile) applyStatus(target, source, effect.volatile)
} }
def applyStatus(target: Monster, status: StatusTemplate)(implicit rng: Random) { def applyStatus(target: Monster, user: Monster, status: StatusTemplate)(implicit rng: Random) {
if (target.isAlive && status != null) { if (target.isAlive && status != null) {
target += status.build target.addStatus(status.build, EffectSource(user, this))
} }
} }
def applyBoosts(target: Monster, boosts: Map[Stat, Int]) { def applyBoosts(target: Monster, boosts: Map[Stat, Int], source: Monster) {
if (target.isAlive) { if (target.isAlive) {
boosts.foreach { boosts.foreach {
case (s, b) => { case (s, b) => {
target.applyBoost(s, b) target.applyBoost(s, b, EffectSource(source, this))
} }
} }
} }

View File

@ -12,9 +12,12 @@ import EffectType.Volatile
object EffectType extends Enumeration { object EffectType extends Enumeration {
val NonVolatile, Volatile, Field, Weather = Value val NonVolatile, Volatile, AbilityEffect, MoveEffect, ItemEffect, Field, Weather = Value
def parse(s : String, default : EffectType) = s match { def parse(s : String, default : EffectType) = s match {
case "ability" => AbilityEffect
case "item" => ItemEffect
case "move" => MoveEffect
case "status" => NonVolatile case "status" => NonVolatile
case "volatile" => Volatile case "volatile" => Volatile
case "weather" => Weather case "weather" => Weather
@ -22,11 +25,29 @@ object EffectType extends Enumeration {
} }
} }
class Status(template: StatusTemplate) { trait Effect {
def name: String
def effectType: EffectType
def isItem = effectType == EffectType.ItemEffect
def isMove = effectType == EffectType.MoveEffect
def isAbility = effectType == EffectType.AbilityEffect
}
case class EffectSource(mon: Monster, effect: Effect) {
def isItem = effect.isItem
def isMove = effect.isMove
def isAbility = effect.isAbility
def triggerMsg = s"[${mon}'s ${effect}]"
}
class Status(template: StatusTemplate) extends Effect {
def name = template.name def name = template.name
// val id // val id
def effectType = template.effectType def effectType = template.effectType
def onStart(mon: Monster)(implicit rng: Random) = template.onStart(this, mon, rng) def onStart(mon: Monster, source: EffectSource)(implicit rng: Random) = template.onStart(this, mon, source, rng)
def onEnd(mon: Monster) = template.onEnd(this, mon) def onEnd(mon: Monster) = template.onEnd(this, mon)
def onModifyStat(mon: Monster, stat: Stat) = template.onModifyStat(this, mon, stat) def onModifyStat(mon: Monster, stat: Stat) = template.onModifyStat(this, mon, stat)
// val onBeforeMovePriority : Int // val onBeforeMovePriority : Int
@ -47,7 +68,7 @@ abstract class StatusTemplate {
val name: String val name: String
// val id // val id
val effectType: EffectType val effectType: EffectType
val onStart: (Status, Monster, Random) => Unit val onStart: (Status, Monster, EffectSource, Random) => Unit
val onEnd: (Status, Monster) => Unit val onEnd: (Status, Monster) => Unit
val onModifyStat: (Status, Monster, Stat) => Fraction val onModifyStat: (Status, Monster, Stat) => Fraction
// val onBeforeMovePriority : Int // val onBeforeMovePriority : Int
@ -91,7 +112,7 @@ object Status {
private var statuses = Map[String, StatusTemplate]() private var statuses = Map[String, StatusTemplate]()
val tokens = YamlHelper.extractMap[StatusToken](Source.fromInputStream(Status.getClass.getResourceAsStream("data/statuses.yaml"))) val tokens = YamlHelper.extractMap[StatusToken](Source.fromInputStream(Status.getClass.getResourceAsStream("data/statuses.yaml")))
def apply(name: String) = { def apply(name: String): StatusTemplate = {
if (!statuses.contains(name)) { if (!statuses.contains(name)) {
statuses = statuses.updated(name, tokens(name).instantiate()) statuses = statuses.updated(name, tokens(name).instantiate())
} }
@ -107,21 +128,21 @@ object Status {
import fmon.util._ import fmon.util._
""" """
def compileOnStart(code: String): (Status, Monster /*, source, source effect */, Random ) => Unit = { def compileOnStart(code: String): (Status, Monster, EffectSource, Random ) => Unit = {
if (code == null) { if (code == null) {
(_, _, _) => () (_, _, _, _) => ()
} else { } else {
val tree = tb.parse( val tree = tb.parse(
s""" s"""
|$header |$header
|def onStart(self:Status, mon: Monster, rng: Random) = { |def onStart(self:Status, mon: Monster, source: EffectSource, rng: Random) = {
| $code | $code
|} |}
|onStart _ |onStart _
""".stripMargin) """.stripMargin)
val f = tb.compile(tree) val f = tb.compile(tree)
val wrapper = f() val wrapper = f()
wrapper.asInstanceOf[(Status, Monster, Random) => Unit] wrapper.asInstanceOf[(Status, Monster, EffectSource, Random) => Unit]
} }
} }

View File

@ -15,6 +15,7 @@ aftermath:
num: 106 num: 106
onAfterDamage: |- onAfterDamage: |-
if ((source != null) && (source != mon) && (move != null) && move.flags("contact") && !mon.isAlive) { if ((source != null) && (source != mon) && (move != null) && move.flags("contact") && !mon.isAlive) {
trigger
println(s"$source is damaged in the aftermath!") println(s"$source is damaged in the aftermath!")
source.takeDamage(source(Hp) / 4); source.takeDamage(source(Hp) / 4);
} }
@ -30,7 +31,7 @@ flamebody:
onAfterDamage: |- onAfterDamage: |-
if (move != null && move.flags("contact")) { if (move != null && move.flags("contact")) {
if (rng.chance(3, 10)) { if (rng.chance(3, 10)) {
source += Status("brn"); source.addStatus(Status("brn"), EffectSource(mon, self))
} }
} }
rating: 2 rating: 2
@ -42,9 +43,8 @@ gooey:
num: 183 num: 183
onAfterDamage: |- onAfterDamage: |-
if (move != null && move.flags("contact")) { if (move != null && move.flags("contact")) {
//this.add('-ability', target, 'Gooey'); trigger
source.applyBoost(Speed, -1) source.applyBoost(Speed, -1, effect)
//this.boost({'spe': -1}, source, target, null, true);
} }
rating: 2.5 rating: 2.5
shortDesc: Pokemon making contact with this Pokemon have their Speed lowered by shortDesc: Pokemon making contact with this Pokemon have their Speed lowered by
@ -58,6 +58,7 @@ innardsout:
num: 215 num: 215
onAfterDamage: |- onAfterDamage: |-
if (source != null && source != mon && move != null /* && move.effectType === 'Move'*/ && !mon.isAlive) { if (source != null && source != mon && move != null /* && move.effectType === 'Move'*/ && !mon.isAlive) {
trigger
println(s"$source is damaged in the aftermath!") println(s"$source is damaged in the aftermath!")
source.takeDamage(damage)//, source, target); source.takeDamage(damage)//, source, target);
} }
@ -74,6 +75,7 @@ ironbarbs:
num: 160 num: 160
onAfterDamage: |- onAfterDamage: |-
if (source != null && source != mon && move != null && move.flags("contact")) { if (source != null && source != mon && move != null && move.flags("contact")) {
trigger
println(s"Pointed barbs dug into $source!") println(s"Pointed barbs dug into $source!")
source.takeDamage(source(Hp) / 8)//, source, target) source.takeDamage(source(Hp) / 8)//, source, target)
} }
@ -88,7 +90,7 @@ poisonpoint:
onAfterDamage: |- onAfterDamage: |-
if (move != null && move.flags("contact")) { if (move != null && move.flags("contact")) {
if (rng.chance(3, 10)) { if (rng.chance(3, 10)) {
source += Status("psn") source.addStatus(Status("psn"), EffectSource(mon, self))
} }
} }
rating: 2 rating: 2
@ -102,6 +104,7 @@ roughskin:
num: 24 num: 24
onAfterDamage: |- onAfterDamage: |-
if (source != null && source != mon && move != null && move.flags("contact")) { if (source != null && source != mon && move != null && move.flags("contact")) {
trigger
println(s"$source is damaged by rough skin!") println(s"$source is damaged by rough skin!")
source.takeDamage(source(Hp) / 8)//, source, target) source.takeDamage(source(Hp) / 8)//, source, target)
} }
@ -115,6 +118,7 @@ stamina:
num: 192 num: 192
onAfterDamage: |- onAfterDamage: |-
if (move != null /*&& effect.effectType == 'Move' && effect.id != 'confused'*/) { if (move != null /*&& effect.effectType == 'Move' && effect.id != 'confused'*/) {
trigger
mon.applyBoost(PDef, +1) mon.applyBoost(PDef, +1)
} }
rating: 3 rating: 3
@ -127,7 +131,7 @@ static:
onAfterDamage: |- onAfterDamage: |-
if (move != null && move.flags("contact")) { if (move != null && move.flags("contact")) {
if (rng.chance(3, 10)) { if (rng.chance(3, 10)) {
source += Status("par"); source.addStatus(Status("par"), EffectSource(mon, self))
} }
} }
rating: 2 rating: 2
@ -139,8 +143,9 @@ tanglinghair:
num: 221 num: 221
onAfterDamage: |- onAfterDamage: |-
if (move != null && move.flags("contact")) { if (move != null && move.flags("contact")) {
this.add('-ability', target, 'Tangling Hair'); //this.add('-ability', target, 'Tangling Hair');
source.applyBoost(Speed, -1) trigger
source.applyBoost(Speed, -1, effect)
//this.boost({'spe': -1}, source, target, null, true); //this.boost({'spe': -1}, source, target, null, true);
} }
rating: 2.5 rating: 2.5
@ -156,7 +161,9 @@ weakarmor:
onAfterDamage: |- onAfterDamage: |-
if (move.category == Physical) { if (move.category == Physical) {
//this.boost({'def': -1, 'spe': 2}, target, target); //this.boost({'def': -1, 'spe': 2}, target, target);
trigger
mon.applyBoost(PDef, -1) mon.applyBoost(PDef, -1)
trigger
mon.applyBoost(Speed, +2) mon.applyBoost(Speed, +2)
} }
rating: 1 rating: 1

View File

@ -10,6 +10,9 @@ brn:
1.frac 1.frac
} }
onStart: | onStart: |
if (!source.isMove) {
print(s"[${source.mon}'s ${source.effect}]")
}
println(s"${mon} was burned!") println(s"${mon} was burned!")
/* /*
if (sourceEffect && sourceEffect.id === 'flameorb') { if (sourceEffect && sourceEffect.id === 'flameorb') {
@ -77,6 +80,9 @@ par:
num: 0 num: 0
effectType: 'Status' effectType: 'Status'
onStart: | onStart: |
if (!source.isMove) {
print(s"[${source.mon}'s ${source.effect}]")
}
println(s"${mon} was paralyzed!") println(s"${mon} was paralyzed!")
/* /*
if (sourceEffect && sourceEffect.effectType === 'Ability') { if (sourceEffect && sourceEffect.effectType === 'Ability') {