mirror of
https://github.com/psforever/PSF-LoginServer.git
synced 2026-01-19 18:44:45 +00:00
Merge branch 'master' into adv-regen
This commit is contained in:
commit
6d13ae972e
|
|
@ -66,7 +66,7 @@ lazy val psforeverSettings = Seq(
|
||||||
"io.kamon" %% "kamon-apm-reporter" % "2.1.20",
|
"io.kamon" %% "kamon-apm-reporter" % "2.1.20",
|
||||||
"org.json4s" %% "json4s-native" % "4.0.1",
|
"org.json4s" %% "json4s-native" % "4.0.1",
|
||||||
"io.getquill" %% "quill-jasync-postgres" % "3.7.2",
|
"io.getquill" %% "quill-jasync-postgres" % "3.7.2",
|
||||||
"org.flywaydb" % "flyway-core" % "7.10.0",
|
"org.flywaydb" % "flyway-core" % "7.11.0",
|
||||||
"org.postgresql" % "postgresql" % "42.2.22",
|
"org.postgresql" % "postgresql" % "42.2.22",
|
||||||
"com.typesafe" % "config" % "1.4.1",
|
"com.typesafe" % "config" % "1.4.1",
|
||||||
"com.github.pureconfig" %% "pureconfig" % "0.16.0",
|
"com.github.pureconfig" %% "pureconfig" % "0.16.0",
|
||||||
|
|
|
||||||
|
|
@ -142,6 +142,9 @@ object AvatarActor {
|
||||||
/** Deinitialize implants (before zoning or respawning) */
|
/** Deinitialize implants (before zoning or respawning) */
|
||||||
final case class DeinitializeImplants() extends Command
|
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 */
|
/** Shorthand for DeinitializeImplants and InitializeImplants */
|
||||||
final case class ResetImplants() extends Command
|
final case class ResetImplants() extends Command
|
||||||
|
|
||||||
|
|
@ -174,7 +177,7 @@ object AvatarActor {
|
||||||
|
|
||||||
private case class ServiceManagerLookupResult(result: ServiceManager.LookupResult) extends Command
|
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
|
private case class SetImplantInitialized(implantType: ImplantType) extends Command
|
||||||
|
|
||||||
|
|
@ -869,8 +872,7 @@ class AvatarActor(
|
||||||
Behaviors.same
|
Behaviors.same
|
||||||
|
|
||||||
case RestoreStamina(stamina) =>
|
case RestoreStamina(stamina) =>
|
||||||
assert(stamina > 0)
|
if (stamina > 0 && session.get.player.HasGUID) {
|
||||||
if (session.get.player.HasGUID) {
|
|
||||||
val totalStamina = math.min(avatar.maxStamina, avatar.stamina + stamina)
|
val totalStamina = math.min(avatar.maxStamina, avatar.stamina + stamina)
|
||||||
val fatigued = if (avatar.fatigued && totalStamina >= 20) {
|
val fatigued = if (avatar.fatigued && totalStamina >= 20) {
|
||||||
avatar.implants.zipWithIndex.foreach {
|
avatar.implants.zipWithIndex.foreach {
|
||||||
|
|
@ -892,8 +894,11 @@ class AvatarActor(
|
||||||
Behaviors.same
|
Behaviors.same
|
||||||
|
|
||||||
case ConsumeStamina(stamina) =>
|
case ConsumeStamina(stamina) =>
|
||||||
assert(stamina > 0, s"consumed stamina must be larger than 0, but is: $stamina")
|
if (stamina > 0) {
|
||||||
consumeThisMuchStamina(stamina)
|
consumeThisMuchStamina(stamina)
|
||||||
|
} else {
|
||||||
|
log.warn(s"consumed stamina must be larger than 0, but is: $stamina")
|
||||||
|
}
|
||||||
Behaviors.same
|
Behaviors.same
|
||||||
|
|
||||||
case SuspendStaminaRegeneration(duration) =>
|
case SuspendStaminaRegeneration(duration) =>
|
||||||
|
|
@ -915,6 +920,10 @@ class AvatarActor(
|
||||||
deinitializeImplants()
|
deinitializeImplants()
|
||||||
Behaviors.same
|
Behaviors.same
|
||||||
|
|
||||||
|
case ResetImplant(implantType) =>
|
||||||
|
resetAnImplant(implantType)
|
||||||
|
Behaviors.same
|
||||||
|
|
||||||
case ResetImplants() =>
|
case ResetImplants() =>
|
||||||
deinitializeImplants()
|
deinitializeImplants()
|
||||||
initializeImplants()
|
initializeImplants()
|
||||||
|
|
@ -1138,6 +1147,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 = {
|
def deactivateImplant(implantType: ImplantType): Unit = {
|
||||||
avatar.implants.zipWithIndex.collectFirst {
|
avatar.implants.zipWithIndex.collectFirst {
|
||||||
case (Some(implant), index) if implant.definition.implantType == implantType => (implant, index)
|
case (Some(implant), index) if implant.definition.implantType == implantType => (implant, index)
|
||||||
|
|
|
||||||
|
|
@ -7710,19 +7710,32 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
projectile.Resolve()
|
projectile.Resolve()
|
||||||
val outProjectile = if (projectile.profile.ProjectileDamageTypes.contains(DamageType.Aggravated)) {
|
val outProjectile =
|
||||||
val quality = projectile.profile.Aggravated match {
|
if (projectile.profile.ProjectileDamageTypes.contains(DamageType.Aggravated)) {
|
||||||
case Some(aggravation)
|
//aggravated
|
||||||
if aggravation.targets.exists(validation => validation.test(target)) &&
|
val quality = projectile.profile.Aggravated match {
|
||||||
aggravation.info.exists(_.damage_type == AggravatedDamage.basicDamageType(resolution)) =>
|
case Some(aggravation)
|
||||||
ProjectileQuality.AggravatesTarget
|
if aggravation.targets.exists(validation => validation.test(target)) &&
|
||||||
case _ =>
|
aggravation.info.exists(_.damage_type == AggravatedDamage.basicDamageType(resolution)) =>
|
||||||
ProjectileQuality.Normal
|
ProjectileQuality.AggravatesTarget
|
||||||
|
case _ =>
|
||||||
|
ProjectileQuality.Normal
|
||||||
|
}
|
||||||
|
projectile.quality(quality)
|
||||||
|
} else if (projectile.tool_def.Size == EquipmentSize.Melee) {
|
||||||
|
//melee
|
||||||
|
val quality = player.avatar.implants.flatten.find { entry => entry.definition == GlobalDefinitions.melee_booster } match {
|
||||||
|
case Some(booster) if booster.active && player.avatar.stamina > 9 =>
|
||||||
|
avatarActor ! AvatarActor.ConsumeStamina(10)
|
||||||
|
ProjectileQuality.Modified(25f)
|
||||||
|
case _ =>
|
||||||
|
ProjectileQuality.Normal
|
||||||
|
}
|
||||||
|
projectile.quality(quality)
|
||||||
|
} else {
|
||||||
|
//normal
|
||||||
|
projectile
|
||||||
}
|
}
|
||||||
projectile.quality(quality)
|
|
||||||
} else {
|
|
||||||
projectile
|
|
||||||
}
|
|
||||||
Some(DamageInteraction(SourceEntry(target), ProjectileReason(resolution, outProjectile, target.DamageModel), pos))
|
Some(DamageInteraction(SourceEntry(target), ProjectileReason(resolution, outProjectile, target.DamageModel), pos))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2415,7 +2415,7 @@ object GlobalDefinitions {
|
||||||
chainblade_projectile.InitialVelocity = 100
|
chainblade_projectile.InitialVelocity = 100
|
||||||
chainblade_projectile.Lifespan = .02f
|
chainblade_projectile.Lifespan = .02f
|
||||||
ProjectileDefinition.CalculateDerivedFields(chainblade_projectile)
|
ProjectileDefinition.CalculateDerivedFields(chainblade_projectile)
|
||||||
chainblade_projectile.Modifiers = MaxDistanceCutoff
|
chainblade_projectile.Modifiers = List(MeleeBoosted, MaxDistanceCutoff)
|
||||||
|
|
||||||
colossus_100mm_projectile.Name = "colossus_100mm_projectile"
|
colossus_100mm_projectile.Name = "colossus_100mm_projectile"
|
||||||
colossus_100mm_projectile.Damage0 = 58
|
colossus_100mm_projectile.Damage0 = 58
|
||||||
|
|
@ -2766,7 +2766,7 @@ object GlobalDefinitions {
|
||||||
forceblade_projectile.InitialVelocity = 100
|
forceblade_projectile.InitialVelocity = 100
|
||||||
forceblade_projectile.Lifespan = .02f
|
forceblade_projectile.Lifespan = .02f
|
||||||
ProjectileDefinition.CalculateDerivedFields(forceblade_projectile)
|
ProjectileDefinition.CalculateDerivedFields(forceblade_projectile)
|
||||||
forceblade_projectile.Modifiers = MaxDistanceCutoff
|
forceblade_projectile.Modifiers = List(MeleeBoosted, MaxDistanceCutoff)
|
||||||
|
|
||||||
frag_cartridge_projectile.Name = "frag_cartridge_projectile"
|
frag_cartridge_projectile.Name = "frag_cartridge_projectile"
|
||||||
// TODO for later, maybe : set_resource_parent frag_cartridge_projectile game_objects frag_grenade_projectile
|
// TODO for later, maybe : set_resource_parent frag_cartridge_projectile game_objects frag_grenade_projectile
|
||||||
|
|
@ -3243,7 +3243,7 @@ object GlobalDefinitions {
|
||||||
magcutter_projectile.InitialVelocity = 100
|
magcutter_projectile.InitialVelocity = 100
|
||||||
magcutter_projectile.Lifespan = .02f
|
magcutter_projectile.Lifespan = .02f
|
||||||
ProjectileDefinition.CalculateDerivedFields(magcutter_projectile)
|
ProjectileDefinition.CalculateDerivedFields(magcutter_projectile)
|
||||||
magcutter_projectile.Modifiers = MaxDistanceCutoff
|
magcutter_projectile.Modifiers = List(MeleeBoosted, MaxDistanceCutoff)
|
||||||
|
|
||||||
melee_ammo_projectile.Name = "melee_ammo_projectile"
|
melee_ammo_projectile.Name = "melee_ammo_projectile"
|
||||||
melee_ammo_projectile.Damage0 = 25
|
melee_ammo_projectile.Damage0 = 25
|
||||||
|
|
@ -3252,7 +3252,7 @@ object GlobalDefinitions {
|
||||||
melee_ammo_projectile.InitialVelocity = 100
|
melee_ammo_projectile.InitialVelocity = 100
|
||||||
melee_ammo_projectile.Lifespan = .02f
|
melee_ammo_projectile.Lifespan = .02f
|
||||||
ProjectileDefinition.CalculateDerivedFields(melee_ammo_projectile)
|
ProjectileDefinition.CalculateDerivedFields(melee_ammo_projectile)
|
||||||
melee_ammo_projectile.Modifiers = MaxDistanceCutoff
|
melee_ammo_projectile.Modifiers = List(MeleeBoosted, MaxDistanceCutoff)
|
||||||
|
|
||||||
meteor_common.Name = "meteor_common"
|
meteor_common.Name = "meteor_common"
|
||||||
meteor_common.DamageAtEdge = .1f
|
meteor_common.DamageAtEdge = .1f
|
||||||
|
|
|
||||||
|
|
@ -748,8 +748,22 @@ class PlayerControl(player: Player, avatarActor: typed.ActorRef[AvatarActor.Comm
|
||||||
}
|
}
|
||||||
//choose
|
//choose
|
||||||
if (target.Health > 0) {
|
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)
|
DamageAwareness(target, cause, damageToHealth, damageToArmor, damageToStamina, damageToCapacitor)
|
||||||
} else {
|
} else {
|
||||||
|
//ded
|
||||||
DestructionAwareness(target, cause)
|
DestructionAwareness(target, cause)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,8 @@ object DamageResolution extends Enumeration {
|
||||||
AggravatedDirectBurn, //continuous direct hit aggravated damage
|
AggravatedDirectBurn, //continuous direct hit aggravated damage
|
||||||
AggravatedSplash, //splashed aggravated damage
|
AggravatedSplash, //splashed aggravated damage
|
||||||
AggravatedSplashBurn, //continuous 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
|
= Value
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
* @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 {
|
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)
|
def source: DamageProperties = EnvironmentReason.selectDamage(body)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ final case class SuicideReason()
|
||||||
*/
|
*/
|
||||||
def source: DamageProperties = SuicideReason.damageProperties
|
def source: DamageProperties = SuicideReason.damageProperties
|
||||||
|
|
||||||
def resolution: DamageResolution.Value = DamageResolution.Resolved
|
def resolution: DamageResolution.Value = DamageResolution.Suicide
|
||||||
|
|
||||||
def same(test: DamageReason): Boolean = {
|
def same(test: DamageReason): Boolean = {
|
||||||
test.source eq source
|
test.source eq source
|
||||||
|
|
|
||||||
|
|
@ -293,6 +293,19 @@ case object FlakBurst extends ProjectileDamageModifiers.Mod {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the damage is resolved by way of a melee weapon,
|
||||||
|
* the damage might be increased if the attack was initiated
|
||||||
|
* while the attacker was under the effect of an active Melee Boost implant.
|
||||||
|
* @see `GlobalDefinitions.melee_booster`
|
||||||
|
* @see `ProjectileQuality`
|
||||||
|
*/
|
||||||
|
case object MeleeBoosted extends ProjectileDamageModifiers.Mod {
|
||||||
|
override def calculate(damage: Int, data: DamageInteraction, cause: ProjectileReason): Int = {
|
||||||
|
cause.projectile.quality.mod.toInt + damage
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Functions */
|
/* Functions */
|
||||||
object ProjectileDamageModifierFunctions {
|
object ProjectileDamageModifierFunctions {
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue