diff --git a/core/src/me/msoucy/ptures/controller/Engine.kt b/core/src/me/msoucy/ptures/controller/Engine.kt index 413bab9..7c24424 100644 --- a/core/src/me/msoucy/ptures/controller/Engine.kt +++ b/core/src/me/msoucy/ptures/controller/Engine.kt @@ -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() 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 { - 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 = 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 } } } \ No newline at end of file diff --git a/core/src/me/msoucy/ptures/model/Creature.kt b/core/src/me/msoucy/ptures/model/Creature.kt index 08226fc..f74f075 100644 --- a/core/src/me/msoucy/ptures/model/Creature.kt +++ b/core/src/me/msoucy/ptures/model/Creature.kt @@ -15,6 +15,8 @@ class Creature { val skills = mutableListOf() val statuses = mutableListOf() + 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) diff --git a/core/src/me/msoucy/ptures/model/Skills.kt b/core/src/me/msoucy/ptures/model/Skills.kt index 48cbe61..3478500 100644 --- a/core/src/me/msoucy/ptures/model/Skills.kt +++ b/core/src/me/msoucy/ptures/model/Skills.kt @@ -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) + @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) { diff --git a/core/src/me/msoucy/ptures/model/Status.kt b/core/src/me/msoucy/ptures/model/Status.kt index 695296e..b95ca7d 100644 --- a/core/src/me/msoucy/ptures/model/Status.kt +++ b/core/src/me/msoucy/ptures/model/Status.kt @@ -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()) } } diff --git a/core/src/me/msoucy/ptures/view/TextView.kt b/core/src/me/msoucy/ptures/view/TextView.kt index 67a586b..09b3376 100644 --- a/core/src/me/msoucy/ptures/view/TextView.kt +++ b/core/src/me/msoucy/ptures/view/TextView.kt @@ -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 { - return creature + private fun chooseTarget(skill: Skill, possibleTargets: List): List { + return possibleTargets } - override fun chooseSkill(possibleTargets : List) : SkillChoice { + override fun chooseSkill(possibleTargets: List) { - 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) } \ No newline at end of file diff --git a/core/src/me/msoucy/ptures/view/ViewBase.kt b/core/src/me/msoucy/ptures/view/ViewBase.kt index 115d59e..98d246f 100644 --- a/core/src/me/msoucy/ptures/view/ViewBase.kt +++ b/core/src/me/msoucy/ptures/view/ViewBase.kt @@ -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) : SkillChoice + abstract fun chooseSkill(possibleTargets : List) abstract fun displayName() abstract fun displaySkills()