function init(hero) {
    hero.setName("Upgraded Kratos");
    hero.setAliases("God_of_War", "GOW", "Tattooed_Warrior");
    hero.setVersion("\u00A7c\u00A7lGOW \u00A7f\u00A7l2018\u00A7r");
    hero.setTier(10);
    
    hero.setHelmet("Head");
    hero.setChestplate("Body");
    hero.setLeggings("Legs");
    hero.setBoots("Boots");
    
    hero.addPowers("gowhp:godofwar_upgraded", "gowhp:leviathanaxe_upgraded", "gowhp:bladesofchaos", "gowhp:guardianshield_upgraded", "gowhp:spartanrage_upgraded");
    hero.addAttribute("PUNCH_DAMAGE", 10.5, 0);
    hero.addAttribute("KNOCKBACK", 1.0, 0);
    hero.addAttribute("JUMP_HEIGHT", 1.25, 0);
    hero.addAttribute("SPRINT_SPEED", 0.5, 1);
    hero.addAttribute("FALL_RESISTANCE", 120.0, 0);

    hero.addKeyBindFunc("WEAPON_CYCLE", weaponCycle, "Cycle Weapons", 1);
    hero.addKeyBind("LEVIATHANAXE", "Leviathan Axe", 2);
    hero.addKeyBind("BLADESOFCHAOS", "Blades of Chaos", 2);
    hero.addKeyBind("SHIELD", "Guardian Shield", 3);
    hero.addKeyBindFunc("LEVIATHANAXE_RUNIC_CYCLE", leviathanaxerunicCycle, "Cycle Ranged/Runic Attacks", 4);
    hero.addKeyBind("LEVIATHANAXERUNICCYCLEUNAVAILABLE", "\u00A7cUnavailable", 4);
    hero.addKeyBindFunc("BLADESOFCHAOS_RUNIC_CYCLE", bladesofchaosrunicCycle, "Cycle Runic Attacks", 4);
    hero.addKeyBind("BLADESOFCHAOSRUNICCYCLEUNAVAILABLE", "\u00A7cUnavailable", 4);
    hero.addKeyBind("CHARGED_BEAM", "Throw", 5);
    hero.addKeyBind("BOULDERTHROW", "Boulder Throw", 5);
    hero.addKeyBind("LEVIATHANAXETHROWANIMATION", "Throw Leviathan Axe", 5);
    hero.addKeyBind("WRATHOFTHEFROSTANCIENT", "Wrath of the Frost Ancient", 5);
    hero.addKeyBind("BREATHOFTHAMUR", "Breath of Thamur", 5);
    hero.addKeyBind("THECYCLONEOFCHAOS", "Cyclone of Chaos", 5);
    hero.addKeyBind("THEFIREOFARES", "Fire of Ares", 5);
    hero.addKeyBind("SPARTANRAGE", "Spartan Rage", 4);
    hero.addKeyBind("GROUND_SMASH", "Ground Smash", 3);
    
    hero.setDefaultScale(1.1);
    hero.setModifierEnabled(isModifierEnabled);
    hero.setKeyBindEnabled(isKeyBindEnabled);
    hero.addAttributeProfile("LEVIATHANAXE", leviathanaxeProfile);
    hero.addAttributeProfile("BLADESOFCHAOS", bladesofchaosProfile);
    hero.addAttributeProfile("SHIELD", shieldProfile);
    hero.addAttributeProfile("SPARTANRAGE", spartanrageProfile);
    hero.addAttributeProfile("SPARTANRAGETOGGLE", spartanragetoggleProfile);
    hero.addAttributeProfile("RUNICATTACK", runicattackProfile);
    hero.addAttributeProfile("CYCLONEOFCHAOS", cycloneofchaosProfile);
    hero.setAttributeProfile(getAttributeProfile);
    hero.setHasProperty(hasProperty);

    hero.setDamageProfile(entity => entity.getData("gowhp:dyn/leviathanaxe") ? "LEVIATHANAXE_FROST" : null);
    hero.setDamageProfile(entity => entity.getData("gowhp:dyn/bladesofchaos") ? "BLADES_FLAME" : null);
    hero.addDamageProfile("LEVIATHANAXE_FROST", {
        "types": {
            "SHARP": 1.0,
            "LEVIATHAN_ICE": 0.6,
            "JORMUNGANDR_VENOM": 0.25
        }
    });
    hero.addDamageProfile("BLADES_FLAME", {
        "types": {
            "SHARP": 1.0,
            "CHAOS_FLAMES": 0.6,
            "PRIMORDIAL": 0.5
        },
        "properties": {
            "HEAT_TRANSFER": 40,
            "IGNITE": 2
        }
    });

    hero.addSoundEvent("MASK_OPEN", "gowhp:kratos_voice_lines");
    hero.addSoundEvent("MASK_CLOSE", "gowhp:kratos_voice_lines");
    hero.addSoundEvent("STEP", ["gowhp:kratos_walk", "gowhp:kratos_sprint"]);
    hero.addSoundEvent("PUNCH", ["gowhp:kratos_punch", "gowhp:leviathanaxe_hit", "gowhp:bladesofchaos_hit", "gowhp:spartanrage_punch"]);
    hero.addSoundEvent("JUMP", "gowhp:spartanrage_leap");
    hero.addSoundEvent("LAND", "gowhp:spartanrage_land");
}

