Added fixed-damage moves
This commit is contained in:
parent
38dbb7fa92
commit
b6fc98f44e
@ -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)
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user