Moved forced skills into creature

This commit is contained in:
Matt Soucy 2019-12-07 11:08:39 -05:00
parent f496abee18
commit 2683ce69a9
6 changed files with 77 additions and 84 deletions

View File

@ -1,12 +1,10 @@
package me.msoucy.ptures.controller
import me.msoucy.ptures.model.Creature
import me.msoucy.ptures.model.KnockedOut
import me.msoucy.ptures.model.Skill
import me.msoucy.ptures.model.*
import me.msoucy.ptures.model.Target
import me.msoucy.ptures.model.Team
import me.msoucy.ptures.view.BattleView
import me.msoucy.ptures.view.SkillChoice
import me.msoucy.ptures.view.CreatureView
import me.msoucy.ptures.model.SkillChoice
sealed class BattleType(vararg val teams: Team) {
init {
@ -33,16 +31,19 @@ class RaidBattle(val boss: Creature, vararg teams: Team) : BattleType(*teams) {
class Engine(private val battle: BattleType) {
private var currentCreature = 0
private lateinit var currentCreature: CreatureView
// List of all creatures that are involved in the battle
private val creatures get() = battle.teams.flatMap { it.activeCreatures }
val attacker: Creature
// The current attacking creature
private var attacker: CreatureView
get() {
return creatures[currentCreature].creature
return currentCreature
}
private set(value) {
currentCreature = value
}
private val forcedSkills = mutableMapOf<Creature, Skill>()
private val activeCreatures
get() = creatures
@ -50,70 +51,54 @@ class Engine(private val battle: BattleType) {
.sortedBy { it.creature.spd }
fun resolveTurn(view: BattleView) {
forcedSkills.clear()
// All preconditions
for (i in activeCreatures.indices) {
val creature = creatures[i]
for (creature in activeCreatures) {
for (status in creature.creature.statuses) {
status.onTurnStart(this, creature.creature)
status.onTurnStart(creature.creature)
}
}
// Get the moves each creature will use this turn
val moves = activeCreatures.indices.map { i ->
val forcedSkill = forcedSkills[creatures[i].creature]
if (forcedSkill != null) {
SkillChoice(forcedSkill, creatures[nextOpponent(i)].creature)
} else {
creatures[i].chooseSkill(activeCreatures.map { it.creature })
}
activeCreatures.forEach {
it.chooseSkill(activeCreatures.map { c -> c.creature })
}
// Resolve each move
for (i in activeCreatures.indices) {
for (c in activeCreatures) {
// Resolve move
val (skill, target) = moves[i]
currentCreature = i
val (skill, targets) = c.creature.activeSkill!!
currentCreature = c
val attackingCreature = currentCreature
for (step in skill.damageSteps) {
for (targetCreature in getTargetList(step.target, target)) {
if (attacker.hits(targetCreature, step)) {
targetCreature.apply(step, attacker)
for (targetCreature in targets) {
if (attackingCreature.creature.hits(targetCreature, step)) {
targetCreature.apply(step, attackingCreature.creature)
step.applyStatus(targetCreature)
}
}
}
for (step in skill.postSteps) {
for (targetCreature in getTargetList(step.target, target)) {
for (targetCreature in targets) {
step.apply(targetCreature)
}
}
}
// All post conditions
for (creatureView in activeCreatures) {
val creature = creatureView.creature
for (status in creature.statuses) {
status.onTurnEnd(this)
status.onTurnEnd(creature)
}
}
}
private fun getTargetList(target: Target, selected: Creature): List<Creature> {
return when (target) {
Target.Self -> listOf(attacker)
Target.Selected -> listOf(selected)
Target.Others -> creatures.filter { it.creature != attacker }.map { it.creature }
Target.Opponents -> creatures.filter { it.playerId != creatures[currentCreature].playerId }.map { it.creature }
Target.All -> creatures.map { it.creature }
}
}
private fun nextOpponent(idx: Int): Int {
var nextIdx = idx + 1
while (nextIdx != idx) {
if (creatures[nextIdx].playerId != creatures[idx].playerId) {
return nextIdx
}
nextIdx = (nextIdx + 1) % creatures.size
}
// There are no opponents... so use the "none" index
return -1
private fun getTargetList(target: Target, selected: Creature): List<Creature> = when (target) {
Target.Self -> listOf(attacker.creature)
Target.Selected -> listOf(selected)
Target.Others -> creatures.filter { it.creature != attacker.creature }.map { it.creature }
Target.Opponents -> creatures.filter { it.playerId != attacker.playerId }.map { it.creature }
Target.All -> creatures.map { it.creature }
}
}

View File

@ -15,6 +15,8 @@ class Creature {
val skills = mutableListOf<Skill>()
val statuses = mutableListOf<Status>()
var activeSkill : SkillChoice? = null
val atk : Int get() = statFormula(genes.atk, growth.atk)
val def : Int get() = statFormula(genes.def, growth.def)
val spd : Int get() = statFormula(genes.spd, growth.spd)

View File

@ -2,6 +2,8 @@ package me.msoucy.ptures.model
import com.badlogic.gdx.math.MathUtils.random
data class SkillChoice (val skill : Skill, val target : List<Creature>)
@DslMarker
annotation class SkillMarker
@ -105,6 +107,9 @@ object Skills {
val Fly = skill("Fly") {
addStatus(Flying(), Target.Self)
}
val Fly2 = skill("Fly", Attribute.Air) {
damage(60)
}
val Ember = skill("Ember", Attribute.Fire) {
damage(40) {

View File

@ -4,48 +4,49 @@ import me.msoucy.ptures.controller.Engine
sealed class Status {
open fun onTurnStart(engine : Engine, creature : Creature) {
open fun onTurnStart(creature: Creature) {
// Do nothing
}
open fun onAdd(creature : Creature) {
open fun onAdd(creature: Creature) {
// Do nothing
}
open fun onTurnEnd(engine : Engine) {
open fun onTurnEnd(creature: Creature) {
// Do nothing
}
open fun attackMod(creature : Creature) = 1.0
open fun defenseMod(creature : Creature) = 1.0
open fun attackMod(creature: Creature) = 1.0
open fun defenseMod(creature: Creature) = 1.0
}
sealed class VisibleStatus(val label : String = "") : Status()
sealed class VisibleStatus(val label: String = "") : Status()
sealed class CountdownStatus(private var turns : Int) : Status()
{
override fun onTurnEnd(engine : Engine) {
sealed class CountdownStatus(private var turns: Int) : Status() {
override fun onTurnEnd(creature: Creature) {
turns--
if(turns == 0) {
onCountdownReached(engine)
engine.attacker.removeStatus(this)
if (turns == 0) {
onCountdownReached(creature)
creature.removeStatus(this)
}
}
open fun onCountdownReached(engine : Engine) {
open fun onCountdownReached(creature: Creature) {
}
}
object KnockedOut : VisibleStatus("ko")
object Burned : VisibleStatus("burned") {
override fun onTurnEnd(engine : Engine) {
override fun onTurnEnd(creature : Creature) {
// Deal a small amount of damage
}
}
object Stunned : VisibleStatus("stunned")
object Poisoned : VisibleStatus("poisoned")
class Flying : CountdownStatus(1) {
override fun onCountdownReached(engine: Engine) {
super.onCountdownReached(engine)
class Flying(private vararg val targets : Creature) : CountdownStatus(1) {
override fun onCountdownReached(creature: Creature) {
super.onCountdownReached(creature)
creature.activeSkill = SkillChoice(Skills.Fly2, targets.toList())
}
}

View File

@ -2,50 +2,51 @@ package me.msoucy.ptures.view
import me.msoucy.ptures.model.Creature
import me.msoucy.ptures.model.Skill
import me.msoucy.ptures.model.SkillChoice
import me.msoucy.ptures.model.VisibleStatus
class SkillViewText(skill : Skill) : SkillView(skill) {
class SkillViewText(skill: Skill) : SkillView(skill) {
override fun display() {
println(skill.name)
}
override fun displayEnumerated(idx: Int) {
println("${idx+1}: ${skill.name}")
println("${idx + 1}: ${skill.name}")
}
}
class CreatureViewText(playerId : Int, creature : Creature) : CreatureView(playerId, creature) {
class CreatureViewText(playerId: Int, creature: Creature) : CreatureView(playerId, creature) {
private val skillViews = creature.skills.map { SkillViewText(it) }
private fun chooseSkillName() : Skill {
private fun chooseSkillName(): Skill {
println("Skills:")
println("=======")
skillViews.forEachIndexed { index, skillView ->
skillView.displayEnumerated(index)
}
var idx = -1
while(idx != -1) {
while (idx != -1) {
print("> ")
val tmpIdx = readLine()?.toIntOrNull() ?: -1
if (tmpIdx in creature.skills.indices)
{
if (tmpIdx in creature.skills.indices) {
idx = tmpIdx
}
}
return creature.skills[idx]
}
private fun chooseTarget(skill : Skill, possibleTargets : List<Creature>) : Creature {
return creature
private fun chooseTarget(skill: Skill, possibleTargets: List<Creature>): List<Creature> {
return possibleTargets
}
override fun chooseSkill(possibleTargets : List<Creature>) : SkillChoice {
override fun chooseSkill(possibleTargets: List<Creature>) {
val skill = chooseSkillName()
val target = chooseTarget(skill, possibleTargets)
return SkillChoice(skill, target)
if (creature.activeSkill == null) {
val skill = chooseSkillName()
val targets = chooseTarget(skill, possibleTargets)
creature.activeSkill = SkillChoice(skill, targets)
}
}
override fun displayName() {
@ -65,6 +66,6 @@ class CreatureViewText(playerId : Int, creature : Creature) : CreatureView(playe
}
}
class PlayerViewText(playerId : Int) : PlayerView(playerId) {
class PlayerViewText(playerId: Int) : PlayerView(playerId) {
override fun creatureViewFor(creature: Creature) = CreatureViewText(playerId, creature)
}

View File

@ -2,8 +2,7 @@ package me.msoucy.ptures.view
import me.msoucy.ptures.model.Creature
import me.msoucy.ptures.model.Skill
data class SkillChoice (val skill : Skill, val target : Creature)
import me.msoucy.ptures.model.SkillChoice
abstract class SkillView(val skill : Skill) {
abstract fun display()
@ -12,7 +11,7 @@ abstract class SkillView(val skill : Skill) {
abstract class CreatureView(val playerId : Int, val creature: Creature) {
abstract fun chooseSkill(possibleTargets : List<Creature>) : SkillChoice
abstract fun chooseSkill(possibleTargets : List<Creature>)
abstract fun displayName()
abstract fun displaySkills()