function hasProperty(entity, property) {
    return property == "BREATHE_SPACE" || property == "MASK_TOGGLE";
}

function weaponCycle(player, manager) {
  manager.setData(player, "gowhp:dyn/weapon_cycle", player.getData("gowhp:dyn/weapon_cycle") + 1);
  if (player.getData("gowhp:dyn/weapon_cycle") > 1) {
    manager.setData(player, "gowhp:dyn/weapon_cycle", 0);
  }
  return true;
}

function leviathanaxerunicCycle(player, manager) {
  manager.setData(player, "gowhp:dyn/leviathanaxe_runic_cycle", player.getData("gowhp:dyn/leviathanaxe_runic_cycle") + 1);
  if (player.getData("gowhp:dyn/leviathanaxe_runic_cycle") > 2) {
    manager.setData(player, "gowhp:dyn/leviathanaxe_runic_cycle", 0);
  }
  return true;
}

function bladesofchaosrunicCycle(player, manager) {
  manager.setData(player, "gowhp:dyn/bladesofchaos_runic_cycle", player.getData("gowhp:dyn/bladesofchaos_runic_cycle") + 1);
  if (player.getData("gowhp:dyn/bladesofchaos_runic_cycle") > 1) {
    manager.setData(player, "gowhp:dyn/bladesofchaos_runic_cycle", 0);
  }
  return true;
}

function leviathanaxeProfile(profile) {
    profile.inheritDefaults();
    profile.addAttribute("PUNCH_DAMAGE", 14.0, 0);
    profile.addAttribute("SPRINT_SPEED", 0.4, 1);
    profile.addAttribute("JUMP_HEIGHT", 1.15, 0);
}

function bladesofchaosProfile(profile) {
    profile.inheritDefaults();
    profile.addAttribute("PUNCH_DAMAGE", 14.0, 0);
    profile.addAttribute("SPRINT_SPEED", 0.6, 1);
    profile.addAttribute("JUMP_HEIGHT", 1.35, 0);
}

function shieldProfile(profile) {
    profile.inheritDefaults();
    profile.addAttribute("BASE_SPEED", -0.5, 1);
    profile.addAttribute("SPRINT_SPEED", 0.25, 1);
    profile.addAttribute("JUMP_HEIGHT", -1.0, 0);
}

function spartanrageProfile(profile) {
    profile.addAttribute("PUNCH_DAMAGE", 17.0, 0);
    profile.addAttribute("KNOCKBACK", 2.0, 0);
    profile.addAttribute("JUMP_HEIGHT", 2.0, 0);
    profile.addAttribute("SPRINT_SPEED", 1.0, 1);
    profile.addAttribute("FALL_RESISTANCE", 140.0, 0);
}

function spartanragetoggleProfile(profile) {
    profile.revokeAugments();
    profile.addAttribute("BASE_SPEED", -1, 0);
    profile.addAttribute("JUMP_HEIGHT", -10, 0);
}

function runicattackProfile(profile) {
    profile.revokeAugments();
    profile.addAttribute("BASE_SPEED", -1, 0);
    profile.addAttribute("JUMP_HEIGHT", -10, 0);
}

function cycloneofchaosProfile(profile) {
    profile.revokeAugments();
    profile.addAttribute("BASE_SPEED", -0.25, 1);
    profile.addAttribute("JUMP_HEIGHT", -0.5, 0);
}

