You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
182 lines
6.2 KiB
182 lines
6.2 KiB
package wow.doge.mygame.game.entities.player.behaviors
|
|
|
|
import scala.concurrent.Future
|
|
|
|
import akka.actor.typed.Behavior
|
|
import akka.actor.typed.PostStop
|
|
import akka.actor.typed.scaladsl.AskPattern._
|
|
import akka.actor.typed.scaladsl.Behaviors
|
|
import akka.util.Timeout
|
|
import cats.syntax.show._
|
|
import monix.bio.UIO
|
|
import monix.reactive.Observable
|
|
import wow.doge.mygame.game.entities.CharacterStats
|
|
import wow.doge.mygame.game.entities.StatsActor
|
|
import wow.doge.mygame.game.entities.character.CharacterStates._
|
|
import wow.doge.mygame.game.entities.player.PlayerActor
|
|
import wow.doge.mygame.implicits._
|
|
import wow.doge.mygame.subsystems.movement.ImMovementActor
|
|
import wow.doge.mygame.utils.MovementDirection
|
|
|
|
class IdleBehaviorFactory(
|
|
env: PlayerActor.Env,
|
|
nextStateFn: AliveSubstate => Behavior[PlayerActor.Command],
|
|
deadState: Behavior[PlayerActor.Command],
|
|
consumptionMultiplier: Int => Int
|
|
)(implicit timeout: Timeout) {
|
|
import env._
|
|
|
|
implicit val sched = ctx.system.scheduler
|
|
|
|
def behavior =
|
|
IdleBehavior(
|
|
Behaviors
|
|
.receiveMessage[PlayerActor.Command] {
|
|
|
|
case PlayerActor.HandleWalk(curStats, pressed, direction) =>
|
|
if (curStats.stamina.toInt > 0) {
|
|
children.movementActor ! (direction match {
|
|
case MovementDirection.Forward =>
|
|
ImMovementActor.MoveUp(pressed)
|
|
case MovementDirection.Backward =>
|
|
ImMovementActor.MoveDown(pressed)
|
|
case MovementDirection.Left => ImMovementActor.MoveLeft(pressed)
|
|
case MovementDirection.Right =>
|
|
ImMovementActor.MoveRight(pressed)
|
|
})
|
|
if (pressed) nextStateFn(AliveSubstate.Moving(Walking))
|
|
else nextStateFn(AliveSubstate.Idle)
|
|
} else {
|
|
children.movementActor ! ImMovementActor.StopMoving
|
|
Behaviors.same
|
|
}
|
|
|
|
// case PlayerActor.Walk(pressed, Direction.Up) => Behaviors.same
|
|
// case PlayerActor.Walk(pressed, Direction.Down) => Behaviors.same
|
|
// case PlayerActor.Walk(pressed, Direction.Left) => Behaviors.same
|
|
// case PlayerActor.Walk(pressed, Direction.Right) => Behaviors.same
|
|
|
|
case PlayerActor.StopMoving =>
|
|
children.movementActor ! ImMovementActor.StopMoving
|
|
Behaviors.same
|
|
|
|
case PlayerActor.Walk(pressed, direction) =>
|
|
implicit val ec = props.scheduler.value
|
|
for {
|
|
curStats <- children.statsActor.ask(StatsActor.CurrentStats)
|
|
_ <- Future.successful(
|
|
ctx.self ! PlayerActor.HandleWalk(curStats, pressed, direction)
|
|
)
|
|
} yield ()
|
|
Behaviors.same
|
|
|
|
case PlayerActor.Jump =>
|
|
children.movementActor ! ImMovementActor.Jump
|
|
ctx.self.ask(
|
|
PlayerActor.ConsumeStamina(CharacterStats.DamageStamina(10), _)
|
|
)
|
|
Behaviors.same
|
|
|
|
case PlayerActor.TakeDamage(value, replyTo) =>
|
|
implicit val ec = props.scheduler.value
|
|
for {
|
|
res <-
|
|
children.statsActor.ask(StatsActor.TakeDamageResult(value, _))
|
|
_ = ctx.self ! PlayerActor.StatsResponse(res, replyTo)
|
|
|
|
} yield ()
|
|
Behaviors.same
|
|
|
|
case PlayerActor.ConsumeStamina(value, replyTo) =>
|
|
implicit val ec = props.scheduler.value
|
|
val newValue =
|
|
CharacterStats.DamageStamina(consumptionMultiplier(value.toInt))
|
|
for {
|
|
response <- children.statsActor.ask(
|
|
StatsActor.ConsumeStaminaResult(newValue, _)
|
|
)
|
|
_ =
|
|
ctx.self ! PlayerActor
|
|
.StatsResponse(response, replyTo)
|
|
|
|
} yield ()
|
|
Behaviors.same
|
|
|
|
case PlayerActor.CurrentStats(replyTo) =>
|
|
children.statsActor ! StatsActor.CurrentStats(replyTo)
|
|
Behaviors.same
|
|
|
|
case PlayerActor.HealHealth(value, replyTo) =>
|
|
implicit val ec = props.scheduler.value
|
|
for {
|
|
response <- children.statsActor.ask(
|
|
StatsActor.HealHealthResult(value, _)
|
|
)
|
|
_ =
|
|
ctx.self ! PlayerActor
|
|
.StatsResponse(StatsActor.Status.Alive -> response, replyTo)
|
|
} yield ()
|
|
Behaviors.same
|
|
|
|
case PlayerActor.HealStamina(value, replyTo) =>
|
|
implicit val ec = props.scheduler.value
|
|
for {
|
|
response <- children.statsActor.ask(
|
|
StatsActor.HealStaminaResult(value, _)
|
|
)
|
|
_ =
|
|
ctx.self ! PlayerActor
|
|
.StatsResponse(StatsActor.Status.Alive -> response, replyTo)
|
|
|
|
} yield ()
|
|
Behaviors.same
|
|
|
|
case PlayerActor.GetStatus(replyTo) =>
|
|
replyTo ! PlayerActor.Status.Alive
|
|
Behaviors.same
|
|
|
|
case PlayerActor.GetStatsObservable(replyTo) =>
|
|
import monix.{eval => me}
|
|
replyTo !
|
|
UIO(
|
|
Observable
|
|
.repeatEvalF(
|
|
me.Task.deferFuture(props.statsQueue.poll())
|
|
)
|
|
.publish(props.fxScheduler.value)
|
|
.refCount
|
|
)
|
|
|
|
Behaviors.same
|
|
|
|
case PlayerActor.StatsResponse(response, replyTo) =>
|
|
response match {
|
|
case (status, stats) =>
|
|
status match {
|
|
case StatsActor.Status.Dead => ctx.self ! PlayerActor.Die
|
|
case StatsActor.Status.Alive => ()
|
|
}
|
|
props.statsQueue
|
|
.offer(stats)
|
|
.foreach { _ =>
|
|
pprint.log(show"Published stats $stats")
|
|
replyTo ! stats
|
|
}(props.scheduler.value)
|
|
}
|
|
Behaviors.same
|
|
|
|
case PlayerActor.Die => deadState
|
|
|
|
case PlayerActor.LogError(ex) =>
|
|
ctx.log.error(ex.getMessage)
|
|
Behaviors.same
|
|
}
|
|
.receiveSignal {
|
|
case (_, PostStop) =>
|
|
ctx.log.infoP("stopped")
|
|
Behaviors.same
|
|
}
|
|
)
|
|
}
|
|
|
|
final case class IdleBehavior(value: Behavior[PlayerActor.Command])
|