package fmon.stat import scala.util._ import fmon.battle.msg._ import fmon.util._ import Monster._ import Statistic._ class Monster(val base : StorageMon) { def level = base.level val stats = Statistic.buildMap(computeStat) var boosts = Statistic.buildMap(_ => 0) var hp = stats(Hp) def maxhp = stats(Hp) var status : Option[Status] = None var volatile = Seq[Status]() def isAlive = hp > 0 def apply(s : Stat) = { val mod = boosts.getOrElse(s, 0) val mult = if (mod > 0) Fraction(2 + mod, 2) else Fraction(2, 2 - mod) status.foldLeft(1.frac)((m, sts) => m * sts.onModifyStat(this, s)) * mult * stats(s) } def elements = base.form.elements def takeDamage(dmg : Int) : Int = { val actualDmg = Math.min(hp, dmg) hp -= actualDmg actualDmg } def recoverDamage(healing : Int) { hp = Math.min(stats(Hp), hp + healing) } def statuses = volatile ++ status def cureStatus()(implicit reader: SignalConsumer, rng: Random) { status.map(_.onEnd(this)) status = None } def addStatus(s : Status, source: EffectSource)(implicit reader: SignalConsumer, rng: Random) = { if (s.effectType == EffectType.Volatile && !volatile.exists(_.name == s.name)) { volatile +:= s s.onStart(this, source) } else if (s.effectType == EffectType.NonVolatile && status == None) { status = Some(s) s.onStart(this, source) } else { reader ! Message("But it failed!") } } def -=(s : Status)(implicit reader: SignalConsumer, rng: Random) = { if (s.effectType == EffectType.Volatile) { s.onEnd(this) volatile = volatile.filterNot(_.name == s.name) } else { cureStatus() } } def applyBoost(s : Stat, boost : Int, effect: EffectSource)(implicit reader: SignalConsumer, rng: Random) { val modified = boosts.getOrElse(s, 0) + boost boosts = boosts.updated(s, Math.min(MaxBoost, Math.max(-MaxBoost, modified))) if (boost > 0) { reader ! Message(s"$this's $s rose!") } else if (boost < 0) { reader ! Message(s"$this's $s fell!") } } def effectiveness(element : Element) : Double = { elements.foldLeft(1.0)((m, e) => m * (element --> e)) } 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 val score = if(s == Hp) frac + 10 + level else frac + 5 (score * base.gene.nature(s)).toInt } def name = if (base.nickname != null) base.nickname else base.form.name override def toString = name } object Monster { final val MaxBoost = 6 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() }