More Experience Fixes (#1163)

* revenge experience now rate down and capped; fixed issue with the tail of an empty list

* fixed column name difference between database and persistence objects
This commit is contained in:
Fate-JH 2024-01-17 23:32:54 -05:00 committed by GitHub
parent 22d097347b
commit e9daae5802
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 24 additions and 21 deletions

View file

@ -0,0 +1,3 @@
/* Original: V008__Scoring.sql */
ALTER TABLE assistactivity
RENAME COLUMN attacker_id TO killer_id;

View file

@ -332,11 +332,13 @@ game {
# The kill event must have been the exact previous life's death after revive or respawn. # The kill event must have been the exact previous life's death after revive or respawn.
# This only applies if experience is set to 0. # This only applies if experience is set to 0.
# Set to zero and experience = 0 to ignore revenge. # Set to zero and experience = 0 to ignore revenge.
rate = 0.15 rate = 0.05
# If player A kills another player B who killed player A just previously, deposit this experience. # If player A kills another player B who killed player A just previously, deposit this experience.
# The kill event must have been the exact previous life's death after revive or respawn. # The kill event must have been the exact previous life's death after revive or respawn.
# Set to zero to reuse the experience value from the previous kill event. # Set to zero to reuse the experience value from the previous kill event.
experience = 0 default-experience = 0
# When using the experience from the previous kill for revenge bonus, cap the reward at this value.
max-experience = 350
} }
} }

View file

