diff --git a/src/main/scala/net/psforever/actors/session/AvatarActor.scala b/src/main/scala/net/psforever/actors/session/AvatarActor.scala index 445216b8..ff498890 100644 --- a/src/main/scala/net/psforever/actors/session/AvatarActor.scala +++ b/src/main/scala/net/psforever/actors/session/AvatarActor.scala @@ -140,6 +140,9 @@ object AvatarActor { /** Deinitialize implants (before zoning or respawning) */ final case class DeinitializeImplants() extends Command + /** Deinitialize a certain implant, then initialize it again */ + final case class ResetImplant(implant: ImplantType) extends Command + /** Shorthand for DeinitializeImplants and InitializeImplants */ final case class ResetImplants() extends Command @@ -172,7 +175,7 @@ object AvatarActor { private case class ServiceManagerLookupResult(result: ServiceManager.LookupResult) extends Command - private case class SetStamina(stamina: Int) extends Command + final case class SetStamina(stamina: Int) extends Command private case class SetImplantInitialized(implantType: ImplantType) extends Command @@ -841,8 +844,7 @@ class AvatarActor( Behaviors.same case RestoreStamina(stamina) => - assert(stamina > 0) - if (session.get.player.HasGUID) { + if (stamina > 0 && session.get.player.HasGUID) { val totalStamina = math.min(avatar.maxStamina, avatar.stamina + stamina) val fatigued = if (avatar.fatigued && totalStamina >= 20) { avatar.implants.zipWithIndex.foreach { @@ -890,6 +892,10 @@ class AvatarActor( deinitializeImplants() Behaviors.same + case ResetImplant(implantType) => + resetAnImplant(implantType) + Behaviors.same + case ResetImplants() => deinitializeImplants() initializeImplants() @@ -1097,6 +1103,42 @@ class AvatarActor( }) } + def resetAnImplant(implantType: ImplantType): Unit = { + avatar.implants.zipWithIndex.find { + case (Some(imp), _) => imp.definition.implantType == implantType + case (None, _) => false + } match { + case Some((Some(imp), index)) => + //deactivate + if (imp.active) { + deactivateImplant(implantType) + } + //deinitialize + session.get.zone.AvatarEvents ! AvatarServiceMessage( + session.get.zone.id, + AvatarAction.SendResponse( + Service.defaultPlayerGUID, + AvatarImplantMessage(session.get.player.GUID, ImplantAction.Initialization, index, 0) + ) + ) + avatar = avatar.copy( + implants = avatar.implants.updated(index, Some(imp.copy(initialized = false, active = false))) + ) + //restart initialization process + implantTimers(index).cancel() + implantTimers(index) = context.scheduleOnce( + imp.definition.InitializationDuration.seconds, + context.self, + SetImplantInitialized(implantType) + ) + session.get.zone.AvatarEvents ! AvatarServiceMessage( + avatar.name, + AvatarAction.SendResponse(Service.defaultPlayerGUID, ActionProgressMessage(index + 6, 0)) + ) + case _ => ; + } + } + def deactivateImplant(implantType: ImplantType): Unit = { avatar.implants.zipWithIndex.collectFirst { case (Some(implant), index) if implant.definition.implantType == implantType => (implant, index) diff --git a/src/main/scala/net/psforever/objects/avatar/PlayerControl.scala b/src/main/scala/net/psforever/objects/avatar/PlayerControl.scala index 85f4af65..7d75e828 100644 --- a/src/main/scala/net/psforever/objects/avatar/PlayerControl.scala +++ b/src/main/scala/net/psforever/objects/avatar/PlayerControl.scala @@ -748,8 +748,22 @@ class PlayerControl(player: Player, avatarActor: typed.ActorRef[AvatarActor.Comm } //choose if (target.Health > 0) { + //alive + if (target.Health <= 25 && target.Health + damageToHealth > 25 && + (player.avatar.implants.flatten.find { _.definition.implantType == ImplantType.SecondWind } match { + case Some(wind) => wind.initialized + case _ => false + })) { + //activate second wind + player.Health += 25 + player.History(HealFromImplant(PlayerSource(player), 25, ImplantType.SecondWind)) + avatarActor ! AvatarActor.ResetImplant(ImplantType.SecondWind) + avatarActor ! AvatarActor.RestoreStamina(25) + } + //take damage/update DamageAwareness(target, cause, damageToHealth, damageToArmor, damageToStamina, damageToCapacitor) } else { + //ded DestructionAwareness(target, cause) } } diff --git a/src/main/scala/net/psforever/objects/vital/base/DamageResolution.scala b/src/main/scala/net/psforever/objects/vital/base/DamageResolution.scala index 92160782..b38a92f1 100644 --- a/src/main/scala/net/psforever/objects/vital/base/DamageResolution.scala +++ b/src/main/scala/net/psforever/objects/vital/base/DamageResolution.scala @@ -28,6 +28,8 @@ object DamageResolution extends Enumeration { AggravatedDirectBurn, //continuous direct hit aggravated damage AggravatedSplash, //splashed aggravated damage AggravatedSplashBurn, //continuous splashed aggravated damage - Explosion //area of effect damage caused by an internal mechanism; unrelated to Splash + Explosion, //area of effect damage caused by an internal mechanism; unrelated to Splash + Environmental, //died to environmental causes + Suicide //i don't want to be the one the battles always choose = Value } diff --git a/src/main/scala/net/psforever/objects/vital/environment/EnvironmentReason.scala b/src/main/scala/net/psforever/objects/vital/environment/EnvironmentReason.scala index 126aae11..3f1f37ed 100644 --- a/src/main/scala/net/psforever/objects/vital/environment/EnvironmentReason.scala +++ b/src/main/scala/net/psforever/objects/vital/environment/EnvironmentReason.scala @@ -17,7 +17,7 @@ import net.psforever.objects.vital.{NoResistanceSelection, SimpleResolutions, Vi * @param against for the purposes of damage, what kind of target is being acted upon */ final case class EnvironmentReason(body: PieceOfEnvironment, against: DamageCalculations.Selector) extends DamageReason { - def resolution: DamageResolution.Value = DamageResolution.Hit + def resolution: DamageResolution.Value = DamageResolution.Environmental def source: DamageProperties = EnvironmentReason.selectDamage(body) diff --git a/src/main/scala/net/psforever/objects/vital/etc/SuicideReason.scala b/src/main/scala/net/psforever/objects/vital/etc/SuicideReason.scala index 8dff90bf..1d2f4e8c 100644 --- a/src/main/scala/net/psforever/objects/vital/etc/SuicideReason.scala +++ b/src/main/scala/net/psforever/objects/vital/etc/SuicideReason.scala @@ -33,7 +33,7 @@ final case class SuicideReason() */ def source: DamageProperties = SuicideReason.damageProperties - def resolution: DamageResolution.Value = DamageResolution.Resolved + def resolution: DamageResolution.Value = DamageResolution.Suicide def same(test: DamageReason): Boolean = { test.source eq source