Scripts:AntiBaseRape

From BF2 Technical Information Wiki
Jump to navigation Jump to search

Description:

Module
AntiBaseRape.py
Author
SHAnders
Version
1.11

Server side only admin script.

This script will punish players who kill enemy within the area of a safe base. (Control point that can't be captured.)

The punishment is the following:

  1. The victims death score will be lowered by 1
  2. The attackers kill score will will be lowered by 1
  3. The attackers overall score will be lowered by 2 + number of warnings
  4. If warnings > 3 then...
    1. The attackers TKs score will be increased by 1
    2. If attacker is on foot, he/she's health will be lowered to 0
    3. If attacker is in a vehicle, its health will be lowered to 1

1 warning will be removed from players history every 2 minutes

The radius for a safe base is set to 40. (Standard controlpoint capture area is 10.)

Installation as Admin script

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

TODO:

Since not all maps are alike, the requirements for base rape protiction should be able to be altered individualy for each control point.

The Code

# ------------------------------------------------------------------------
# Module: AntiBaseRape.py
# Author: SHAnders
#
# Version 1.11
#
# Changes:
#   v1.1 -> 1.11
#   Fixed the timer to only be started once
#   v1.0 -> 1.1
#   Implemted a baseRapeWarning attribute on players to count safe base kills
#   Implemted allowed amount of safe base kills (3)
#      up to this amount player only loses kill points + 1 score pr baseRapeWarning
#      over this amount player is allso killed
#   Implemtes a timer for removing 1 baseRapeWarning every 2 minutes
#
# Description:
#   Server side only admin script
#
#   This script will punish players who kill enemy within the area of a safe base
#  
# Requirements:
#   None.
#
# Installation as Admin script:
#   1: Save this script as 'AntiBaseRape.py' in your <bf2>/admin/standard_admin directory.
#   2: Add the lines 'import AntiBaseRape' and 'AntiBaseRape.init()' to the file
#      '<bf2>/admin/standard_admin/__init__.py'.
#
# TODO:
#   Since not all maps are alike, the requirements for base rape protiction
#   should be able to be altered individualy for each control point.
#
# Thanks to:
#   Battlefield.no for inspiration from their pingkick.py script
#
# ------------------------------------------------------------------------

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

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

DEFAULT_SAFEBASE_RADIUS = 40 # Default safe area radius (normal commandpoint radius = 10)
ALLOWED_SAFEBASEKILLS = 3
SAFEBASEKILL_TIMER_INTERVAL = 120 # Intervals between removing a point from players.baseRapeWarning

# ------------------------------------------------------------------------
# Variables
# ------------------------------------------------------------------------
 
WarnReduceTimer = None # Timer that reduces the warnings at intervals
 
# ------------------------------------------------------------------------
# Init
# ------------------------------------------------------------------------
 
def init():
   if g_debug: print "AntiBaseRape init"
   host.registerHandler('PlayerConnect', onPlayerConnect, 1)  
   host.registerHandler('PlayerKilled', onPlayerKilled)
 
   # Start the timer that reduces warnings on the SAFEBASEKILL_TIMER_INTERVAL
   WarnReduceTimer = bf2.Timer(onSafeBaseKillTimer, SAFEBASEKILL_TIMER_INTERVAL, 1)
   WarnReduceTimer.setRecurring(SAFEBASEKILL_TIMER_INTERVAL)

   # Connect already connected players if reinitializing
   for p in bf2.playerManager.getPlayers():
      onPlayerConnect(p)
# ------------------------------------------------------------------------


# ------------------------------------------------------------------------
#  onPlayerConnect
# ------------------------------------------------------------------------
def onPlayerConnect(player):
   resetPlayer(player)
# ------------------------------------------------------------------------


# ------------------------------------------------------------------------
# onPlayerKilled
# ------------------------------------------------------------------------
def onPlayerKilled(victim, attacker, weapon, assists, object):
   # killed by self
   if attacker == victim:
      pass
     
   # killed by enemy
   elif attacker != None and attacker.getTeam() != victim.getTeam():
      checkForSafeBase(attacker, victim)
# ------------------------------------------------------------------------


# ------------------------------------------------------------------------
# Reset the bfno pingscript variables placed in the player object:
# ------------------------------------------------------------------------
def resetPlayer(player):
   player.baseRapeWarning = 0
# ------------------------------------------------------------------------


# ------------------------------------------------------------------------
# Check if victim was killed within safebase area
# ------------------------------------------------------------------------
def checkForSafeBase(attacker, victim):
   victimVehicle = victim.getVehicle()
   controlPoints = bf2.objectManager.getObjectsOfType('dice.hfe.world.ObjectTemplate.ControlPoint')
   for cp in controlPoints:
      if cp.cp_getParam('unableToChangeTeam') != 0 and cp.cp_getParam('team') != attacker.getTeam():
         distanceTo = getVectorDistance(victimVehicle.getPosition(), cp.getPosition())
         if DEFAULT_SAFEBASE_RADIUS > float(distanceTo):
            justify(attacker, victim, cp, distanceTo)
# ------------------------------------------------------------------------


# ------------------------------------------------------------------------
# Punish attacker, give victim life back and inform all
# ------------------------------------------------------------------------
def justify(attacker, victim, controlPoint, distanceTo):
   victim.score.deaths += -1
   attacker.score.kills += -1
   attacker.score.score += -2 - attacker.baseRapeWarning
   attacker.baseRapeWarning += 1
   sendWarning(attacker, controlPoint, distanceTo)
   if attacker.baseRapeWarning > ALLOWED_SAFEBASEKILLS:
      attacker.score.TKs += 1
      if attacker.isAlive():
         vehicle = attacker.getVehicle()
         rootVehicle = getRootParent(vehicle)
         if getVehicleType(rootVehicle.templateName) == VEHICLE_TYPE_SOLDIER:
            rootVehicle.setDamage(0)
            # This should kill them !
         else:
            rootVehicle.setDamage(1)
            # a vehicle will likely explode within 1 sec killing entire crew,
            # not so sure about base defenses though
# ------------------------------------------------------------------------


# ------------------------------------------------------------------------
# Send Warning
# ------------------------------------------------------------------------
def sendWarning(player, controlPoint, distanceTo):
   mapName = bf2.gameLogic.getMapName()
   if player.baseRapeWarning > ALLOWED_SAFEBASEKILLS:
      sendMsgAll(player.getName() + " is punished for repeated violating of the no kill rules within safe base area")
   else:
      sendMsgAll(player.getName() + " has violated of the no kill rules within safe base area " + str(player.baseRapeWarning) + " times now")
# ------------------------------------------------------------------------


# ------------------------------------------------------------------------
# remove baseRapeWarnings over time
# ------------------------------------------------------------------------
def onSafeBaseKillTimer(data):
   for p in bf2.playerManager.getPlayers():
      if p.baseRapeWarning <= 0:
         p.baseRapeWarning = 0
      else:
         p.baseRapeWarning += -1
# ------------------------------------------------------------------------


# ------------------------------------------------------------------------
# get distance between two positions
# ------------------------------------------------------------------------
def getVectorDistance(pos1, pos2):
   diffVec = [0.0, 0.0, 0.0]
   diffVec[0] = math.fabs(pos1[0] - pos2[0])
   diffVec[1] = math.fabs(pos1[1] - pos2[1])
   diffVec[2] = math.fabs(pos1[2] - pos2[2])
  
   # Application of Pythagorean theorem to calculate total distance
   return math.sqrt(diffVec[0] * diffVec[0] + diffVec[1] * diffVec[1] + diffVec[2] * diffVec[2])
# ------------------------------------------------------------------------


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