mirror of
https://github.com/2revoemag/PSF-BotServer.git
synced 2026-07-13 15:34:42 +00:00
Members and Squads now deal with their own inherent availabilities; code to transfer knowledge of character squad association by color; old code
This commit is contained in:
parent
2a93e6a8be
commit
f7098618d7
6 changed files with 160 additions and 189 deletions
|
|
@ -79,14 +79,11 @@ class Member {
|
||||||
Position
|
Position
|
||||||
}
|
}
|
||||||
|
|
||||||
def Close() : Unit = {
|
def isAvailable : Boolean = {
|
||||||
role = ""
|
charId == 0
|
||||||
requirements = Set()
|
}
|
||||||
//about the individual filling the position
|
|
||||||
name = ""
|
def isAvailable(certs : Set[CertificationType.Value]) : Boolean = {
|
||||||
health = 0
|
isAvailable && certs.intersect(requirements) == requirements
|
||||||
armor = 0
|
|
||||||
zoneId = 0
|
|
||||||
position = Vector3.Zero
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ package net.psforever.objects.teamwork
|
||||||
|
|
||||||
import net.psforever.objects.entity.IdentifiableEntity
|
import net.psforever.objects.entity.IdentifiableEntity
|
||||||
import net.psforever.packet.game.PlanetSideGUID
|
import net.psforever.packet.game.PlanetSideGUID
|
||||||
import net.psforever.types.PlanetSideEmpire
|
import net.psforever.types.{CertificationType, PlanetSideEmpire}
|
||||||
|
|
||||||
class Squad(squadId : PlanetSideGUID, alignment : PlanetSideEmpire.Value) extends IdentifiableEntity {
|
class Squad(squadId : PlanetSideGUID, alignment : PlanetSideEmpire.Value) extends IdentifiableEntity {
|
||||||
super.GUID_=(squadId)
|
super.GUID_=(squadId)
|
||||||
|
|
@ -53,6 +53,24 @@ class Squad(squadId : PlanetSideGUID, alignment : PlanetSideEmpire.Value) extend
|
||||||
def Size : Int = membership.count(member => member.CharId != 0)
|
def Size : Int = membership.count(member => member.CharId != 0)
|
||||||
|
|
||||||
def Capacity : Int = availability.count(open => open)
|
def Capacity : Int = availability.count(open => open)
|
||||||
|
|
||||||
|
def isAvailable(role : Int) : Boolean = {
|
||||||
|
availability.lift(role) match {
|
||||||
|
case Some(true) =>
|
||||||
|
membership(role).isAvailable
|
||||||
|
case _ =>
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def isAvailable(role : Int, certs : Set[CertificationType.Value]) : Boolean = {
|
||||||
|
availability.lift(role) match {
|
||||||
|
case Some(true) =>
|
||||||
|
membership(role).isAvailable(certs)
|
||||||
|
case _ =>
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object Squad {
|
object Squad {
|
||||||
|
|
|
||||||
|
|
@ -370,7 +370,7 @@ object SquadAction{
|
||||||
* `28` - Auto-approve Requests for Invitation<br>
|
* `28` - Auto-approve Requests for Invitation<br>
|
||||||
* `29` - UNKNOWN<br>
|
* `29` - UNKNOWN<br>
|
||||||
* `30` - UNKNOWN<br>
|
* `30` - UNKNOWN<br>
|
||||||
* `31` - Location Follows Squad Lead<br>
|
* `31` - Location Follows Squad Leader<br>
|
||||||
* `Int`<br>
|
* `Int`<br>
|
||||||
* `10` - Select this Role for Yourself<br>
|
* `10` - Select this Role for Yourself<br>
|
||||||
* `11` - UNKNOWN<br>
|
* `11` - UNKNOWN<br>
|
||||||
|
|
@ -452,10 +452,9 @@ object SquadDefinitionActionMessage extends Marshallable[SquadDefinitionActionMe
|
||||||
case 39 => noSquadSearchResultsCodec
|
case 39 => noSquadSearchResultsCodec
|
||||||
case 40 => findLfsSoldiersForRoleCodec
|
case 40 => findLfsSoldiersForRoleCodec
|
||||||
case 41 => cancelFindCodec
|
case 41 => cancelFindCodec
|
||||||
case 2 | 6 | 11 |
|
case 2 | 6 | 11 | 12 | 13 |
|
||||||
12 | 13 | 14 |
|
14 | 18 | 29 | 30 | 32 |
|
||||||
18 | 29 | 30 | 32 | 33 |
|
33 | 36 | 37 | 42 | 43 => unknownCodec(code)
|
||||||
36 | 37 | 42 | 43 => unknownCodec(code)
|
|
||||||
case _ => failureCodec(code)
|
case _ => failureCodec(code)
|
||||||
}).asInstanceOf[Codec[SquadAction]]
|
}).asInstanceOf[Codec[SquadAction]]
|
||||||
}
|
}
|
||||||
|
|
@ -477,48 +476,3 @@ object SquadDefinitionActionMessage extends Marshallable[SquadDefinitionActionMe
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
("change" specifically indicates the perspective is from the SL; "update" indicates squad members other than the oen who made the change
|
|
||||||
("[#]" indicates the mode is detected but not properly parsed; the length of the combined fields may follow
|
|
||||||
|
|
||||||
[0] - clicking on a squad listed in the "Find Squad" tab / cancel squad search (6 bits/pad?)
|
|
||||||
[2] - ? (6 bits/pad?)
|
|
||||||
[3] - save squad favorite (6 bits/pad?)
|
|
||||||
[4] - load a squad definition favorite (6 bits/pad?)
|
|
||||||
[6] - ? (6 bits/pad?)
|
|
||||||
7 - ?
|
|
||||||
[8] - list squad (6 bits/pad?)
|
|
||||||
10 - select this role for yourself
|
|
||||||
11 - ?
|
|
||||||
12 - ?
|
|
||||||
13 - ?
|
|
||||||
14 - ?
|
|
||||||
15 - ?
|
|
||||||
[16] - ? (6 bits/pad?)
|
|
||||||
[17] - ? (6 bits/pad?)
|
|
||||||
[18] - ? (6 bits/pad?)
|
|
||||||
19 - change purpose
|
|
||||||
20 - change zone
|
|
||||||
21 - change/close squad member position
|
|
||||||
22 - change/add squad member position
|
|
||||||
23 - change squad member req role
|
|
||||||
24 - change squad member req detailed orders
|
|
||||||
25 - change squad member req weapons
|
|
||||||
[26] - reset all (6 bits/pad?)
|
|
||||||
28 - auto-approve requests for invitation
|
|
||||||
29 -
|
|
||||||
30 -
|
|
||||||
31 - location follows squad lead
|
|
||||||
[32] - ? (6 bits/pad?)
|
|
||||||
33 -
|
|
||||||
34 - search for squads with a particular role
|
|
||||||
36 -
|
|
||||||
37 -
|
|
||||||
38 -
|
|
||||||
[39] - ? (?)
|
|
||||||
40 - find LFS soldiers that meet the requirements for this role
|
|
||||||
[41] - cancel search for LFS soldiers (6 bits)
|
|
||||||
[42] - ? (6 bits/pad?)
|
|
||||||
[43] - ? (6 bits/pad?)
|
|
||||||
*/
|
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,6 @@ object SquadResponse {
|
||||||
|
|
||||||
final case class AssociateWithSquad(squad_guid : PlanetSideGUID) extends Response
|
final case class AssociateWithSquad(squad_guid : PlanetSideGUID) extends Response
|
||||||
final case class SetListSquad(squad_guid : PlanetSideGUID) extends Response
|
final case class SetListSquad(squad_guid : PlanetSideGUID) extends Response
|
||||||
final case class Unknown17(squad : Squad, char_id : Long) extends Response
|
|
||||||
|
|
||||||
final case class Membership(request_type : SquadResponseType.Value, unk1 : Int, unk2 : Int, unk3 : Long, unk4 : Option[Long], player_name : String, unk5 : Boolean, unk6 : Option[Option[String]]) extends Response //see SquadMembershipResponse
|
final case class Membership(request_type : SquadResponseType.Value, unk1 : Int, unk2 : Int, unk3 : Long, unk4 : Option[Long], player_name : String, unk5 : Boolean, unk6 : Option[Option[String]]) extends Response //see SquadMembershipResponse
|
||||||
final case class Invite(from_char_id : Long, to_char_id : Long, name : String) extends Response
|
final case class Invite(from_char_id : Long, to_char_id : Long, name : String) extends Response
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,7 @@ class SquadService extends Actor {
|
||||||
*/
|
*/
|
||||||
private val queuedInvites : mutable.LongMap[List[Invitation]] = mutable.LongMap[List[Invitation]]()
|
private val queuedInvites : mutable.LongMap[List[Invitation]] = mutable.LongMap[List[Invitation]]()
|
||||||
/**
|
/**
|
||||||
* The gien player has refused participation into this other player's sqaud.<br>
|
* The given player has refused participation into this other player's squad.<br>
|
||||||
* key - a unique character identifier number; value - a list of unique character identifier numbers
|
* key - a unique character identifier number; value - a list of unique character identifier numbers
|
||||||
*/
|
*/
|
||||||
private val refused : mutable.LongMap[List[Long]] = mutable.LongMap[List[Long]]()
|
private val refused : mutable.LongMap[List[Long]] = mutable.LongMap[List[Long]]()
|
||||||
|
|
@ -65,9 +65,10 @@ class SquadService extends Actor {
|
||||||
*/
|
*/
|
||||||
private val continueToMonitorDetails : mutable.LongMap[PlanetSideGUID] = mutable.LongMap[PlanetSideGUID]()
|
private val continueToMonitorDetails : mutable.LongMap[PlanetSideGUID] = mutable.LongMap[PlanetSideGUID]()
|
||||||
/**
|
/**
|
||||||
* A placeholder for an absent active invite that has not (yet) been accepted or rejected, equal to the then-current active invite.
|
* A placeholder for an absent active invite that has not (yet) been accepted or rejected,
|
||||||
|
* equal to the then-current active invite.
|
||||||
* Created when removing an active invite.
|
* Created when removing an active invite.
|
||||||
* Checked when trying to add a new invite (if found, the invite is queued).
|
* Checked when trying to add a new invite (if found, the new invite is queued).
|
||||||
* Cleared when the next queued invite becomes active.<br>
|
* Cleared when the next queued invite becomes active.<br>
|
||||||
* key - unique character identifier number; value, unique character identifier number
|
* key - unique character identifier number; value, unique character identifier number
|
||||||
*/
|
*/
|
||||||
|
|
@ -91,10 +92,10 @@ class SquadService extends Actor {
|
||||||
*/
|
*/
|
||||||
private val SquadEvents = new GenericEventBus[SquadServiceResponse]
|
private val SquadEvents = new GenericEventBus[SquadServiceResponse]
|
||||||
/**
|
/**
|
||||||
* This collection contains the message-sending contact reference for individuals who may become squad members.
|
* This collection contains the message-sending contact reference for individuals.
|
||||||
* When the user joins the `SquadService` with a `Service.Join` message
|
* When the user joins the `SquadService` with a `Service.Join` message
|
||||||
* that includes their unique character identifier,
|
* that includes their unique character identifier,
|
||||||
* the origin `ActorRef` is added as a subscription.
|
* and the origin `ActorRef` is added as a subscription.
|
||||||
* It is maintained until they disconnect entirely.
|
* It is maintained until they disconnect entirely.
|
||||||
* The subscription is anticipated to belong to an instance of `WorldSessionActor`.<br>
|
* The subscription is anticipated to belong to an instance of `WorldSessionActor`.<br>
|
||||||
* key - unique character identifier number; value - `ActorRef` reference for that character
|
* key - unique character identifier number; value - `ActorRef` reference for that character
|
||||||
|
|
@ -688,7 +689,7 @@ class SquadService extends Actor {
|
||||||
if(squad.Size < squad.Capacity) {
|
if(squad.Size < squad.Capacity) {
|
||||||
val positions = (for {
|
val positions = (for {
|
||||||
(member, index) <- squad.Membership.zipWithIndex
|
(member, index) <- squad.Membership.zipWithIndex
|
||||||
if ValidOpenSquadPosition(squad, index, member, tplayer.Certifications)
|
if squad.isAvailable(index, tplayer.Certifications)
|
||||||
} yield (index, member.Requirements.size))
|
} yield (index, member.Requirements.size))
|
||||||
.toList
|
.toList
|
||||||
.sortBy({ case (_, reqs) => reqs })
|
.sortBy({ case (_, reqs) => reqs })
|
||||||
|
|
@ -814,7 +815,7 @@ class SquadService extends Actor {
|
||||||
}
|
}
|
||||||
(None, None)
|
(None, None)
|
||||||
|
|
||||||
case Some(RequestRole(candidate, guid, _))
|
case Some(RequestRole(_, guid, _))
|
||||||
if squadFeatures.get(guid).nonEmpty && squadFeatures(guid).Squad.Leader.CharId == rejectingPlayer =>
|
if squadFeatures.get(guid).nonEmpty && squadFeatures(guid).Squad.Leader.CharId == rejectingPlayer =>
|
||||||
//rejectingPlayer is the squad leader; candidate is the would-be squad member who was rejected
|
//rejectingPlayer is the squad leader; candidate is the would-be squad member who was rejected
|
||||||
val features = squadFeatures(guid)
|
val features = squadFeatures(guid)
|
||||||
|
|
@ -1024,7 +1025,6 @@ class SquadService extends Actor {
|
||||||
if(memberPosition.CharId > 0) {
|
if(memberPosition.CharId > 0) {
|
||||||
LeaveSquad(memberPosition.CharId, squad)
|
LeaveSquad(memberPosition.CharId, squad)
|
||||||
}
|
}
|
||||||
memberPosition.Close()
|
|
||||||
UpdateSquadListWhenListed(squadFeatures(squad.GUID), SquadInfo().Capacity(squad.Capacity))
|
UpdateSquadListWhenListed(squadFeatures(squad.GUID), SquadInfo().Capacity(squad.Capacity))
|
||||||
UpdateSquadDetail(
|
UpdateSquadDetail(
|
||||||
squad.GUID,
|
squad.GUID,
|
||||||
|
|
@ -1232,11 +1232,11 @@ class SquadService extends Actor {
|
||||||
position.Requirements = Set()
|
position.Requirements = Set()
|
||||||
})
|
})
|
||||||
val features = squadFeatures(squad.GUID)
|
val features = squadFeatures(squad.GUID)
|
||||||
features.LocationFollowsSquadLead = false
|
features.LocationFollowsSquadLead = true
|
||||||
features.AutoApproveInvitationRequests = false
|
features.AutoApproveInvitationRequests = true
|
||||||
UpdateSquadListWhenListed(features, SquadInfo().Task("").ZoneId(None).Capacity(squad.Capacity))
|
UpdateSquadListWhenListed(features, SquadInfo().Task("").ZoneId(None).Capacity(squad.Capacity))
|
||||||
UpdateSquadDetail(squad)
|
UpdateSquadDetail(squad)
|
||||||
Publish(sender, SquadResponse.AssociateWithSquad(PlanetSideGUID(0)))
|
InitialAssociation(squad)
|
||||||
squadFeatures(guid).InitialAssociation = true
|
squadFeatures(guid).InitialAssociation = true
|
||||||
//do not unlist an already listed squad
|
//do not unlist an already listed squad
|
||||||
case Some(squad) =>
|
case Some(squad) =>
|
||||||
|
|
@ -1248,13 +1248,13 @@ class SquadService extends Actor {
|
||||||
case _ =>
|
case _ =>
|
||||||
(pSquadOpt, action) match {
|
(pSquadOpt, action) match {
|
||||||
//the following action can be performed by the squad leader and maybe an unaffiliated player
|
//the following action can be performed by the squad leader and maybe an unaffiliated player
|
||||||
case (Some(squad), SelectRoleForYourself(position)) =>
|
case (Some(_), SelectRoleForYourself(_)) =>
|
||||||
//TODO should be possible, but doesn't work correctly due to UI squad cards not updating as expected
|
//TODO should be possible, but doesn't work correctly due to UI squad cards not updating as expected
|
||||||
// if(squad.Leader.CharId == tplayer.CharId) {
|
// if(squad.Leader.CharId == tplayer.CharId) {
|
||||||
// //squad leader currently disallowed
|
// //squad leader currently disallowed
|
||||||
// } else
|
// } else
|
||||||
// //the squad leader may swap to any open position; a normal member has to validate against requirements
|
// //the squad leader may swap to any open position; a normal member has to validate against requirements
|
||||||
// if(squad.Leader.CharId == tplayer.CharId || ValidOpenSquadPosition(squad, position, tplayer.Certifications)) {
|
// if(squad.Leader.CharId == tplayer.CharId || squad.isAvailable(position, tplayer.Certifications)) {
|
||||||
// squad.Membership.zipWithIndex.find { case (member, _) => member.CharId == tplayer.CharId } match {
|
// squad.Membership.zipWithIndex.find { case (member, _) => member.CharId == tplayer.CharId } match {
|
||||||
// case Some((fromMember, fromIndex)) =>
|
// case Some((fromMember, fromIndex)) =>
|
||||||
// SwapMemberPosition(squad.Membership(position), fromMember)
|
// SwapMemberPosition(squad.Membership(position), fromMember)
|
||||||
|
|
@ -1273,7 +1273,7 @@ class SquadService extends Actor {
|
||||||
//not a member of any squad, but we might become a member of this one
|
//not a member of any squad, but we might become a member of this one
|
||||||
GetSquad(guid) match {
|
GetSquad(guid) match {
|
||||||
case Some(squad) =>
|
case Some(squad) =>
|
||||||
if(ValidOpenSquadPosition(squad, position, tplayer.Certifications)) {
|
if(squad.isAvailable(position, tplayer.Certifications)) {
|
||||||
//we could join but we may need permission from the squad leader first
|
//we could join but we may need permission from the squad leader first
|
||||||
AddInviteAndRespond(
|
AddInviteAndRespond(
|
||||||
squad.Leader.CharId,
|
squad.Leader.CharId,
|
||||||
|
|
@ -1940,7 +1940,7 @@ class SquadService extends Actor {
|
||||||
* @param list a list of players to squads with expected entry redundancy
|
* @param list a list of players to squads with expected entry redundancy
|
||||||
*/
|
*/
|
||||||
def RemoveProximityInvites(list : Iterable[(Long, PlanetSideGUID)]) : Unit = {
|
def RemoveProximityInvites(list : Iterable[(Long, PlanetSideGUID)]) : Unit = {
|
||||||
val (ids, squads) = list.unzip
|
val (_, squads) = list.unzip
|
||||||
squads.toSeq.distinct.foreach { squad =>
|
squads.toSeq.distinct.foreach { squad =>
|
||||||
squadFeatures.get(squad) match {
|
squadFeatures.get(squad) match {
|
||||||
case Some(features) =>
|
case Some(features) =>
|
||||||
|
|
@ -2039,7 +2039,6 @@ class SquadService extends Actor {
|
||||||
* @see `IndirectInvite`
|
* @see `IndirectInvite`
|
||||||
* @see `SquadFeatures::AutoApproveInvitationRequests`
|
* @see `SquadFeatures::AutoApproveInvitationRequests`
|
||||||
* @see `VacancyInvite`
|
* @see `VacancyInvite`
|
||||||
* @see `ValidOpenSquadPosition`
|
|
||||||
* @param squad the squad
|
* @param squad the squad
|
||||||
* @param invitedPlayer the unique character identifier for the player being invited
|
* @param invitedPlayer the unique character identifier for the player being invited
|
||||||
* @param invitingPlayer the unique character identifier for the player who invited the former
|
* @param invitingPlayer the unique character identifier for the player who invited the former
|
||||||
|
|
@ -2049,8 +2048,8 @@ class SquadService extends Actor {
|
||||||
*/
|
*/
|
||||||
def HandleVacancyInvite(squad : Squad, invitedPlayer : Long, invitingPlayer : Long, recruit : Player) : Option[(Squad, Int)] = {
|
def HandleVacancyInvite(squad : Squad, invitedPlayer : Long, invitingPlayer : Long, recruit : Player) : Option[(Squad, Int)] = {
|
||||||
//accepted an invitation to join an existing squad
|
//accepted an invitation to join an existing squad
|
||||||
squad.Membership.zipWithIndex.find({ case (member, index) =>
|
squad.Membership.zipWithIndex.find({ case (_, index) =>
|
||||||
ValidOpenSquadPosition(squad, index, member, recruit.Certifications)
|
squad.isAvailable(index, recruit.Certifications)
|
||||||
}) match {
|
}) match {
|
||||||
case Some((_, line)) =>
|
case Some((_, line)) =>
|
||||||
//position in squad found
|
//position in squad found
|
||||||
|
|
@ -2206,7 +2205,6 @@ class SquadService extends Actor {
|
||||||
* @see `SquadResponse.Join`
|
* @see `SquadResponse.Join`
|
||||||
* @see `StatConverter.Health`
|
* @see `StatConverter.Health`
|
||||||
* @see `UpdateSquadListWhenListed`
|
* @see `UpdateSquadListWhenListed`
|
||||||
* @see `ValidOpenSquadPosition`
|
|
||||||
* @param player the new squad member;
|
* @param player the new squad member;
|
||||||
* this player is NOT the squad leader
|
* this player is NOT the squad leader
|
||||||
* @param squad the squad the player is joining
|
* @param squad the squad the player is joining
|
||||||
|
|
@ -2217,7 +2215,7 @@ class SquadService extends Actor {
|
||||||
def JoinSquad(player : Player, squad : Squad, position : Int) : Boolean = {
|
def JoinSquad(player : Player, squad : Squad, position : Int) : Boolean = {
|
||||||
val charId = player.CharId
|
val charId = player.CharId
|
||||||
val role = squad.Membership(position)
|
val role = squad.Membership(position)
|
||||||
if(UserEvents.get(charId).nonEmpty && squad.Leader.CharId != charId && ValidOpenSquadPosition(squad, position, role, player.Certifications)) {
|
if(UserEvents.get(charId).nonEmpty && squad.Leader.CharId != charId && squad.isAvailable(position, player.Certifications)) {
|
||||||
role.Name = player.Name
|
role.Name = player.Name
|
||||||
role.CharId = charId
|
role.CharId = charId
|
||||||
role.Health = StatConverter.Health(player.Health, player.MaxHealth, min=1, max=64)
|
role.Health = StatConverter.Health(player.Health, player.MaxHealth, min=1, max=64)
|
||||||
|
|
@ -2616,19 +2614,6 @@ class SquadService extends Actor {
|
||||||
SquadEvents.unsubscribe(sender) //just to make certain
|
SquadEvents.unsubscribe(sender) //just to make certain
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Dispatch a message entailing the composition of this squad
|
|
||||||
* and focus on any specific aspects of it, purported as being changed recently.
|
|
||||||
* @see `SquadInfo`
|
|
||||||
* @see `UpdateSquadList(Squad, Option[SquadInfo])`
|
|
||||||
* @param squad the squad
|
|
||||||
* @param changes the highlighted aspects of the squad;
|
|
||||||
* these "changes" do not have to reflect the actual squad but are related to the contents of the message
|
|
||||||
*/
|
|
||||||
private def UpdateSquadList(squad : Squad, changes : SquadInfo) : Unit = {
|
|
||||||
UpdateSquadList(squad, Some(changes))
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dispatch a message entailing the composition of this squad when that squad is publicly available
|
* Dispatch a message entailing the composition of this squad when that squad is publicly available
|
||||||
* and focus on any specific aspects of it, purported as being changed recently.
|
* and focus on any specific aspects of it, purported as being changed recently.
|
||||||
|
|
@ -2989,63 +2974,4 @@ object SquadService {
|
||||||
member.Requirements = position.requirements
|
member.Requirements = position.requirements
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Determine if the indicated squad role can be used for a player trying to join the squad.
|
|
||||||
* @see `ValidOpenSquadPosition`
|
|
||||||
* @param squad the squad
|
|
||||||
* @param position the position of the squad role being tested
|
|
||||||
* @param certs the certifications being offered for comparison testing
|
|
||||||
* @return `true`, if the squad role may accept the player with the given certification permissions;
|
|
||||||
* `false`, otherwise
|
|
||||||
*/
|
|
||||||
def ValidOpenSquadPosition(squad : Squad, position : Int, certs : Set[CertificationType.Value]) : Boolean = {
|
|
||||||
squad.Membership.lift(position) match {
|
|
||||||
case Some(member) =>
|
|
||||||
ValidOpenSquadPosition(squad, position, member, certs)
|
|
||||||
case None =>
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Determine if the indicated squad role can be used for a player trying to join the squad.
|
|
||||||
* @see `AvailableSquadPosition`
|
|
||||||
* @param squad the squad
|
|
||||||
* @param position the position of the squad role being tested
|
|
||||||
* @param member the squad role being tested
|
|
||||||
* @param certs the certifications being offered for comparison testing
|
|
||||||
* @return `true`, if the squad role may accept the player with the given certification permissions;
|
|
||||||
* `false`, otherwise
|
|
||||||
*/
|
|
||||||
def ValidOpenSquadPosition(squad : Squad, position : Int, member : Member, certs : Set[CertificationType.Value]) : Boolean = {
|
|
||||||
AvailableSquadPosition(squad, position, member) && certs.intersect(member.Requirements) == member.Requirements
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Determine if the indicated squad role is unoccupied but is also capable of being occupied.
|
|
||||||
* @see `AvailableSquadPosition(Squad, Int, Member)`
|
|
||||||
* @param squad the squad
|
|
||||||
* @param position the position of the squad role being tested
|
|
||||||
* @return `true`, if the squad role is unoccupied;
|
|
||||||
* `false`, otherwise
|
|
||||||
*/
|
|
||||||
def AvailableSquadPosition(squad : Squad, position : Int) : Boolean = squad.Membership.lift(position) match {
|
|
||||||
case Some(member) =>
|
|
||||||
AvailableSquadPosition(squad, position, member)
|
|
||||||
case None =>
|
|
||||||
false
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Determine if the indicated squad role is unoccupied but is also capable of being occupied.
|
|
||||||
* @param squad the squad
|
|
||||||
* @param position the position of the squad role being tested
|
|
||||||
* @param member the squad role being tested
|
|
||||||
* @return `true`, if the squad role is unoccupied;
|
|
||||||
* `false`, otherwise
|
|
||||||
*/
|
|
||||||
def AvailableSquadPosition(squad : Squad, position : Int, member : Member) : Boolean = {
|
|
||||||
squad.Availability(position) && member.CharId == 0
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -119,7 +119,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
*/
|
*/
|
||||||
var interstellarFerryTopLevelGUID : Option[PlanetSideGUID] = None
|
var interstellarFerryTopLevelGUID : Option[PlanetSideGUID] = None
|
||||||
val squadUI : LongMap[SquadUIElement] = new LongMap[SquadUIElement]()
|
val squadUI : LongMap[SquadUIElement] = new LongMap[SquadUIElement]()
|
||||||
val squad_supplement_id : Int = 11
|
var squad_supplement_id : Int = 0
|
||||||
/**
|
/**
|
||||||
* `AvatarConverter` can only rely on the `Avatar`-local Looking For Squad variable.
|
* `AvatarConverter` can only rely on the `Avatar`-local Looking For Squad variable.
|
||||||
* When joining or creating a squad, the original state of the avatar's local LFS variable is blanked.
|
* When joining or creating a squad, the original state of the avatar's local LFS variable is blanked.
|
||||||
|
|
@ -396,11 +396,6 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
case SquadResponse.SetListSquad(squad_guid) =>
|
case SquadResponse.SetListSquad(squad_guid) =>
|
||||||
sendResponse(SquadDefinitionActionMessage(squad_guid, 0, SquadAction.SetListSquad()))
|
sendResponse(SquadDefinitionActionMessage(squad_guid, 0, SquadAction.SetListSquad()))
|
||||||
|
|
||||||
case SquadResponse.Unknown17(squad, char_id) =>
|
|
||||||
sendResponse(
|
|
||||||
SquadDefinitionActionMessage(squad.GUID, 0, SquadAction.Unknown(33))
|
|
||||||
)
|
|
||||||
|
|
||||||
case SquadResponse.Membership(request_type, unk1, unk2, char_id, opt_char_id, player_name, unk5, unk6) =>
|
case SquadResponse.Membership(request_type, unk1, unk2, char_id, opt_char_id, player_name, unk5, unk6) =>
|
||||||
val name = request_type match {
|
val name = request_type match {
|
||||||
case SquadResponseType.Invite if unk5 =>
|
case SquadResponseType.Invite if unk5 =>
|
||||||
|
|
@ -433,27 +428,31 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
val membershipPositions = squad.Membership
|
val membershipPositions = squad.Membership
|
||||||
.zipWithIndex
|
.zipWithIndex
|
||||||
.filter { case (_, index ) => positionsToUpdate.contains(index) }
|
.filter { case (_, index ) => positionsToUpdate.contains(index) }
|
||||||
|
StartBundlingPackets()
|
||||||
membershipPositions.find({ case(member, _) => member.CharId == avatar.CharId }) match {
|
membershipPositions.find({ case(member, _) => member.CharId == avatar.CharId }) match {
|
||||||
case Some((ourMember, ourIndex)) =>
|
case Some((ourMember, ourIndex)) =>
|
||||||
//we are joining the squad
|
//we are joining the squad
|
||||||
//load each member's entry (our own too)
|
//load each member's entry (our own too)
|
||||||
|
squad_supplement_id = squad.GUID.guid + 1
|
||||||
membershipPositions.foreach { case(member, index) =>
|
membershipPositions.foreach { case(member, index) =>
|
||||||
sendResponse(SquadMemberEvent.Add(squad_supplement_id, member.CharId, index, member.Name, member.ZoneId, unk7 = 0))
|
sendResponse(SquadMemberEvent.Add(squad_supplement_id, member.CharId, index, member.Name, member.ZoneId, unk7 = 0))
|
||||||
squadUI(member.CharId) = SquadUIElement(member.Name, index, member.ZoneId, member.Health, member.Armor, member.Position)
|
squadUI(member.CharId) = SquadUIElement(member.Name, index, member.ZoneId, member.Health, member.Armor, member.Position)
|
||||||
}
|
}
|
||||||
//repeat our entry
|
//repeat our entry
|
||||||
sendResponse(SquadMemberEvent.Add(squad_supplement_id, ourMember.CharId, ourIndex, ourMember.Name, ourMember.ZoneId, unk7 = 0)) //repeat of our entry
|
sendResponse(SquadMemberEvent.Add(squad_supplement_id, ourMember.CharId, ourIndex, ourMember.Name, ourMember.ZoneId, unk7 = 0)) //repeat of our entry
|
||||||
|
val playerGuid = player.GUID
|
||||||
//turn lfs off
|
//turn lfs off
|
||||||
val factionOnContinentChannel = s"${continent.Id}/${player.Faction}"
|
val factionOnContinentChannel = s"${continent.Id}/${player.Faction}"
|
||||||
if(avatar.LFS) {
|
if(avatar.LFS) {
|
||||||
avatar.LFS = false
|
avatar.LFS = false
|
||||||
sendResponse(PlanetsideAttributeMessage(player.GUID, 53, 0))
|
sendResponse(PlanetsideAttributeMessage(playerGuid, 53, 0))
|
||||||
avatarService ! AvatarServiceMessage(factionOnContinentChannel, AvatarAction.PlanetsideAttribute(player.GUID, 53, 0))
|
avatarService ! AvatarServiceMessage(factionOnContinentChannel, AvatarAction.PlanetsideAttribute(playerGuid, 53, 0))
|
||||||
}
|
}
|
||||||
//squad colors
|
//squad colors
|
||||||
sendResponse(PlanetsideAttributeMessage(player.GUID, 31, squad_supplement_id))
|
GiveSquadColorsInZone()
|
||||||
avatarService ! AvatarServiceMessage(factionOnContinentChannel, AvatarAction.PlanetsideAttribute(player.GUID, 31, squad_supplement_id))
|
avatarService ! AvatarServiceMessage(factionOnContinentChannel, AvatarAction.PlanetsideAttribute(playerGuid, 31, squad_supplement_id))
|
||||||
sendResponse(PlanetsideAttributeMessage(player.GUID, 32, ourIndex)) //associate with member position in squad
|
//associate with member position in squad
|
||||||
|
sendResponse(PlanetsideAttributeMessage(playerGuid, 32, ourIndex))
|
||||||
//a finalization? what does this do?
|
//a finalization? what does this do?
|
||||||
sendResponse(SquadDefinitionActionMessage(squad.GUID, 0, SquadAction.Unknown(18)))
|
sendResponse(SquadDefinitionActionMessage(squad.GUID, 0, SquadAction.Unknown(18)))
|
||||||
updateSquad = UpdatesWhenEnrolledInSquad
|
updateSquad = UpdatesWhenEnrolledInSquad
|
||||||
|
|
@ -461,11 +460,16 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
case _ =>
|
case _ =>
|
||||||
//other player is joining our squad
|
//other player is joining our squad
|
||||||
//load each member's entry
|
//load each member's entry
|
||||||
membershipPositions.foreach { case(member, index) =>
|
GiveSquadColorsInZone(
|
||||||
sendResponse(SquadMemberEvent.Add(squad_supplement_id, member.CharId, index, member.Name, member.ZoneId, unk7 = 0))
|
membershipPositions.map { case(member, index) =>
|
||||||
squadUI(member.CharId) = SquadUIElement(member.Name, index, member.ZoneId, member.Health, member.Armor, member.Position)
|
val charId = member.CharId
|
||||||
}
|
sendResponse(SquadMemberEvent.Add(squad_supplement_id, charId, index, member.Name, member.ZoneId, unk7 = 0))
|
||||||
|
squadUI(charId) = SquadUIElement(member.Name, index, member.ZoneId, member.Health, member.Armor, member.Position)
|
||||||
|
charId
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
StopBundlingPackets()
|
||||||
//send an initial dummy update for map icon(s)
|
//send an initial dummy update for map icon(s)
|
||||||
sendResponse(SquadState(PlanetSideGUID(squad_supplement_id),
|
sendResponse(SquadState(PlanetSideGUID(squad_supplement_id),
|
||||||
membershipPositions
|
membershipPositions
|
||||||
|
|
@ -475,6 +479,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
))
|
))
|
||||||
|
|
||||||
case SquadResponse.Leave(squad, positionsToUpdate) =>
|
case SquadResponse.Leave(squad, positionsToUpdate) =>
|
||||||
|
StartBundlingPackets()
|
||||||
positionsToUpdate.find({ case(member, _) => member == avatar.CharId }) match {
|
positionsToUpdate.find({ case(member, _) => member == avatar.CharId }) match {
|
||||||
case Some((ourMember, ourIndex)) =>
|
case Some((ourMember, ourIndex)) =>
|
||||||
//we are leaving the squad
|
//we are leaving the squad
|
||||||
|
|
@ -484,10 +489,12 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
squadUI.remove(member)
|
squadUI.remove(member)
|
||||||
}
|
}
|
||||||
//uninitialize
|
//uninitialize
|
||||||
|
val playerGuid = player.GUID
|
||||||
sendResponse(SquadMemberEvent.Remove(squad_supplement_id, ourMember, ourIndex)) //repeat of our entry
|
sendResponse(SquadMemberEvent.Remove(squad_supplement_id, ourMember, ourIndex)) //repeat of our entry
|
||||||
sendResponse(PlanetsideAttributeMessage(player.GUID, 31, 0)) //disassociate with squad?
|
sendResponse(PlanetsideAttributeMessage(playerGuid, 31, 0)) //disassociate with squad?
|
||||||
sendResponse(PlanetsideAttributeMessage(player.GUID, 32, 0)) //disassociate with member position in squad?
|
avatarService ! AvatarServiceMessage(s"${continent.Id}/${player.Faction}", AvatarAction.PlanetsideAttribute(playerGuid, 31, 0))
|
||||||
sendResponse(PlanetsideAttributeMessage(player.GUID, 34, 4294967295L)) //unknown, perhaps unrelated?
|
sendResponse(PlanetsideAttributeMessage(playerGuid, 32, 0)) //disassociate with member position in squad?
|
||||||
|
sendResponse(PlanetsideAttributeMessage(playerGuid, 34, 4294967295L)) //unknown, perhaps unrelated?
|
||||||
lfs = false
|
lfs = false
|
||||||
//a finalization? what does this do?
|
//a finalization? what does this do?
|
||||||
sendResponse(SquadDefinitionActionMessage(PlanetSideGUID(0), 0, SquadAction.Unknown(18)))
|
sendResponse(SquadDefinitionActionMessage(PlanetSideGUID(0), 0, SquadAction.Unknown(18)))
|
||||||
|
|
@ -495,11 +502,17 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
squadChannel = None
|
squadChannel = None
|
||||||
case _ =>
|
case _ =>
|
||||||
//remove each member's entry
|
//remove each member's entry
|
||||||
positionsToUpdate.foreach { case(member, index) =>
|
GiveSquadColorsInZone(
|
||||||
sendResponse(SquadMemberEvent.Remove(squad_supplement_id, member, index))
|
positionsToUpdate.map { case(member, index) =>
|
||||||
squadUI.remove(member)
|
sendResponse(SquadMemberEvent.Remove(squad_supplement_id, member, index))
|
||||||
}
|
squadUI.remove(member)
|
||||||
|
member
|
||||||
|
},
|
||||||
|
value = 0
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
StopBundlingPackets()
|
||||||
|
squad_supplement_id = 0
|
||||||
|
|
||||||
case SquadResponse.AssignMember(squad, from_index, to_index) =>
|
case SquadResponse.AssignMember(squad, from_index, to_index) =>
|
||||||
//we've already swapped position internally; now we swap the cards
|
//we've already swapped position internally; now we swap the cards
|
||||||
|
|
@ -3045,10 +3058,6 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
deadState = DeadState.Alive
|
deadState = DeadState.Alive
|
||||||
sendResponse(AvatarDeadStateMessage(DeadState.Alive, 0, 0, tplayer.Position, player.Faction, true))
|
sendResponse(AvatarDeadStateMessage(DeadState.Alive, 0, 0, tplayer.Position, player.Faction, true))
|
||||||
//looking for squad (members)
|
//looking for squad (members)
|
||||||
if(squadUI.nonEmpty && squadUI(avatar.CharId).index == 0) {
|
|
||||||
sendResponse(PlanetsideAttributeMessage(guid, 31, 1))
|
|
||||||
avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.PlanetsideAttribute(guid, 31, 1))
|
|
||||||
}
|
|
||||||
if(tplayer.LFS || lfs) {
|
if(tplayer.LFS || lfs) {
|
||||||
sendResponse(PlanetsideAttributeMessage(guid, 53, 1))
|
sendResponse(PlanetsideAttributeMessage(guid, 53, 1))
|
||||||
avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.PlanetsideAttribute(guid, 53, 1))
|
avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.PlanetsideAttribute(guid, 53, 1))
|
||||||
|
|
@ -3103,30 +3112,97 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* These messages are dispatched when first starting up the client and connecting to the server for the first time.
|
||||||
|
* While many of thee messages will be reused for other situations, they appear in this order only during startup.
|
||||||
|
*/
|
||||||
def FirstTimeSquadSetup() : Unit = {
|
def FirstTimeSquadSetup() : Unit = {
|
||||||
sendResponse(SquadDetailDefinitionUpdateMessage.Init)
|
sendResponse(SquadDetailDefinitionUpdateMessage.Init)
|
||||||
|
sendResponse(ReplicationStreamMessage(5, Some(6), Vector.empty)) //clear squad list
|
||||||
sendResponse(SquadDefinitionActionMessage(PlanetSideGUID(0), 0, SquadAction.Unknown(6)))
|
sendResponse(SquadDefinitionActionMessage(PlanetSideGUID(0), 0, SquadAction.Unknown(6)))
|
||||||
//only need to load these once
|
//only need to load these once - they persist between zone transfers and respawns
|
||||||
avatar.SquadLoadouts.Loadouts.foreach {
|
avatar.SquadLoadouts.Loadouts.foreach {
|
||||||
case (index, loadout : SquadLoadout) =>
|
case (index, loadout : SquadLoadout) =>
|
||||||
sendResponse(SquadDefinitionActionMessage(PlanetSideGUID(0), index, SquadAction.ListSquadFavorite(loadout.task)))
|
sendResponse(SquadDefinitionActionMessage(PlanetSideGUID(0), index, SquadAction.ListSquadFavorite(loadout.task)))
|
||||||
}
|
}
|
||||||
|
//non-squad GUID-0 counts as the settings when not joined with a squad
|
||||||
sendResponse(SquadDefinitionActionMessage(PlanetSideGUID(0), 0, SquadAction.AssociateWithSquad()))
|
sendResponse(SquadDefinitionActionMessage(PlanetSideGUID(0), 0, SquadAction.AssociateWithSquad()))
|
||||||
sendResponse(SquadDefinitionActionMessage(PlanetSideGUID(0), 0, SquadAction.SetListSquad()))
|
sendResponse(SquadDefinitionActionMessage(PlanetSideGUID(0), 0, SquadAction.SetListSquad()))
|
||||||
sendResponse(SquadDefinitionActionMessage(PlanetSideGUID(0), 0, SquadAction.Unknown(18)))
|
sendResponse(SquadDefinitionActionMessage(PlanetSideGUID(0), 0, SquadAction.Unknown(18)))
|
||||||
squadService ! SquadServiceMessage(player, continent, SquadServiceAction.InitSquadList())
|
squadService ! SquadServiceMessage(player, continent, SquadServiceAction.InitSquadList())
|
||||||
squadService ! SquadServiceMessage(player, continent, SquadServiceAction.InitCharId())
|
squadService ! SquadServiceMessage(player, continent, SquadServiceAction.InitCharId())
|
||||||
squadSetup = SubsequentSpawnSquadSetup
|
squadSetup = RespawnSquadSetup
|
||||||
}
|
}
|
||||||
|
|
||||||
def SubsequentSpawnSquadSetup() : Unit = {
|
/**
|
||||||
|
* These messages are used during each subsequent respawn to reset the squad colors on player nameplates and marquees.
|
||||||
|
* By using `squadUI` to maintain relevant information about squad members,
|
||||||
|
* especially the unique character identifier number,
|
||||||
|
* only the zone-specific squad members will receive the important messages about their squad member's spawn.
|
||||||
|
*/
|
||||||
|
def RespawnSquadSetup() : Unit = {
|
||||||
if(squadUI.nonEmpty) {
|
if(squadUI.nonEmpty) {
|
||||||
//sendResponse(PlanetsideAttributeMessage(player.GUID, 31, squad_supplement_id))
|
sendResponse(PlanetsideAttributeMessage(player.GUID, 31, squad_supplement_id))
|
||||||
val (_, ourCard) = squadUI.find { case (id, card) => id == player.CharId }.get
|
avatarService ! AvatarServiceMessage(s"${continent.Id}/${player.Faction}", AvatarAction.PlanetsideAttribute(player.GUID, 31, squad_supplement_id))
|
||||||
sendResponse(PlanetsideAttributeMessage(player.GUID, 32, ourCard.index))
|
sendResponse(PlanetsideAttributeMessage(player.GUID, 32, squadUI(player.CharId).index))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* These messages are used during each subsequent respawn to reset the squad colors on player nameplates and marquees.
|
||||||
|
* During a zone change,
|
||||||
|
* on top of other squad mates in the zone needing to have their knowledge of this player's squad colors changed,
|
||||||
|
* the player must also set squad colors for each other squad members.
|
||||||
|
* Default respawn functionality may resume afterwards.
|
||||||
|
*/
|
||||||
|
def ZoneChangeSquadSetup() : Unit = {
|
||||||
|
RespawnSquadSetup()
|
||||||
|
GiveSquadColorsInZone()
|
||||||
|
squadSetup = RespawnSquadSetup
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocate all squad members in zone and give their nameplates and their marquees the appropriate squad color.
|
||||||
|
*/
|
||||||
|
def GiveSquadColorsInZone() : Unit = {
|
||||||
|
GiveSquadColorsInZone(squadUI.keys, squad_supplement_id)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocate the listed squad members in zone and give their nameplates and their marquees the appropriate squad color.
|
||||||
|
* @param members members of the squad to target
|
||||||
|
*/
|
||||||
|
def GiveSquadColorsInZone(members : Iterable[Long]) : Unit = {
|
||||||
|
GiveSquadColorsInZone(members, squad_supplement_id)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocate the listed squad members in zone and give their nameplates and their marquees the appropriate squad color.
|
||||||
|
* @see `PlanetsideAttributeMessage`
|
||||||
|
* @param members members of the squad to target
|
||||||
|
* @param value the assignment value
|
||||||
|
*/
|
||||||
|
def GiveSquadColorsInZone(members : Iterable[Long], value : Long) : Unit = {
|
||||||
|
SquadMembersInZone(members).foreach {
|
||||||
|
members => sendResponse(PlanetsideAttributeMessage(members.GUID, 31, value))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For the listed squad member unique character identifier numbers,
|
||||||
|
* find and return all squad members in the current zone.
|
||||||
|
* @param members members of the squad to target
|
||||||
|
* @return a list of `Player` objects
|
||||||
|
*/
|
||||||
|
def SquadMembersInZone(members : Iterable[Long]) : Iterable[Player] = {
|
||||||
|
val players = continent.LivePlayers
|
||||||
|
for {
|
||||||
|
charId <- members
|
||||||
|
player = players.find { _.CharId == charId }
|
||||||
|
if player.nonEmpty
|
||||||
|
} yield player.get
|
||||||
|
}
|
||||||
|
|
||||||
def handleControlPkt(pkt : PlanetSideControlPacket) = {
|
def handleControlPkt(pkt : PlanetSideControlPacket) = {
|
||||||
pkt match {
|
pkt match {
|
||||||
case sync @ ControlSync(diff, _, _, _, _, _, fa, fb) =>
|
case sync @ ControlSync(diff, _, _, _, _, _, fa, fb) =>
|
||||||
|
|
@ -4729,24 +4805,24 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
if(squadUI.nonEmpty) {
|
if(squadUI.nonEmpty) {
|
||||||
if(!lfs && squadUI(player.CharId).index == 0) {
|
if(!lfs && squadUI(player.CharId).index == 0) {
|
||||||
lfs = true
|
lfs = true
|
||||||
avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.PlanetsideAttribute(player.GUID, 53, 1))
|
avatarService ! AvatarServiceMessage(s"${continent.Id}/${player.Faction}", AvatarAction.PlanetsideAttribute(player.GUID, 53, 1))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(!avatar.LFS) {
|
else if(!avatar.LFS) {
|
||||||
avatar.LFS = true
|
avatar.LFS = true
|
||||||
avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.PlanetsideAttribute(player.GUID, 53, 1))
|
avatarService ! AvatarServiceMessage(s"${continent.Id}/${player.Faction}", AvatarAction.PlanetsideAttribute(player.GUID, 53, 1))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(action == 37) { //Looking For Squad OFF
|
else if(action == 37) { //Looking For Squad OFF
|
||||||
if(squadUI.nonEmpty) {
|
if(squadUI.nonEmpty) {
|
||||||
if(lfs && squadUI(player.CharId).index == 0) {
|
if(lfs && squadUI(player.CharId).index == 0) {
|
||||||
lfs = false
|
lfs = false
|
||||||
avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.PlanetsideAttribute(player.GUID, 53, 0))
|
avatarService ! AvatarServiceMessage(s"${continent.Id}/${player.Faction}", AvatarAction.PlanetsideAttribute(player.GUID, 53, 0))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(avatar.LFS) {
|
else if(avatar.LFS) {
|
||||||
avatar.LFS = false
|
avatar.LFS = false
|
||||||
avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.PlanetsideAttribute(player.GUID, 53, 0))
|
avatarService ! AvatarServiceMessage(s"${continent.Id}/${player.Faction}", AvatarAction.PlanetsideAttribute(player.GUID, 53, 0))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -8739,6 +8815,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
})
|
})
|
||||||
DisownDeployables()
|
DisownDeployables()
|
||||||
drawDeloyableIcon = RedrawDeployableIcons //important for when SetCurrentAvatar initializes the UI next zone
|
drawDeloyableIcon = RedrawDeployableIcons //important for when SetCurrentAvatar initializes the UI next zone
|
||||||
|
squadSetup = ZoneChangeSquadSetup
|
||||||
continent.Population ! Zone.Population.Leave(avatar)
|
continent.Population ! Zone.Population.Leave(avatar)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue