# Date of release 05/12/2008
import es
import gamethread
import keyvalues
import langlib
import math

# plugin information
info = {}
info['name'] = "Playerlib EventScripts python library"
info['version'] = "oy10c"
info['author'] = "Don, Mattie, Mikey, SuperDave, et al"
info['url'] = "http://www.eventscripts.com/pages/Playerlib/"
info['description'] = "Provides and sets player information"
info['tags'] = ""


# this will be our global list of filters
filters = {}

_primary_weapons = ['awp', 'scout', 'aug', 'mac10', 'tmp', 'mp5navy', 'ump45', 'p90', 'galil', 'famas', 'ak47', 'sg552', 'sg550', 'g3sg1', 'm249', 'm3', 'xm1014', 'm4a1']
_secondary_weapons = ['glock', 'usp', 'p228', 'deagle', 'elite', 'fiveseven']
_weapons_ammo = {'awp':'005', 'scout':'002', 'aug':'002', 'mac10':'008', 'tmp':'006', 'mp5navy':'006', 'ump45':'008', 'p90':'010', 'galil':'003', 'famas':'003', 'ak47':'002', 'sg552':'003', 'sg550':'003', 'g3sg1':'002', 'm249':'004', 'm3':'007', 'xm1014':'007', 'm4a1':'003', 'glock':'006', 'usp':'008', 'p228':'009', 'deagle':'001', 'elite':'006', 'fiveseven':'010'}
#_weapons_ammo = ["awp" : "005"]

# custom exceptions we can throw.
# This probably needs more added to it, but it should be fine.
class _PlayerlibError:
    def __init__(self, message):
        self.message = message

    def __str__(self):
        return self.message

class UseridError(_PlayerlibError):
    pass

class PlayerError(_PlayerlibError):
    pass

# Scripters won't instatiate this class directly. They'll probably use:
# myPlayer = playerlib.getPlayer(userid)
# myPlayerList = playerlib.getPlayerList(filtername)

