Scripts:ThreatAndWorth

From BF2 Technical Information Wiki
Revision as of 15:33, 22 June 2018 by Pireax (talk | contribs) (Created page with "__TOC__ == Description == ; Module : <code>ThreatAndWorth.py</code> ; Author : SHAnders ; Version : 1.01 Server side only admin script or mod addon, you deside the usage!...")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

Description

Module
ThreatAndWorth.py
Author
SHAnders
Version
1.01

Server side only admin script or mod addon, you deside the usage!

Features

Worth

This script will reward player kills based upon a worth schema. Each players will be assigned a 'worth' when they get killed or kill. If victim worth > attacker worth, the attacker is assigned a bonus. Worth is calculated by vehicle, and players position within it plus an addition if player is squadleader or commander, snipers are worth only to other snipers.

Threat

This script implements threat rating. The lower the attacker threat raking and the higher the victim threat rating, the higher the bonus and vice versa. Threat rating is based uppon a calculation of a player kills, deaths and scores compared to the average player in the game. Threat rating can be disabled by setting: USE_THREAT_RATING = False.

Survival

At the end of the game players will be rewarded upon their survival rating. The more enemies you kill and the less you get killed, the higher the bonus.

Survivalrating can be disabled by setting : USE_SURVIVAL_RATING = False

Commander

To please a few people out there it is now possible to disable the commander in this script.

Commander can be disabled by setting: DISABLE_COMMANDER = True

Installation

Installation as Admin script -- not a mod, adds scoring changes to all games on server:

  1. Save this script as ThreatAndWorth.py in your admin/standard_admin directory.
  2. Add the lines import ThreatAndWorth and ThreatAndWorth.init() to the file admin/standard_admin/__init__.py.

Installation as Mod addon -- adds scoring changes only to your mod:

  1. Save this script as ThreatAndWorth.py in your mods/<mod_lib>/python/game directory.
  2. Add the lines import ThreatAndWorth and ThreatAndWorth.init() to the file mods/<mod_lib>/python/game/__init__.py.

TODO:

Team score
Additional points for actions made within 30-50 feet of a commander/squadleader attack/defend/fix/blowup/asembly order

Thanks To

Battlefield.no for inspiration from their pingkick.py script

The Code

 # ------------------------------------------------------------------------
# Module: ThreatAndWorth.py
# Author: SHAnders
#
# Version 1.01
# Changes
# 1.0 -> 1.01
#    Updated the messagetimer to only start once
#
# Description:
#   Server side only admin script or mod addon, you deside the usage !
#
#   This script will reward player kills based uppon a worthschema
#   Each players will be assigned a 'worth' when they get killed or kill
#   If victim worth > attacker worth, the attacker is assigned a bonus.
#   Worth is calculated by vehicle, and players position within it plus
#   an addition if player is squadleader or commander, snipers are worth only to other snipers.
#
#   This script implement threat rating. The lower the attacker threat raking
#   and the higher the victim threat rating, the higher the bonus and vice versa.
#   Threat rating is based uppon a calculation of a player kills, deaths & scores
#   compared to the average player in the game.
#
#   At the end of the game players will be rewarded uppon their survival rating.
#   The more enemies you kill and the less you get killed, the higher the bonus.
#
#   To please a few people out there it is now posible to disable the commander in this script.
#
#   The scoring system provided by ThreatAndWorth refines the idear and system
#   implemted by the earlier scoringBonuses v1.0
#   ThreatAndWorth therfor replaces the scoringBonuses script.
#
# Requirements:
#   None.
#
# Installation as Admin script -- Not a mod, adds scoring changes to all games on server:
#   1: Save this script as 'ThreatAndWorth.py' in your <bf2>/admin/standard_admin directory.
#   2: Add the lines 'import ThreatAndWorth' and 'ThreatAndWorth.init()' to the file
#      '<bf2>/admin/standard_admin/__init__.py'.
#
# Installation as Mod addon -- adds scoring changes only to your mod:
#   1: Save this script as 'ThreatAndWorth.py' in your <bf2>/mods/<mod_lib>/python/game directory.
#   2: Add the lines 'import ThreatAndWorth' and 'ThreatAndWorth.init()' to the file
#      '<bf2>/mods/<mod_lib>/python/game/__init__.py'.
#
# TODO:
#   Team score:
#     Additional points for actions made within 30-50 feet of a commander/squadleader
#     attack/defend/fix/blowup/asembly order
#
# Thanks to:
#   Battlefield.no for inspiration from their pingkick.py script
#
# ------------------------------------------------------------------------

