class EarthgrabTotem(Skill): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.model = Model('sprites/blueflare1.vmt', True) self.model._precache() self.effect = TempEntity('BeamRingPoint', start_radius=120, end_radius=0, model_index=self.model.index, halo_index=self.model.index, life_time=1.5, amplitude=10, red=10, green=255, blue=10, alpha=245, flags=0, start_width=6, end_width=6) if not root_sound.is_precached: root_sound.precache() @classproperty def description(cls): return 'Root your enemies to the ground, 16-24% chance.' @classproperty def max_level(cls): return 8 _msg_a = '{{GREEN}}Rooted {{RED}}{name} {{PALE_GREEN}}to the ground.' _msg_b = '{{PALE_GREEN}}You have been {{GREEN}}rooted {{PALE_GREEN}}to the ground by {{RED}}{name}.' @events('player_pre_attack') def _on_player_pre_attack(self, attacker, victim, **kwargs): if self.level == 0: return if randint(1, 100) <= 16 + self.level and not victim.stuck: victim.stuck = True victim.delay(1.5, victim.__setattr__, args=('stuck', False)) send_wcs_saytext_by_index(self._msg_a.format(name=victim.name), attacker.index) send_wcs_saytext_by_index(self._msg_b.format(name=attacker.name), victim.index) root_sound.index = victim.index root_sound.origin = victim.origin root_sound.play() self.effect.create(center=victim.origin) self.effect.create(center=victim.origin, start_radius=80)
class HammerOfJustice(Skill): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self._model = Model("sprites/lgtning.vmt", True) self._model._precache() if not stun_sound.is_precached: stun_sound.precache() @classproperty def description(cls): return 'Slam your hammer into the ground, to knock up and enemy and stun them.' @classproperty def max_level(cls): return 6 @events('player_pre_attack') def _on_player_pre_attack(self, attacker, victim, **kwargs): if randint( 1, 100) < 10 + self.level and not victim.stuck and self.level > 0: victim.base_velocity = Vector(0, 0, 400) victim.delay(0.8, victim.__setattr__, args=('stuck', True)) victim.delay(1.8, victim.__setattr__, args=('stuck', False)) bottom_vector = victim.origin top_vector = victim.origin top_vector.z += 100 _effect = TempEntity('BeamPoints', alpha=255, red=100, blue=255, green=100, amplitude=10, end_width=20, start_width=20, life_time=2, fade_length=2, halo_index=self._model.index, model_index=self._model.index, start_point=top_vector, end_point=bottom_vector) _effect.create() stun_sound.index = victim.index stun_sound.origin = victim.origin stun_sound.play()
class BidBadVoodoo(Skill): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.cooldowns = CooldownDict() self._godmode = False self.model = Model("sprites/strider_bluebeam.vmt", True) self.model._precache() self.effect = TempEntity('BeamFollow', model=self.model, halo=self.model, alpha=255, red=220, blue=220, green=220, amplitude=10, end_width=20, start_width=20, fade_length=2) if not godmode_sound.is_precached: godmode_sound.precache() @classproperty def description(cls): return 'Gives you immunity to all damage for a short time. Ultimate.' @classproperty def max_level(cls): return 6 @classmethod def is_available(cls, player): return player.race.level > 8 @property def duration(self): return 1 + (self.level * 0.3) _msg_a = '{{RED}}Bid Bad Voodoo {{PALE_GREEN}}is active for {{ORANGE}}{time} {{PALE_GREEN}}seconds!' _msg_b = '{RED}Bid Bad Voodoo {PALE_GREEN}is deactivating in {ORANGE}1 {PALE_GREEN}second!' _msg_c = '{{RED}}Bid Bad Voodoo {{PALE_GREEN}}is on cooldown for {{DULL_RED}}{time:0.1f} seconds.' @events('player_spawn', 'player_upgrade_skill') def _on_player_spawn_reset(self, player, **kwargs): self.cooldowns['ultimate'] = 4 self._godmode = False @events('player_pre_victim') def _on_player_pre_victim(self, info, **kwargs): if self._godmode: info.damage = 0 @clientcommands('ultimate') def _on_player_ultimate(self, player, **kwargs): if self.level == 0: return _cooldown = self.cooldowns['ultimate'] if _cooldown <= 0: self._godmode = True Delay(self.duration, self.__setattr__, args=('_godmode', False)) self.effect.create(life_time=self.duration, entity=player) send_wcs_saytext_by_index(self._msg_a.format(time=self.duration), player.index) Delay(self.duration - 1, send_wcs_saytext_by_index, args=(self._msg_b, player.index)) godmode_sound.index = player.index godmode_sound.origin = player.origin godmode_sound.play() self.cooldowns['ultimate'] = (30 - self.level) else: send_wcs_saytext_by_index(self._msg_c.format(time=_cooldown), player.index)
class ChainLightning(Skill): laser = Model('sprites/lgtning.vmt', True) def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.cooldowns = CooldownDict() self.beam = TempEntity('BeamPoints', alpha=255, red=255, green=200, blue=200, life_time=1.0, start_width=15, end_width=15, frame_rate=255) self.laser = Model('sprites/lgtning.vmt') self.laser._precache() @classproperty def description(cls): return 'You channel a lightning rod which ricochets from player to player.' @classproperty def max_level(cls): return 8 @classmethod def is_available(cls, player): return player.race.level > 8 _msg_a = '{GREEN}Chain Lightning {RED}hit enemies{PALE_GREEN}!' _msg_c = '{{GREEN}}Chain Lightning {{PALE_GREEN}}is on cooldown for {{DULL_RED}}{time:0.1f} {{PALE_GREEN}}seconds.' _msg_f = '{GREEN}Chain Lightning {PALE_GREEN}found {DULL_RED}no enemies{PALE_GREEN}!' def _find_closest_player(self, player, team_index, length=99999, exclusions=[]): _target = None for target in player_dict.values(): if target.dead or target.team_index == team_index or target in exclusions or target.ultimate_immune: continue _distance = player.origin.get_distance(target.origin) if _distance < length: _target = target length = _distance return _target def _find_chain_players(self, player, length, count): _last_target = player team_index = player.team_index _targets = [] while count > 0: if not _last_target: break _target = self._find_closest_player(_last_target, team_index, length, _targets) _targets.append(_target) _last_target = _target count -= 1 return _targets @events('player_spawn') def _on_player_spawn_reset(self, player, **kwargs): self.cooldowns['ultimate'] = 4 @clientcommands('ultimate') def _on_player_ultimate(self, player, **kwargs): if self.level == 0: return _cooldown = self.cooldowns['ultimate'] if _cooldown <= 0: last_target = player targets = self._find_chain_players(player, 500, 3) if targets[0] == None: send_wcs_saytext_by_index(self._msg_f, player.index) return for target in targets: if not target: continue target.take_damage(20 + 5 * self.level, attacker_index=player.index, skip_hooks=True) location1 = last_target.origin.copy() location2 = target.origin.copy() location1.z += 40 location2.z += 40 self.beam.create(start_point=location1, end_point=location2, halo=self.laser, model=self.laser) last_target = target chain_sound.index = player.index chain_sound.origin = player.origin chain_sound.play() send_wcs_saytext_by_index(self._msg_a, player.index) self.cooldowns['ultimate'] = 20 else: send_wcs_saytext_by_index(self._msg_c.format(time=_cooldown), player.index)
class UltimatePowers(Skill): laser = Model('sprites/lgtning.vmt', True) ultimate_names = [ "Teleport", "Entangling Roots", "Chain Lightning", "Restoration" ] def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.ultimate_index = -1 self.ultimates = [ self.teleport, self.roots, self.chain_lightning, self.health_boost ] self.cooldowns = CooldownDict() ## Chain Lightning self.beam = TempEntity('BeamPoints', alpha=255, red=255, green=200, blue=200, life_time=1.0, start_width=15, end_width=15, frame_rate=255) self.laser = Model('sprites/lgtning.vmt') self.laser._precache() ## Entangling Roots self.beam2 = TempEntity('BeamPoints', alpha=255, red=0, green=200, blue=0, life_time=1.0, start_width=15, end_width=15, frame_rate=255) self.laser._precache() self.effect = TempEntity('BeamRingPoint', start_radius=120, end_radius=0, model_index=self.laser.index, halo_index=self.laser.index, life_time=1.5, amplitude=10, red=10, green=255, blue=10, alpha=245, flags=0, start_width=6, end_width=6) @classproperty def description(cls): return 'On spawn, your ultimate with be teleport, roots, chain lightning or health boost. Ultimate. 80% chance.' @classproperty def max_level(cls): return 8 @property def distance(self): return 300 + 75 * self.level @property def range(self): return 225 + ((self.level - 1) * 25) @property def duration(self): return 2 + (self.level * 0.125) def calc_health(self, player): return (self.level * 5) + max(65 - player.health, 0) _msg_spawn = '{{GREEN}}Ultimate Powers {{PALE_GREEN}}has provided you {{ORANGE}}{ultimate}{{PALE_GREEN}}.' _msg_none = '{GREEN}Ultimate Powers {PALE_GREEN}has not provided you an {ORANGE}ultimate{PALE_GREEN}.' _msg_chain = '{GREEN}Ultimate Powers {RED}hit enemies{PALE_GREEN}!' _msg_healed = '{{GREEN}}Ultimate Powers healed {{PALE_GREEN}}you for {{GREEN}}{health}HP{{PALE_GREEN}}.' _msg_c = '{{GREEN}}Ultimate Powers {{PALE_GREEN}}is on cooldown for {{DULL_RED}}{time:0.1f} {{PALE_GREEN}}seconds.' _msg_failed = '{GREEN}Ultimate Powers {DULL_RED}failed{PALE_GREEN}!' def _find_closest_player(self, player, team_index, length=99999, exclusions=[]): _target = None for target in player_dict.values(): if target.dead or target.team_index == team_index or target in exclusions or target.ultimate_immune: continue _distance = player.origin.get_distance(target.origin) if _distance < length: _target = target length = _distance return _target def _find_chain_players(self, player, length, count): _last_target = player team_index = player.team_index _targets = [] while count > 0: if not _last_target: break _target = self._find_closest_player(_last_target, team_index, length, _targets) _targets.append(_target) _last_target = _target count -= 1 return _targets def _find_players_within(self, player, length=99999, exclusions=[]): targets = [] for target in player_dict.values(): if target.dead or target.team == player.team or target in exclusions or target.ultimate_immune: continue distance = player.origin.get_distance(target.origin) if distance < length: targets.append(target) return targets def _get_trace(self, start, end, mask, player, trace): engine_trace.trace_ray(Ray(start, end), ContentMasks.ALL, TraceFilterSimple((player, )), trace) return trace def validate_teleport(self, player, origin, teleport_vector): ## These vectors should create a line diagonally through the player model, ## allowing us to see if the teleport is safe. trace_vector1 = teleport_vector.copy() trace_vector2 = teleport_vector.copy() trace_vector1.z += 72 trace_vector1.x += 26 trace_vector1.y -= 26 trace_vector2.x -= 26 trace_vector2.y += 26 check1 = self._get_trace(origin, teleport_vector, ContentMasks.PLAYER_SOLID, player, GameTrace()) check2 = self._get_trace(trace_vector1, trace_vector2, ContentMasks.PLAYER_SOLID, player, GameTrace()) return check1, check2 def teleport(self, player): view_vector = player.view_vector origin = player.origin.copy() teleport_vector = origin + (view_vector * self.distance) origin.z += 50 check1, check2 = self.validate_teleport(player, origin, teleport_vector) if check1.did_hit() or check2.did_hit(): teleport_vector = check1.end_position - (view_vector * 50) check3, check4 = self.validate_teleport(player, origin, teleport_vector) if check3.did_hit() or check4.did_hit(): send_wcs_saytext_by_index(self._msg_failed, player.index) return else: player.teleport(teleport_vector, None, None) teleport_sound.play(player.index) self.cooldowns['ultimate'] = 5 else: player.teleport(teleport_vector, None, None) teleport_sound.play(player.index) self.cooldowns['ultimate'] = 6 def roots(self, player): last_target = player targets = self._find_players_within(player, self.range) if len(targets) == 0: send_wcs_saytext_by_index(self._msg_failed, player.index) return for target in targets: if not target: continue target.stuck = True target.delay(self.duration, target.__setattr__, args=('stuck', False)) location1 = last_target.origin.copy() location2 = target.origin.copy() location1.z += 40 location2.z += 40 self.beam2.create(start_point=location1, end_point=location2, halo=self.laser, model=self.laser) last_target = target self.effect.create(center=target.origin) self.effect.create(center=target.origin, start_radius=80) root_sound.index = player.index root_sound.origin = player.origin root_sound.play() self.cooldowns['ultimate'] = 20 send_wcs_saytext_by_index(self._msg_chain, player.index) def chain_lightning(self, player): last_target = player targets = self._find_chain_players(player, 500, 3) if targets[0] == None: send_wcs_saytext_by_index(self._msg_failed, player.index) return for target in targets: if not target: continue target.take_damage(20 + 5 * self.level, attacker_index=player.index, skip_hooks=True) location1 = last_target.origin.copy() location2 = target.origin.copy() location1.z += 40 location2.z += 40 self.beam.create(start_point=location1, end_point=location2, halo=self.laser, model=self.laser) last_target = target chain_sound.index = player.index chain_sound.origin = player.origin chain_sound.play() self.cooldowns['ultimate'] = 30 send_wcs_saytext_by_index(self._msg_chain, player.index) def health_boost(self, player): if player.health < 200: health = self.calc_health(player) player.health += health send_wcs_saytext_by_index(self._msg_healed.format(health=health), player.index) self.cooldowns['ultimate'] = 20 @events('player_spawn') def _on_player_spawn(self, player, **kwargs): if self.level == 0 or randint(0, 101) > 80: self.ultimate_index = -1 return self.ultimate_index = randint(0, 3) self.cooldowns['ultimate'] = 4 send_wcs_saytext_by_index( self._msg_spawn.format( ultimate=self.ultimate_names[self.ultimate_index]), player.index) @clientcommands('ultimate') def _on_player_ultimate(self, player, **kwargs): if self.level == 0 or self.ultimate_index == -1: send_wcs_saytext_by_index(self._msg_none, player.index) return _cooldown = self.cooldowns['ultimate'] if _cooldown <= 0: self.ultimates[self.ultimate_index](player) else: send_wcs_saytext_by_index(self._msg_c.format(time=_cooldown), player.index)
class DivineShield(Skill): @classproperty def description(cls): return 'Gives you immunity to all damage for a short time. Ultimate.' @classproperty def max_level(cls): return 4 @classmethod def is_available(cls, player): return player.race.level > 8 def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.cooldowns = CooldownDict() self._godmode = False self._model = Model("sprites/halo.vmt", True) self._model._precache() if not godmode_sound.is_precached: godmode_sound.precache() def kill_effect(self, effect): if not effect.basehandle.is_valid(): return effect.call_input('Kill') _msg_a = '{{ORANGE}}Divine Shield {{PALE_GREEN}}is active for {{ORANGE}}{time} {{PALE_GREEN}}seconds!' _msg_c = '{{ORANGE}}Divine Shield {{PALE_GREEN}}is on {{DULL_RED}}cooldown {{PALE_GREEN}}for {time:0.1f} seconds.' @events('player_spawn', 'player_upgrade_skill') def _on_player_spawn_reset(self, player, **eargs): self.cooldowns['ultimate'] = 4 self._godmode = False @events('player_pre_victim') def _on_player_pre_victim(self, info, **eargs): if self._godmode: info.damage = 0 @clientcommands('ultimate') def _on_player_ultimate(self, player, **eargs): if self.level == 0: return _cooldown = self.cooldowns['ultimate'] if _cooldown <= 0: duration = (self.level * 0.5) + 1 self._godmode = True Delay(duration, self.__setattr__, args=('_godmode', False)) effect = Entity.create('env_sprite') location = player.origin location.z += 40 effect.teleport(location, None, None) effect.add_output('model sprites/halo.vmt') effect.add_output('scale 10') effect.call_input('ShowSprite') attach_entity_to_player(player, effect) Delay(duration, self.kill_effect, args=(effect, )) send_wcs_saytext_by_index(self._msg_a.format(time=duration), player.index) godmode_sound.index = player.index godmode_sound.origin = player.origin godmode_sound.play() self.cooldowns['ultimate'] = 30 else: send_wcs_saytext_by_index(self._msg_c.format(time=_cooldown), player.index)
class HolyLight(Skill): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.cooldowns = CooldownDict() self._model = Model("sprites/lgtning.vmt", True) self._model._precache() if not heal_sound.is_precached: heal_sound.precache() @classproperty def description(cls): return 'Heal yourself for a small amount. Max 150HP. Ability.' @classproperty def max_level(cls): return 6 @property def health(self): return 10 + (4 * self.level) _msg_a = '{{YELLOW}}Holy Light {{PALE_GREEN}}healed you for {{GREEN}}{amount}' _msg_c = '{{YELLOW}}Holy Light {{PALE_GREEN}}is on cooldown for {{DULL_RED}}{time} {{PALE_GREEN}}seconds.' @events('player_spawn', 'player_upgrade_skill') def _on_player_spawn(self, player, **kwargs): self.cooldowns['ability'] = 4 @clientcommands('ability') def _on_player_ability(self, player, **kwargs): if self.level == 0: return _cooldown = self.cooldowns['ability'] if _cooldown <= 0: player.health = min(player.health + self.health, 150) send_wcs_saytext_by_index(self._msg_a.format(amount=self.health), player.index) location = player.origin location.z += 40 self._effect = TempEntity('GlowSprite', model_index=self._model.index, life_time=0.8, amplitude=6, origin=location, scale=1.5, brightness=255) self._effect.create() heal_sound.index = player.index heal_sound.origin = location heal_sound.play() self.cooldowns['ability'] = 10 else: send_wcs_saytext_by_index(self._msg_c.format(time=int(_cooldown)), player.index)