function getAttributeProfile(entity) {
    if (entity.getData("gowhp:dyn/bladesofchaos") && entity.getData("fiskheroes:beam_charging") && entity.getData("gowhp:dyn/bladesofchaos_runic_cycle") == 0) {
        return "CYCLONEOFCHAOS";
    }
    if (((entity.getData("gowhp:dyn/leviathanaxe") && !entity.getData("gowhp:dyn/leviathanaxe_runic_cycle") == 0) || entity.getData("gowhp:dyn/bladesofchaos")) && entity.getData("fiskheroes:beam_charging") && (entity.getData("gowhp:dyn/leviathanaxe_runic_cycle") == 1 || entity.getData("gowhp:dyn/leviathanaxe_runic_cycle") == 2 || entity.getData("gowhp:dyn/bladesofchaos_runic_cycle") == 1)) {
        return "RUNICATTACK";
    }
    if (entity.getData("fiskheroes:shield_blocking")) {
        return "SHIELD";
    }
    if (entity.getData("gowhp:dyn/leviathanaxe")) {
        return "LEVIATHANAXE";
    }
    if (entity.getData("gowhp:dyn/bladesofchaos")) {
        return "BLADESOFCHAOS";
    }
    if (entity.getData("gowhp:dyn/spartanrage") && entity.getInterpolatedData("gowhp:dyn/spartanrage_animation_timer") < 0.5) {
        return "SPARTANRAGETOGGLE";
    }
    if (entity.getData("gowhp:dyn/spartanrage")) {
        return "SPARTANRAGE";
    }
}

function isModifierEnabled(entity, modifier) {
    switch (modifier.name()) {
    case "gowhp:dyn/leviathanaxe":
        return entity.getData("gowhp:dyn/weapon_cycle") == 0 && !entity.getData("gowhp:dyn/spartanrage") && !entity.getData("gowhp:dyn/bladesofchaos");
    case "gowhp:dyn/bladesofchaos":
        return entity.getData("gowhp:dyn/weapon_cycle") == 1 && !entity.getData("gowhp:dyn/spartanrage") && !entity.getData("gowhp:dyn/leviathanaxe");
    case "fiskheroes:shield":
        return !entity.getData("gowhp:dyn/spartanrage") && !entity.getData("fiskheroes:beam_charging");
    case "gowhp:dyn/spartanrage":
        return !entity.getData("gowhp:dyn/leviathanaxe") && !entity.getData("gowhp:dyn/bladesofchaos");
    case "fiskheroes:arrow_catching":
        return entity.getData("gowhp:dyn/spartanrage") && !entity.getData("gowhp:dyn/leviathanaxe") && !entity.getData("fiskheroes:shield");
    case "fiskheroes:fire_immunity":
        return entity.getData("gowhp:dyn/spartanrage") || entity.getData("gowhp:dyn/bladesofchaos");
    case "fiskheroes:regeneration":
      switch (modifier.id()) {
        case "default":
          return !entity.getData("gowhp:dyn/spartanrage");
        case "spartanrageregen":
          return entity.getData("gowhp:dyn/spartanrage");
      };
    case "fiskheroes:leaping":
      switch (modifier.id()) {
        case "default":
          return !entity.getData("gowhp:dyn/spartanrage");
        case "spartanrageleap":
          return entity.getData("gowhp:dyn/spartanrage");
      };
    case "fiskheroes:charged_beam":
      switch (modifier.id()) {
        case "boulderthrow":
          return entity.getData("gowhp:dyn/spartanrage") && entity.isOnGround();
        case "leviathanaxethrow":
          return entity.getData("gowhp:dyn/leviathanaxe") && entity.getData("gowhp:dyn/leviathanaxe_runic_cycle") == 0;
        case "wrathofthefrostancient":
          return entity.getData("gowhp:dyn/leviathanaxe") && entity.getData("gowhp:dyn/leviathanaxe_runic_cycle") == 1;
        case "breathofthamur":
          return entity.getData("gowhp:dyn/leviathanaxe") && entity.getData("gowhp:dyn/leviathanaxe_runic_cycle") == 2;
        case "cycloneofchaos":
          return entity.getData("gowhp:dyn/bladesofchaos") && entity.getData("gowhp:dyn/bladesofchaos_runic_cycle") == 0;
        case "fireofares":
          return entity.getData("gowhp:dyn/bladesofchaos") && entity.getData("gowhp:dyn/bladesofchaos_runic_cycle") == 1;
      };
    case "fiskheroes:fireball":
        return entity.getData("gowhp:dyn/bladesofchaos") && !entity.getData("fiskheroes:beam_charging");
    default:
        return true;
    }
}

