import es
import gamethread
import random
import playerlib
import time

import wcs
from wcs import wcs

raceName = 'Shadow Hunter'
race     = wcs.Race(raceName)

""" Load the strings into the variable text """
text     = race.loadStrings()

""" ############################### """
""" ### Begin the configuration ### """
""" ############################### """

config   = race.config()

raceMinLevel         = config.addVar('raceMinLevel',        60, 'The minimum total level a user must have before having the ability to play Shadow Hunter')


config.addComment()
config.addComment('********************')
config.addComment('Healing Wave')
config.addComment('  This skill is used by binding a key to +ability2.')
config.addComment('  when the player looks at another team mate, a healing')
config.addComment('  beam will bounce from player to player, the beam slowly')
config.addComment('  getting weaker.')
config.addComment('********************')
config.addComment()

healingMaxlevel        = config.addVar('healingMaxLevel',         5, 'The maximum level of the Healing Wave skill')
healingLevelInterval   = config.addVar('healingLevelInterval',    2, 'The intervals between the abilities to upgrade their Healing Wave skill')
healingStartMultiplier = config.addVar('healingStartMultiplier', 15, 'How much health the first person will receive multipied by the players level.')
healingLossPercent     = config.addVar('healingLossPercent',     40, 'How much effect each \'jump\' will loose. ')

config.addComment()
config.addComment('********************')
config.addComment('Hex')
config.addComment('  This skill has a chance of halving a players speed for X amount of seconds.')
config.addComment('********************')
config.addComment()
hexMaxLevel            = config.addVar('hexMaxLevel',      6, 'The maximum level of the Hex skill')
hexLevelInterval       = config.addVar('hexLevelInterval', 1, 'The intervals between the abilities to upgrade their Hex skill')
hexPercentage          = config.addVar('hexPercentage',    18, 'This is the chance the skill will happen multiplied by their level.')

config.addComment()
config.addComment('********************')
config.addComment('Serpent Wards')
config.addComment('  This skill places a serpent ward at the players current location which attackes')
config.addComment('  nearby enemies. Used by pressing the ability +ability')
config.addComment('********************')
config.addComment()
serpentMaxLevel        = config.addVar('serpentMaxLevel',      6, 'The maximum level of the Serpent Wards skill')
serpentLevelInterval   = config.addVar('serpentLevelInterval', 3, 'The intervals between the abilities to upgrade their Serpent Wards skill')
serpentMaxWards        = config.addVar('serpentMaxWards',      2, 'The maximum amount of wards at any 1 time.')

config.addComment()
config.addComment('********************')
config.addComment('Big Bad Voodo')
config.addComment('  This ultimate turns all near team-mates invinisible for X seconds.')
config.addComment('********************')
config.addComment()
voodoMinLevel          = config.addVar('voodoMinLevel',      6, 'The required level to be able to buy level 1 of Big Bad Boodo')
voodoMaxLevel          = config.addVar('voodoMaxLevel',      6, 'The maximum level of the Big Bad Boodo skill')
voodoLevelInterval     = config.addVar('voodoLevelInterval', 3, 'The intervals between the abilities to upgrade their Big Bad Boodo skill')
voodoTime              = config.addVar('voodoTime',          1, 'The amount of seconds team-mates will stay invinsible for multiplied by the players voodo level.')

config.load(True)

""" ##################### """
""" ### END OF CONFIG ### """
""" ##################### """

race.registerSkill('Healing Wave', int(healingMaxlevel), int(healingLevelInterval), 'Calls forth a wave of energy that heals a target and bounces to nearby friendlies. (+ability2)')
race.registerSkill('Hex', int(hexMaxLevel), int(hexLevelInterval), 'Have a chance to slow down your enemies!')
race.registerSkill('Serpent Ward', int(serpentMaxLevel), int(serpentLevelInterval), 'Summons an immobile serpentine ward to attack the Shadow Hunter\'s enemies (+ability)')
race.registerUltimate('Big Bad Voodo', int(voodoMinLevel), int(voodoMaxLevel), int(voodoLevelInterval), 'Turns all friendly units invulnerable in an area around the Shadow Hunter.')

