diff --git a/src/main/kotlin/app/demo/MeleeCombatDemo.kt b/src/main/kotlin/app/demo/MeleeCombatDemo.kt index 0228b9d..0e1559b 100644 --- a/src/main/kotlin/app/demo/MeleeCombatDemo.kt +++ b/src/main/kotlin/app/demo/MeleeCombatDemo.kt @@ -11,6 +11,7 @@ import game.map.GameMapBuilder import game.map.Terrain import game.reducer.action.* import game.reducer.event.ON_DAMAGE_REDUCER +import game.reducer.event.ON_DEATH_REDUCER import game.rpg.Damage import game.rpg.character.Defense import game.rpg.character.ability.DamageEffect @@ -95,7 +96,7 @@ class MeleeCombatDemo : TileApplication(60, 45, 20, 20) { buildEntity() add(SimpleBody(gameMap.size.getIndex(15, 10)) as Body) add(Combat(listOf(meleeAttack), defense)) - add(Player as Controller) + add(AI as Controller) add(Graphic(UnicodeTile("O", Color.GREEN))) add(Health()) add(Statistics(mapOf(fighting to 6, speed to 6, toughness to 8))) @@ -110,6 +111,7 @@ class MeleeCombatDemo : TileApplication(60, 45, 20, 20) { is Init -> INIT_REDUCER(state, action) is Move -> MOVE_REDUCER(state, action) is OnDamage -> ON_DAMAGE_REDUCER(state, action) + is OnDeath -> ON_DEATH_REDUCER(state, action) is UseAbility -> USE_ABILITY_REDUCER(state, action) } } diff --git a/src/main/kotlin/game/action/Action.kt b/src/main/kotlin/game/action/Action.kt index a2995fa..a22e85f 100644 --- a/src/main/kotlin/game/action/Action.kt +++ b/src/main/kotlin/game/action/Action.kt @@ -12,4 +12,5 @@ data class Move(val entity: Int, val direction: Direction) : Action() data class UseAbility(val entity: Int, val ability: Int, val position: Int) : Action() // events -data class OnDamage(val entity: Int, val damage: Damage) : Action() \ No newline at end of file +data class OnDamage(val entity: Int, val damage: Damage) : Action() +data class OnDeath(val entity: Int) : Action() \ No newline at end of file diff --git a/src/main/kotlin/game/reducer/event/OnDamageReducer.kt b/src/main/kotlin/game/reducer/event/OnDamageReducer.kt index feb9909..e326d8b 100644 --- a/src/main/kotlin/game/reducer/event/OnDamageReducer.kt +++ b/src/main/kotlin/game/reducer/event/OnDamageReducer.kt @@ -1,8 +1,10 @@ package game.reducer.event +import game.action.Action import game.action.OnDamage +import game.action.OnDeath import game.component.Health -import game.component.HealthState +import game.component.HealthState.DEAD import game.component.Statistics import game.rpg.character.skill.SkillUsage import game.rpg.check.* @@ -19,13 +21,14 @@ import util.redux.random.RandomNumberState private val logger = KotlinLogging.logger {} -val ON_DAMAGE_REDUCER: Reducer = a@{ state, action -> +val ON_DAMAGE_REDUCER: Reducer = a@{ state, action -> + if (action !is OnDamage) throw IllegalArgumentException("Action must be OnDamage!") val id = action.entity val healthStorage = state.getStorage() val health = healthStorage.getOrThrow(id) - if (health.state == HealthState.DEAD) { + if (health.state == DEAD) { return@a noFollowUps(addMessage(state, Message("Entity $id is already dead!", Color.YELLOW))) } @@ -44,6 +47,7 @@ val ON_DAMAGE_REDUCER: Reducer = a@{ state, action -> val updatedStorage = mutableListOf>() val updatedData = mutableListOf(rng.createState()) + val events = mutableListOf() val newHealth = updateHealth(health, result) @@ -51,6 +55,10 @@ val ON_DAMAGE_REDUCER: Reducer = a@{ state, action -> logger.info("Change to $newHealth") updatedStorage += healthStorage.updateAndRemove(mapOf(id to newHealth)) + if (newHealth.state == DEAD) { + events.add(OnDeath(id)) + } + updateMessageLog(state, health, newHealth, id, updatedData) } else { val messageLog = state.getData() @@ -58,7 +66,7 @@ val ON_DAMAGE_REDUCER: Reducer = a@{ state, action -> updatedData += messageLog.add(message) } - noFollowUps(state.copy(updatedStorage, updatedData)) + Pair(state.copy(updatedStorage, updatedData), events) } private fun updateMessageLog( diff --git a/src/main/kotlin/game/reducer/event/OnDeathReducer.kt b/src/main/kotlin/game/reducer/event/OnDeathReducer.kt new file mode 100644 index 0000000..f7f44fd --- /dev/null +++ b/src/main/kotlin/game/reducer/event/OnDeathReducer.kt @@ -0,0 +1,23 @@ +package game.reducer.event + +import game.action.OnDeath +import game.component.Controller +import game.rpg.time.TimeSystem +import mu.KotlinLogging +import util.ecs.EcsState +import util.redux.Reducer +import util.redux.noFollowUps + +private val logger = KotlinLogging.logger {} + +val ON_DEATH_REDUCER: Reducer = a@{ state, action -> + val storage = state.getStorage() + val newStorage = storage.updateAndRemove(removed = setOf(action.entity)) + + val system = state.getData() + val newSystem = system.remove(action.entity) + + logger.info("Entity ${action.entity} died. storage={} time={}", newStorage, newSystem) + noFollowUps(state.copy(listOf(newStorage), listOf(newSystem))) +} + diff --git a/src/main/kotlin/util/ecs/storage/ComponentStorage.kt b/src/main/kotlin/util/ecs/storage/ComponentStorage.kt index 8f774a1..9294a29 100644 --- a/src/main/kotlin/util/ecs/storage/ComponentStorage.kt +++ b/src/main/kotlin/util/ecs/storage/ComponentStorage.kt @@ -8,5 +8,5 @@ interface ComponentStorage { fun getList(vararg entities: Int): List fun getAll(): Collection fun getIds(): Set - fun updateAndRemove(updated: Map, removed: Set = emptySet()): ComponentStorage + fun updateAndRemove(updated: Map = emptyMap(), removed: Set = emptySet()): ComponentStorage } \ No newline at end of file