mirror of
https://github.com/psforever/PSF-LoginServer.git
synced 2026-01-20 02:54:46 +00:00
exp for ntu and ntu silo operation restored; message about progress system given more limited scope; adjusted cep for llu carrier kill; kd accumulates by kills and maintains between lives; ifflock does not discriminate rehack faction; no rewards for killing allies, or self
This commit is contained in:
parent
52deb2b212
commit
7f61206ddd
|
|
@ -362,7 +362,7 @@ game {
|
|||
# If a player died while carrying an lattice logic unit,
|
||||
# award the player who is accredited with the kill command experience as long as the time it had been carried longer than this duration.
|
||||
# Can set to Duration.Inf to never pass.
|
||||
llu-slayer-credit-duration = 1 minute
|
||||
llu-slayer-credit-duration = 30 seconds
|
||||
# If a player died while carrying an lattice logic unit,
|
||||
# and satisfies the carrying duration,
|
||||
# award the player who is accredited with the kill command experience.
|
||||
|
|
@ -389,6 +389,11 @@ game {
|
|||
# Anyone who is currently enrolled in the promotion system remains enrolled during normal game play.
|
||||
# Relenting on the promotion debt back to battle rank 2 is still possible.
|
||||
active = true
|
||||
# This battle rank and any battle ranks of ordinal decrement that allow opt-in to the progression system.
|
||||
broadcast-battle-rank = 1
|
||||
# This is the minimum battle rank that can be set as part of the promotion system.
|
||||
# Used to escape debt and return to normal play.
|
||||
reset-battle-rank = 2
|
||||
# This is the maximum battle rank that can be set as part of the promotion system.
|
||||
max-battle-rank = 13
|
||||
# How much direct combat contributes to paying back promotion debt.
|
||||
|
|
|
|||
|
|
@ -1063,6 +1063,9 @@ class AvatarActor(
|
|||
case DeleteAvatar(id) =>
|
||||
import ctx._
|
||||
val performDeletion = for {
|
||||
_ <- ctx.run(query[persistence.Weaponstatsession].filter(_.avatarId == lift(id)).delete)
|
||||
_ <- ctx.run(query[persistence.Kdasession].filter(_.avatarId == lift(id)).delete)
|
||||
_ <- ctx.run(query[persistence.Buildingcapture].filter(_.avatarId == lift(id)).delete)
|
||||
_ <- ctx.run(query[persistence.Shortcut].filter(_.avatarId == lift(id)).delete)
|
||||
_ <- ctx.run(query[persistence.Implant].filter(_.avatarId == lift(id)).delete)
|
||||
_ <- ctx.run(query[persistence.Loadout].filter(_.avatarId == lift(id)).delete)
|
||||
|
|
@ -1646,11 +1649,16 @@ class AvatarActor(
|
|||
if ({
|
||||
val oldBr = BattleRank.withExperience(avatar.bep).value
|
||||
val newBr = BattleRank.withExperience(bep).value
|
||||
if (Config.app.game.promotion.active && oldBr == 1 && newBr > 1 && newBr < Config.app.game.promotion.maxBattleRank + 1) {
|
||||
val resetBr = Config.app.game.promotion.resetBattleRank
|
||||
if (
|
||||
Config.app.game.promotion.active &&
|
||||
oldBr <= Config.app.game.promotion.broadcastBattleRank &&
|
||||
newBr > resetBr && newBr < Config.app.game.promotion.maxBattleRank + 1
|
||||
) {
|
||||
experienceDebt = bep
|
||||
AvatarActor.saveExperienceDebt(avatar.id, bep, bep)
|
||||
true
|
||||
} else if (experienceDebt > 0 && newBr == 2) {
|
||||
} else if (experienceDebt > 0 && newBr == resetBr) {
|
||||
experienceDebt = 0
|
||||
AvatarActor.saveExperienceDebt(avatar.id, exp = 0, bep)
|
||||
true
|
||||
|
|
@ -1663,7 +1671,6 @@ class AvatarActor(
|
|||
setCep(0L)
|
||||
}
|
||||
restoreBasicCerts()
|
||||
removeAllImplants()
|
||||
sessionActor ! SessionActor.CharSaved
|
||||
sessionActor ! SessionActor.SendResponse(ChatMsg(ChatMessageType.UNK_229, "@AckSuccessSetBattleRank"))
|
||||
} else if (experienceDebt > 0) {
|
||||
|
|
@ -1674,9 +1681,9 @@ class AvatarActor(
|
|||
Behaviors.same
|
||||
|
||||
case AwardCep(cep) =>
|
||||
if (experienceDebt > 0L) {
|
||||
if (experienceDebt == 0L) {
|
||||
setCep(avatar.cep + cep)
|
||||
} else {
|
||||
} else if (cep > 0) {
|
||||
sessionActor ! SessionActor.SendResponse(ExperienceAddedMessage(0))
|
||||
}
|
||||
Behaviors.same
|
||||
|
|
@ -1851,16 +1858,77 @@ class AvatarActor(
|
|||
}
|
||||
|
||||
def performAvatarLogin(avatarId: Long, accountId: Long, replyTo: ActorRef[AvatarLoginResponse]): Unit = {
|
||||
performAvatarLogin0(avatarId, accountId, replyTo)
|
||||
// import ctx._
|
||||
// val result = for {
|
||||
// //log this login
|
||||
// _ <- ctx.run(
|
||||
// query[persistence.Avatar]
|
||||
// .filter(_.id == lift(avatarId))
|
||||
// .update(_.lastLogin -> lift(LocalDateTime.now()))
|
||||
// )
|
||||
// //log this choice of faction (no empire switching)
|
||||
// _ <- ctx.run(
|
||||
// query[persistence.Account]
|
||||
// .filter(_.id == lift(accountId))
|
||||
// .update(
|
||||
// _.lastFactionId -> lift(avatar.faction.id),
|
||||
// _.avatarLoggedIn -> lift(avatarId)
|
||||
// )
|
||||
// )
|
||||
// //retrieve avatar data
|
||||
// loadouts <- initializeAllLoadouts()
|
||||
// implants <- ctx.run(query[persistence.Implant].filter(_.avatarId == lift(avatarId)))
|
||||
// certs <- ctx.run(query[persistence.Certification].filter(_.avatarId == lift(avatarId)))
|
||||
// locker <- loadLocker(avatarId)
|
||||
// friends <- loadFriendList(avatarId)
|
||||
// ignored <- loadIgnoredList(avatarId)
|
||||
// shortcuts <- loadShortcuts(avatarId)
|
||||
// saved <- AvatarActor.loadSavedAvatarData(avatarId)
|
||||
// debt <- AvatarActor.loadExperienceDebt(avatarId)
|
||||
// card <- AvatarActor.loadCampaignKdaData(avatarId)
|
||||
// } yield (loadouts, implants, certs, locker, friends, ignored, shortcuts, saved, debt, card)
|
||||
// result.onComplete {
|
||||
// case Success((_loadouts, implants, certs, lockerInv, friendsList, ignoredList, shortcutList, saved, debt, card)) =>
|
||||
// avatarCopy(
|
||||
// avatar.copy(
|
||||
// loadouts = avatar.loadouts.copy(suit = _loadouts),
|
||||
// certifications =
|
||||
// certs.map(cert => Certification.withValue(cert.id)).toSet ++ Config.app.game.baseCertifications,
|
||||
// implants = implants.map(implant => Some(Implant(implant.toImplantDefinition))).padTo(3, None),
|
||||
// shortcuts = shortcutList,
|
||||
// locker = lockerInv,
|
||||
// people = MemberLists(
|
||||
// friend = friendsList,
|
||||
// ignored = ignoredList
|
||||
// ),
|
||||
// cooldowns = Cooldowns(
|
||||
// purchase = AvatarActor.buildCooldownsFromClob(saved.purchaseCooldowns, Avatar.purchaseCooldowns, log),
|
||||
// use = AvatarActor.buildCooldownsFromClob(saved.useCooldowns, Avatar.useCooldowns, log)
|
||||
// ),
|
||||
// scorecard = card
|
||||
// )
|
||||
// )
|
||||
// // if we need to start stamina regeneration
|
||||
// tryRestoreStaminaForSession(stamina = 1).collect { _ => defaultStaminaRegen(initialDelay = 0.5f seconds) }
|
||||
// experienceDebt = debt
|
||||
// replyTo ! AvatarLoginResponse(avatar)
|
||||
// case Failure(e) =>
|
||||
// log.error(e)("db failure")
|
||||
// }
|
||||
}
|
||||
|
||||
def performAvatarLogin0(avatarId: Long, accountId: Long, replyTo: ActorRef[AvatarLoginResponse]): Unit = {
|
||||
import ctx._
|
||||
val result = for {
|
||||
//log this login
|
||||
_ <- ctx.run(
|
||||
loginTime <- ctx.run(
|
||||
query[persistence.Avatar]
|
||||
.filter(_.id == lift(avatarId))
|
||||
.update(_.lastLogin -> lift(LocalDateTime.now()))
|
||||
)
|
||||
//log this choice of faction (no empire switching)
|
||||
_ <- ctx.run(
|
||||
loginFaction <- ctx.run(
|
||||
query[persistence.Account]
|
||||
.filter(_.id == lift(accountId))
|
||||
.update(
|
||||
|
|
@ -1868,50 +1936,64 @@ class AvatarActor(
|
|||
_.avatarLoggedIn -> lift(avatarId)
|
||||
)
|
||||
)
|
||||
//retrieve avatar data
|
||||
loadouts <- initializeAllLoadouts()
|
||||
} yield (loginTime, loginFaction)
|
||||
result.onComplete {
|
||||
case Success(_) =>
|
||||
sessionActor ! SessionActor.AvatarLoadingSync(step = 0)
|
||||
performAvatarLogin1(avatarId, replyTo)
|
||||
case Failure(e) =>
|
||||
log.error(e)("db failure")
|
||||
}
|
||||
}
|
||||
|
||||
def performAvatarLogin1(avatarId: Long, replyTo: ActorRef[AvatarLoginResponse]): Unit = {
|
||||
import ctx._
|
||||
val result = for {
|
||||
//retrieve avatar data for OCDM packet
|
||||
implants <- ctx.run(query[persistence.Implant].filter(_.avatarId == lift(avatarId)))
|
||||
certs <- ctx.run(query[persistence.Certification].filter(_.avatarId == lift(avatarId)))
|
||||
debt <- AvatarActor.loadExperienceDebt(avatarId)
|
||||
locker <- loadLocker(avatarId)
|
||||
} yield (certs, implants, locker, debt)
|
||||
result.onComplete {
|
||||
case Success((certs, implants, lockerInv, debt)) =>
|
||||
avatarCopy(
|
||||
avatar.copy(
|
||||
certifications =
|
||||
certs.map(cert => Certification.withValue(cert.id)).toSet ++ Config.app.game.baseCertifications,
|
||||
implants = implants.map(implant => Some(Implant(implant.toImplantDefinition))).padTo(3, None),
|
||||
locker = lockerInv
|
||||
)
|
||||
)
|
||||
experienceDebt = debt
|
||||
// if we need to start stamina regeneration
|
||||
tryRestoreStaminaForSession(stamina = 1).collect { _ => defaultStaminaRegen(initialDelay = 0.5f seconds) }
|
||||
sessionActor ! SessionActor.AvatarLoadingSync(step = 1)
|
||||
replyTo ! AvatarLoginResponse(avatar)
|
||||
performAvatarLogin2(avatarId, replyTo)
|
||||
case Failure(e) =>
|
||||
log.error(e)("db failure")
|
||||
}
|
||||
}
|
||||
|
||||
//noinspection ScalaUnusedSymbol
|
||||
def performAvatarLogin2(avatarId: Long, replyTo: ActorRef[AvatarLoginResponse]): Unit = {
|
||||
val result = for {
|
||||
//retrieve avatar data for other packets
|
||||
loadouts <- initializeAllLoadouts()
|
||||
friends <- loadFriendList(avatarId)
|
||||
ignored <- loadIgnoredList(avatarId)
|
||||
shortcuts <- loadShortcuts(avatarId)
|
||||
saved <- AvatarActor.loadSavedAvatarData(avatarId)
|
||||
debt <- AvatarActor.loadExperienceDebt(avatarId)
|
||||
card <- AvatarActor.loadCampaignKdaData(avatarId)
|
||||
} yield (loadouts, implants, certs, locker, friends, ignored, shortcuts, saved, debt, card)
|
||||
} yield (loadouts, friends, ignored, shortcuts, saved, card)
|
||||
result.onComplete {
|
||||
case Success((_loadouts, implants, certs, lockerInv, friendsList, ignoredList, shortcutList, saved, debt, card)) =>
|
||||
//shortcuts must have a hotbar option for each implant
|
||||
// val implantShortcuts = shortcutList.filter {
|
||||
// case Some(e) => e.purpose == 0
|
||||
// case None => false
|
||||
// }
|
||||
// implants.filterNot { implant =>
|
||||
// implantShortcuts.exists {
|
||||
// case Some(a) => a.tile.equals(implant.name)
|
||||
// case None => false
|
||||
// }
|
||||
// }.foreach { c =>
|
||||
// shortcutList.indexWhere { _.isEmpty } match {
|
||||
// case -1 => ()
|
||||
// case index =>
|
||||
// shortcutList.update(index, Some(AvatarShortcut(2, c.name)))
|
||||
// }
|
||||
// }
|
||||
//
|
||||
case Success((loadoutList, friendsList, ignoredList, shortcutList, saved, card)) =>
|
||||
avatarCopy(
|
||||
avatar.copy(
|
||||
loadouts = avatar.loadouts.copy(suit = _loadouts),
|
||||
certifications =
|
||||
certs.map(cert => Certification.withValue(cert.id)).toSet ++ Config.app.game.baseCertifications,
|
||||
implants = implants.map(implant => Some(Implant(implant.toImplantDefinition))).padTo(3, None),
|
||||
loadouts = avatar.loadouts.copy(suit = loadoutList),
|
||||
shortcuts = shortcutList,
|
||||
locker = lockerInv,
|
||||
people = MemberLists(
|
||||
friend = friendsList,
|
||||
ignored = ignoredList
|
||||
),
|
||||
people = MemberLists(friend = friendsList, ignored = ignoredList),
|
||||
cooldowns = Cooldowns(
|
||||
purchase = AvatarActor.buildCooldownsFromClob(saved.purchaseCooldowns, Avatar.purchaseCooldowns, log),
|
||||
use = AvatarActor.buildCooldownsFromClob(saved.useCooldowns, Avatar.useCooldowns, log)
|
||||
|
|
@ -1919,10 +2001,7 @@ class AvatarActor(
|
|||
scorecard = card
|
||||
)
|
||||
)
|
||||
// if we need to start stamina regeneration
|
||||
tryRestoreStaminaForSession(stamina = 1).collect { _ => defaultStaminaRegen(initialDelay = 0.5f seconds) }
|
||||
experienceDebt = debt
|
||||
replyTo ! AvatarLoginResponse(avatar)
|
||||
sessionActor ! SessionActor.AvatarLoadingSync(step = 2)
|
||||
case Failure(e) =>
|
||||
log.error(e)("db failure")
|
||||
}
|
||||
|
|
@ -3046,7 +3125,6 @@ class AvatarActor(
|
|||
}
|
||||
player.HistoryAndContributions()
|
||||
}
|
||||
zone.actor ! ZoneActor.RewardOurSupporters(playerSource, historyTranscript, killStat, exp)
|
||||
val target = killStat.info.targetAfter.asInstanceOf[PlayerSource]
|
||||
val targetMounted = target.seatedIn.map { case (v: VehicleSource, seat) =>
|
||||
val definition = v.Definition
|
||||
|
|
@ -3077,6 +3155,7 @@ class AvatarActor(
|
|||
}
|
||||
if (exp > 0L) {
|
||||
setBep(avatar.bep + exp, msg)
|
||||
zone.actor ! ZoneActor.RewardOurSupporters(playerSource, historyTranscript, killStat, exp)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1282,7 +1282,10 @@ class ChatActor(
|
|||
false
|
||||
}
|
||||
} else if (contents.startsWith("!progress")) {
|
||||
if (!session.account.gm && BattleRank.withExperience(session.avatar.bep).value < Config.app.game.promotion.maxBattleRank + 1) {
|
||||
val ourRank = BattleRank.withExperience(session.avatar.bep).value
|
||||
if (!session.account.gm &&
|
||||
(ourRank <= Config.app.game.promotion.broadcastBattleRank ||
|
||||
ourRank > Config.app.game.promotion.resetBattleRank && ourRank < Config.app.game.promotion.maxBattleRank + 1)) {
|
||||
setBattleRank(dropFirstWord(contents), session, AvatarActor.Progress)
|
||||
true
|
||||
} else {
|
||||
|
|
@ -1299,7 +1302,7 @@ class ChatActor(
|
|||
|
||||
private def dropFirstWord(str: String): String = {
|
||||
val noExtraSpaces = str.replaceAll("\\s+", " ").toLowerCase.trim
|
||||
noExtraSpaces.indexOf({ char: String => char.equals(" ") }) match {
|
||||
noExtraSpaces.indexOf(" ") match {
|
||||
case -1 => ""
|
||||
case beforeFirstBlank => noExtraSpaces.drop(beforeFirstBlank + 1)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -81,6 +81,8 @@ object SessionActor {
|
|||
|
||||
final case class UpdateIgnoredPlayers(msg: FriendsResponse) extends Command
|
||||
|
||||
final case class AvatarLoadingSync(step: Int) extends Command
|
||||
|
||||
final case object CharSaved extends Command
|
||||
|
||||
private[session] case object CharSavedMsg extends Command
|
||||
|
|
@ -255,6 +257,9 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
|
|||
case SessionActor.SetConnectionState(state) =>
|
||||
sessionFuncs.connectionState = state
|
||||
|
||||
case SessionActor.AvatarLoadingSync(state) =>
|
||||
sessionFuncs.zoning.spawn.handleAvatarLoadingSync(state)
|
||||
|
||||
/* uncommon messages (utility, or once in a while) */
|
||||
case SessionActor.AvatarAwardMessageBundle(pkts, delay) =>
|
||||
sessionFuncs.zoning.spawn.performAvatarAwardMessageDelivery(pkts, delay)
|
||||
|
|
|
|||
|
|
@ -3,8 +3,6 @@ package net.psforever.actors.session.support
|
|||
|
||||
import akka.actor.typed.scaladsl.adapter._
|
||||
import akka.actor.{ActorContext, typed}
|
||||
import net.psforever.objects.avatar.SpecialCarry
|
||||
import net.psforever.objects.serverobject.llu.CaptureFlag
|
||||
import net.psforever.packet.game.objectcreate.ConstructorData
|
||||
import net.psforever.services.Service
|
||||
import net.psforever.objects.zones.exp
|
||||
|
|
@ -496,25 +494,6 @@ class SessionAvatarHandlers(
|
|||
sendResponse(ChatMsg(ChatMessageType.UNK_227, "@SVCP_Killed_OnPadOnCreate"))
|
||||
case _ => ()
|
||||
}
|
||||
adversarial.collect {
|
||||
case attacker
|
||||
if player.Carrying.contains(SpecialCarry.CaptureFlag) &&
|
||||
attacker.Faction != player.Faction &&
|
||||
sessionData
|
||||
.specialItemSlotGuid
|
||||
.flatMap { continent.GUID }
|
||||
.collect {
|
||||
case llu: CaptureFlag =>
|
||||
System.currentTimeMillis() - llu.LastCollectionTime > Config.app.game.experience.cep.lluSlayerCreditDuration.toMillis
|
||||
case _ =>
|
||||
false
|
||||
}
|
||||
.contains(true) =>
|
||||
continent.AvatarEvents ! AvatarServiceMessage(
|
||||
attacker.Name,
|
||||
AvatarAction.AwardCep(attacker.CharId, Config.app.game.experience.cep.lluSlayerCredit)
|
||||
)
|
||||
}
|
||||
adversarial.map {_.Name }.orElse { Some(s"a ${reason.getClass.getSimpleName}") }
|
||||
}.getOrElse { s"an unfortunate circumstance (probably ${player.Sex.pronounObject} own fault)" }
|
||||
log.info(s"${player.Name} has died, killed by $cause")
|
||||
|
|
|
|||
|
|
@ -1579,6 +1579,24 @@ class SessionData(
|
|||
case Some(llu: CaptureFlag) => Some((llu, llu.Carrier))
|
||||
case _ => None
|
||||
}) match {
|
||||
case Some((llu, Some(carrier: Player)))
|
||||
if carrier.GUID == player.GUID && !player.isAlive =>
|
||||
player.LastDamage.foreach { damage =>
|
||||
damage
|
||||
.interaction
|
||||
.adversarial
|
||||
.map { _.attacker }
|
||||
.collect {
|
||||
case attacker
|
||||
if attacker.Faction != player.Faction &&
|
||||
System.currentTimeMillis() - llu.LastCollectionTime >= Config.app.game.experience.cep.lluSlayerCreditDuration.toMillis =>
|
||||
continent.AvatarEvents ! AvatarServiceMessage(
|
||||
attacker.Name,
|
||||
AvatarAction.AwardCep(attacker.CharId, Config.app.game.experience.cep.lluSlayerCredit)
|
||||
)
|
||||
}
|
||||
}
|
||||
continent.LocalEvents ! CaptureFlagManager.DropFlag(llu)
|
||||
case Some((llu, Some(carrier: Player))) if carrier.GUID == player.GUID =>
|
||||
continent.LocalEvents ! CaptureFlagManager.DropFlag(llu)
|
||||
case Some((_, Some(carrier: Player))) =>
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ import net.psforever.objects.inventory.InventoryItem
|
|||
import net.psforever.objects.serverobject.mount.Seat
|
||||
import net.psforever.objects.serverobject.tube.SpawnTube
|
||||
import net.psforever.objects.sourcing.{PlayerSource, SourceEntry, VehicleSource}
|
||||
import net.psforever.objects.vital.{InGameHistory, ReconstructionActivity, SpawningActivity}
|
||||
import net.psforever.objects.vital.{InGameHistory, IncarnationActivity, ReconstructionActivity, SpawningActivity}
|
||||
import net.psforever.packet.game.{CampaignStatistic, MailMessage, SessionStatistic}
|
||||
|
||||
import scala.collection.mutable
|
||||
|
|
@ -79,7 +79,7 @@ object ZoningOperations {
|
|||
"High Command",
|
||||
"Progress versus Promotion",
|
||||
"If you consider yourself as a veteran soldier, despite looking so green, please read this.\n" ++
|
||||
"You only have this opportunity while you are battle rank 1." ++
|
||||
s"You only have this opportunity while you are less than or equal to battle rank ${Config.app.game.promotion.broadcastBattleRank}." ++
|
||||
"\n\n" ++
|
||||
"The normal method of rank advancement comes from the battlefield - fighting enemies, helping allies, and capturing facilities. " ++
|
||||
"\n\n" ++
|
||||
|
|
@ -91,7 +91,7 @@ object ZoningOperations {
|
|||
"In addition, you will be ineligible of having your command experience be recognized during this time." ++
|
||||
"\n\n" ++
|
||||
"If you wish to continue, set your desired battle rank now - use '!progress' followed by a battle rank index. " ++
|
||||
"If you accept, but it becomes too much of burden, you may ask to revert to battle rank 2 at any time. " ++
|
||||
s"If you accept, but it becomes too much of burden, you may ask to revert to battle rank ${Config.app.game.promotion.resetBattleRank} at any time. " ++
|
||||
"Your normal sense of progress will be restored."
|
||||
)
|
||||
)
|
||||
|
|
@ -629,22 +629,7 @@ class ZoningOperations(
|
|||
ServiceManager.serviceManager ! Lookup("propertyOverrideManager")
|
||||
sendResponse(PlanetsideAttributeMessage(PlanetSideGUID(0), 112, 0)) // disable festive backpacks
|
||||
sendResponse(ReplicationStreamMessage(5, Some(6), Vector.empty)) //clear squad list
|
||||
(
|
||||
FriendsResponse.packetSequence(
|
||||
MemberAction.InitializeFriendList,
|
||||
avatar.people.friend
|
||||
.map { f =>
|
||||
game.Friend(f.name, AvatarActor.onlineIfNotIgnoredEitherWay(avatar, f.name))
|
||||
}
|
||||
) ++
|
||||
//ignored list (no one ever online)
|
||||
FriendsResponse.packetSequence(
|
||||
MemberAction.InitializeIgnoreList,
|
||||
avatar.people.ignored.map { f => game.Friend(f.name) }
|
||||
)
|
||||
).foreach {
|
||||
sendResponse
|
||||
}
|
||||
spawn.initializeFriendsAndIgnoredLists()
|
||||
//the following subscriptions last until character switch/logout
|
||||
galaxyService ! Service.Join("galaxy") //for galaxy-wide messages
|
||||
galaxyService ! Service.Join(s"${avatar.faction}") //for hotspots, etc.
|
||||
|
|
@ -2797,16 +2782,7 @@ class ZoningOperations(
|
|||
}
|
||||
|
||||
sendResponse(PlanetsideAttributeMessage(PlanetSideGUID(0), 82, 0))
|
||||
avatar.shortcuts
|
||||
.zipWithIndex
|
||||
.collect { case (Some(shortcut), index) =>
|
||||
sendResponse(CreateShortcutMessage(
|
||||
guid,
|
||||
index + 1,
|
||||
Some(AvatarShortcut.convert(shortcut))
|
||||
))
|
||||
}
|
||||
sendResponse(ChangeShortcutBankMessage(guid, 0))
|
||||
initializeShortcutsAndBank(guid)
|
||||
//Favorites lists
|
||||
avatarActor ! AvatarActor.InitialRefreshLoadouts()
|
||||
|
||||
|
|
@ -2940,20 +2916,28 @@ class ZoningOperations(
|
|||
}
|
||||
.collect { case Some(thing: PlanetSideGameObject with FactionAffinity) => Some(SourceEntry(thing)) }
|
||||
.flatten
|
||||
player.LogActivity({
|
||||
if (player.History.headOption.exists { _.isInstanceOf[SpawningActivity] }) {
|
||||
ReconstructionActivity(PlayerSource(player), continent.Number, effortBy)
|
||||
} else {
|
||||
SpawningActivity(PlayerSource(player), continent.Number, effortBy)
|
||||
}
|
||||
})
|
||||
val lastEntryOpt = player.History.lastOption
|
||||
if (lastEntryOpt.exists { !_.isInstanceOf[IncarnationActivity] }) {
|
||||
player.LogActivity({
|
||||
lastEntryOpt match {
|
||||
case Some(_) =>
|
||||
ReconstructionActivity(PlayerSource(player), continent.Number, effortBy)
|
||||
case None =>
|
||||
SpawningActivity(PlayerSource(player), continent.Number, effortBy)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
upstreamMessageCount = 0
|
||||
setAvatar = true
|
||||
if (
|
||||
BattleRank.withExperience(tplayer.avatar.bep).value == 1 &&
|
||||
Config.app.game.promotion.active &&
|
||||
!account.gm) {
|
||||
!account.gm && /* gm's are excluded */
|
||||
Config.app.game.promotion.active && /* play versus progress system must be active */
|
||||
BattleRank.withExperience(tplayer.avatar.bep).value <= Config.app.game.promotion.broadcastBattleRank && /* must be below a certain battle rank */
|
||||
avatar.scorecard.Lives.isEmpty && /* first life after login */
|
||||
avatar.scorecard.CurrentLife.prior.isEmpty && /* no revives */
|
||||
player.History.size == 1 /* did nothing but come into existence */
|
||||
) {
|
||||
ZoningOperations.reportProgressionSystem(context.self)
|
||||
}
|
||||
}
|
||||
|
|
@ -2968,6 +2952,59 @@ class ZoningOperations(
|
|||
HandleSetCurrentAvatar(tplayer)
|
||||
}
|
||||
|
||||
/**
|
||||
* Respond to feedback of how the avatar's data is being handled
|
||||
* in a way that properly reflects the state of the server at the moment.
|
||||
* @param state indicator for the progress of the avatar
|
||||
*/
|
||||
def handleAvatarLoadingSync(state: Int): Unit = {
|
||||
if (state == 2 && zoneLoaded.contains(true)) {
|
||||
initializeFriendsAndIgnoredLists()
|
||||
initializeShortcutsAndBank(player.GUID)
|
||||
avatarActor ! AvatarActor.RefreshPurchaseTimes()
|
||||
loginAvatarStatisticsFields()
|
||||
avatarActor ! AvatarActor.InitialRefreshLoadouts()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up and dispatch a list of `FriendsResponse` packets related to both formal friends and ignored players.
|
||||
*/
|
||||
def initializeFriendsAndIgnoredLists(): Unit = {
|
||||
(
|
||||
FriendsResponse.packetSequence(
|
||||
MemberAction.InitializeFriendList,
|
||||
avatar.people.friend
|
||||
.map { f =>
|
||||
game.Friend(f.name, AvatarActor.onlineIfNotIgnoredEitherWay(avatar, f.name))
|
||||
}
|
||||
) ++
|
||||
//ignored list (no one ever online)
|
||||
FriendsResponse.packetSequence(
|
||||
MemberAction.InitializeIgnoreList,
|
||||
avatar.people.ignored.map { f => game.Friend(f.name) }
|
||||
)
|
||||
).foreach {
|
||||
sendResponse
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up and dispatch a list of `CreateShortcutMessage` packets and a single `ChangeShortcutBankMessage` packet.
|
||||
*/
|
||||
def initializeShortcutsAndBank(guid: PlanetSideGUID): Unit = {
|
||||
avatar.shortcuts
|
||||
.zipWithIndex
|
||||
.collect { case (Some(shortcut), index) =>
|
||||
sendResponse(CreateShortcutMessage(
|
||||
guid,
|
||||
index + 1,
|
||||
Some(AvatarShortcut.convert(shortcut))
|
||||
))
|
||||
}
|
||||
sendResponse(ChangeShortcutBankMessage(guid, 0))
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw the icon for this deployable object.<br>
|
||||
* <br>
|
||||
|
|
@ -3247,7 +3284,7 @@ class ZoningOperations(
|
|||
|
||||
/**
|
||||
* Accessible method to switch population of the Character Info window's statistics page
|
||||
* from whatever it currently js to after each respawn.
|
||||
* from whatever it currently is to after each respawn.
|
||||
* At the time of "login", only campaign (total, historical) deaths are reported for convenience.
|
||||
* At the time of "respawn", all fields - campaign and session - should be reported if applicable.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -163,6 +163,7 @@ object ScoreCard {
|
|||
case PlanetSideEmpire.VS => fields.copy(vs_s = fields.vs_s + 1)
|
||||
case PlanetSideEmpire.NEUTRAL => fields.copy(ps_s = fields.ps_s + 1)
|
||||
}
|
||||
statisticMap.put(objectId, outEntry)
|
||||
outEntry
|
||||
case _ =>
|
||||
val out = Statistic(0, 0, 0, 0, 0, 0, 0, 0)
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ class IFFLockControl(lock: IFFLock)
|
|||
.orElse {
|
||||
case CommonMessages.Use(player, Some(item: SimpleItem))
|
||||
if item.Definition == GlobalDefinitions.remote_electronics_kit =>
|
||||
if (lock.Faction != player.Faction && lock.HackedBy.isEmpty) {
|
||||
if (lock.Faction != player.Faction) {
|
||||
sender() ! CommonMessages.Progress(
|
||||
GenericHackables.GetHackSpeed(player, lock),
|
||||
GenericHackables.FinishHacking(lock, player, 1114636288L),
|
||||
|
|
@ -42,8 +42,7 @@ class IFFLockControl(lock: IFFLock)
|
|||
} else {
|
||||
val log = org.log4s.getLogger
|
||||
log.warn(s"IFF lock is being hacked by ${player.Faction}, but don't know how to handle this state:")
|
||||
log.warn(s"Lock - Faction=${lock.Faction}, HackedBy=${lock.HackedBy}")
|
||||
log.warn(s"Player - Faction=${player.Faction}")
|
||||
log.warn(s"Lock - Faction=${lock.Faction}, HackedBy=${lock.HackedBy.map{_.player}}")
|
||||
}
|
||||
|
||||
case IFFLock.DoorOpenRequest(target, door, replyTo) =>
|
||||
|
|
|
|||
|
|
@ -192,12 +192,11 @@ class ResourceSiloControl(resourceSilo: ResourceSilo)
|
|||
//experience is reported as normal
|
||||
val deposit: Long =
|
||||
(Config.app.game.experience.sep.ntuSiloDepositReward.toFloat *
|
||||
math.floor(amount).toFloat /
|
||||
math.floor(resourceSilo.MaxNtuCapacitor / resourceSilo.Definition.ChargeTime.toMillis.toFloat)
|
||||
amount / (resourceSilo.MaxNtuCapacitor * resourceSilo.Definition.ChargeTime.toSeconds.toFloat)
|
||||
).toLong
|
||||
vehicle.Zone.AvatarEvents ! AvatarServiceMessage(
|
||||
owner.name,
|
||||
AvatarAction.AwardBep(0, deposit, ExperienceType.Normal)
|
||||
AvatarAction.AwardBep(owner.charId, deposit, ExperienceType.Normal)
|
||||
)
|
||||
zones.exp.ToDatabase.reportNtuActivity(owner.charId, resourceSilo.Zone.Number, resourceSilo.Owner.GUID.guid, deposit)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -133,6 +133,7 @@ trait AntTransferBehavior extends TransferBehavior with NtuStorageBehavior {
|
|||
ActivatePanelsForChargingEvent(ChargeTransferObject)
|
||||
}
|
||||
|
||||
//noinspection ScalaUnusedSymbol
|
||||
def WithdrawAndTransmit(vehicle: Vehicle, maxRequested: Float): Any = {
|
||||
val chargeable = ChargeTransferObject
|
||||
var chargeToDeposit = Math.min(Math.min(chargeable.NtuCapacitor, 100), maxRequested)
|
||||
|
|
@ -188,7 +189,7 @@ trait AntTransferBehavior extends TransferBehavior with NtuStorageBehavior {
|
|||
transferTarget match {
|
||||
case Some(silo: ResourceSilo) =>
|
||||
scala.math.min(
|
||||
scala.math.min(silo.MaxNtuCapacitor / silo.Definition.ChargeTime.toMillis.toFloat, chargeable.NtuCapacitor),
|
||||
scala.math.min(silo.MaxNtuCapacitor / silo.Definition.ChargeTime.toSeconds.toFloat, chargeable.NtuCapacitor),
|
||||
max
|
||||
)
|
||||
case _ =>
|
||||
|
|
|
|||
|
|
@ -50,14 +50,16 @@ trait SupportActivityCausedByAnother {
|
|||
def amount: Int
|
||||
}
|
||||
|
||||
trait IncarnationActivity extends GeneralActivity
|
||||
|
||||
final case class SpawningActivity(src: SourceEntry, zoneNumber: Int, unit: Option[SourceEntry])
|
||||
extends GeneralActivity
|
||||
extends IncarnationActivity
|
||||
|
||||
final case class ReconstructionActivity(src: SourceEntry, zoneNumber: Int, unit: Option[SourceEntry])
|
||||
extends GeneralActivity
|
||||
extends IncarnationActivity
|
||||
|
||||
final case class RevivingActivity(target: SourceEntry, user: PlayerSource, amount: Int, equipment: EquipmentDefinition)
|
||||
extends GeneralActivity with SupportActivityCausedByAnother
|
||||
extends IncarnationActivity with SupportActivityCausedByAnother
|
||||
|
||||
final case class ShieldCharge(amount: Int, cause: Option[SourceEntry])
|
||||
extends GeneralActivity
|
||||
|
|
|
|||
|
|
@ -315,8 +315,10 @@ object KillAssists {
|
|||
history: Iterable[InGameActivity]
|
||||
): Long = {
|
||||
//base value (the kill experience before modifiers)
|
||||
val base = Support.baseExperience(victim, history)
|
||||
if (base > 1) {
|
||||
lazy val base = Support.baseExperience(victim, history)
|
||||
if (killer.Faction == victim.Faction || killer.unique == victim.unique) {
|
||||
0L
|
||||
} else if (base > 1) {
|
||||
//include battle rank disparity modifier
|
||||
val battleRankDisparity = {
|
||||
import net.psforever.objects.avatar.BattleRank
|
||||
|
|
|
|||
|
|
@ -289,9 +289,11 @@ case class CommandExperiencePoints(
|
|||
)
|
||||
|
||||
case class PromotionSystem(
|
||||
active: Boolean,
|
||||
maxBattleRank: Int,
|
||||
battleExperiencePointsModifier: Float,
|
||||
supportExperiencePointsModifier: Float,
|
||||
captureExperiencePointsModifier: Float
|
||||
active: Boolean,
|
||||
broadcastBattleRank: Int,
|
||||
resetBattleRank: Int,
|
||||
maxBattleRank: Int,
|
||||
battleExperiencePointsModifier: Float,
|
||||
supportExperiencePointsModifier: Float,
|
||||
captureExperiencePointsModifier: Float
|
||||
)
|
||||
|
|
|
|||
Loading…
Reference in a new issue