@ -7,7 +7,6 @@ import net.psforever.objects.sourcing.PlayerSource
import net.psforever.packet.game.objectcreate.{CaptureFlagData, PlacementData} import net.psforever.packet.game.objectcreate.{CaptureFlagData, PlacementData}
import net.psforever.types.{PlanetSideEmpire, PlanetSideGUID, Vector3} import net.psforever.types.{PlanetSideEmpire, PlanetSideGUID, Vector3}
import java.util.concurrent.TimeUnit
import scala.util.{Success, Try} import scala.util.{Success, Try}
class CaptureFlagConverter extends ObjectCreateConverter[CaptureFlag]() { class CaptureFlagConverter extends ObjectCreateConverter[CaptureFlag]() {

View file

@ -19,8 +19,6 @@ import net.psforever.objects.serverobject.llu.{CaptureFlag, CaptureFlagSocket}
import net.psforever.objects.serverobject.structures.participation.{MajorFacilityHackParticipation, NoParticipation, ParticipationLogic, TowerHackParticipation} import net.psforever.objects.serverobject.structures.participation.{MajorFacilityHackParticipation, NoParticipation, ParticipationLogic, TowerHackParticipation}
import net.psforever.objects.serverobject.terminals.capture.CaptureTerminal import net.psforever.objects.serverobject.terminals.capture.CaptureTerminal
import java.util.concurrent.TimeUnit
class Building( class Building(
private val name: String, private val name: String,
private val building_guid: Int, private val building_guid: Int,

View file

@ -190,10 +190,10 @@ object KillAssists {
val victimUnique = victim.unique val victimUnique = victim.unique
val lastDeath = killer.progress.prior.flatMap(_.death) val lastDeath = killer.progress.prior.flatMap(_.death)
val sameLastKiller = lastDeath.map(_.assailant.map(_.unique)).flatMap(_.headOption).contains(victimUnique) val sameLastKiller = lastDeath.map(_.assailant.map(_.unique)).flatMap(_.headOption).contains(victimUnique)
if (revenge.experience != 0 && sameLastKiller) { if (revenge.defaultExperience != 0 && sameLastKiller) {
revenge.experience revenge.defaultExperience
} else if (sameLastKiller) { } else if (sameLastKiller) {
(lastDeath.map(_.experienceEarned).get * revenge.rate).toLong math.min(revenge.maxExperience, (lastDeath.map(_.experienceEarned.toFloat).getOrElse(0f) * revenge.rate).toLong)
} else { } else {
0L 0L
} }
@ -400,7 +400,7 @@ object KillAssists {
shots = firstWeapon.shots + 1, shots = firstWeapon.shots + 1,
time = time, time = time,
contributions = firstWeapon.contributions + percentage contributions = firstWeapon.contributions + percentage
) +: mod.weapons.tail ) +: mod.weapons.drop(1)
} else { } else {
WeaponStats(newEntry, amount, 1, time, percentage) +: mod.weapons WeaponStats(newEntry, amount, 1, time, percentage) +: mod.weapons
} }
@ -427,7 +427,7 @@ object KillAssists {
case 0 => case 0 =>
//ongoing attack by same player //ongoing attack by same player
val entry = order.head val entry = order.head
(entry._1, entry._2 + amount) +: order.tail (entry._1, entry._2 + amount) +: order.drop(1)
case _ => case _ =>
//different player than immediate prior attacker //different player than immediate prior attacker
(whoId, amount) +: order (whoId, amount) +: order
@ -437,7 +437,7 @@ object KillAssists {
order.headOption match { order.headOption match {
case Some((id, dam)) => case Some((id, dam)) =>
if (id == 0L) { if (id == 0L) {
(0L, dam + amount) +: order.tail //pool (0L, dam + amount) +: order.drop(1) //pool
} else { } else {
(0L, amount) +: order //new (0L, amount) +: order //new
} }
@ -486,11 +486,11 @@ object KillAssists {
} else if (weaponSum > reduceByValue) { } else if (weaponSum > reduceByValue) {
newOrderPos = (id, total - amt) +: newOrderPos newOrderPos = (id, total - amt) +: newOrderPos
val remainder = pweapons.drop(index) val remainder = pweapons.drop(index)
remainder.headOption.map(_.copy(amount = weaponSum - reduceByValue)) ++ remainder.tail remainder.headOption.map(_.copy(amount = weaponSum - reduceByValue)) ++ remainder.drop(1)
} else { } else {
newOrderPos = (id, total - amt) +: newOrderPos newOrderPos = (id, total - amt) +: newOrderPos
val remainder = pweapons.drop(index) val remainder = pweapons.drop(index)
remainder.headOption.map(_.copy(amount = reduceByValue - weaponSum)) ++ remainder.tail remainder.headOption.map(_.copy(amount = reduceByValue - weaponSum)) ++ remainder.drop(1)
}) ++ pweapons.take(index).map(_.copy(amount = 0)) }) ++ pweapons.take(index).map(_.copy(amount = 0))
} }
participants.put(id, part.copy(amount = part.amount - reduceByValue, weapons = trimmedWeapons.toSeq)) participants.put(id, part.copy(amount = part.amount - reduceByValue, weapons = trimmedWeapons.toSeq))

View file

@ -44,6 +44,7 @@ object Support {
fullLifespan fullLifespan
) )
if (shortLifeBonus > TheShortestLifeIsWorth) { if (shortLifeBonus > TheShortestLifeIsWorth) {
//long life factors
val longLifeBonus: Long = { val longLifeBonus: Long = {
val threat = baseExperienceLongLifeFactors(victim, recordOfWornTimes, defaultValue = 100f * shortLifeBonus.toFloat) val threat = baseExperienceLongLifeFactors(victim, recordOfWornTimes, defaultValue = 100f * shortLifeBonus.toFloat)
if (withKills) { if (withKills) {
@ -52,7 +53,6 @@ object Support {
(threat * 0.85f).toLong (threat * 0.85f).toLong
} }
} }
//long life factors
shortLifeBonus + longLifeBonus shortLifeBonus + longLifeBonus
} else { } else {
//the shortest life is afforded no additional bonuses //the shortest life is afforded no additional bonuses

View file

@ -52,7 +52,7 @@ object RecoveryExperienceContribution {
recoveryParticipants.put( recoveryParticipants.put(
id, id,
entry.copy( entry.copy(
weapons = weapons.head.copy(amount = math.max(0, weapons.head.amount - ramt), time = time) +: weapons.tail, weapons = weapons.head.copy(amount = math.max(0, weapons.head.amount - ramt), time = time) +: weapons.drop(1),
amount = math.max(0, entry.amount - ramt), amount = math.max(0, entry.amount - ramt),
time = time time = time
) )
@ -65,7 +65,7 @@ object RecoveryExperienceContribution {
recoveryParticipants.put( recoveryParticipants.put(
id, id,
entry.copy( entry.copy(
weapons = weapons.tail :+ weapons.head.copy(amount = 0, time = time), weapons = weapons.drop(1) :+ weapons.head.copy(amount = 0, time = time),
amount = math.max(0, entry.amount - ramt), amount = math.max(0, entry.amount - ramt),
time = time time = time
) )
@ -214,7 +214,7 @@ object RecoveryExperienceContribution {
recoveryParticipants.put( recoveryParticipants.put(
charId, charId,
entry.copy( entry.copy(
weapons = head.copy(amount = head.amount + amtToGain, shots = head.shots + 1, time = time) +: entry.weapons.tail, weapons = head.copy(amount = head.amount + amtToGain, shots = head.shots + 1, time = time) +: entry.weapons.drop(1),
amount = entry.amount + amtToGain, amount = entry.amount + amtToGain,
total = entry.total + amtToGain, total = entry.total + amtToGain,
shots = entry.shots + 1, shots = entry.shots + 1,

View file

@ -523,7 +523,7 @@ object SquadHeader {
linkedInfo linkedInfo
} else { } else {
val (code, data) = infoList.head val (code, data) = infoList.head
linkSquadInfo(infoList.tail, LinkedSquadInfo(code, data, Some(linkedInfo))) linkSquadInfo(infoList.drop(1), LinkedSquadInfo(code, data, Some(linkedInfo)))
} }
} }

View file

@ -916,7 +916,7 @@ object SquadDetailDefinitionUpdateMessage extends Marshallable[SquadDetailDefini
out out
} else { } else {
val (code, data) = list.head val (code, data) = list.head
linkFields(list.tail, LinkedFields(code, data, Some(out))) linkFields(list.drop(1), LinkedFields(code, data, Some(out)))
} }
} }
@ -1184,7 +1184,7 @@ object SquadDetailDefinitionUpdateMessage extends Marshallable[SquadDetailDefini
out out
} else { } else {
val (code, data) = list.head val (code, data) = list.head
linkFields(list.tail, LinkedFields(code, data, Some(out))) linkFields(list.drop(1), LinkedFields(code, data, Some(out)))
} }
} }

View file

@ -284,7 +284,8 @@ case class BattleExperiencePointsLifespan(
case class BattleExperiencePointsRevenge( case class BattleExperiencePointsRevenge(
rate: Float, rate: Float,
experience: Long defaultExperience: Long,
maxExperience: Long
) )
case class SupportExperiencePoints( case class SupportExperiencePoints(