# THOUGHTS: Right now it seems a Player object will be somewhat of a static
#  view of a player for some information, but might be on-the-fly for playergetset
#  info. How do we make that clear to scripters? Or do we take the performance
#  hit and make everything dynamic even though right now that requires
#  refreshing all of the es.createplayerlist() attributes at once?
class Player:
    userid = 0

    # default initialization routine. Give us a userid.
    def __init__(self, playerid):
        try:
            # We'll be nice and convert the playerid to an int in case they gave
            # us a string userid.
            self.userid = int(playerid)
            # Check if it's a valid userid. Otherwise we throw.
            if not es.exists('userid', self.userid):
                raise UseridError, str(self.userid) + ' is an invalid userid'
            # Maybe use es.createplayerlist(userid) to get initial values?
            self.refreshAttributes()
            # TODO: What else do we need to initialize?
        except TypeError, e:
            raise TypeError, 'Player argument expected a userid'

    def refreshAttributes(self):
        """
        Refresh the attributes for this player from ES. These are cached in
        the player object for performance.
        """
        # If this fails maybe they gave us the wrong userid, so maybe it should
        # except all the way up? Probably need a cleaner exception, though.
        try:
            self.attributes = es.createplayerlist(self.userid)[self.userid]
        except KeyError:
            raise PlayerError, 'player has left the server'

    def get(self, param, passparam=""):
        # This is all the parameters from the original playerget
        param = str(param).lower()
        # passparam = str(passparam).lower()
        # GET PRIMARY
        if param == "primary":
            weapon_found = 0
            weapon_index = 0
            index = 0
            while ((weapon_found == 0) and (index < len(_primary_weapons))):
                weapon_index = int(self.get("weaponindex", _primary_weapons[index]))
                if weapon_index > 0:
                  weapon_found = 1
                  return _primary_weapons[index]
                index += 1
            return '0'
        # GET SECONDARY
        elif param == "secondary":
            weapon_found = 0
            weapon_index = 0
            index = 0
            while ((weapon_found == 0) and (index < len(_secondary_weapons))):
                weapon_index = int(self.get("weaponindex", _secondary_weapons[index]))
                if weapon_index > 0:
                  weapon_found = 1
                  return _secondary_weapons[index]
                index += 1
            return '0'
        # GET HE GRENADE
        elif param == "he":
            return es.getplayerprop(self.userid, "CBasePlayer.localdata.m_iAmmo.011")
        # GET SMOKE GRENADE
        elif param == "sg":
            return es.getplayerprop(self.userid, "CBasePlayer.localdata.m_iAmmo.013")
        # GET FLASHBANG
        elif param == "fb":
            return es.getplayerprop(self.userid, "CBasePlayer.localdata.m_iAmmo.012")
        # GET C4 - THE BOMB
        elif param == "c4":
            myHe = self.get("weaponindex", "weapon_c4")
            if int(myHe) > 0:
                return '1'
            else:
                return '0'
        # GET WEAPON AMMO
        elif param == "ammo":
            myWeapon = passparam
            if ((passparam == '1') or (passparam == "primary")):
                myWeapon = self.get("primary")
            elif ((passparam == '2') or (passparam == "secondary")):
                myWeapon = self.get("secondary")
            # Note: change this when you make the above methods return None instead of '0':
            if myWeapon == '0':
                return 0
            if passparam.startswith('weapon_'):
                myWeapon = passparam[7:]
            myAmmoPath = 'CBasePlayer.localdata.m_iAmmo.' + _weapons_ammo[myWeapon]
            return es.getplayerprop(self.userid, myAmmoPath)
        # GET WEAPON CLIP
        elif param == "clip":
            myWeapon = passparam
            if ((passparam == '1') or (passparam == "primary")):
                myWeapon = self.get("primary")
            elif ((passparam == '2') or (passparam == "secondary")):
                myWeapon = self.get("secondary")
            if myWeapon == '0':
                return '0'
            if passparam.startswith('weapon_'):
                passparam = passparam[7:]
            myWeaponIndex = self.get("weaponindex", myWeapon)
            return es.getindexprop(myWeaponIndex, 'CBaseCombatWeapon.LocalWeaponData.m_iClip1')
        # GET WEAPON INDEX
        elif param == "weaponindex":
            if "weapon_" not in passparam:
                passparam = "weapon_" + passparam
            myHandle = es.getplayerhandle(self.userid)
            # get a list of all of those weapons
            myList = es.createentitylist(passparam)
            # this is the end of the propertyname we want to check
            pname = "m_hOwner"
            # for every weapon in that list
            for item in myList.keys():
                # let's check all of their property names
                for prop in myList[item].keys():
                    # if the properyname is long enough and it ends in "m_hOwner"
                    if len(prop) > len(pname) and prop[-len(pname):] == pname:
                        # return it if it's owned by that player
                        if myList[item][prop] == myHandle:
                            return item
                        else:
                            break
                            # didn't find it
            return 0
        # GET VIEWANGLE
        elif param == "viewangle":
            myRotation = es.getplayerprop(self.userid, "CBaseEntity.m_angRotation")
            myRotation = es.splitvectorstring(myRotation)
            myEyeAngle0 = es.getplayerprop(self.userid, "CCSPlayer.m_angEyeAngles[0]")
            myEyeAngle1 = es.getplayerprop(self.userid, "CCSPlayer.m_angEyeAngles[1]")
            if myEyeAngle1 < 0:
                myEyeAngle1 += 360
            myViewAngle = (float(myEyeAngle0), float(myEyeAngle1), float(myRotation[2]))
            return myViewAngle
        # GET PLAYER CASH
        elif param == "cash":
            return es.getplayerprop(self.userid, "CCSPlayer.m_iAccount")
        # GET PLAYER HEALTH
        elif param == "health":
            return es.getplayerprop(self.userid, "CBasePlayer.m_iHealth")
        # GET PLAYER ARMOR
        elif param == "armor":
            return es.getplayerprop(self.userid, "CCSPlayer.m_ArmorValue")
        # GET PLAYER SPEEED
        elif param == "speed":
            return es.getplayerprop(self.userid, "CBasePlayer.localdata.m_flLaggedMovementValue")
        # GET DEFUSER
        elif param == "defuser":
            return es.getplayerprop(self.userid, "CCSPlayer.m_bHasDefuser")
        # GET VIEWVECTOR
        elif param == "viewvector":
            myEyeAngle0 = es.getplayerprop(self.userid, "CCSPlayer.m_angEyeAngles[0]")
            myEyeAngle1 = es.getplayerprop(self.userid, "CCSPlayer.m_angEyeAngles[1]")
            myX = math.cos(math.radians(myEyeAngle1))
            myY = math.sin(math.radians(myEyeAngle1))
            myZ = -1 * math.sin(math.radians(myEyeAngle0))
            myViewVector = (myX, myY, myZ)
            return myViewVector
        # GET DISTANCE
        elif param == "distance":
            isString = isinstance(passparam, basestring)
            myLocation = es.getplayerlocation(self.userid)
            if isString:
                hisLocation = es.getplayerlocation(passparam)
            else:
                hisLocation = es.getplayerlocation(passparam[0])
            myX = (float(myLocation[0]) - float(hisLocation[0]))
            myY = (float(myLocation[1]) - float(hisLocation[1]))
            myZ = (float(myLocation[2]) - float(hisLocation[2]))
            if isString == True:
                return math.sqrt(math.pow(myX,2) + math.pow(myY,2) + math.pow(myZ,2))
            elif passparam[1] == 'x':
                return myX
            elif passparam[1] == 'y':
                return myY
            elif passparam[1] == 'z':
                return myZ
            elif passparam[1] == 'xy':
                return math.sqrt(math.pow(myX,2) + math.pow(myY,2))
            elif passparam[1] == 'xz':
                return math.sqrt(math.pow(myX,2) + math.pow(myZ,2))
            elif passparam[1] == 'yz':
                return math.sqrt(math.pow(myY,2) + math.pow(myZ,2))
            elif passparam[1] == 'xyz':
                return math.sqrt(math.pow(myX,2) + math.pow(myY,2) + math.pow(myZ,2))
            else:
                return '0'
        # GET ISDEAD
        elif param == "isdead":
            #return es.getplayerprop(self.userid, "CBasePlayer.pl.deadflag")
            return self.attributes['isdead'];
        # GET NOCLIP
        elif param == "noclip":
            movetype = es.getplayerprop(self.userid, "CBaseEntity.movetype")
            if (movetype == 8):
                return '1'
            else:
                return '0'
        # GET JETPACK
        elif param == "jetpack":
            movetype = es.getplayerprop(self.userid, "CBaseEntity.movetype")
            if (movetype == 4):
                return '1'
            else:
                return '0'
        # GET FREEZE
        elif param == "freeze":
            movetype = es.getplayerprop(self.userid, "CBaseEntity.movetype")
            if (movetype == 0):
                return '1'
            else:
                return '0'
        # GET LOCATION
        elif param == "location":
            return es.getplayerlocation(self.userid)
        # GET FLASH ALPHA
        elif param == "flashalpha":
            return es.getplayerprop(self.userid, "CCSPlayer.m_flFlashMaxAlpha")
        # GET FLASH DURATION
        elif param == "flashduration":
            return es.getplayerprop(self.userid, "CCSPlayer.m_flFlashDuration")
        # GET COLOR
        elif param == "color":
            color = es.getplayerprop(self.userid, "CBaseEntity.m_clrRender")
            retval = []
            retval.append(color & 0xff)
            retval.append((color & 0xff00) >> 8)
            retval.append((color & 0xff0000) >> 16)
            retval.append((color & 0xff000000) >> 24)
            return tuple(map(int, retval))
        # GET LANG
        elif param == "lang":
            if "language" in self.attributes and self.attributes['language']:
              return langlib.getLangAbbreviation(self.attributes['language']) 
            else:
              return langlib.getDefaultLang()
        # GET ISDUCKED
        elif param == "isducked":
            return es.getplayerprop(self.userid, 'CBasePlayer.localdata.m_Local.m_bDucked') % 2
        # GET NIGHTVISION
        elif param == "nightvision":
            return es.getplayerprop(self.userid, 'CCSPlayer.m_bHasNightVision') % 2
        # GET NIGHTVISIONON
        elif param == "nightvisionon":
            return es.getplayerprop(self.userid, 'CCSPlayer.m_bNightVisionOn') % 2
        # GET INBUYZONE
        elif param == "inbuyzone":
            return es.getplayerprop(self.userid, 'CCSPlayer.m_bInBuyZone') % 2
        # GET INBOMBZONE
        elif param == "inbombzone":
            return es.getplayerprop(self.userid, 'CCSPlayer.m_bInBombZone') % 2
        # GET INRESCUEZONE
        elif param == "inrescuezone":
            return es.getplayerprop(self.userid, 'CCSPlayer.m_bInHostageRescueZone') % 2
        # GET IS DEFUSING
        elif param == "isdefusing":
            return es.getplayerprop(self.userid, 'CCSPlayer.m_bIsDefusing') % 2
        # GET HASHELMET
        elif param == "hashelmet":
            return es.getplayerprop(self.userid, 'CCSPlayer.m_bHasHelmet') % 2
        # GET ONGROUND
        elif param == "onground":
            return es.getplayerprop(self.userid, 'CBasePlayer.m_fFlags') & 1
        # GET VIEWCOORD
        elif param == "viewcoord":
            es.server.cmd('es_prop_dynamic_create %s props_c17/tv_monitor01_screen.mdl' % self.userid)
            location = es.getindexprop(es.ServerVar('eventscripts_lastgive'), 'CBaseEntity.m_vecOrigin')
            es.server.cmd('es_xremove %s' % es.ServerVar('eventscripts_lastgive'))
            return location
        # GET ATTRIBUTES
        elif self.attributes.has_key(param):
            return self.attributes[param]
        # GET NEARPLAYER
        #Syntax: .Get("nearplayer", <distance>)
        elif param == "nearplayer":
            nearlist = []
            x1,y1,z1 = es.getplayerlocation(self.userid)
            for id in es.getUseridList():
                x2,y2,z2 = es.getplayerlocation(id)
                if abs(x1-x2) <= passparam and abs(y1-y2) <= passparam and abs(z1-z2) <= passparam and id != self.userid:
                    nearlist.append(id)
            return nearlist
        # GET NEARCOORD
        #Syntax: .Get("nearcoord", (<x location>,<y location>,<z location>,<distance>))
        elif param == "nearcoord":
            nearlist = []
            x1,y1,z1 = passparam[0],passparam[1],passparam[2]
            for id in es.getUseridList():
                x2,y2,z2 = es.getplayerlocation(id)
                if abs(x1-x2) <= passparam[3] and abs(y1-y2) <= passparam[3] and abs(z1-z2) <= passparam[3]:
                    nearlist.append(id)
            return nearlist
        # GET CLOSEST PLAYER
        elif param == "closestplayer":
            xx,yy,zz = es.getplayerlocation(self.userid)
            if passparam:
                mylist = map(lambda x: [((xx-x[0]) ** 2 + (yy-x[1]) ** 2 + (zz-x[2]) ** 2) ** 0.5, x[3]], map(lambda x: list(es.getplayerlocation(x)) + [x], filter(lambda x: es.getplayerteam(x) == passparam and not es.getplayerprop(x, 'CBasePlayer.pl.deadflag') and not x == self.userid, es.getUseridList())))
            else:
                mylist = map(lambda x: [((xx-x[0]) ** 2 + (yy-x[1]) ** 2 + (zz-x[2]) ** 2) ** 0.5, x[3]], map(lambda x: list(es.getplayerlocation(x)) + [x], filter(lambda x: not es.getplayerprop(x, 'CBasePlayer.pl.deadflag') and not x == self.userid, es.getUseridList())))
            if mylist:
                return min(mylist)
            return (None,None)
        else:
            raise KeyError, "No such info '%s' in Player" % param

    def set(self, param, value=""):
        # This is all the parameters from the original playerset
        param = str(param).lower()
        # SET AMMO
        if param == "ammo":
            myWeapon = str(value[0])
            if ((str(value[0]) == '1') or (str(value[0]) == 'primary')):
                myWeapon = self.get('primary')
            elif ((str(value[0]) == '2') or (str(value[0]) == 'secondary')):
                myWeapon = self.get("secondary")
            elif myWeapon.startswith('weapon_'):
                myWeapon = myWeapon[7:]
            if myWeapon == '0':
                raise ValueError, 'Player has no weapon corresponding with %s' % value[0]
            else:
                es.setplayerprop(self.userid, 'CBasePlayer.localdata.m_iAmmo.' + _weapons_ammo[myWeapon], value[1])
        # SET CLIP
        elif param == "clip":
            myWeapon = str(value[0])
            if ((str(value[0]) == '1') or (str(value[0]) == 'primary')):
                myWeapon = self.get("primary")
            elif ((str(value[0]) == '2') or (str(value[0]) == 'secondary')):
                myWeapon = self.get("secondary")
            elif myWeapon.startswith('weapon_'):
                myWeapon = myWeapon[7:]
            if myWeapon == '0':
                raise ValueError, 'Player has no weapon corresponding with %s' % value[0]
            else:
                es.setindexprop(self.get('weaponindex', myWeapon), "CBaseCombatWeapon.LocalWeaponData.m_iClip1", value[1])
        # SET HEALTH
        elif param == "health":
            es.setplayerprop(self.userid, "CBasePlayer.m_iHealth", value)
        # SET ARMOR
        elif param == "armor":
            es.setplayerprop(self.userid, "CCSPlayer.m_ArmorValue", value)
        # SET SPEED
        elif param == "speed":
            es.setplayerprop(self.userid, "CBasePlayer.localdata.m_flLaggedMovementValue", value)
        # SET CASH
        elif param == "cash":
            es.setplayerprop(self.userid, "CCSPlayer.m_iAccount", value)
        # SET DEFUSER
        elif param == "defuser":
            es.setplayerprop(self.userid, "CCSPlayer.m_bHasDefuser", value)
        # SET NIGHTVISION
        elif param == "nightvision":
            es.setplayerprop(self.userid, "CCSPlayer.m_bHasNightVision", value)
        # SET NIGHTVISION ON
        elif param == "nightvisionon":
            es.setplayerprop(self.userid, "CCSPlayer.m_bNightVisionOn", value)
        # SET VIEWPLAYER
        elif param == "viewplayer":
            myLocation = es.getplayerlocation(self.userid)
            hisLocation = es.getplayerlocation(value[0])
            myVector = es.createvectorstring(myLocation[0], myLocation[1], myLocation[2])
            hisVector = es.createvectorstring(hisLocation[0], hisLocation[1], hisLocation[2])
            ourVector = es.createvectorfrompoints(myVector, hisVector)
            ourVector = es.splitvectorstring(ourVector)
            myViewAngle = self.get('viewangle')
            ourAtan = math.degrees(math.atan(float(ourVector[1])/float(ourVector[0])))
            if float(ourVector[0]) < 0:
                RealAngle = ourAtan + 180
            else:
                if float(ourVector[1]) < 0:
                    RealAngle = ourAtan + 360
                else:
                    RealAngle = ourAtan
            yAngle = RealAngle
            xAngle = 0 - math.degrees(math.atan(ourVector[2]/math.sqrt(math.pow(float(ourVector[1]),2) + math.pow(float(ourVector[0]),2))))
            es.server.cmd('es_xsetang %s %s %s %s' % (self.userid, xAngle, yAngle, myViewAngle[2]))
        # SET VIEWCOORD
        elif param == "viewcoord":
            myLocation = es.getplayerlocation(self.userid)
            myVector = es.createvectorstring(myLocation[0], myLocation[1], myLocation[2])
            theVector = es.createvectorstring(value[0], value[1], value[2])
            ourVector = es.createvectorfrompoints(myVector, theVector)
            ourVector = es.splitvectorstring(ourVector)
            myViewAngle = self.get('viewangle')
            ourAtan = math.degrees(math.atan(float(ourVector[1])/float(ourVector[0])))
            if float(ourVector[0]) < 0:
                RealAngle = ourAtan + 180
            else:
                if float(ourVector[1]) < 0:
                    RealAngle = ourAtan + 360
                else:
                    RealAngle = ourAtan
            yAngle = RealAngle
            xAngle = 0 - math.degrees(math.atan(ourVector[2]/math.sqrt(math.pow(float(ourVector[1]),2) + math.pow(float(ourVector[0]),2))))
            es.server.cmd('es_xsetang %s %s %s %s' % (self.userid, xAngle, yAngle, myViewAngle[2]))
        # SET PUSH
        elif param == "push":
            myVector = self.get('viewvector')
            horzX = float(value[0]) * float(myVector[0])
            horzY = float(value[0]) * float(myVector[1])
            if str(value[2]) == '0':
                vertZ = float(myVector[2]) * float(value[1])
            else:
                vertZ = value[1]
            myNewVector = es.createvectorstring(horzX, horzY, vertZ)
            es.setplayerprop(self.userid,"CBasePlayer.localdata.m_vecBaseVelocity", myNewVector)
        # SET MODEL
        elif param == "model":
            myModel = value.replace("/", "\\")
            if not myModel.startswith("models\\"):
                myModel = "models\\" + myModel
            if not myModel.endswith(".mdl"):
                myModel = myModel + ".mdl"
            es.setplayerprop(self.userid, "CBaseEntity.m_nModelIndex", es.precachemodel(myModel))
            self.set('color', ['255', '255', '255', '255'])
        # SET COLOR
        elif param == "color":
            value = map(int, value)
            color = value[0]
            color += value[1] << 8
            color += value[2] << 16
            if len(value) >= 4:
                color += value[3] << 24
            else:
                color += self.get("color")[3] << 24
            if color >= 2**31: color -= 2**32
            oldRenderMode = es.getplayerprop(self.userid, "CBaseEntity.m_nRenderMode")
            oldRenderFX = es.getplayerprop(self.userid, "CBaseEntity.m_nRenderFX")
            newRenderMode = oldRenderMode | 1
            newRenderFX = oldRenderFX | 256
            es.setplayerprop(self.userid, "CBaseEntity.m_nRenderMode", newRenderMode)
            es.setplayerprop(self.userid, "CBaseEntity.m_nRenderFX", newRenderFX)
            es.setplayerprop(self.userid, "CBaseEntity.m_clrRender", color)
        # SET NOCLIP
        elif param == "noclip":
            if str(value) == '1':
                es.setplayerprop(self.userid, "CBaseEntity.movetype", '8')
            elif str(value) == '0':
                es.setplayerprop(self.userid, "CBaseEntity.movetype", '2')
        # SET JETPACK
        elif param == "jetpack":
            if str(value) == '1':
                es.setplayerprop(self.userid, "CBaseEntity.movetype", '4')
            elif str(value) == '0':
                es.setplayerprop(self.userid, "CBaseEntity.movetype", '2')
        # SET FREEZE
        elif param == "freeze":
            if str(value) == '1':
                es.setplayerprop(self.userid, "CBaseEntity.movetype", '0')
            elif str(value) == '0':
                es.setplayerprop(self.userid, "CBaseEntity.movetype", '2')
        # SET LOCATION
        elif param == "location":
            es.server.cmd('es_xsetpos %s %s %s %s' % (self.userid, str(value[0]), str(value[1]), str(value[2])))
        # SET MOVE TO
        elif param == "moveto":
            hisLocation = list(es.getplayerlocation(value))
            hisLocation[0] = float(hisLocation[0]) + 50
            hisLocation[2] = float(hisLocation[2]) + 10
            es.server.cmd('es_xsetpos %s %s %s %s' % (self.userid, hisLocation[0], hisLocation[1], hisLocation[2]))
        # SET FLASH ALPHA AND DURATION
        elif param == "flash":
            es.setplayerprop(self.userid, "CCSPlayer.m_flFlashMaxAlpha", str(value[0]))
            es.setplayerprop(self.userid, "CCSPlayer.m_flFlashDuration", str(value[1]))
        # SET HE
        elif param == "he":
            es.setplayerprop(self.userid, "CBasePlayer.localdata.m_iAmmo.011", value)
        # SET FB
        elif param == "fb":
            es.setplayerprop(self.userid, "CBasePlayer.localdata.m_iAmmo.012", value)
        # SET SG
        elif param == "sg":
            es.setplayerprop(self.userid, "CBasePlayer.localdata.m_iAmmo.013", value)
        # SET HASHELMET
        elif param == "hashelmet":
            es.setplayerprop(self.userid, "CCSPlayer.m_bHasHelmet", value)
        # SET WEAPONCOLOR
        elif param == "weaponcolor":
            value = map(int, value)
            color = value[0]
            color += value[1] << 8
            color += value[2] << 16
            if len(value) >= 4:
                color += value [3] << 24
            else:
                color += self.get("color")[3] << 24
            if color >= 2**31: color -= 2**32
            oldRenderMode = es.getplayerprop(self.userid, "CBaseEntity.m_nRenderMode")
            oldRenderFX = es.getplayerprop(self.userid, "CBaseEntity.m_nRenderFX")
            newRenderMode = oldRenderMode | 1
            newRenderFX = oldRenderFX | 256
            for entity in es.createentitylist(str(self.attributes["weapon"])):
                if es.getplayerhandle(self.userid) == es.getindexprop(entity, 'CBaseEntity.m_hOwnerEntity'):
                    es.setindexprop(entity, "CBaseEntity.m_nRenderMode", newRenderMode)
                    es.setindexprop(entity, "CBaseEntity.m_nRenderFX", newRenderFX)
                    es.setindexprop(entity, "CBaseEntity.m_clrRender", color)
                    break
        elif param == "burn":
            es.server.cmd('es_xfire %s !self ignite'%self.userid)
        elif param == "extinguish":
            flamelist = es.createentitylist("entityflame") 
            handle = es.getplayerhandle(self.userid) 
            for flame_entity in flamelist: 
                string = es.getindexprop(flame_entity, 'CEntityFlame.m_hEntAttached') 
                if string == handle: 
                    es.setindexprop(flame_entity, 'CEntityFlame.m_flLifetime', 0) 
                    break
        else:
            raise KeyError, "No such info '%s' in Player" % param

    def add(self, param, value):
        # This is all the add parameters from the original playerset plus clip and ammo
        param = str(param).lower()
        # ADD AMMO
        if param == "ammo":
            myWeapon = str(value[0])
            es.msg(myWeapon)
            temp = int(self.get("ammo", myWeapon)) + int(value[1])
            es.msg(str(temp) + " " + myWeapon)
            self.set("ammo", (myWeapon, temp))
        # ADD CLIP
        elif param == "clip":
            myWeapon = str(value[0])
            temp = int(self.get("clip", myWeapon)) + int(value[1])
            self.set("clip", (myWeapon, temp))
        # ADD HEALTH
        elif param == "health":
            temp = int(self.get("health") )
            self.set("health", int(value) + temp )
        # ADD ARMOR
        elif param == "armor":
            temp = int(self.get("armor") )
            self.set("armor", int(value) + temp )
        # ADD SPEED
        elif param == "speed":
            temp = float(self.get("speed") )
            self.set("speed", float(value) + temp )
        # ADD CASH
        elif param == "cash":
            temp = int(self.get("cash") )
            self.set("cash", int(value) + temp )
        else:
            raise KeyError, "No such info '%s' in Player" % param 

    def getOnline(self):
        return es.exists('userid', self.userid)

    def kill(self):
        '''
        Slays the player in this gameframe.
        '''
        es.server.queuecmd('es_xsexec %d kill' % (self.userid))

    def kick(self, reason=None):
        '''
        Kicks the player from the server (with an optional reason).
        '''
        if reason is not None:
            # This is very light injection protection.
            # We could do better than just remove them.
            reason = reason.replace(';', '')
            reason = reason.replace('//', '')
            if reason.count('"') % 2:
                # Uneven amount of quotes.
                reason += '"'

            es.server.queuecmd('kickid %d %s' % (self.userid, reason))
        else:
            es.server.queuecmd('kickid ' + str(self.userid))

    def banId(self, time, kick=False, reason=None):
        '''
        Bans the player from the server by SteamID (and optionally kick with a reason).
        '''
        es.server.queuecmd('banid %d %s' % (time, self.attributes['steamid']))
        es.server.queuecmd('writeid')
        if kick:
            self.kick(reason)

    def banAddr(self, time, kick=False, reason=None):
        '''
        Bans the player from the server by IP address (and optionally kick with a reason).
        '''
        es.server.queuecmd('addip %d %s' % (time, self.attributes['address'][:self.attributes['address'].find(':')]))
        es.server.queuecmd('writeip')
        if kick:
            self.kick(reason)

    def __int__(self):
        return self.userid

    # more stuff in the class


# now for the module functions

# allow them to save a a filter function for things like "#all", "#t", etc.
def registerPlayerListFilter(filtername, filterfunction):
    filters[filtername] = filterfunction

def unregisterPlayerListFilter(filtername):
    if filters.has_key(filtername):
        del filters[filtername]

def getPlayer(userid):
    try:
        # Why not just use the Player constructor?
        return Player(userid)
    except (UseridError, TypeError), e:
        raise e

def getPlayerList(filtername=None):
    """
    Retrieves a list of Player objects.
    """
    # I haven't tested it, but this should create a list of Players objects
    # mapped to the current user list.
    playerlist = map(getPlayer, es.getUseridList())
    # added this to get rif of spaces in the filter.
    if filtername is not None:
        filtername = filtername.strip(' ')
        # use the filtername to lookup from filters dictionary
        # apply this filter to the playerlist
        # I have no idea if this works, I've never tried filter() before
        # playerlist = filter(filters[filtername], playerlist)
        for y in filtername.split(","):
            playerlist = filter(filters[y], playerlist)

    return playerlist

def getUseridList(userspec):
    """
    getUseridList returns either a list of filtered players or a userid
    if used with a partial name or exact steamid
    """
    if not userspec: return []
    if userspec == "#all":
        return es.getUseridList()
    if userspec[0] == "#":
        return map(int, getPlayerList(userspec))
    else:
        userid = es.getuserid(userspec)
        if userid == 0: return []
        return [userid]

