support for advanced regen implant; not pretty, but it works

This commit is contained in:
Jason_DiDonato@yahoo.com 2021-06-30 19:43:37 -04:00
parent 76f283c617
commit 540eec5bdd

View file

@ -13,7 +13,9 @@ import net.psforever.objects.equipment.{Equipment, EquipmentSlot}
import net.psforever.objects.inventory.InventoryItem import net.psforever.objects.inventory.InventoryItem
import net.psforever.objects.loadouts.{InfantryLoadout, Loadout, VehicleLoadout} import net.psforever.objects.loadouts.{InfantryLoadout, Loadout, VehicleLoadout}
import net.psforever.objects._ import net.psforever.objects._
import net.psforever.objects.ballistics.PlayerSource
import net.psforever.objects.locker.LockerContainer import net.psforever.objects.locker.LockerContainer
import net.psforever.objects.vital.HealFromImplant
import net.psforever.packet.game.objectcreate.ObjectClass import net.psforever.packet.game.objectcreate.ObjectClass
import net.psforever.packet.game._ import net.psforever.packet.game._
import net.psforever.types._ import net.psforever.types._
@ -761,7 +763,7 @@ class AvatarActor(
if (!implant.initialized) { if (!implant.initialized) {
log.warn(s"requested activation of uninitialized implant $implantType") log.warn(s"requested activation of uninitialized implant $implantType")
} else if ( } else if (
!consumeStamina(implant.definition.ActivationStaminaCost) || !consumeThisMuchStamina(implant.definition.ActivationStaminaCost) ||
avatar.stamina < implant.definition.StaminaCost avatar.stamina < implant.definition.StaminaCost
) { ) {
// not enough stamina to activate // not enough stamina to activate
@ -796,7 +798,33 @@ class AvatarActor(
// TODO costInterval should be an option ^ // TODO costInterval should be an option ^
if (interval.toMillis > 0) { if (interval.toMillis > 0) {
implantTimers(slot) = context.system.scheduler.scheduleWithFixedDelay(interval, interval)(() => { implantTimers(slot) = context.system.scheduler.scheduleWithFixedDelay(interval, interval)(() => {
if (!consumeStamina(implant.definition.StaminaCost)) { val player = session.get.player
if (implantType match {
case ImplantType.AdvancedRegen =>
//for every 1hp: 2sp (running), 1.5sp (standing), 1sp (crouched)
// to simulate '1.5sp (standing)', find if 0.0...1.0 * 100 is an even number
val cost = implant.definition.StaminaCost -
(if (player.Crouching || (!player.isMoving && (math.random() * 100) % 2 == 1)) 1 else 0)
val aliveAndWounded = player.isAlive && player.Health < player.MaxHealth
if (aliveAndWounded && consumeThisMuchStamina(cost)) {
//heal
val originalHealth = player.Health
val zone = player.Zone
val events = zone.AvatarEvents
val guid = player.GUID
val newHealth = player.Health = originalHealth + 1
player.History(HealFromImplant(PlayerSource(player), 1, implantType))
events ! AvatarServiceMessage(
zone.id,
AvatarAction.PlanetsideAttributeToAll(guid, 0, newHealth)
)
false
} else {
!aliveAndWounded
}
case _ =>
!player.isAlive || !consumeThisMuchStamina(implant.definition.StaminaCost)
}) {
context.self ! DeactivateImplant(implantType) context.self ! DeactivateImplant(implantType)
} }
}) })
@ -865,7 +893,7 @@ class AvatarActor(
case ConsumeStamina(stamina) => case ConsumeStamina(stamina) =>
assert(stamina > 0, s"consumed stamina must be larger than 0, but is: $stamina") assert(stamina > 0, s"consumed stamina must be larger than 0, but is: $stamina")
consumeStamina(stamina) consumeThisMuchStamina(stamina)
Behaviors.same Behaviors.same
case SuspendStaminaRegeneration(duration) => case SuspendStaminaRegeneration(duration) =>
@ -1012,34 +1040,50 @@ class AvatarActor(
p.future p.future
} }
/** Consumes given stamina and returns false if current stamina was too low to consume the full amount */ /**
def consumeStamina(stamina: Int): Boolean = { * Drain at most a given amount of stamina from the player's pool of stamina.
if (stamina == 0) return true * If the player's reserves become zero in the act, inform the player that he is fatigued
if (!session.get.player.HasGUID) return false * meaning that he will only be able to walk, all implants will deactivate,
val consumed = (avatar.stamina - stamina) >= 0 * and all exertion that require stamina use will become impossible until a threshold of stamina is regained.
val totalStamina = math.max(0, avatar.stamina - stamina) * @param stamina an amount to drain
val fatigued = if (!avatar.fatigued && totalStamina == 0) { * @return `true`, as long as the amount of stamina can be drained in total;
context.self ! DeactivateActiveImplants() * `false`, otherwise
*/
def consumeThisMuchStamina(stamina: Int): Boolean = {
if (stamina < 1) {
true true
} else { } else {
totalStamina == 0 val resultingStamina = avatar.stamina - stamina
} val totalStamina = math.max(0, resultingStamina)
if (!avatar.fatigued && fatigued) { val alreadyFatigued = avatar.fatigued
avatar.implants.zipWithIndex.foreach { val becomeFatigued = !alreadyFatigued && totalStamina == 0
case (Some(implant), slot) => avatar = avatar.copy(stamina = totalStamina, fatigued = alreadyFatigued || becomeFatigued)
if (implant.active) { val player = session.get.player
deactivateImplant(implant.definition.implantType) if (player.HasGUID) {
if (becomeFatigued) {
avatar.implants.zipWithIndex.foreach {
case (Some(implant), slot) =>
if (implant.active) {
deactivateImplant(implant.definition.implantType)
}
sessionActor ! SessionActor.SendResponse(
AvatarImplantMessage(player.GUID, ImplantAction.OutOfStamina, slot, 1)
)
case _ => ;
} }
sessionActor ! SessionActor.SendResponse( }
AvatarImplantMessage(session.get.player.GUID, ImplantAction.OutOfStamina, slot, 1) sessionActor ! SessionActor.SendResponse(PlanetsideAttributeMessage(player.GUID, 2, avatar.stamina))
) } else if (becomeFatigued) {
case _ => () avatar = avatar.copy(implants = avatar.implants.zipWithIndex.collect {
case (Some(implant), slot) if implant.active =>
implantTimers(slot).cancel()
Some(implant.copy(active = false))
case (out, _) =>
out
})
} }
resultingStamina >= 0
} }
avatar = avatar.copy(stamina = totalStamina, fatigued = fatigued)
sessionActor ! SessionActor.SendResponse(PlanetsideAttributeMessage(session.get.player.GUID, 2, avatar.stamina))
consumed
} }
def initializeImplants(): Unit = { def initializeImplants(): Unit = {