import host
import bf2
from bf2.stats.constants import *
from bf2 import g_debug
from bf2.stats.stats import onGameStatusChanged

# ------------------------------------------------------------------------
# Constants
# ------------------------------------------------------------------------

WORTHSCHEMA = { VEHICLE_TYPE_ARMOR : [ 6, 3, 1, 1, 1, 1, 1, 1 ],
        VEHICLE_TYPE_AVIATOR : [ 8, 3, 1, 1, 1, 1, 1, 1 ],
        VEHICLE_TYPE_AIRDEFENSE    : [ 1 ],
        VEHICLE_TYPE_HELICOPTER    : [ 6, 3, 3, 1, 1, 1, 1, 1 ],
        VEHICLE_TYPE_TRANSPORT    : [ 3, 3, 1, 1, 1, 1, 1, 1 ],
        VEHICLE_TYPE_ARTILLERY    : [ 1 ],
        VEHICLE_TYPE_GRNDDEFENSE : [ 1 ],
        VEHICLE_TYPE_PARACHUTE : [ 1 ],
        VEHICLE_TYPE_SOLDIER : [ 0 ] } # index 0 is allways used for victim, 0-7 are all used for attacker

# Aditional worth, only the greatest applies
VICTIM_SNIPER = 2             # Only applies when attacker is sniper
VICTIM_SQUADLEADER = 4        # Killing a squadleader in a jet gives good points, But why would he/she be there anyway ... squad members cant spawn there?
VICTIM_COMMANDER = 6          # Killing a commander in a jet gives good points, But why would he/she be there anyway ... should he/she not bee doing something else?

DEFAULT_VICTIM_WORTH = 1      # Victim will allways be worth this + whats in the WORTHSCHEMA
USE_THREAT_RATING = True      # Low threat rated players get more points for kills on higher threat rated players [True, False]
PUBLIC_SCORES = 1             # Score earnings will be made public to the following: [0 = None, 1 = Team, 2 = All]
USE_SURVIVAL_RATING = True    # At end game players with high survivalrating will be rewarded with (SurvivalRating * (kills - deaths) / restraint) [True, False]
SURVIVAL_RATING_RESTRAINT = 3 # The higher the number, the lower the bonus (without it the bonus can get very high) [1..*]
DISABLE_COMMANDER = False     # Not all like the commander, setting this to True will disable this posibility  [True, False]

WELCOME_MSG = "Server is using ThreatAndWorth script v1.0"

# ------------------------------------------------------------------------
# Variables
# ------------------------------------------------------------------------
 
MsgTimer = None # Welcome msg Timer

# ------------------------------------------------------------------------
# Init
# ------------------------------------------------------------------------
def init():
   host.unregisterGameStatusHandler(onGameStatusChanged) # We need to unregister this to change endscores
   host.registerGameStatusHandler(onGameStatusChangedThreatAndWorth)
   host.registerGameStatusHandler(onGameStatusChanged) # We need to register it again after our own handler to make the game work :)
   MsgTimer = bf2.Timer(onMsgTimer,10,1)
   if g_debug: print "ThreatAndWort init"
# ------------------------------------------------------------------------
  

# ------------------------------------------------------------------------
# onGameStatusChangedThreatAndWorth
# ------------------------------------------------------------------------
def onGameStatusChangedThreatAndWorth(status):
   if status == bf2.GameStatus.Playing:
      host.registerHandler('PlayerKilled', onPlayerKilled)
      if DISABLE_COMMANDER:
         host.sh_setEnableCommander(0)

   elif status == bf2.GameStatus.EndGame:
      if USE_SURVIVAL_RATING:
         CalculateSurvivalRatingBonus()
# ------------------------------------------------------------------------

# ------------------------------------------------------------------------
# onPlayerKilled
# ------------------------------------------------------------------------
def onPlayerKilled(victim, attacker, weapon, assists, object):
   victimVehicle = victim.getVehicle()
  
   # killed by remote controlled vehicle, no score awarded in this game
   if victimVehicle and victimVehicle.getIsRemoteControlled():
      pass
     
   # no attacker, killed by object
   elif attacker == None:
      pass
     
   # killed by self
   elif attacker == victim:
      pass
     
   # killed by own team
   elif attacker.getTeam() == victim.getTeam():
      pass

   # killed by enemy
   else:
      CalculateThreatAndWorth(attacker, victim)
