diff --git a/src/main/scala/net/psforever/actors/session/normal/GeneralLogic.scala b/src/main/scala/net/psforever/actors/session/normal/GeneralLogic.scala index e5a7f8417..1d8b02624 100644 --- a/src/main/scala/net/psforever/actors/session/normal/GeneralLogic.scala +++ b/src/main/scala/net/psforever/actors/session/normal/GeneralLogic.scala @@ -162,8 +162,7 @@ class GeneralLogic(val ops: GeneralOperations, implicit val context: ActorContex case None => () } val eagleEye: Boolean = ops.canSeeReallyFar - val isNotVisible: Boolean = player.spectator || - sessionLogic.zoning.zoningStatus == Zoning.Status.Deconstructing || + val isNotVisible: Boolean = sessionLogic.zoning.zoningStatus == Zoning.Status.Deconstructing || (player.isAlive && sessionLogic.zoning.spawn.deadState == DeadState.RespawnTime) continent.AvatarEvents ! AvatarServiceMessage( continent.id, @@ -716,7 +715,7 @@ class GeneralLogic(val ops: GeneralOperations, implicit val context: ActorContex val (target1, target2, bailProtectStatus, velocity) = (ctype, sessionLogic.validObject(p, decorator = "GenericCollision/Primary")) match { case (CollisionIs.OfInfantry, out @ Some(user: Player)) if user == player => - val bailStatus = session.flying || player.spectator || session.speed > 1f || player.BailProtection + val bailStatus = session.flying || session.speed > 1f || player.BailProtection player.BailProtection = false val v = if (player.avatar.implants.exists { case Some(implant) => implant.definition.implantType == ImplantType.Surge && implant.active diff --git a/src/main/scala/net/psforever/objects/BoomerDeployable.scala b/src/main/scala/net/psforever/objects/BoomerDeployable.scala index 612fbe112..dd7e600e2 100644 --- a/src/main/scala/net/psforever/objects/BoomerDeployable.scala +++ b/src/main/scala/net/psforever/objects/BoomerDeployable.scala @@ -4,8 +4,11 @@ package net.psforever.objects import akka.actor.{ActorContext, Props} import net.psforever.objects.ce.{Deployable, DeployedItem} import net.psforever.objects.guid.{GUIDTask, TaskWorkflow} +import net.psforever.objects.serverobject.affinity.FactionAffinity +import net.psforever.objects.serverobject.damage.Damageable import net.psforever.objects.serverobject.{CommonMessages, PlanetSideServerObject} import net.psforever.objects.sourcing.{PlayerSource, SourceEntry} +import net.psforever.objects.vital.Vitality import net.psforever.objects.vital.etc.TriggerUsedReason import net.psforever.objects.vital.interaction.DamageInteraction import net.psforever.objects.zones.Zone @@ -58,8 +61,7 @@ class BoomerDeployableControl(mine: BoomerDeployable) case CommonMessages.Use(player, Some(trigger: BoomerTrigger)) if mine.Trigger.contains(trigger) => // the trigger damages the mine, which sets it off, which causes an explosion // think of this as an initiator to the proper explosion - mine.Destroyed = true - ExplosiveDeployableControl.DamageResolution( + HandleDamage( mine, DamageInteraction( SourceEntry(mine), @@ -68,8 +70,7 @@ class BoomerDeployableControl(mine: BoomerDeployable) ).calculate()(mine), damage = 0 ) - - case _ => ; + case _ => () } def loseOwnership(@unused faction: PlanetSideEmpire.Value): Unit = { @@ -97,14 +98,27 @@ class BoomerDeployableControl(mine: BoomerDeployable) container.Slot(index).Equipment = None case Some(Zone.EquipmentIs.OnGround()) => zone.Ground ! Zone.Ground.RemoveItem(guid) - case _ => ; + case _ => () } zone.AvatarEvents! AvatarServiceMessage( zone.id, AvatarAction.ObjectDelete(Service.defaultPlayerGUID, guid) ) TaskWorkflow.execute(GUIDTask.unregisterObject(zone.GUID, trigger)) - case None => ; + case None => () } } + + /** + * Boomers are not bothered by explosive sympathy + * but can still be affected by sources of jammering. + * @param obj the entity being damaged + * @param damage the amount of damage + * @param data historical information about the damage + * @return `true`, if the target can be affected; + * `false`, otherwise + */ + override def CanDetonate(obj: Vitality with FactionAffinity, damage: Int, data: DamageInteraction): Boolean = { + !mine.Destroyed && (data.cause.isInstanceOf[TriggerUsedReason] || Damageable.CanJammer(obj, data)) + } } diff --git a/src/main/scala/net/psforever/objects/ExplosiveDeployable.scala b/src/main/scala/net/psforever/objects/ExplosiveDeployable.scala index 928abb746..462df5b39 100644 --- a/src/main/scala/net/psforever/objects/ExplosiveDeployable.scala +++ b/src/main/scala/net/psforever/objects/ExplosiveDeployable.scala @@ -90,14 +90,34 @@ abstract class ExplosiveDeployableControl(mine: ExplosiveDeployable) val originalHealth = mine.Health val cause = applyDamageTo(mine) val damage = originalHealth - mine.Health - if (CanDetonate(mine, damage, cause.interaction)) { - ExplosiveDeployableControl.DamageResolution(mine, cause, damage) + if (Interaction(mine, damage, cause.interaction)) { + HandleDamage(mine, cause, damage) } else { mine.Health = originalHealth } } } + def Interaction(obj: Vitality with FactionAffinity, damage: Int, data: DamageInteraction): Boolean = { + !mine.Destroyed && (if (damage == 0 && data.cause.source.SympatheticExplosion) { + Damageable.CanDamageOrJammer(obj, damage = 1, data) + } else { + Damageable.CanDamageOrJammer(obj, damage, data) + }) + } + + final def HandleDamage(target: ExplosiveDeployable, cause: DamageResult, damage: Int): Unit = { + target.LogActivity(cause) + if (CanDetonate(target, damage, cause.interaction)) { + ExplosiveDeployableControl.explodes(target, cause) + ExplosiveDeployableControl.DestructionAwareness(target, cause) + } else if (target.Health == 0) { + ExplosiveDeployableControl.DestructionAwareness(target, cause) + } else { + ExplosiveDeployableControl.DamageAwareness(target, cause, damage) + } + } + /** * A supplement for checking target susceptibility * to account for sympathetic explosives even if there is no damage. @@ -117,6 +137,11 @@ abstract class ExplosiveDeployableControl(mine: ExplosiveDeployable) Damageable.CanDamageOrJammer(mine, damage, data) }) } + + def explode(target: ExplosiveDeployable, cause: DamageResult): Unit = { + ExplosiveDeployableControl.explodes(target, cause) + ExplosiveDeployableControl.DestructionAwareness(target, cause) + } } object ExplosiveDeployableControl { @@ -126,14 +151,8 @@ object ExplosiveDeployableControl { * @param cause na * @param damage na */ - def DamageResolution(target: ExplosiveDeployable, cause: DamageResult, damage: Int): Unit = { - target.LogActivity(cause) - if (cause.interaction.cause.source.SympatheticExplosion) { - explodes(target, cause) - DestructionAwareness(target, cause) - } else if (target.Health == 0) { - DestructionAwareness(target, cause) - } else if (!target.Jammed && Damageable.CanJammer(target, cause.interaction)) { + def DamageAwareness(target: ExplosiveDeployable, cause: DamageResult, damage: Int): Unit = { + if (!target.Jammed && Damageable.CanJammer(target, cause.interaction)) { if ( { target.Jammed = cause.interaction.cause match { case o: ProjectileReason => @@ -158,6 +177,7 @@ object ExplosiveDeployableControl { * @param cause na */ def explodes(target: Damageable.Target, cause: DamageResult): Unit = { + target.Destroyed = true target.Health = 1 // short-circuit logic in DestructionAwareness val zone = target.Zone zone.Activity ! Zone.HotSpot.Activity(cause) @@ -268,7 +288,7 @@ class MineDeployableControl(mine: ExplosiveDeployable) mine.Definition.innateDamage.map { _.DamageRadius }.getOrElse(mine.Definition.triggerRadius) )) - case _ => ; + case _ => () } override def finalizeDeployable(callback: ActorRef): Unit = { @@ -287,33 +307,36 @@ class MineDeployableControl(mine: ExplosiveDeployable) } def setTriggered(instigator: Option[PlanetSideServerObject], delay: Long): Unit = { - instigator match { - case Some(_) if isConstructed.contains(true) && setup.isCancelled => - //re-use the setup timer here - import scala.concurrent.ExecutionContext.Implicits.global - setup = context.system.scheduler.scheduleOnce(delay milliseconds, self, MineDeployableControl.Triggered()) - case _ => ; - } + instigator + .collect { + case _ if isConstructed.contains(true) && setup.isCancelled => + //re-use the setup timer here + import scala.concurrent.ExecutionContext.Implicits.global + setup = context.system.scheduler.scheduleOnce(delay milliseconds, self, MineDeployableControl.Triggered()) + } } def explodes(instigator: Option[PlanetSideServerObject]): Unit = { - instigator match { - case Some(_) => - //explosion - mine.Destroyed = true - ExplosiveDeployableControl.DamageResolution( - mine, - DamageInteraction( - SourceEntry(mine), - MineDeployableControl.trippedMineReason(mine), - mine.Position - ).calculate()(mine), - damage = 0 - ) - case None => + instigator + .collect { + case _ => + //explosion + mine.Destroyed = true + ExplosiveDeployableControl.DamageAwareness( + mine, + DamageInteraction( + SourceEntry(mine), + MineDeployableControl.trippedMineReason(mine), + mine.Position + ).calculate()(mine), + damage = 0 + ) + } + .orElse { //reset setup = Default.Cancellable - } + None + } } } diff --git a/src/main/scala/net/psforever/objects/global/GlobalDefinitionsDeployable.scala b/src/main/scala/net/psforever/objects/global/GlobalDefinitionsDeployable.scala index da633d60a..57f234f91 100644 --- a/src/main/scala/net/psforever/objects/global/GlobalDefinitionsDeployable.scala +++ b/src/main/scala/net/psforever/objects/global/GlobalDefinitionsDeployable.scala @@ -34,7 +34,7 @@ object GlobalDefinitionsDeployable { boomer.Name = "boomer" boomer.Descriptor = "Boomers" - boomer.MaxHealth = 100 + boomer.MaxHealth = 50 boomer.Damageable = true boomer.DamageableByFriendlyFire = false boomer.Repairable = false @@ -58,7 +58,7 @@ object GlobalDefinitionsDeployable { he_mine.Name = "he_mine" he_mine.Descriptor = "Mines" - he_mine.MaxHealth = 100 + he_mine.MaxHealth = 50 he_mine.Damageable = true he_mine.DamageableByFriendlyFire = false he_mine.Repairable = false @@ -82,7 +82,7 @@ object GlobalDefinitionsDeployable { jammer_mine.Name = "jammer_mine" jammer_mine.Descriptor = "JammerMines" - jammer_mine.MaxHealth = 100 + jammer_mine.MaxHealth = 50 jammer_mine.Damageable = true jammer_mine.DamageableByFriendlyFire = false jammer_mine.Repairable = false diff --git a/src/main/scala/net/psforever/objects/vital/etc/TriggerUsedReason.scala b/src/main/scala/net/psforever/objects/vital/etc/TriggerUsedReason.scala index 6a8b088c8..fd77eebb8 100644 --- a/src/main/scala/net/psforever/objects/vital/etc/TriggerUsedReason.scala +++ b/src/main/scala/net/psforever/objects/vital/etc/TriggerUsedReason.scala @@ -50,7 +50,6 @@ final case class TriggerUsedReason(user: PlayerSource, item_guid: PlanetSideGUID object TriggerUsedReason { private val triggered = new DamageProperties { Damage0 = 1 //token damage - SympatheticExplosion = true //sets off a boomer } /** basic damage, no resisting, quick and simple */ diff --git a/src/main/scala/net/psforever/packet/game/DamageFeedbackMessage.scala b/src/main/scala/net/psforever/packet/game/DamageFeedbackMessage.scala index f88bcf039..141266395 100644 --- a/src/main/scala/net/psforever/packet/game/DamageFeedbackMessage.scala +++ b/src/main/scala/net/psforever/packet/game/DamageFeedbackMessage.scala @@ -1,51 +1,55 @@ // Copyright (c) 2019 PSForever package net.psforever.packet.game +import net.psforever.packet.GamePacketOpcode.Type import net.psforever.packet.{GamePacketOpcode, Marshallable, PacketHelpers, PlanetSideGamePacket} import net.psforever.types.PlanetSideGUID -import scodec.Codec +import scodec.bits.BitVector +import scodec.{Attempt, Codec} import scodec.codecs._ import shapeless.{::, HNil} /** - * na - * @param unk1 na - * @param unk2 if no global unique identifier (below), the alternate identification for the entity - * @param unk2a the global unique identifier of the entity inflicting the damage - * @param unk2b if no global unique identifier (above), the name of the entity inflicting the damage - * @param unk2c if no global unique identifier (above), the object type of the entity inflicting the damage - * @param unk3 if no global unique identifier (below), the alternate identification for the entity - * @param unk3a the global unique identifier of the entity absorbing the damage - * @param unk3b if no global unique identifier (above), the name of the entity absorbing the damage - * @param unk3c if no global unique identifier (above), the object type of the entity absorbing the damage - * @param unk3d na - * @param unk4 an indicator for the target-specific vital statistic being affected - * @param unk5 the amount of damage - * @param unk6 na - */ + * na + * @param unk1 na + * @param unk2 a modifier that customizes one of the values for the `unk2...` determination values; + * when not using the GUID field, `true` when using the string field + * @param unk2a the global unique identifier of the entity inflicting the damage + * @param unk2b if no global unique identifier (above), the name of the entity inflicting the damage + * @param unk2c if no global unique identifier (above), the object type of the entity inflicting the damage + * @param unk3 a modifier that customizes one of the values for the `unk3...` determination values; + * when not using the GUID field, `true` when using the string field + * @param unk3a the global unique identifier of the entity absorbing the damage + * @param unk3b if no global unique identifier (above), the name of the entity absorbing the damage + * @param unk3c if no global unique identifier (above), the object type of the entity absorbing the damage + * @param unk3d na + * @param unk4 an indicator for the target-specific vital statistic being affected + * @param unk5 the amount of damage + * @param unk6 na + */ final case class DamageFeedbackMessage( - unk1: Int, - unk2: Boolean, - unk2a: Option[PlanetSideGUID], - unk2b: Option[String], - unk2c: Option[Int], - unk3: Boolean, - unk3a: Option[PlanetSideGUID], - unk3b: Option[String], - unk3c: Option[Int], - unk3d: Option[Int], - unk4: Int, - unk5: Long, - unk6: Int -) extends PlanetSideGamePacket { + unk1: Int, + unk2: Option[Boolean], + unk2a: Option[PlanetSideGUID], + unk2b: Option[String], + unk2c: Option[Int], + unk3: Option[Boolean], + unk3a: Option[PlanetSideGUID], + unk3b: Option[String], + unk3c: Option[Int], + unk3d: Option[Int], + unk4: Int, + unk5: Long, + unk6: Int + ) extends PlanetSideGamePacket { assert( { val unk2aEmpty = unk2a.isEmpty val unk2bEmpty = unk2b.isEmpty val unk2cEmpty = unk2c.isEmpty - if (unk2a.nonEmpty) unk2bEmpty && unk2cEmpty - else if (unk2b.nonEmpty) unk2 && unk2aEmpty && unk2cEmpty - else unk2aEmpty && !unk2 && unk2bEmpty && unk2c.nonEmpty + if (!unk2aEmpty) unk2bEmpty && unk2cEmpty + else if (!unk2bEmpty) unk2aEmpty && unk2cEmpty + else unk2aEmpty && unk2bEmpty && !unk2cEmpty } ) assert( @@ -53,58 +57,104 @@ final case class DamageFeedbackMessage( val unk3aEmpty = unk3a.isEmpty val unk3bEmpty = unk3b.isEmpty val unk3cEmpty = unk3c.isEmpty - if (unk3a.nonEmpty) unk3bEmpty && unk3cEmpty - else if (unk3b.nonEmpty) unk3 && unk3aEmpty && unk3cEmpty - else unk3aEmpty && !unk3 && unk3bEmpty && unk3c.nonEmpty + if (!unk3aEmpty) unk3bEmpty && unk3cEmpty + else if (!unk3bEmpty) unk3aEmpty && unk3cEmpty + else unk3aEmpty && unk3bEmpty && !unk3cEmpty } ) assert(unk3a.isEmpty == unk3d.nonEmpty) type Packet = DamageFeedbackMessage - def opcode = GamePacketOpcode.DamageFeedbackMessage - def encode = DamageFeedbackMessage.encode(this) + def opcode: Type = GamePacketOpcode.DamageFeedbackMessage + def encode: Attempt[BitVector] = DamageFeedbackMessage.encode(this) } object DamageFeedbackMessage extends Marshallable[DamageFeedbackMessage] { - def apply(unk1: Int, - unk2: PlanetSideGUID, - unk3: PlanetSideGUID, - unk4: Int, - unk5: Long): DamageFeedbackMessage = - DamageFeedbackMessage(unk1, true, Some(unk2), None, None, true, Some(unk3), None, None, None, unk4, unk5, 0) + def apply( + unk1: Int, + unk2a: Option[PlanetSideGUID], + unk2b: Option[String], + unk2c: Option[Int], + unk3a: Option[PlanetSideGUID], + unk3b: Option[String], + unk3c: Option[Int], + unk3d: Option[Int], + unk4: Int, + unk5: Long + ): DamageFeedbackMessage = { + DamageFeedbackMessage(unk1, None, unk2a, unk2b, unk2c, None, unk3a, unk3b, unk3c, unk3d, unk4, unk5, 0) + } + + def apply( + unk1: Int, + unk2: PlanetSideGUID, + unk3: PlanetSideGUID, + unk4: Int, + unk5: Long + ): DamageFeedbackMessage = { + DamageFeedbackMessage(unk1, None, Some(unk2), None, None, None, Some(unk3), None, None, None, unk4, unk5, 0) + } + + private case class EntryFields( + usesGuid: Boolean, + usesStr: Boolean, + guidOpt: Option[PlanetSideGUID], + strOpt: Option[String], + intOpt: Option[Int] + ) + + /** + * na + * @param adjustment na; + * can not be a negative number + * @return na + */ + private def entityFieldFormatCodec(adjustment: Int): Codec[EntryFields] = { + ((bool :: bool) >>:~ { case usesGuid :: usesString :: HNil => + conditional(usesGuid, PlanetSideGUID.codec) :: + conditional(!usesGuid && usesString, PacketHelpers.encodedWideStringAligned(adjustment)) :: + conditional(!usesGuid && !usesString, uintL(bits = 11)) + }).xmap[EntryFields]( + { + case (a :: b :: HNil) :: c :: d :: e :: HNil => EntryFields(a, b, c, d, e) + }, + { + case EntryFields(a, b, c, d, e) => (a :: b :: HNil) :: c :: d :: e :: HNil + } + ) + } implicit val codec: Codec[DamageFeedbackMessage] = ( - ("unk1" | uint4) :: - (bool >>:~ { u2 => - bool >>:~ { u3 => - ("unk2a" | conditional(u2, PlanetSideGUID.codec)) :: - (("unk2b" | conditional(!u2 && u3, PacketHelpers.encodedWideStringAligned(6))) >>:~ { u2b => - ("unk2c" | conditional(!u2 && !u3, uintL(11))) :: - (bool >>:~ { u5 => - bool >>:~ { u6 => - ("unk3a" | conditional(u5, PlanetSideGUID.codec)) :: - ("unk3b" | conditional( - !u5 && u6, - PacketHelpers.encodedWideStringAligned(if (u2b.nonEmpty) 3 else 1) - )) :: - ("unk3c" | conditional(!u5 && !u6, uintL(11))) :: - ("unk3d" | conditional(!u5, uint2)) :: - ("unk4" | uint(3)) :: - ("unk5" | uint32L) :: - ("unk6" | uint2) - } - }) - }) + ("unk1" | uint4) :: { + entityFieldFormatCodec(adjustment = 4) >>:~ { fieldsA => + val offset = if (fieldsA.usesGuid) { 0 } else if (fieldsA.usesStr) { 6 } else { 5 } + entityFieldFormatCodec(offset) >>:~ { fieldsB => + ("unk3d" | conditional(!fieldsB.usesGuid, uint2)) :: + ("unk4" | uint(bits = 3)) :: + ("unk5" | uint32L) :: + ("unk6" | uint2) + } } - }) - ).xmap[DamageFeedbackMessage]( + }).xmap[DamageFeedbackMessage]( { - case u1 :: _ :: u2 :: u2a :: u2b :: u2c :: _ :: u3 :: u3a :: u3b :: u3c :: u3d :: u4 :: u5 :: u6 :: HNil => - DamageFeedbackMessage(u1, u2, u2a, u2b, u2c, u3, u3a, u3b, u3c, u3d, u4, u5, u6) + case u1 :: EntryFields(_, u2, u2a, u2b, u2c) :: EntryFields(_, u3, u3a, u3b, u3c) :: u3d :: u4 :: u5 :: u6 :: HNil => + val u2False = if (u2a.nonEmpty && !u2) { Some(false) } else { None } + val u3False = if (u3a.nonEmpty && !u3) { Some(false) } else { None } + DamageFeedbackMessage(u1, u2False, u2a, u2b, u2c, u3False, u3a, u3b, u3c, u3d, u4, u5, u6) }, { case DamageFeedbackMessage(u1, u2, u2a, u2b, u2c, u3, u3a, u3b, u3c, u3d, u4, u5, u6) => - u1 :: u2a.nonEmpty :: u2 :: u2a :: u2b :: u2c :: u3a.nonEmpty :: u3 :: u3a :: u3b :: u3c :: u3d :: u4 :: u5 :: u6 :: HNil + val(u2Boola, u2Boolb) = if (u2a.nonEmpty) { + (true, u2.getOrElse(true)) + } else { + (false, u2b.nonEmpty) + } + val(u3Boola, u3Boolb) = if (u3a.nonEmpty) { + (true, u3.getOrElse(true)) + } else { + (false, u3b.nonEmpty) + } + u1 :: EntryFields(u2Boola, u2Boolb, u2a, u2b, u2c) :: EntryFields(u3Boola, u3Boolb, u3a, u3b, u3c) :: u3d :: u4 :: u5 :: u6 :: HNil } ) } diff --git a/src/test/scala/game/DamageFeedbackMessageTest.scala b/src/test/scala/game/DamageFeedbackMessageTest.scala index c8eb4dae4..584ce608f 100644 --- a/src/test/scala/game/DamageFeedbackMessageTest.scala +++ b/src/test/scala/game/DamageFeedbackMessageTest.scala @@ -13,13 +13,11 @@ class DamageFeedbackMessageTest extends Specification { "decode (string 1)" in { PacketCoding.decodePacket(string).require match { - case DamageFeedbackMessage(unk1, unk2, unk2a, unk2b, unk2c, unk3, unk3a, unk3b, unk3c, unk3d, unk4, unk5, unk6) => + case DamageFeedbackMessage(unk1, _, unk2a, unk2b, unk2c, _, unk3a, unk3b, unk3c, unk3d, unk4, unk5, unk6) => unk1 mustEqual 3 - unk2 mustEqual true unk2a.contains(PlanetSideGUID(2913)) mustEqual true unk2b.isEmpty mustEqual true unk2c.isEmpty mustEqual true - unk3 mustEqual true unk3a.contains(PlanetSideGUID(2913)) mustEqual true unk3b.isEmpty mustEqual true unk3c.isEmpty mustEqual true @@ -34,13 +32,11 @@ class DamageFeedbackMessageTest extends Specification { "decode (string 2)" in { PacketCoding.decodePacket(string_2).require match { - case DamageFeedbackMessage(unk1, unk2, unk2a, unk2b, unk2c, unk3, unk3a, unk3b, unk3c, unk3d, unk4, unk5, unk6) => + case DamageFeedbackMessage(unk1, _, unk2a, unk2b, unk2c, _, unk3a, unk3b, unk3c, unk3d, unk4, unk5, unk6) => unk1 mustEqual 5 - unk2 mustEqual true unk2a.contains(PlanetSideGUID(2454)) mustEqual true unk2b.isEmpty mustEqual true unk2c.isEmpty mustEqual true - unk3 mustEqual false unk3a.contains(PlanetSideGUID(216)) mustEqual true unk3b.isEmpty mustEqual true unk3c.isEmpty mustEqual true @@ -56,18 +52,15 @@ class DamageFeedbackMessageTest extends Specification { "encode (string 1)" in { val msg = DamageFeedbackMessage( 3, - true, Some(PlanetSideGUID(2913)), None, None, - true, Some(PlanetSideGUID(2913)), None, None, None, 1, - 2, - 0 + 2 ) val pkt = PacketCoding.encodePacket(msg).require.toByteVector @@ -77,11 +70,11 @@ class DamageFeedbackMessageTest extends Specification { "encode (string 2)" in { val msg = DamageFeedbackMessage( 5, - true, + None, Some(PlanetSideGUID(2454)), None, None, - false, + Some(false), Some(PlanetSideGUID(216)), None, None, @@ -99,252 +92,129 @@ class DamageFeedbackMessageTest extends Specification { //unk2: no parameters DamageFeedbackMessage( 3, - true, None, None, None, - true, Some(PlanetSideGUID(2913)), None, None, None, 1, - 2, - 0 + 2 ) must throwA[AssertionError] //unk2: two exclusive parameters DamageFeedbackMessage( 3, - true, Some(PlanetSideGUID(2913)), Some("error"), None, - true, Some(PlanetSideGUID(2913)), None, None, None, 1, - 2, - 0 + 2 ) must throwA[AssertionError] DamageFeedbackMessage( 3, - true, Some(PlanetSideGUID(2913)), None, Some(5), - true, Some(PlanetSideGUID(2913)), None, None, None, 1, - 2, - 0 + 2 ) must throwA[AssertionError] DamageFeedbackMessage( 3, - true, None, Some("error"), Some(5), - true, Some(PlanetSideGUID(2913)), None, None, None, 1, - 2, - 0 + 2 ) must throwA[AssertionError] //unk2: all parameters DamageFeedbackMessage( 3, - true, Some(PlanetSideGUID(2913)), Some("error"), Some(5), - true, Some(PlanetSideGUID(2913)), None, None, None, 1, - 2, - 0 - ) must throwA[AssertionError] - //unk2: mismatched flag for strings - DamageFeedbackMessage( - 3, - true, - None, - None, - Some(5), - true, - Some(PlanetSideGUID(2913)), - None, - None, - None, - 1, - 2, - 0 - ) must throwA[AssertionError] - DamageFeedbackMessage( - 3, - false, - None, - Some("error"), - None, - true, - Some(PlanetSideGUID(2913)), - None, - None, - None, - 1, - 2, - 0 + 2 ) must throwA[AssertionError] //unk3: no parameters DamageFeedbackMessage( 3, - true, Some(PlanetSideGUID(2913)), None, None, - true, None, None, None, None, 1, - 2, - 0 + 2 ) must throwA[AssertionError] //unk3: two exclusive parameters DamageFeedbackMessage( 3, - true, Some(PlanetSideGUID(2913)), None, None, - true, Some(PlanetSideGUID(2913)), Some("error"), None, None, 1, - 2, - 0 + 2 ) must throwA[AssertionError] DamageFeedbackMessage( 3, - true, Some(PlanetSideGUID(2913)), None, None, - true, Some(PlanetSideGUID(2913)), None, Some(5), None, 1, - 2, - 0 + 2 ) must throwA[AssertionError] DamageFeedbackMessage( 3, - true, Some(PlanetSideGUID(2913)), None, None, - true, None, Some("error"), Some(5), Some(1), 1, - 2, - 0 + 2 ) must throwA[AssertionError] //unk3: all parameters DamageFeedbackMessage( 3, - true, Some(PlanetSideGUID(2913)), None, None, - true, Some(PlanetSideGUID(2913)), Some("error"), Some(5), None, 1, - 2, - 0 - ) must throwA[AssertionError] - //unk3: mismatched fields - DamageFeedbackMessage( - 3, - true, - Some(PlanetSideGUID(2913)), - None, - None, - true, - Some(PlanetSideGUID(2913)), - None, - None, - Some(5), - 1, - 2, - 0 - ) must throwA[AssertionError] - DamageFeedbackMessage( - 3, - true, - Some(PlanetSideGUID(2913)), - None, - None, - true, - None, - Some("Error"), - None, - None, - 1, - 2, - 0 - ) must throwA[AssertionError] - //unk3: mismatched flag for strings - DamageFeedbackMessage( - 3, - true, - Some(PlanetSideGUID(2913)), - None, - None, - true, - None, - None, - Some(5), - None, - 1, - 2, - 0 - ) must throwA[AssertionError] - DamageFeedbackMessage( - 3, - true, - Some(PlanetSideGUID(2913)), - None, - None, - false, - None, - Some("error"), - None, - None, - 1, - 2, - 0 + 2 ) must throwA[AssertionError] } }