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 {
|
object Game {
|
||||||
def main(args : Array[String]): Unit = {
|
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: _*)
|
Application.launch(classOf[Game], args: _*)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -46,7 +29,7 @@ class Game extends Application {
|
|||||||
implicit val rng = new scala.util.Random()
|
implicit val rng = new scala.util.Random()
|
||||||
val form1 = Form("Diabolo")
|
val form1 = Form("Diabolo")
|
||||||
val form2 = Form("Chanilla")
|
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 movepool2 = IndexedSeq(Move("flail"))
|
||||||
val p1 = TrainerID("Jaeda", Gender.Female, 0)
|
val p1 = TrainerID("Jaeda", Gender.Female, 0)
|
||||||
val p2 = TrainerID("Wild Monster", Gender.Male, 0)
|
val p2 = TrainerID("Wild Monster", Gender.Male, 0)
|
||||||
|
@ -53,7 +53,8 @@ abstract class Move extends MoveTurn {
|
|||||||
val desc: String
|
val desc: String
|
||||||
val category: MoveType
|
val category: MoveType
|
||||||
val pow: Int
|
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 prior: Int
|
||||||
val accuracy: Int
|
val accuracy: Int
|
||||||
val pp: 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) = {
|
override def useMove(user: Monster, target: Monster)(implicit reader: SignalConsumer, rng: Random) = {
|
||||||
reader ! Message(s"$user used $name.")
|
reader ! Message(s"$user used $name.")
|
||||||
if (attackRoll(user, target)) {
|
if (attackRoll(user, target)) {
|
||||||
if (pow > 0 || powCallback != null) {
|
if (pow > 0 || powCallback != null || damageCallback != null) {
|
||||||
val dmg = damageRoll(user, target)
|
val dmg = damageRoll(user, target)
|
||||||
val actualDmg = target.takeDamage(dmg)
|
val actualDmg = target.takeDamage(dmg)
|
||||||
if (dmg == actualDmg) {
|
if (dmg == actualDmg) {
|
||||||
@ -133,21 +134,24 @@ abstract class Move extends MoveTurn {
|
|||||||
}
|
}
|
||||||
|
|
||||||
def damageRoll(user: Monster, target: Monster)(implicit reader: SignalConsumer, rng: Random) = {
|
def damageRoll(user: Monster, target: Monster)(implicit reader: SignalConsumer, rng: Random) = {
|
||||||
val atkStat = if (category == MoveType.Physical) PAtk else MAtk
|
if (damageCallback != null) {
|
||||||
val defStat = if (category == MoveType.Physical) PDef else MDef
|
damageCallback(user, this, target, reader, rng)
|
||||||
// TODO : Fixed damage
|
} else {
|
||||||
val actualPow = if (powCallback != null) powCallback(user, this, target) else pow
|
val atkStat = if (category == MoveType.Physical) PAtk else MAtk
|
||||||
val baseDmg = (2 * user.level / 5 + 2) * actualPow * user(atkStat) / (target(defStat) * 50) + 2
|
val defStat = if (category == MoveType.Physical) PDef else MDef
|
||||||
val effectiveness = target.effectiveness(element)
|
val actualPow = if (powCallback != null) powCallback(user, this, target, reader, rng) else pow
|
||||||
val multiplier = effectiveness * critMultiplier(user, target)
|
val baseDmg = (2 * user.level / 5 + 2) * actualPow * user(atkStat) / (target(defStat) * 50) + 2
|
||||||
if (effectiveness > 1.0) {
|
val effectiveness = target.effectiveness(element)
|
||||||
reader ! Message("It's super effective!")
|
val multiplier = effectiveness * critMultiplier(user, target)
|
||||||
} else if (effectiveness < 1.0) {
|
if (effectiveness > 1.0) {
|
||||||
reader ! Message("It's not very effective.")
|
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) = {
|
def critMultiplier(user: Monster, target: Monster)(implicit reader: SignalConsumer, rng: Random) = {
|
||||||
@ -195,6 +199,7 @@ case class MoveToken(
|
|||||||
@JsonScalaEnumeration(classOf[MoveTypeType]) val category: MoveType,
|
@JsonScalaEnumeration(classOf[MoveTypeType]) val category: MoveType,
|
||||||
val basePower: Option[Int],
|
val basePower: Option[Int],
|
||||||
val basePowerCallback: String,
|
val basePowerCallback: String,
|
||||||
|
val damage: String,
|
||||||
val priority: Int,
|
val priority: Int,
|
||||||
val accuracy: Option[Int],
|
val accuracy: Option[Int],
|
||||||
val pp: Int,
|
val pp: Int,
|
||||||
@ -219,6 +224,7 @@ case class MoveToken(
|
|||||||
val category = token.category
|
val category = token.category
|
||||||
val pow = token.basePower.getOrElse(0)
|
val pow = token.basePower.getOrElse(0)
|
||||||
val powCallback = Move.compilePowCallback(token.basePowerCallback)
|
val powCallback = Move.compilePowCallback(token.basePowerCallback)
|
||||||
|
val damageCallback = Move.compileDamageCallback(token.damage)
|
||||||
val prior = token.priority
|
val prior = token.priority
|
||||||
val pp = token.pp
|
val pp = token.pp
|
||||||
val element = Element(token.`type`)
|
val element = Element(token.`type`)
|
||||||
@ -247,14 +253,16 @@ object Move {
|
|||||||
moves(name)
|
moves(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
def compilePowCallback(code: String): (Monster, Move, Monster) => Int = {
|
def compilePowCallback(code: String): (Monster, Move, Monster, SignalConsumer, Random) => Int = {
|
||||||
if (code != null) {
|
if (code != null) {
|
||||||
val tb = runtimeMirror(getClass.getClassLoader).mkToolBox()
|
val tb = runtimeMirror(getClass.getClassLoader).mkToolBox()
|
||||||
val tree = tb.parse(
|
val tree = tb.parse(
|
||||||
s"""
|
s"""
|
||||||
|
|import scala.util.Random
|
||||||
|
|import fmon.battle.msg._
|
||||||
|import fmon.stat._
|
|import fmon.stat._
|
||||||
|import fmon.stat.Statistic._
|
|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
|
| $code
|
||||||
|}
|
|}
|
||||||
|callback _
|
|callback _
|
||||||
@ -262,10 +270,14 @@ object Move {
|
|||||||
val f = tb.compile(tree)
|
val f = tb.compile(tree)
|
||||||
val wrapper = f()
|
val wrapper = f()
|
||||||
|
|
||||||
wrapper.asInstanceOf[(Monster, Move, Monster) => Int]
|
wrapper.asInstanceOf[(Monster, Move, Monster, SignalConsumer, Random) => Int]
|
||||||
} else {
|
} else {
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def compileDamageCallback(code: String): (Monster, Move, Monster, SignalConsumer, Random) => Int = {
|
||||||
|
compilePowCallback(code)
|
||||||
|
}
|
||||||
}
|
}
|
@ -1621,6 +1621,25 @@ dragonpulse:
|
|||||||
target: Any
|
target: Any
|
||||||
type: Dragon
|
type: Dragon
|
||||||
zMovePower: 160
|
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:
|
dragonrush:
|
||||||
accuracy: 75
|
accuracy: 75
|
||||||
basePower: 100
|
basePower: 100
|
||||||
@ -2021,6 +2040,34 @@ extremespeed:
|
|||||||
target: Normal
|
target: Normal
|
||||||
type: Normal
|
type: Normal
|
||||||
zMovePower: 160
|
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:
|
fairywind:
|
||||||
accuracy: 100
|
accuracy: 100
|
||||||
basePower: 40
|
basePower: 40
|
||||||
@ -4081,6 +4128,28 @@ nastyplot:
|
|||||||
target: Self
|
target: Self
|
||||||
type: Dark
|
type: Dark
|
||||||
zMoveEffect: clearnegativeboost
|
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:
|
needlearm:
|
||||||
accuracy: 100
|
accuracy: 100
|
||||||
basePower: 60
|
basePower: 60
|
||||||
@ -4125,6 +4194,27 @@ nightdaze:
|
|||||||
target: Normal
|
target: Normal
|
||||||
type: Dark
|
type: Dark
|
||||||
zMovePower: 160
|
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:
|
nightslash:
|
||||||
accuracy: 100
|
accuracy: 100
|
||||||
basePower: 70
|
basePower: 70
|
||||||
@ -4799,7 +4889,27 @@ psychocut:
|
|||||||
target: Normal
|
target: Normal
|
||||||
type: Psychic
|
type: Psychic
|
||||||
zMovePower: 140
|
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:
|
quickattack:
|
||||||
accuracy: 100
|
accuracy: 100
|
||||||
basePower: 40
|
basePower: 40
|
||||||
@ -5244,6 +5354,29 @@ seedflare:
|
|||||||
target: Normal
|
target: Normal
|
||||||
type: Grass
|
type: Grass
|
||||||
zMovePower: 190
|
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:
|
shadowball:
|
||||||
accuracy: 100
|
accuracy: 100
|
||||||
basePower: 80
|
basePower: 80
|
||||||
@ -5803,6 +5936,26 @@ snarl:
|
|||||||
target: AllAdjacentFoes
|
target: AllAdjacentFoes
|
||||||
type: Dark
|
type: Dark
|
||||||
zMovePower: 100
|
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:
|
spacialrend:
|
||||||
accuracy: 95
|
accuracy: 95
|
||||||
basePower: 100
|
basePower: 100
|
||||||
@ -6140,6 +6293,30 @@ submission:
|
|||||||
target: Normal
|
target: Normal
|
||||||
type: Fighting
|
type: Fighting
|
||||||
zMovePower: 160
|
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:
|
superpower:
|
||||||
accuracy: 100
|
accuracy: 100
|
||||||
basePower: 120
|
basePower: 120
|
||||||
@ -6763,6 +6940,34 @@ vitalthrow:
|
|||||||
target: Normal
|
target: Normal
|
||||||
type: Fighting
|
type: Fighting
|
||||||
zMovePower: 140
|
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:
|
waterfall:
|
||||||
accuracy: 100
|
accuracy: 100
|
||||||
basePower: 80
|
basePower: 80
|
||||||
@ -6985,6 +7190,26 @@ workup:
|
|||||||
type: Normal
|
type: Normal
|
||||||
zMoveBoost:
|
zMoveBoost:
|
||||||
PAtk: 1
|
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:
|
zapcannon:
|
||||||
accuracy: 50
|
accuracy: 50
|
||||||
basePower: 120
|
basePower: 120
|
||||||
|
@ -18,4 +18,5 @@ package object stat {
|
|||||||
implicit def rngDice(rng : Random) = new Dice(rng)
|
implicit def rngDice(rng : Random) = new Dice(rng)
|
||||||
implicit def ptrToMonster(ptr : MonsterPtr) : Monster = ptr.mon
|
implicit def ptrToMonster(ptr : MonsterPtr) : Monster = ptr.mon
|
||||||
implicit def templateToStatus(status: StatusTemplate): Status = status.build
|
implicit def templateToStatus(status: StatusTemplate): Status = status.build
|
||||||
|
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user