# ------------------------------------------------------------------------


# ------------------------------------------------------------------------
# addBonus
# ------------------------------------------------------------------------
def addBonus(player, points):
   # commander doesnt get bonus for regular actions, only for pure commander tasks.
   if not player.isCommander():
      player.score.score += points
     
   # commander score
   commander = bf2.playerManager.getCommander(player.getTeam())
   if commander != None and commander.isValid() and player != commander and points > 0:
      preScore = commander.score.score
      numPlayers = bf2.playerManager.getNumberOfAlivePlayersInTeam(commander.getTeam())
      if numPlayers > 0:
         commander.score.score += float(points) / numPlayers
         scoreGotten = commander.score.score - preScore
         if scoreGotten > 0:
            commander.score.cmdScore += scoreGotten
# ------------------------------------------------------------------------


# ------------------------------------------------------------------------
# Callback function for timer, that delays a message at round start:
# I hope the fellows at Battlefield.no dont mind me using this !
# ------------------------------------------------------------------------
def onMsgTimer(data):
   global msgtimer
   sendMsgAll( WELCOME_MSG )
   msgtimer.destroy()
   msgtimer = None
# ------------------------------------------------------------------------

# ------------------------------------------------------------------------
# Send message to all on server
# ------------------------------------------------------------------------
def sendMsgAll(msg):
   host.rcon_invoke("game.sayAll \"" + str(msg) + "\"")
# ------------------------------------------------------------------------


# ------------------------------------------------------------------------
# Send message to all on a team
# ------------------------------------------------------------------------
def sendMsgTeam(msg, team):
   host.rcon_invoke("game.sayTeam " + str(team) + " \"" + str(msg) + "\"")
# ------------------------------------------------------------------------


# ------------------------------------------------------------------------
# Calculate survival endgame points
# ------------------------------------------------------------------------
def CalculateSurvivalRatingBonus():
   playerArgs = bf2.playerManager.getPlayers()
   for p in playerArgs:
      survivalRating = GetPlayerSurvivalRating(p)
      if survivalRating > 0:
         points = round((p.score.kills - p.score.deaths) * survivalRating / SURVIVAL_RATING_RESTRAINT, 0)
         addBonus(p, int(points))
# ------------------------------------------------------------------------


# ------------------------------------------------------------------------
# Get a players survival rating
# ------------------------------------------------------------------------
def GetPlayerSurvivalRating( player ):
   kills = float(player.score.kills + 1)
   deaths = float(player.score.deaths + 1)
   survivalRating = kills / deaths
   return round(survivalRating, 2)
# ------------------------------------------------------------------------


# ------------------------------------------------------------------------
# Calculate threat and worth points
# ------------------------------------------------------------------------
def CalculateThreatAndWorth(attacker, victim):
   victimVehicle = victim.getVehicle()
   victimRootVehicle = getRootParent(victimVehicle)
   attackerVehicle = attacker.getVehicle()
   attackerRootVehicle = getRootParent(attackerVehicle)

   points = 0

   attackerWorth = GetPlayerWorth( attacker )
   victimWorth = GetPlayerWorth( victim ) + GetAdditionalVictimWorth(attacker, victim)

   tmpPoints = victimWorth - attackerWorth
   if tmpPoints > 0:
      if USE_THREAT_RATING:
         attackerThreatRating = GetPlayerThreatRating( attacker )
         victimThreatRating = GetPlayerThreatRating( victim )
         threatRatingFactor = round((victimThreatRating / attackerThreatRating),3)
         if threatRatingFactor < 0.125:
            threatRatingFactor = 0
         if threatRatingFactor < 0.25:
            threatRatingFactor = 0.125
         elif threatRatingFactor < 0.5:
            threatRatingFactor = 0.25
         elif threatRatingFactor < 0.75:
            threatRatingFactor = 0.5
         elif threatRatingFactor < 1.5:
            threatRatingFactor = 1
         elif threatRatingFactor < 2:
            threatRatingFactor = 1.5
         else:
            threatRatingFactor = 2
         tmpPoints = int(round( threatRatingFactor * tmpPoints,0))
      points = tmpPoints
      if points > 0:
         addBonus(attacker, points)
         if PUBLIC_SCORES == 2:
            sendMsgAll( attacker.getName() + " earn points: " + str(points))
         elif PUBLIC_SCORES == 1:
            sendMsgTeam( attacker.getName() + " earn points: " + str(points), attacker.getTeam())
