104 lines
2.9 KiB
Scala
104 lines
2.9 KiB
Scala
package fmon.stat
|
|
|
|
import scala.util._
|
|
|
|
import fmon._
|
|
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(Config.maxBoost, Math.max(-Config.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 {
|
|
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()
|
|
} |