race.registerMinLevel(int(raceMinLevel))

serpentWardsDict = {}
class serpentWards(object):
    def __init__(self, userid, index):
        self.userid   = str(userid)
        self.team     = es.getplayerteam(self.userid)
        self.level    = wcs.GetLevel(self.userid, raceName, 'Serpent Ward')
        self.index    = str(index)
        self.start    = 0
        self.location = tuple() 
        
    def addLocation(self, x, y = None, z = None):
        if not (isinstance(x, list) or isinstance(x, tuple)):
            x = tuple((x, y, z))
        self.location = x
        self.start    = time.time()
        
    def hurtLoop(self):
        if time.time() - self.start <= 20:
            x, y, z = self.location
            wcs.effect.RingCustom('#a', '0', 'sprites/lgtning.vmt', x, y, z, 20, self.level * 40, 1, 20, 100, 1, 255, 150, 70, 100, 10)
            for player in filter(lambda x: es.getplayerteam(x) != self.team and not es.getplayerprop(x, 'CBasePlayer.pl.deadflag'), es.getUseridList() ):
                xx, yy, zz = es.getplayerlocation(player)
                if ((xx - x) ** 2 + (yy - y) ** 2 + (zz - z) ** 2) ** 0.5 <= (self.level * 40):
                    wcs.Command(player).Damage(self.level * random.randint(4,6), 32, self.userid)
                    wcs.effect.BeamCustom('#a', '0', 'sprites/lgtning.vmt', x, y, z + 30, xx, yy, zz + 30, 1, 10, 20, 255, 150, 70, 255)
            gamethread.delayedname(1, 'serpent_loop', self.hurtLoop)
        else:
            if es.exists('userid', self.userid):
                es.tell(self.userid, '#multi', text('serpent gone', {'index' : self.index}, playerlib.getPlayer(self.userid).get("lang") ) )
            if len(serpentWardsDict[self.userid]) == 1:
                del serpentWardsDict[self.userid]
            else:
                del serpentWardsDict[self.userid][self.index]
                
def player_ability_on(ev):
    userid  = str(ev['userid'])
    serpent = wcs.GetLevel(userid, raceName, 'Serpent Ward')
    if serpent:
        cooldown = wcs.Command(userid).GetCoolDown('Serpent Ward')
        if not cooldown:
            if not serpentWardsDict.has_key(userid) or len(serpentWardsDict[userid]) < int(serpentMaxWards):
                if not serpentWardsDict.has_key(userid):
                    serpentWardsDict[userid] = {}
                    instance = serpentWardsDict[userid]['1'] = serpentWards(userid, '1')
                else:
                    index = str(max(map(int, serpentWardsDict[userid])) + 1)
                    instance = serpentWardsDict[userid][index] = serpentWards(userid, index)
                instance.addLocation(es.getplayerlocation(userid))
                instance.hurtLoop()
                wcs.Command(userid).SetCoolDown('Serpent Ward', 10)
            else:
                es.tell(userid, '#green', text('max wards', lang = playerlib.getPlayer(userid).get("lang") ) )
        else:
            es.tell(userid, '#multi', text('cooldown', {'skill':'Serpent Ward', 'time': cooldown}, playerlib.getPlayer(userid).get("lang") ) )
            
def round_end(ev):
    serpentWardsDict.clear()
    gamethread.cancelDelayed('serpent_loop')
    
def player_disconnect(ev):
    userid = ev['userid']
    if serpentWardsDict.has_key(userid):
        del serpentWardsDict[userid]
    
def player_ability_on2(ev):
    userid   = int(ev['userid'])
    cooldown = wcs.Command(userid).GetCoolDown('Healing Wave')
    if not cooldown:
        level = wcs.GetLevel(userid, raceName, 'Healing Wave')
        if level:
            heal = level * int(healingStartMultiplier)
            x,y,z = es.getplayerlocation(userid)
            wcs.effect.BeamCustom('#a', 0, 'sprites/halo01.vmt', x, y, z, x, y, z + 400, 5, 80, 40, 255, 0, 255, 155)
            wcs.Command(userid).SetCoolDown('Healing Wave', 20)
            wcs.Command(userid).GetViewPlayer(safeGetPlayer, heal, [userid])
    else:
        es.tell(userid, '#multi', text('cooldown', {'skill':'Healing Wave', 'time': cooldown}, playerlib.getPlayer(userid).get("lang") ) )
        