def returnAll(x):
    return True

def returnTeam0(x):
    if x.attributes['teamid'] == 0:
        return True
    return False

def returnTeam1(x):
    if x.attributes['teamid'] == 1:
        return True
    return False

def returnTeam2(x):
    if x.attributes['teamid'] == 2:
        return True
    return False

def returnTeam3(x):
    if x.attributes['teamid'] == 3:
        return True
    return False

def returnAlive(x):
    if not x.attributes['isdead']:
        return True
    return False

def returnDead(x):
    if x.attributes['isdead']:
        return True
    return False

def returnHuman(x):
    if not x.attributes['isbot']:
        return True
    return False

def returnBot(x):
    if x.attributes['isbot']:
        return True
    return False

def list2string(somelist, separator):
    result = ""
    for item in somelist:
        result += str(item) + str(separator)
    result = result[0:-len(str(separator))]
    return result

def uniqueid(userid, botname=None):
    # uniqueid(userid,[add botname])
    userid = int(userid)
    if not es.exists('userid',userid):
        es.dbgmsg(0,'uniqueid: The userid ' + str(userid) + ' does not exist')
        return 0
    else:
        # Regular steamids will automatically be set on the line below:
        uniqueid = es.getplayersteamid(int(userid))
        if not uniqueid:
            uniqueid = es.createplayerlist()[userid]['steamid']
        if 'LAN' in str(uniqueid):
            # This code is for LAN steamids:
            address = es.createplayerlist()[userid]['address'].split(':')[0]
            uniqueid = 'LAN_%d:%s' %(len(address),address.replace('.',''))
        elif 'BOT' in str(uniqueid):
            # This code is for BOT steamids:
            if botname:
               bot = es.createplayerlist()[int(userid)]['name']
               uniqueid = ('BOT_%s' %bot).upper()
            else:
               uniqueid = 'BOT'.upper()
        return uniqueid

def uniqueid_oldschool():
    # uniqueid <var> <userid> [add botname]
    if es.getargv(1):
        es.set(es.getargv(1),uniqueid(int(es.getargv(2)),es.getargv(3)))
    else:
        es.dbgmsg(0,'uniqueid: No variable provided to be set.')

# default filters
def _registerDefaultFilters():
    registerPlayerListFilter("#all", returnAll)
    registerPlayerListFilter("#un", returnTeam0)
    registerPlayerListFilter("#spec", returnTeam1)
    registerPlayerListFilter("#t", returnTeam2)
    registerPlayerListFilter("#ct", returnTeam3)
    registerPlayerListFilter("#alive", returnAlive)
    registerPlayerListFilter("#dead", returnDead)
    registerPlayerListFilter("#human", returnHuman)
    registerPlayerListFilter("#bot", returnBot)
_registerDefaultFilters()
