def __init__(self, global_path_finder: GlobalPathFinder): super().__init__(global_path_finder, Millis(2000), 24, 0, Millis(600))
from typing import Optional from pythongame.core.ability_effects import register_ability_effect, AbilityResult, AbilityWasUsedSuccessfully from pythongame.core.buff_effects import register_buff_effect, get_buff_effect, \ StatModifyingBuffEffect from pythongame.core.common import BuffType, Millis, AbilityType, UiIconSprite, SoundId, PeriodicTimer, HeroUpgradeId, \ HeroStat from pythongame.core.game_data import register_ability_data, AbilityData, register_ui_icon_sprite_path, \ register_buff_text, ABILITIES from pythongame.core.game_state import GameState, WorldEntity, NonPlayerCharacter, Event, BuffEventOutcome, \ EnemyDiedEvent from pythongame.core.hero_upgrades import register_hero_upgrade_effect from pythongame.core.visual_effects import VisualCircle COOLDOWN = Millis(25000) BUFF_DURATION = Millis(10000) BUFF_TYPE = BuffType.BLOOD_LUST LIFE_STEAL_BONUS_RATIO = 0.15 SPEED_BONUS = 0.3 BLOODLUST_INCREASED_DURATION_FROM_KILL = Millis(1000) BLOODLUST_UPGRADED_INCREASED_DURATION_FROM_KILL = Millis(1500) SWORD_SLASH_CD_BONUS = Millis(100) # This variable is updated when picking the talent has_blood_lust_duration_increase_upgrade = False def _apply_ability(game_state: GameState) -> AbilityResult: game_state.player_state.gain_buff_effect(get_buff_effect(BUFF_TYPE), BUFF_DURATION) return AbilityWasUsedSuccessfully()
def apply_middle_effect(self, game_state: GameState, buffed_entity: WorldEntity, buffed_npc: NonPlayerCharacter, time_passed: Millis): if self.timer.update_and_check_if_ready(time_passed): visual_effect = VisualCircle( (250, 0, 0,), buffed_entity.get_center_position(), 25, 30, Millis(350), 1, buffed_entity) game_state.visual_effects.append(visual_effect)
def __init__(self, global_path_finder: GlobalPathFinder): super().__init__(global_path_finder, Millis(2000), 3, 0.1, Millis(900))
from pythongame.core.ability_effects import register_ability_effect, AbilityWasUsedSuccessfully, AbilityFailedToExecute, \ AbilityResult from pythongame.core.buff_effects import get_buff_effect, AbstractBuffEffect, register_buff_effect from pythongame.core.common import AbilityType, Millis, BuffType, UiIconSprite, SoundId, PeriodicTimer, \ PLAYER_ENTITY_SIZE from pythongame.core.damage_interactions import deal_player_damage_to_enemy, DamageType from pythongame.core.game_data import register_ui_icon_sprite_path from pythongame.core.game_state import GameState, NonPlayerCharacter, CameraShake from pythongame.core.math import translate_in_direction from pythongame.core.visual_effects import VisualRect, VisualCross, create_visual_stun_text from pythongame.core.world_entity import WorldEntity ABILITY_TYPE = AbilityType.INFUSE_DAGGER DEBUFF = BuffType.DAMAGED_BY_INFUSED_DAGGER DAMAGE_PER_TICK = 2 DAMAGE_TICK_INTERVAL = Millis(400) DEBUFF_DURATION = Millis(5000) TOTAL_DOT_DAMAGE = DEBUFF_DURATION // DAMAGE_TICK_INTERVAL * DAMAGE_PER_TICK def _apply_ability(game_state: GameState) -> AbilityResult: player_entity = game_state.game_world.player_entity rect_w = 28 slash_center_pos = translate_in_direction( player_entity.get_center_position(), player_entity.direction, rect_w / 2 + PLAYER_ENTITY_SIZE[0] * 0.25) slash_rect = Rect(int(slash_center_pos[0] - rect_w / 2), int(slash_center_pos[1] - rect_w / 2), rect_w, rect_w) affected_enemies = game_state.game_world.get_enemy_intersecting_rect( slash_rect) if not affected_enemies:
def apply_middle_effect(self, game_state: GameState, buffed_entity: WorldEntity, buffed_npc: NonPlayerCharacter, time_passed: Millis): if self.timer.update_and_check_if_ready(time_passed): player_center_position = game_state.player_entity.get_center_position() projectile_pos = get_position_from_center_position(player_center_position, PROJECTILE_SIZE) entity = WorldEntity(projectile_pos, PROJECTILE_SIZE, Sprite.PROJECTILE_PLAYER_ARCANE_FIRE, game_state.player_entity.direction, PROJECTILE_SPEED) projectile = Projectile(entity, create_projectile_controller(ProjectileType.PLAYER_ARCANE_FIRE)) game_state.projectile_entities.append(projectile) game_state.visual_effects.append(VisualRect((250, 0, 250), player_center_position, 45, 60, Millis(250), 1))
def __init__(self, item_type: ItemType): super().__init__(item_type) self.timer = PeriodicTimer(Millis(5000)) self.min_dmg = 1 self.max_dmg = 3
def __init__(self): self.timer = PeriodicTimer(Millis(80)) self.graphics_size = 40
StatModifyingBuffEffect from pythongame.core.common import AbilityType, Millis, UiIconSprite, SoundId, BuffType, HeroUpgradeId, HeroStat, \ PeriodicTimer from pythongame.core.damage_interactions import deal_player_damage_to_enemy, DamageType from pythongame.core.game_data import register_ui_icon_sprite_path, \ register_buff_text from pythongame.core.game_state import GameState, NonPlayerCharacter, CameraShake from pythongame.core.math import translate_in_direction from pythongame.core.visual_effects import VisualCircle, VisualRect, VisualLine from pythongame.core.world_entity import WorldEntity ABILITY_TYPE = AbilityType.DASH BUFF_FROM_STEALTH = BuffType.AFTER_DASH BUFF_FROM_STEALTH_DURATION = Millis(7_000) BUFF_SPEED = BuffType.SPEED_BUFF_FROM_DASH BUFF_SPEED_DURATION = Millis(2000) DAMAGE = 5 FROM_STEALTH_DODGE_CHANCE_BOOST = 0.1 FROM_STEALTH_LIFE_STEAL_BOOST = 0.15 FROM_STEALTH_MAGIC_RESIST_CHANCE_BOOST = 0.2 def _apply_ability(game_state: GameState) -> AbilityResult: player_entity = game_state.game_world.player_entity previous_position = player_entity.get_center_position() used_from_stealth = game_state.player_state.has_active_buff( BuffType.STEALTHING) for distance in range(40, 200, 10): new_position = translate_in_direction(
import random from pythongame.core.ability_effects import register_ability_effect, AbilityWasUsedSuccessfully, AbilityResult from pythongame.core.buff_effects import get_buff_effect, AbstractBuffEffect, register_buff_effect from pythongame.core.common import AbilityType, Millis, BuffType, UiIconSprite, SoundId, PeriodicTimer from pythongame.core.damage_interactions import deal_player_damage_to_enemy, DamageType from pythongame.core.game_data import register_ability_data, AbilityData, register_ui_icon_sprite_path, \ register_buff_as_channeling from pythongame.core.game_state import GameState, WorldEntity, NonPlayerCharacter, CameraShake from pythongame.core.sound_player import play_sound from pythongame.core.visual_effects import VisualRect, VisualCircle, create_visual_stun_text STUN_DURATION = Millis(3500) CHANNELING_STOMP = BuffType.CHANNELING_STOMP STUNNED_BY_STOMP = BuffType.STUNNED_BY_STOMP MIN_DMG = 2 MAX_DMG = 5 def _apply_ability(game_state: GameState) -> AbilityResult: game_state.player_state.gain_buff_effect(get_buff_effect(CHANNELING_STOMP), Millis(500)) return AbilityWasUsedSuccessfully() class ChannelingStomp(AbstractBuffEffect): def __init__(self): self.timer = PeriodicTimer(Millis(80)) self.graphics_size = 40
def _apply_ability(game_state: GameState) -> AbilityResult: game_state.player_state.gain_buff_effect(get_buff_effect(CHANNELING_STOMP), Millis(500)) return AbilityWasUsedSuccessfully()
from pythongame.core.buff_effects import AbstractBuffEffect, register_buff_effect from pythongame.core.common import Millis, BuffType, SoundId from pythongame.core.game_state import GameState, WorldEntity, NonPlayerCharacter from pythongame.core.sound_player import play_sound from pythongame.core.visual_effects import create_teleport_effects BUFF_TYPE = BuffType.BEING_SPAWNED DELAY = Millis(1000) class BeingSpawned(AbstractBuffEffect): def __init__(self): self.time_since_start = 0 self.has_spawn_happened = False def apply_start_effect(self, game_state: GameState, buffed_entity: WorldEntity, buffed_npc: NonPlayerCharacter): game_state.player_state.stun_status.add_one() game_state.player_entity.set_not_moving() game_state.player_entity.visible = False def apply_middle_effect(self, game_state: GameState, buffed_entity: WorldEntity, buffed_npc: NonPlayerCharacter, time_passed: Millis): self.time_since_start += time_passed if not self.has_spawn_happened and self.time_since_start > DELAY / 2: self.has_spawn_happened = True game_state.visual_effects += create_teleport_effects( buffed_entity.get_center_position())
import random from pythongame.core.abilities import AbilityData, register_ability_data from pythongame.core.ability_effects import register_ability_effect, AbilityWasUsedSuccessfully, AbilityResult from pythongame.core.buff_effects import get_buff_effect, AbstractBuffEffect, register_buff_effect from pythongame.core.common import AbilityType, Millis, BuffType, UiIconSprite, SoundId, PeriodicTimer from pythongame.core.damage_interactions import deal_player_damage_to_enemy, DamageType from pythongame.core.game_data import register_ui_icon_sprite_path, \ register_buff_as_channeling from pythongame.core.game_state import GameState, NonPlayerCharacter, CameraShake from pythongame.core.sound_player import play_sound from pythongame.core.visual_effects import VisualRect, VisualCircle, create_visual_stun_text from pythongame.core.world_entity import WorldEntity STUN_DURATION = Millis(2500) CHANNELING_STOMP = BuffType.CHANNELING_STOMP STUNNED_BY_STOMP = BuffType.STUNNED_BY_STOMP MIN_DMG = 2 MAX_DMG = 5 def _apply_ability(game_state: GameState) -> AbilityResult: game_state.player_state.gain_buff_effect(get_buff_effect(CHANNELING_STOMP), Millis(500)) return AbilityWasUsedSuccessfully() class ChannelingStomp(AbstractBuffEffect): def __init__(self): self.timer = PeriodicTimer(Millis(80))
register_portrait_icon_sprite_path, register_hero_data, HeroData, \ InitialPlayerStateData, register_buff_text from pythongame.core.game_state import PlayerLevelBonus, GameState, Event, PlayerBlockedEvent from pythongame.core.hero_upgrades import register_hero_upgrade_effect, HeroUpgrade, AbstractHeroUpgradeEffect from pythongame.core.item_data import randomized_item_id from pythongame.core.talents import TalentsConfig, TalentTierConfig, TalentTierOptionConfig from pythongame.core.view.image_loading import SpriteSheet from pythongame.game_data.abilities.ability_bloodlust import BLOODLUST_UPGRADED_INCREASED_DURATION_FROM_KILL from pythongame.game_data.abilities.ability_sword_slash import ABILITY_SLASH_UPGRADED_COOLDOWN from pythongame.game_data.heroes.generic_talents import TALENT_CHOICE_ARMOR_DAMAGE, TALENT_CHOICE_HEALTH_MANA, \ TALENT_CHOICE_HEALTH_MANA_REGEN, TALENT_CHOICE_MOVE_SPEED_MAGIC_RESIST HERO_ID = HeroId.WARRIOR BUFF_RETRIBUTION = BuffType.BUFFED_FROM_RETRIBUTION_TALENT BUFF_RETRIBUTION_DURATION = Millis(2000) BUFF_RETRIBUTION_BONUS_BLOCK_CHANCE = 0.05 BUFF_RETRIBUTION_BONUS_DAMAGE = 0.4 def register_hero_warrior(): sprite = Sprite.HERO_WARRIOR portrait_icon_sprite = PortraitIconSprite.HERO_WARRIOR player_sprite_sheet = SpriteSheet( "resources/graphics/enemy_sprite_sheet_3.png") original_sprite_size = (32, 32) scaled_sprite_size = (48, 48) x = 6 indices_by_dir = { Direction.DOWN: [(x + i, 4) for i in range(3)], Direction.LEFT: [(x + i, 5) for i in range(3)],
from pythongame.core.game_data import register_ability_data, AbilityData, register_ui_icon_sprite_path, \ register_entity_sprite_initializer, register_buff_as_channeling, ABILITIES from pythongame.core.game_state import GameState, NonPlayerCharacter, WorldEntity, Projectile, CameraShake from pythongame.core.hero_upgrades import register_hero_upgrade_effect from pythongame.core.math import get_position_from_center_position from pythongame.core.projectile_controllers import AbstractProjectileController, register_projectile_controller, \ create_projectile_controller from pythongame.core.view.image_loading import SpriteInitializer from pythongame.core.visual_effects import VisualCircle, VisualRect ARCANE_FIRE_MANA_COST = 40 ARCANE_FIRE_UPGRADED_MANA_COST = 60 ARCANE_FIRE_COOLDOWN = Millis(30_000) ARCANE_FIRE_UPGRADED_COOLDOWN = Millis(10_000) CHANNEL_DURATION = Millis(1000) CHANNEL_PROJECTILE_INTERVAL = Millis(70) PROJECTILE_SIZE = (30, 30) PROJECTILE_SPEED = 0.7 DAMAGE = 1 MAX_TOTAL_DAMAGE = int(round(CHANNEL_DURATION / CHANNEL_PROJECTILE_INTERVAL)) def _apply_channel_attack(game_state: GameState) -> AbilityResult: game_state.player_state.gain_buff_effect(get_buff_effect(BuffType.CHANNELING_ARCANE_FIRE), CHANNEL_DURATION) return AbilityWasUsedSuccessfully() class Channeling(AbstractBuffEffect): def __init__(self): self.timer = PeriodicTimer(CHANNEL_PROJECTILE_INTERVAL)
def __init__(self): super().__init__(BUFF_SPEED, {HeroStat.MOVEMENT_SPEED: 0.4}) self.timer = PeriodicTimer(Millis(100))
def apply_start_effect(self, game_state: GameState, buffed_entity: WorldEntity, buffed_npc: NonPlayerCharacter): game_state.player_state.stun_status.add_one() game_state.player_entity.set_not_moving() game_state.camera_shake = CameraShake(Millis(50), CHANNEL_DURATION, 5)
from pythongame.core.abilities import AbilityData, register_ability_data from pythongame.core.ability_effects import register_ability_effect, AbilityResult, AbilityWasUsedSuccessfully from pythongame.core.buff_effects import AbstractBuffEffect, register_buff_effect, get_buff_effect from pythongame.core.common import BuffType, Millis, AbilityType, SoundId, HeroId, UiIconSprite, PeriodicTimer, \ HeroUpgradeId, HeroStat from pythongame.core.damage_interactions import deal_player_damage_to_enemy, DamageType from pythongame.core.game_data import register_ui_icon_sprite_path, \ HEROES, register_buff_as_channeling from pythongame.core.game_state import GameState, NonPlayerCharacter, CameraShake from pythongame.core.math import translate_in_direction, get_middle_point from pythongame.core.sound_player import play_sound from pythongame.core.visual_effects import VisualRect, VisualCircle from pythongame.core.world_entity import WorldEntity CHARGE_DURATION = Millis(500) IMPACT_STUN_DURATION = Millis(200) BONUS_SPEED_MULTIPLIER = 5 BUFF_TYPE_CHARGING = BuffType.CHARGING BUFF_TYPE_STUNNED = BuffType.STUNNED_FROM_CHARGE_IMPACT MIN_DMG = 4 MAX_DMG = 8 def _apply_ability(game_state: GameState) -> AbilityResult: game_state.player_state.gain_buff_effect( get_buff_effect(BUFF_TYPE_CHARGING), CHARGE_DURATION) return AbilityWasUsedSuccessfully()
def apply_enemy_collision(self, npc: NonPlayerCharacter, game_state: GameState, projectile: Projectile): if npc not in self._enemies_hit: deal_player_damage_to_enemy(game_state, npc, DAMAGE, DamageType.MAGIC) game_state.visual_effects.append( VisualCircle((250, 100, 250), npc.world_entity.get_center_position(), 15, 25, Millis(100), 0)) self._enemies_hit.append(npc)
def __init__(self): self.graphics_timer = PeriodicTimer(Millis(40)) self.time_since_start = 0
from pythongame.core.buff_effects import register_buff_effect, get_buff_effect, \ StatModifyingBuffEffect from pythongame.core.common import ItemType, Sprite, BuffType, Millis, HeroStat, StatModifierInterval from pythongame.core.game_data import UiIconSprite from pythongame.core.game_state import Event, GameState, PlayerWasAttackedEvent from pythongame.core.item_effects import AbstractItemEffect from pythongame.core.item_inventory import ItemEquipmentCategory from pythongame.game_data.items.register_items_util import register_custom_effect_item BUFF_TYPE_SLOWED = BuffType.SLOWED_FROM_NOBLE_DEFENDER SLOW_AMOUNT = 0.3 SLOW_DURATION = Millis(1500) class ItemEffect(AbstractItemEffect): def item_handle_event(self, event: Event, game_state: GameState): if isinstance(event, PlayerWasAttackedEvent): game_state.player_state.gain_buff_effect( get_buff_effect(BUFF_TYPE_SLOWED), SLOW_DURATION) class SlowedFromNobleDefender(StatModifyingBuffEffect): def __init__(self): super().__init__(BUFF_TYPE_SLOWED, {HeroStat.MOVEMENT_SPEED: -SLOW_AMOUNT}) def register_noble_defender(): item_type = ItemType.NOBLE_DEFENDER register_custom_effect_item( item_type=item_type,
def apply_middle_effect(self, game_state: GameState, buffed_entity: WorldEntity, buffed_npc: NonPlayerCharacter, time_passed: Millis) -> Optional[bool]: self.time_since_start += time_passed charger_center_pos = buffed_entity.get_center_position() if self.graphics_timer.update_and_check_if_ready(time_passed): visual_circle = VisualCircle((250, 250, 250), charger_center_pos, 15, 25, Millis(120), 2, None) game_state.game_world.visual_effects.append(visual_circle) rect_w = 32 # NOTE: We assume that this ability is used by this specific hero hero_entity_size = HEROES[HeroId.WARRIOR].entity_size impact_pos = translate_in_direction( charger_center_pos, buffed_entity.direction, rect_w / 2 + hero_entity_size[0] / 2) impact_rect = Rect(int(impact_pos[0] - rect_w / 2), int(impact_pos[1] - rect_w / 2), rect_w, rect_w) affected_enemies = game_state.game_world.get_enemy_intersecting_rect( impact_rect) for enemy in affected_enemies: visual_impact_pos = get_middle_point( charger_center_pos, enemy.world_entity.get_center_position()) damage = MIN_DMG # Talent: Apply damage bonus even if using charge in melee range has_melee_upgrade = game_state.player_state.has_upgrade( HeroUpgradeId.ABILITY_CHARGE_MELEE) damage_increased = self.time_since_start > float( CHARGE_DURATION) * 0.3 or has_melee_upgrade if damage_increased: # TODO Stun target as a bonus here damage = MAX_DMG deal_player_damage_to_enemy(game_state, enemy, damage, DamageType.PHYSICAL, visual_emphasis=damage_increased) game_state.game_world.visual_effects.append( VisualRect((250, 170, 0), visual_impact_pos, 45, 25, IMPACT_STUN_DURATION, 2, None)) game_state.game_world.visual_effects.append( VisualRect((150, 0, 0), visual_impact_pos, 35, 20, IMPACT_STUN_DURATION, 2, None)) game_state.player_state.gain_buff_effect( get_buff_effect(BUFF_TYPE_STUNNED), IMPACT_STUN_DURATION) enemy.gain_buff_effect(get_buff_effect(BUFF_TYPE_STUNNED), IMPACT_STUN_DURATION) game_state.camera_shake = CameraShake(Millis(50), Millis(150), 12) play_sound(SoundId.ABILITY_CHARGE_HIT) has_stomp_cooldown_upgrade = game_state.player_state.has_upgrade( HeroUpgradeId.ABILITY_CHARGE_RESET_STOMP_COOLDOWN) if has_stomp_cooldown_upgrade: game_state.player_state.set_ability_cooldown_to_zero( AbilityType.STOMP) # The buff should end upon impact return True return False
from pygame.rect import Rect from pythongame.core.ability_effects import register_ability_effect, AbilityWasUsedSuccessfully, AbilityResult from pythongame.core.buff_effects import get_buff_effect from pythongame.core.common import AbilityType, Millis, BuffType, HeroId, UiIconSprite, SoundId, HeroUpgradeId from pythongame.core.damage_interactions import deal_player_damage_to_enemy, DamageType from pythongame.core.game_data import register_ability_data, AbilityData, register_ui_icon_sprite_path, \ HEROES, ABILITIES from pythongame.core.game_state import GameState from pythongame.core.hero_upgrades import register_hero_upgrade_effect from pythongame.core.math import translate_in_direction from pythongame.core.visual_effects import VisualRect ABILITY_TYPE = AbilityType.SWORD_SLASH ABILITY_SLASH_COOLDOWN = Millis(700) ABILITY_SLASH_UPGRADED_COOLDOWN = Millis(600) MIN_DMG = 2 MAX_DMG = 5 def _apply_ability(game_state: GameState) -> AbilityResult: player_entity = game_state.player_entity rect_w = 36 # Note: We assume that this ability is used by this specific hero hero_entity_size = HEROES[HeroId.WARRIOR].entity_size slash_pos = translate_in_direction(player_entity.get_center_position(), player_entity.direction, rect_w / 2 + hero_entity_size[0] * 0.25)
def __init__(self): super().__init__(BUFF_TYPE, {HeroStat.DAMAGE: DAMAGE_MODIFIER_INCREASE}) self.timer = PeriodicTimer(Millis(300))
def __init__(self, global_path_finder: GlobalPathFinder): super().__init__(global_path_finder, Millis(1500), 12, 0, Millis(900))
def __init__(self): self.graphics_timer = PeriodicTimer(Millis(500))
def __init__(self): super().__init__(BUFF_TYPE, {HeroStat.LIFE_STEAL: LIFE_STEAL_BONUS_RATIO, HeroStat.MOVEMENT_SPEED: SPEED_BONUS}) self.timer = PeriodicTimer(Millis(250))
def create_sprint_visual_effect(buffed_entity, game_state): game_state.visual_effects.append( VisualCircle((150, 50, 0), buffed_entity.get_center_position(), 20, 22, Millis(250), 2, buffed_entity))
def __init__(self, global_path_finder: GlobalPathFinder): super().__init__(global_path_finder) self.timer = PeriodicTimer(Millis(500))
def __init__(self): self.dmg_timer = PeriodicTimer(Millis(1000)) self.graphics_timer = PeriodicTimer(Millis(400))