def safeGetPlayer(userid, target, heal, banned):
    if target and es.exists('userid', target):
        wcs.Command(target).Heal(heal)
        banned.append(target)
        x,y,z   = es.getplayerlocation(target)
        team    = es.getplayerteam(target)
        allowed = filter(lambda x: x not in banned and wcs.Command(target).Distance(x) <= 500 and not wcs.Command(x).IsDead() and es.getplayerteam(x) == team, es.getUseridList() )
        if len(allowed):
            randomPlayer = random.choice(allowed)
            wcs.effect.Beam4(target, randomPlayer, 4, 255, 0, 0)
            wcs.effect.Ring4(randomPlayer, 150, 75, 4, 60, 80, 0, 255, 0)
            heal = int(round(heal * ( (100 - (int(healingLossPercent) ) ) / 100.) ) )
            wcs.Command(randomPlayer).Heal(heal)
            gamethread.delayed(0.5, safeGetPlayer,(target, randomPlayer, heal, banned ) )
    else:
        es.tell(userid, '#multi', text('healing no player', lang = playerlib.getPlayer(userid).get("lang") ) )
        
def player_hurt(ev):
    userid   = int(ev['userid'])
    attacker = int(ev['attacker'])
    if ev['es_userteam'] != ev['es_attackerteam'] and attacker and not wcs.Command(userid).ReturnDict('Hexed'):
        Hex = wcs.GetLevel(attacker, raceName, 'Hex')
        if Hex and (random.randint(1,100) <= (int(hexPercentage) * Hex)):   
            wcs.Command(userid).UpdateDict('Hexed', 1)
            speed   = wcs.Command(userid).ReturnDict('Speed')
            divider = speed/(1 + (Hex * 0.2))
            # This should divide the speed by: 1.2, 1.4, 1.6, 1.8, 2.0, 2.2
            wcs.Command(userid).Speed(speed / divider)
            tokens             = {}
            tokens['speed']    = round(100 * divider  * speed, 1)
            tokens['attacker'] = ev['es_attackername']
            tokens['victim']   = ev['es_username']
            es.tell(userid,   '#multi', text('hex victim',   tokens, playerlib.getPlayer(userid).get("lang") ) )
            es.tell(attacker, '#multi', text('hex attacker', tokens, playerlib.getPlayer(attacker).get("lang") ) )
            gamethread.delayed(3, wcs.Command(userid).Speed, speed)
            gamethread.delayed(3, wcs.Command(userid).UpdateDict, ('Hexed', 0) )
        
def player_spawn(ev):
    wcs.Command(ev['userid']).UpdateDict('Hexed', 0)
        
def player_ultimate_on(ev):
    userid = int(ev['userid'])
    voodo = wcs.GetLevel(userid, raceName, 'Big Bad Voodo')
    if voodo:
        wcs.Command(userid).Near(voodo * 50, God, '%s' % ('#t' if ev['es_userteam'] == '2' else '#ct') )
        wcs.Command(userid).SetCoolDown('Big Bad Voodo', 30)
        x, y, z = es.getplayerlocation(userid)
        wcs.effect.RingCustom('#a', '0', 'sprites/lgtning.vmt', x, y, z, 20, voodo * 50, 1, 20, 100, 1, 255, 0, 0, 100, 10)
		
def God(userid, target):
    voodo = wcs.GetLevel(target, raceName, 'Big Bad Voodo')
    wcs.Command(userid).God(voodo * int(voodoTime))
    wcs.effect.Ring4(userid, 150, 50, voodo, 50, 100, 255, 0, 255)
    es.tell(userid, '#multi', text('voodo', {'time': voodo * int(voodoTime)}, playerlib.getPlayer(userid).get("lang") ) )