# ------------------------------------------------------------------------


# ------------------------------------------------------------------------
# Calculate additional victim worth
# ------------------------------------------------------------------------
def GetAdditionalVictimWorth(attacker, victim):
   attackerKitType = getKitType(attacker.getKit().templateName)
   attackerVehicle = attacker.getVehicle()
   attackerVehicleType = getVehicleType(attackerVehicle.templateName)

   victimKitType = getKitType(victim.getKit().templateName)
   victimVehicle = victim.getVehicle()
   victimVehicleType = getVehicleType(victimVehicle.templateName)

   attackerTeamMsg = ""
   victimTeamMsg = ""

   worth = DEFAULT_VICTIM_WORTH

   # SNIPER
   if attackerVehicleType == VEHICLE_TYPE_SOLDIER:
      if victimVehicleType == VEHICLE_TYPE_SOLDIER:
         if attackerKitType == KIT_TYPE_SNIPER and victimKitType == KIT_TYPE_SNIPER:
            worth += VICTIM_SNIPER
            attackerTeamMsg = attacker.getName() + " has eliminated enemy sniper"

   # SQUADLEADER
   if victim.isSquadLeader():
      worth += VICTIM_SQUADLEADER
      attackerTeamMsg = attacker.getName() + " has eliminated a enemy squadleader " + victim.getName()

   # COMMANDER
   if victim.isCommander():
      worth += VICTIM_COMMANDER
      attackerTeamMsg = attacker.getName() + " has eliminated enemy commander " + victim.getName()
      victimTeamMsg = "You commander has been eliminated"

   if attackerTeamMsg != "":
      sendMsgTeam(attackerTeamMsg, attacker.getTeam())

   if victimTeamMsg != "":
      sendMsgTeam(victimTeamMsg, victim.getTeam())

   return worth
# ------------------------------------------------------------------------


# ------------------------------------------------------------------------
# Calculate a players worth
# ------------------------------------------------------------------------
def GetPlayerWorth( player ):
   worth = -1
   vehicle = player.getVehicle()
   rootVehicle = getRootParent(vehicle)
   vehicleType = getVehicleType(rootVehicle.templateName)
   args = WORTHSCHEMA[vehicleType]
   index = GetPlayerIndexInVehicle( player, rootVehicle )
   if index > -1:
      worth = args[index]
   return worth
# ------------------------------------------------------------------------


# ------------------------------------------------------------------------
# Get a players index inside a vehicle
# ------------------------------------------------------------------------
def GetPlayerIndexInVehicle( player, vehicle ):
   # This dosn't work on dead player/vehicles ... it allways return 0

   playerArgs = vehicle.getOccupyingPlayers()
   index = -1
   found = False
   while index < len(playerArgs) and not found:
      index += 1
      if playerArgs[index] == player:
         found = True        
   return index
# ------------------------------------------------------------------------


# ------------------------------------------------------------------------
# Get a players threat rating
# ------------------------------------------------------------------------
def GetPlayerThreatRating( player ):
   score = 0
   kills = 0
   deaths = 0
   playerArgs = bf2.playerManager.getPlayers()
   for p in playerArgs:
      score += p.score.score
      kills += p.score.kills
      deaths += p.score.deaths

   avgScore = float(score)/len(playerArgs)
   avgKills = float(kills)/len(playerArgs)
   avgDeaths = float(deaths)/len(playerArgs)

   if player.score.score <= 0:
      scoreFactor = 1/avgScore
   else:
      scoreFactor = float(player.score.score)/avgScore

   if player.score.kills <= 0:
      killsFactor = 1/avgKills
   else:
      killsFactor = float(player.score.kills)/avgKills

   if player.score.deaths <= 0:
      deathsFactor = avgDeaths/1
   else:
      deathsFactor = avgDeaths/float(player.score.deaths)

   threatRating = round(killsFactor * deathsFactor * scoreFactor,3)

   return threatRating
# ------------------------------------------------------------------------