function isKeyBindEnabled(entity, keyBind) {
    switch (keyBind) {
        case "WEAPON_CYCLE":
            return !entity.getData("gowhp:dyn/spartanrage") && !entity.getData("fiskheroes:shield_blocking") && !(entity.getData("gowhp:dyn/leviathanaxe") || entity.getData("gowhp:dyn/bladesofchaos"));
        case "LEVIATHANAXE":
            return entity.getHeldItem().isEmpty() && entity.getData("gowhp:dyn/weapon_cycle") == 0 && !entity.getData("gowhp:dyn/spartanrage") && !entity.getData("gowhp:dyn/bladesofchaos") && !entity.getData("fiskheroes:shield_blocking");
        case "BLADESOFCHAOS":
            return entity.getHeldItem().isEmpty() && entity.getData("gowhp:dyn/weapon_cycle") == 1 && !entity.getData("gowhp:dyn/spartanrage") && !entity.getData("gowhp:dyn/leviathanaxe") && !entity.getData("fiskheroes:shield_blocking");
        case "SHIELD":
            return !entity.getData("gowhp:dyn/spartanrage") && !entity.getData("fiskheroes:beam_charging");
        case "SPARTANRAGE":
            return !entity.getData("gowhp:dyn/leviathanaxe") && !entity.getData("gowhp:dyn/bladesofchaos");
        case "BOULDERTHROW":
            return entity.getData("gowhp:dyn/spartanrage") && entity.isOnGround();
        case "LEVIATHANAXE_RUNIC_CYCLE":
            return entity.getData("gowhp:dyn/leviathanaxe") && !entity.getData("fiskheroes:shield") && !((entity.getData("gowhp:dyn/leviathanaxe_runic_cycle") == 0 || entity.getData("gowhp:dyn/leviathanaxe_runic_cycle") == 1 || entity.getData("gowhp:dyn/leviathanaxe_runic_cycle") == 2) && entity.getData("fiskheroes:beam_charging"));
        case "LEVIATHANAXERUNICCYCLEUNAVAILABLE":
            return ((entity.getData("gowhp:dyn/leviathanaxe_runic_cycle") == 0 || entity.getData("gowhp:dyn/leviathanaxe_runic_cycle") == 1 || entity.getData("gowhp:dyn/leviathanaxe_runic_cycle") == 2) && entity.getData("fiskheroes:beam_charging"));
        case "BLADESOFCHAOS_RUNIC_CYCLE":
            return entity.getData("gowhp:dyn/bladesofchaos") && !entity.getData("fiskheroes:shield") && !((entity.getData("gowhp:dyn/bladesofchaos_runic_cycle") == 0 || entity.getData("gowhp:dyn/bladesofchaos_runic_cycle") == 1) && entity.getData("fiskheroes:beam_charging"));
        case "BLADESOFCHAOSRUNICCYCLEUNAVAILABLE":
            return ((entity.getData("gowhp:dyn/bladesofchaos_runic_cycle") == 0 || entity.getData("gowhp:dyn/bladesofchaos_runic_cycle") == 1) && entity.getData("fiskheroes:beam_charging"));
        case "LEVIATHANAXETHROWANIMATION":
            return entity.getData("gowhp:dyn/leviathanaxe") && !entity.getData("fiskheroes:shield") && entity.getData("gowhp:dyn/leviathanaxe_runic_cycle") == 0 && entity.getData("fiskheroes:beam_charging");
        case "WRATHOFTHEFROSTANCIENT":
            return entity.getData("gowhp:dyn/leviathanaxe") && !entity.getData("fiskheroes:shield") && entity.getData("gowhp:dyn/leviathanaxe_runic_cycle") == 1;
        case "BREATHOFTHAMUR":
            return entity.getData("gowhp:dyn/leviathanaxe") && !entity.getData("fiskheroes:shield") && entity.getData("gowhp:dyn/leviathanaxe_runic_cycle") == 2;
        case "THECYCLONEOFCHAOS":
            return entity.getData("gowhp:dyn/bladesofchaos") && !entity.getData("fiskheroes:shield") && entity.getData("gowhp:dyn/bladesofchaos_runic_cycle") == 0;
        case "THEFIREOFARES":
            return entity.getData("gowhp:dyn/bladesofchaos") && !entity.getData("fiskheroes:shield") && entity.getData("gowhp:dyn/bladesofchaos_runic_cycle") == 1;
        case "CHARGED_BEAM":
            return ((entity.getData("gowhp:dyn/spartanrage") && entity.isOnGround()) || entity.getData("gowhp:dyn/leviathanaxe") || entity.getData("gowhp:dyn/bladesofchaos")) && !entity.getData("fiskheroes:shield");
        case "GROUND_SMASH":
            return entity.getHeldItem().isEmpty() && !entity.getData("fiskheroes:shield") && entity.getData("gowhp:dyn/spartanrage");
        default:
            return true;
    }
}