/* Set up your elemental and default items. Format is: ["weapon type", ["element", "item1 mods", "item2 mods"], etc] Mods should be written exactly as in game, so they will be equipped correctly. Default items are used if you don't have a correct element against the foe, or if it's a non-elemental foe. Default items should be written as full names. List items for the particular element in the order from the best to the worst. You can omit whole elements and weapon types if you don't want the script to use them. */ var elemental_items = [ ["hammer", //["aether", "D",], ["poison", "dP+9", "D+7"], ["vigor", "dL+8"], ["default", "poison hammer dP+9", "vigor hammer dL+8"], ], ["wand", ["poison", "dP+9"], ["vigor", "dL+9"], ["aether", "d+9"], ["default", "poison wand dP+9", "vigor wand dL+9"], ], ["staff", ["fire", "dF+9"] ], ["crossbow", ["poison", "dP"], ["fire", "dF+9"], ["ice", "dI+12"], ], /* ["sword", ["aether", "dU+9","dU+8"], ["fire", "D+7", "dF"], ["ice", "dI"], ["poison", "dP", "D"], ["vigor", "D", "dL+10", "dL+9"], ["default", "aether sword dU+9", "aether sword dU+8", "vigor sword dL", "poison sword D"], ], */ ["shield", //["vigor", "A"], ["poison", "A"], //["ice", "A"], //["aether", "A"], //["fire", "A"], ["default", "compound"], ], ] /* These non-elemental items can be used as weapon types in the lists below. */ var special_weapons = ["bardiche", "blade", "heavy hammer", "repeater", "arm"] /* Weapon type priority for single targets: 1. First type + foe's weak element. 2. Default weapon of the first type. 3. Second type + foe's weak element. 4. Continue 1-3 until a weapon is found. If a weapon type isn't listed here, it will not be used. */ var for_melee_single_target = [ "sword", "hammer", ] /* If true, then script can use dX weapons for dps purposes if you don't have a D weapon of that element. */ var use_mods_for_dmg = false /* How many regular enemies are needed to start using AoE weapons instead of single target. */ var aoe_threshold = 4 /* Weapons to use for melee AoE, same priority logic as the regular melee. */ var for_melee_aoe = ["arm"] /* If this is set to `true`, script will prefer to use ranged items from lists below instead of melee. */ var prefer_ranged = false /* Will prefer ranged weapons only for these enemies, but will try to get in melee if they are near */ var prefer_ranged_foes = [] /* Will exclusively use single-target ranged against these enemies */ var must_ranged_foes = ["wasp", "wasp nest", "mosquito", "huge mosquito"] /* Used for scripted bosses, for `ranged_foes`, or when `prefer_ranged` is true. */ var for_ranged_single_target = ["crossbow", "repeating","wand", ] /* Enable this _only_ if you have 10* repeating crossbow without attack speed enchant. Increases effective attack speed. */ var enable_repeating_aac = true /* Weapons to use for ranged AoE. Ranged AoE is triggered by the same threshold as melee AoE.*/ var for_ranged_aoe = ["wand", "staff"] /* Weapons to use against `immune_to_physical` enemies. */ var for_phys_immune = ["wand", "staff"] /* Full name of the shield with the highest evade%, will be used to block big boss attacks */ var evade_shield = "poison shield +10" /* Script will try to stunlock these enemies instead of using any other tactics. Supported: poena, ceiling decorator, ice elemental. */ var do_stunlock = [ "poena", "ceiling decorator", "ice elemental" ] // Full names of weapons to use for stunlocking var stunlock_weapons = [ "poison hammer dP+9", "vigor hammer dL+8"] /* How much HP a non-boss enemy must have to use dU weapons on it instead of other tactics. If 0, will not specifically unmake. */ var unmaking_threshold = 600 /* When to debuff bosses: "never", "always", or "smite" (only if Smite buff is active). */ var debuff_bosses = "always" /* When to debuff regular enemies: "never", "always", or "smite" (only if Smite buff is active). */ var debuff_non_bosses = "smite" /* If item is not listed here, its `R` ability won't be used. Supported: dash, bash, bardiche, hammer, blade, skeleton_arm, mask, quarterstaff, fire_talisman, cinderwisp. */ var useable_abilities = ["dash", "bash", "skeleton_arm", "mask", "blade", "hammer", "fire_talisman", "bardiche", "quarterstaff", // "cinderwisp" // will spend your fire runes ] /* Advanced: these are default values, change them accordingly if you have speed enchants on these weapons. */ var hammer_frames = 14 var bardiche_frames = 22 /* `dmg * (crit_mult + base_crit_mult)`, script won't use the bardiche ability if non-boss's HP is lower than twice this damage*/ var bardiche_dmg = 52 * (7.6 + 2) /* Use scripted potions for bosses. */ var use_potions_for_bosses = true /* Drink crit/speed potion right at the start of phase1 of these boss fights. Overrides default logic that prefers to drink during the "hardest" phase. Supported: xylo, mushrooms, pallas, bronze, naga. The rest already drink the potion in phase1. */ var fast_potion_bosses = [ "xylo", "mushrooms", "pallas", ] /* Fraction of HP to consider low. When on low HP, will prioritize `ah` shield and `dL` weapon over foe's elemental weakness. If 1, will always try to lifesteal to max (useful for clearing zones with full HP). If 0, will never force lifesteal. */ var low_hp_threshold = 0.5 /* Switch to 1h+shield against non-boss foes when `low_hp_threshold` is reached */ var use_shield_on_low_hp = true // Choose amount based on your `dI` weapon var max_chill_stacks = 6 /* When to use Cinder ability (if listed in `useable_abilities`). Will use at max_stacks, or if boss's HP is lower than stacks * dmg. */ var max_ignition_stacks = 10 var cinderwisp_dmg = 24 /* At least this many enemies must be present to use Smite ability. */ var smite_threshold = 7 // Depends on level/enchants of your BFG. var smite_damage = 85 // Enable smiting two screens at once var long_long_smite = true /* If you're doing the "kill unique foes" step of the Blade of the Fallen God quest, fill this array with names of the enemies you've already defeated. */ var bfg_defeated_foes = [] /* Set to true if you're doing Skeleton Arm quests. Prioritizes last-hitting foes with the Arm ability */ var pickpocket_quest = false // These depend on level/enchants of the Arm var arm_damage = 44 var max_pickpocket_stacks = 3 /* Cultist Mask quests. "simple" - steps 1 and 3 (uses on CD) "prevent" - step 4: do it in Rocky. Script will approach the scout, use mask, get hit as long as the debuff lasts, and quit the zone. */ var mask_quest = false // Show ability cooldowns in UI var ui_show_cd = true // Show your buffs/debuffs in UI var ui_show_statuses = true // Debug (noisy, useful for research) var ui_show_debug = false /* If true, script will exit the location if your current time > average time. */ var speedrun = false // If true, will use hatchet and shovel var harvesting = false func progress() ?pickup.distance<9 return equip_L("star")&equip_R("trisk") ?long_long_smite&smite_two_screens() return true ?healwalk() return true ?ff=explode return avoid_explosion() ?ll=caves check_stunlock() ?!ib&!at_boss free_mind=true return regular_fight() ?loc.stars>5&!pickpocket_quest dr("skeleton_arm") ?ll=rocky ?fi="acronian_scout" return fight_scout() return fight_dysan() :?ll=deadwood return fight_xyloalgia() :?ll=caves ?is(fi,"cool_bat") ?can_stunlock& ^do_stunlock.Contains("ceiling decorator") dr("mask") dr("blade") dr("bardiche") return stunlock() return auto_melee_miniboss() : return fight_bolesh() :?ll=fungus_forest_boss return fight_mushrooms() :?ll=mushroom&is(fi,"epic_snail") return dr("hammer")& ^dr("bash")&auto_melee_miniboss() :?ll=undead_crypt_boss return fight_pallas() :?ll=halls return ranged("aoe") :?ll=bronze_guardian return fight_bronze_guardian() :?ll=icy_ridge ?fi="ice_elemental_elite" ?!at_boss ?can_stunlock& ^do_stunlock.Contains("ice elemental") dr("mask") dr("blade") dr("hammer") return stunlock() : return auto_melee_miniboss() : return ranged("aoe") return fight_hrimnir() :?ll=temple& ^is(fi,"acronian_cultist") excluded_items="vigor" return auto_melee_miniboss() :?ll=nagaraja return fight_nagaraja() : dbg("Fighting unknown boss:"+fi) auto_melee_boss() func healwalk() ?ff&(fd<23) ?hp<(maxhp/4)&item.potion!empty& ^(item.potion="healing"| ^item.potion="vampiric") activate potion return false :?harvesting&harvest.distance<3& ^_harvest() return true :?should_summon() return equip_L("trisk")&summon() :?can_qs_dash() return qs_dash() ae_shield() ?hp3 scrolling++ screen.Next() : scrolling=0 screen.ResetOffset() ?foe_ehp<600&foe_ehp>0&cd_ok& ^fd<25& ^(fc>5|scrolling>15) return smite() return scrolling>0 func try_evade() ?can_mind set_lock("mind",2) return backflip() return hard_block() func hard_block() return equip_L("quest")& ^equip_R(evade_shield) func evade_at(t) ?ft>=t return try_evade() ?ft(t-bardiche_frames) dr("bardiche") ?ft>(t-hammer_frames) dr("hammer") return false func soft_block() ?lock return false return equip_R(evade_shield) func around(t) return ft>(t-2)&ft<(t+2) func fight_scout() ?is(mask_quest,"prevent") equip_L("trisk") ?fs=32&ft>11&can_mask() return mask() ?get_cd("mask")>0& ^!foe_debuff("debuff_feeble") return loc.Leave() ?have_dashing equip_R("dashing") return : auto_melee_miniboss() var last_state=0 var dysan_step=-1 func fight_dysan() dr("skeleton_arm") var delay=chill_delay() var hit=28 ?loc.stars>10 hit=22 ?ff=phase1 dr("blade") maybe_drink() ?(fs=33&ft=23)| ^(fs=32&around(hit+delay)) return soft_block() :?ff=phase2 ?smite_at_exact()|dash_closer()| ^(fs=33&use_abilities()) return true f=f_weapon("melee",false, ^weak_elem,"stats","false") ?f equip_L(f) ?fs=32&around(58+delay) return soft_block() f=false ?should_debuff() f=f_debuff_weapon("melee", ^false,debuff_elems[0],false) ?f return equip_R(f) return ae_R("melee",false) :?ff=phase3 weak_elem="default" hit=20+math.Max(0,delay-6) ?fs=32&ft>hit&dysan_step=0 ^&fd>10&can_hammer() return hammer() var resist=foe_buff("adaptive_defense") ?!(low_hp&is(resist,"vigor")) excluded_items=resist ?(last_state=32&fs=33)| ^(last_state=33&fs=2)| ^(last_state=2&fs=32) dysan_step++ :?(fs!32)&(fs!33)& ^(fs!2) dysan_step=0 last_state=fs ?fs=32&dysan_step>=6& ^evade_at(hit) dysan_step=0 return :?fs=115&ft<=70& ^evade_at(70) return set_lock("boss",7) :?fs=32&(dysan_step<7)& ^around(48+delay) return soft_block() auto_melee_boss() func fight_xyloalgia() dr("skeleton_arm") var stunlock_poena=loc.stars>5& ^can_stunlock&do_stunlock.Contains("poena") ?ff=phase1 ?fast_potion_bosses.Contains("xylo") maybe_drink() ?stunlock_poena dr("mask") dr("hammer") dr("blade") dr("bardiche") ?fs=32& ^evade_at(31+chill_delay()) return auto_melee_boss() :?ff=phase2 ?unsummon() return excluded_items="dU" ?stunlock_poena stunlock() :?(disable_debuffs&fh>(fm/4))| ^(fs=32&ft=41) hard_block() : auto_melee_boss() func fight_bolesh() ?fs=133&(around(11)|around(16)) hard_block() :?fs=142&evade_at(60) return :?can_mind& ^!foe_buff("spider_buff_damage") maybe_drink() return use_abilities()| ^auto_melee_boss() : ?for_ranged_single_target. ^Contains("repeating") return equip_L("repeating") ranged("single") func fight_mushrooms() var delay=chill_delay() ?ff=phase1 ?fast_potion_bosses.Contains("mushrooms") maybe_drink() dr("skeleton_arm") ?fs=32&evade_at(46+delay) return :?fs=33&ft=fd+4 return soft_block() :?ff=mushroom_boss_fat maybe_drink() ?fs=32&evade_at(26+delay) return auto_melee_boss() func fight_pallas() dr("skeleton_arm") ?ff=phase1 ?fast_potion_bosses.Contains("pallas") maybe_drink() ?fs=32&ft=68 soft_block() : auto_melee_boss() :?ff=phase2 maybe_drink() ?fc>2 return ranged("aoe") auto_melee_boss() func fight_bronze_guardian() ?fast_potion_bosses.Contains("bronze") maybe_drink() ?fs=32&ft=33& ^armor1 ranged("aoe") : ranged("single") :?ib&fs=132&ft>24 set_lock("boss",2) auto_melee_boss() :?ib&fs=142&ft>83 set_lock("boss",2) ?fc>1 ranged("aoe") : ranged("single") :?ib&fc=1 ?fa>0 ?can_hammer() return hammer() return melee("dps") maybe_drink() auto_melee_boss() :?fd<8 auto_melee() : auto_melee_boss() var dists=[3,4] func is_snowball_near() var x=screen.FromWorldX(pos.x) var y=screen.FromWorldZ(pos.z) for dist:dists ?draw.GetSymbol(x+dist,y-3)="("& ^draw.GetSymbol(x+dist+1,y-3)="_"& ^draw.GetSymbol(x+dist+2,y-3)=")" return true return false var naga_step=0 func fight_nagaraja() ?fast_potion_bosses.Contains("naga") maybe_drink() var to_dodge=1 ?loc.stars>10 to_dodge=4 :?loc.stars>5 to_dodge=2 ?is_poison_near() ?naga_step<=to_dodge ?can_mind&fd<12 naga_step=0 maybe_drink() auto_melee_boss() : naga_step++ qs_dash() : evade_naga() :?fs=112&ft=59& ^fd<10 evade_naga() :?naga_step<=to_dodge ?use_abilities() return ?fs=32|fs=33| ^((fs=101|fs=112) ^&ft<20) excluded_items="wand" f=f_dps_weapon("ranged",false,true) ?f return equip_L(f) excluded_items=false ranged("single") : maybe_drink() auto_melee_boss() func evade_naga() ?can_mind naga_step=0 return backflip() : return soft_block() func is_poison_near() var x=screen.FromWorldX(pos.x) var y=screen.FromWorldZ(pos.z) return draw.GetSymbol(x+2,y-6)="("| ^(draw.GetSymbol(x+1,y-6)="(") func regular_fight() ?must_ranged_foe() return ranged("single") ?ff=immune_to_ranged|ff=ranged return auto_melee() ?prefer_ranged_foe()&can_aoe& ^fd>melee_aoe_range return auto_ranged() ?prefer_ranged return (can_backflip()&backflip())| ^auto_ranged() return auto_melee() func must_ranged_foe() for enemy:must_ranged_foes ?ff=enemy return true func prefer_ranged_foe() for enemy:prefer_ranged_foes ?ff=enemy return true func auto_melee() ?use_abilities() return true :?can_aoe&fd<=melee_aoe_range return melee("aoe") :?low_hp&use_shield_on_low_hp return melee("def") return melee("dps") func melee(mode) ?dash_closer() return true var aoe=is(mode,"aoe") ?should_unmake() ?te_unmake("melee",aoe) mode="unmake" return approach() :?should_debuff() ?te_debuff("melee",aoe) mode="debuff" return approach() ?is(mode,"def") ae_L("melee",false) ?use_shield_on_low_hp ae_shield() ae_R("melee",false) : ae_dps("melee",aoe) return approach() func approach() var range=6 ?f_type range=get(weapon_ranges,f_type)+1 ?fd>range ?!is_2hander(f_type) ae_shield() return true func dash_closer() ?can_dash() return dash() :?should_qs_dash() return qs_dash() return false func auto_ranged() ?use_abilities() return true :?can_aoe&for_ranged_aoe.Count()>0& ^fd<=ranged_range return ranged("aoe") :?for_ranged_single_target.Count()>0 return ranged("single") return auto_melee() func ranged(mode) var aoe=is(mode,"aoe") ?!aoe&must_ranged_foe()& ^for_ranged_single_target. ^Contains("repeating") return equip_L("repeating") ?should_unmake() ?te_unmake("melee",aoe) mode="unmake" :?should_debuff() ?te_debuff("ranged",aoe) return return ae_dps("ranged",aoe) func auto_melee_boss() ?use_abilities()|dash_closer() return true ?should_unmake()& ^te_unmake("melee",false) return approach() :?should_debuff() ?te_debuff("melee",false) return approach() ae_dps("melee",false) return approach() func auto_melee_miniboss() return dr("blade")& ^dr("mask")&dr("cinderwisp")& ^auto_melee() var can_stunlock=do_stunlock.Count()>0& ^stunlock_weapons.Count()>0 func check_stunlock() ?can_stunlock&fi!"cool_bat"& ^do_stunlock.Contains("ceiling decorator") dr("hammer") func stunlock() dr("skeleton_arm") ?dash_closer() return true ?disable_debuffs return maybe_drink()&melee("dps") var stunned=foe_debuff("stun") ?(can_hammer()&fd<=17)| ^is(lock,"hammer") return hammer() :?(stunned>bardiche_frames+10)& ^should_bard()|is(lock,"bardiche") return bardiche() :?stunned>10 ?should_cinder() return cinder() ?should_smite() return smite() ?should_mask() return mask() :?stunned<=3 ?get_cd("bash")<=0&fd<10& ^foe_ehp>100&can_backflip() return backflip() ?can_qs_dash() return qs_dash() f=false for it:stunlock_weapons ?!f&!(it=excluded_items)& ^!(it=foe_elem) f=it ?f equip_L(f) : equip_L(stunlock_weapons[0]) f=false ?should_unmake() f=f_unmake_weapon("melee", ^false,false) :?should_debuff() f=f_debuff_weapon("melee", ^false,debuff_elems[0],false) ?f equip_R(f) : ae_R("melee",false) var _equip_L=false func equip_L(it) _equip_L=it ?is_2hander(it)|is_2hander(f_type) return aac(it) equipL @it@ return it var _equip_R=false func equip_R(it) _equip_R=it ?is_2hander(it)|is_2hander(f_type) return aac(it) equipR @it@ return it func is_2hander(ty) return ty&all_2h_types.Contains(ty) func ae_L(range,aoe) f=f_dps_weapon(range,aoe,true) ?f return equip_L(f) return false func ae_R(range,aoe) f=f_dps_weapon(range,aoe,false) ?f return equip_R(f) return ae_shield() func ae_shield() f=false f_type=false ?low_hp f=get_item("shield","vigor","mod") ?!f f=get_item("shield",weak_elem,"stats") ?!f f=get_item("shield","default","") ?f return equip_R(f) return false func ae_dps(range,aoe) f=f_dps_weapon(range,aoe,true) ?!f return false equip_L(f) ?is_2hander(f_type) return f f=f_dps_weapon(range,aoe,false) ?f return equip_R(f) return false func f_dps_weapon(range,aoe,allow_2h) f=false ?low_hp f=f_weapon(range,aoe, ^"vigor","mod",allow_2h) ?!f f=f_weapon(range,aoe, ^weak_elem,"stats",allow_2h) return f func te_debuff(range,aoe) f=false for elem:debuff_elems f=f_debuff_weapon(range,aoe, ^elem,!_equip_L) ?f ?!_equip_L equip_L(f) ?is_2hander(f_type) return true :?!_equip_R ?low_hp return ae_R(range,aoe) return equip_R(f) ?_equip_L ?!_equip_R return ae_R(range,aoe) : return false return true func f_debuff_weapon(range,aoe, ^elem,allow_2h) f=f_weapon(range,aoe, ^elem,"mod",allow_2h) ?!f&range="melee"& ^!(ff=immune_to_ranged|ff=ranged) f=f_weapon("ranged",aoe,elem, ^"mod",allow_2h) return f func te_unmake(range,aoe) ?prefer_ranged&fd>melee_range range="ranged" f=f_unmake_weapon(range,aoe,true) ?!f aoe=false f=f_unmake_weapon(range,aoe,true) ?!f return false equip_L(f) ?is_2hander(f_type) return true ?low_hp return ae_R(range,aoe) f=f_unmake_weapon(range,aoe,false) ?f return equip_R(f) return ae_R() func f_unmake_weapon(range,aoe,allow_2h) f=f_weapon(range,aoe, ^"aether","mod",allow_2h) ?!f&range="melee" f=f_weapon("ranged",aoe, ^"aether","mod",allow_2h) return f func f_weapon(range,aoe,elem, ^purpose,allow_2h) f=false f_type=false var types=get_preferred_types(range,aoe) for ty:types ?allow_2h|!is_2hander(ty) ?!elem_types.Contains(ty)& ^!is(purpose,"mod") f_type=ty return ty f=get_item(ty,elem,purpose) ?!f&purpose="stats" ?use_mods_for_dmg f=get_item(ty,elem,"mod") ?!f f=get_item(ty,"default","") ?f f_type=ty return f return false func get_preferred_types(range,aoe) ?phys_immune| ^(can_aoe&ff=magic_vulnerability) return for_phys_immune var types=for_melee_single_target ?is(range,"melee") ?fa>0 ?aoe types=aa_aoe_types : types=aa_st_types :?aoe types=for_melee_aoe : ?aoe types=for_ranged_aoe : types=for_ranged_single_target return types var excluded_items="" func get_item(ty,elem,purpose) var h ?is(elem,"default") h=hash([ty,"default"]) : h=hash([ty,elem,purpose]) var items=try_get(all_items,h,false) ?!items|items.Count()=0 return false for it:items ?(!_equip_L|!is(it,_equip_L))& ^(!excluded_items|!(it=excluded_items)) return it return false func should_unmake() return unmaking_threshold>0&!ib& ^fm>=unmaking_threshold var only_dot=false func can_debuff() only_dot=false ?disable_debuffs return false ?ib ?is(debuff_bosses,"never") return false ?is(debuff_bosses,"smite")&smite_stacks=0 ?ll=Rocky return true ?cbd("debuff_dot") only_dot=true return true return false ?!ib&(is(debuff_non_bosses,"never")| ^is(debuff_non_bosses,"smite")&smite_stacks=0) return false return true var disable_debuffs=false var debuff_elems=[] func should_debuff() ?!can_debuff() return false debuff_elems.Clear() ?cbd("debuff_dot") debuff_elems.Add("fire") ?only_dot return true ?cbd("debuff_chill") debuff_elems.Add("ice") ?cbd("debuff_damage") debuff_elems.Add("poison") var c=debuff_elems.Count() ?c>1& ^ff=debuff_elems[0] var move=debuff_elems[0] debuff_elems.Emplace(0,debuff_elems[c-1]) debuff_elems.Emplace(c-1,move) return c>0 func cbd(debuff_uid) ?(ff="immune_to_"+debuff_uid) return false ?is(debuff_uid,"debuff_chill") var c=foe_debuff("debuff_chill") return c10&fd<16 func dash() ?!disable_debuffs&cu("bash") return equip_R("bashing") :?cu("dash") return equip_R("dashing") return false func can_qs_dash() return cu("quarterstaff")& ^ca() func should_qs_dash() return (prefer_ranged&fd>28)| ^(fd>16| ^fd<11&fd>5)& ^can_qs_dash() func qs_dash() equip_L("quarterstaff") return use("quarterstaff") func can_backflip() return cu("mind")&free_mind& ^screen.FromWorldX(pos.x)>5 func backflip() ae_shield() return equip_L("mind") func can_slap() return cu("skeleton_arm")& ^!(fi="ice_pillar")& ^fd<7&!phys_immune& ^ca() func should_slap() return can_slap()&(!pickpocket_quest| ^foe_ehp<=arm_damage) func slap() ?pickpocket_stacks0 ?foe_ehp<=smite_damage&can_smite() for e:bfg_defeated_foes ?ff=e return false return true return false return (fc>=smite_threshold ^&foe_ehp<=smite_damage)&can_smite() func smite() equip_L("blade") return use("blade") func smite_at_exact() dr("blade") ?fh<=smite_damage&get_cd("blade")<=0 return smite() return false func can_hammer() return cu("hammer")&!phys_immune& ^fd<=21&ca() func should_hammer() ?!can_hammer() return false return is(lock,"hammer")| ^(ib|can_aoe&fd<15) ^&(fa>0|ff=spawner| ^can_debuff()& ^!(ff=immune_to_stun)) func hammer() set_lock("hammer",hammer_frames) equip_L("heavy hammer") return use("hammer") func can_bard() return cu("bardiche")& ^fd<=9&!phys_immune& ^ca() func should_bard() return is(lock,"bardiche")|ib& ^!aspd_down&(foe_ehp>=(bardiche_dmg * 2)| ^foe_ehp0 equip_R("fire talisman") return use("fire_talisman") return false func can_cinder() return summon.GetId()="cinderwisp"& ^cu("cinderwisp")&ca() func should_cinder() return ib&can_cinder()& ^(summon.GetVar("ignition",0)>= ^max_ignition_stacks|foe_ehp<= ^max_ignition_stacks * cinderwisp_dmg) func cinder() activate cinderwisp return true func use_abilities() ?is(mask_quest,"simple")&can_mask() return mask() ?pickpocket_quest&can_slap() return slap() ?should_cinder() return cinder() ?should_mask() return mask() ?should_hammer() return hammer() ?should_smite() return smite() ?should_bard() return bardiche() ?should_slap() return slap() return false var aac_tick=1 func aac(weapon) _equip_L=weapon equip @weapon@ ?!ai.idle return true ?is(lock,"hammer")| ^is(lock,"bardiche") return true ?weapon="repeating" ?!enable_repeating_aac return weapon aac_tick-- ?aac_tick=0 aac_tick=2 equip blade equip @weapon@ return weapon ?weapon="wand"|weapon="staff" return true equip wand equip @weapon@ return weapon var elem_types=["sword","big sword","wand", "shield","crossbow","staff","hammer"] var all_2h_types=["bardiche","arm","blade", "heavy hammer","repeating","staff", "quarterstaff","shovel","crossbow"] var ranged_2h_types=["repeating","crossbow", "staff"] var al_elems=["aether","fire","ice", "poison","vigor"] var aa_st_types=[] var aa_aoe_types=[] var all_items=[] func _prepare_items() for item_type:elemental_items ?item_type.Count()>1 var ty=item_type[0] for i=1 .. item_type.Count()-1 var suffixes=item_type[i] ?suffixes.Count()>1 _categorize_item(ty,suffixes) for a:[ ^[for_melee_single_target,aa_st_types], ^[for_melee_aoe,aa_aoe_types]] var source=a[0] var dest=a[1] ?source.Contains("heavy hammer") dest.Add("heavy hammer") ?source.Contains("hammer") dest.Add("hammer") for w:source ?!(w="hammer") dest.Add(w) func _categorize_item(ty,suffixes) var elem=suffixes[0] for j=1 .. suffixes.Count()-1 var suffix=suffixes[j] ?is(elem,"default") add_item(hash([ty,"default"]),suffix) : var purpose=get_purpose(suffix) var full_name=string.Join(" ", ^[elem,ty,suffix]) var h=hash([ty,elem,purpose]) add_item(h,full_name) func hash(parts) return string.Join("-",parts) var elem_mods=["f","F","i","I", "p","P","h","L","u","U"] func get_purpose(suffix) ?string.Size(suffix)>1& ^elem_mods.Contains(string.Sub(suffix,1,1)) return "mod" return "stats" func add_item(hash,_name) var idx=all_items.IndexOf(hash) var arr ?idx=-1 arr=[_name] all_items.Add(hash) all_items.Add(arr) : arr=all_items[idx+1] ?!arr.Contains(_name) arr.Add(_name) var all_statuses=[ ["berserk","Berserk","+"], ["smite","Smite","+"], ["pick_pocket","Pickpocket","+"], ["vampiric","Vamp","+"], ["lucky_crit","CritUp","+"], ["lucky_mult","CritMultUp","+"], ["invisibility","Invis","+"], ["debuff_damage","DmgDown","-"], ["debuff_duration_damage","DmgDown","-"], ["spider_debuff_damage","DmgDown","-"], ["dysangelos_debuff_damage","DmgDown","-"], ["puff_debuff_damage","DmgDown","-"], ["debuff_yeti_chill","AtkSlow","-"], ["debuff_attack_speed","AtkSlow","-"], ["debuff_move_speed","MoveSlow","-"], ["debuff_chill","Chill","-"], ["stun","Stun","-"], ["pallas_phase2_debuff","RangeDown","-"], ["debuff_dot","FireDoT","-"], ["ignition","Ignition","-"] ] var status_uids=[] func _prepare_statuses() for info:all_statuses status_uids.Add(info[0]) var my_buffs=[] var my_debuffs=[] var unk_effects=[] var pickpocket_stacks=0 var smite_stacks=0 var stunned=false var aspd_down=false func _update_my_effects() my_buffs.Clear() my_debuffs.Clear() pickpocket_stacks=0 smite_stacks=0 stunned=false aspd_down=false for s:[buffs.string,debuffs.string] var splt=string.Split(s,":",",",false) var arr_size=splt.Count() ?arr_size>0 for i=1 .. arr_size-3 _parse_status(splt,i) i=i+3 var ignore_statuses=[ "quarterstaff_buff_attack_speed", "quarterstaff_buff_stun", "bardiche_buff_aoe_chance", "bardiche_buff_crit_chance", "bardiche_buff_crit_mult", "bardiche_buff_move_speed", ] var aspd_debuffs=[ "debuff_chill","debuff_attack_speed", "debuff_yeti_chill", ] var buff_template="{0}({1}) {2}" func _parse_status(splt,i) var uid=splt[i] var idx=status_uids.IndexOf(uid) ?idx=-1 ?!ignore_statuses.Contains(uid)& ^!unk_effects.Contains(uid) unk_effects.Add(uid) return var info=all_statuses[idx] var num=int.Parse(splt[i+1]) var dur=int.Parse(splt[i+2]) var _name=string.Format(buff_template, ^info[1],num,time.FormatDigital(dur)) ?info[2]="+" my_buffs.Add(_name) : my_debuffs.Add(_name) ?is(uid,"stun") stunned=true :?is(uid,"pick_pocket") pickpocket_stacks=num :?is(uid,"smite") smite_stacks=num :?aspd_debuffs.Contains(uid) aspd_down=true func foe_buff(uid) return get_foe_effect(foe.buffs.string,uid) func foe_debuff(uid) return get_foe_effect(foe.debuffs.string,uid) func chill_delay() return 7 * foe_debuff("debuff_chill") func get_foe_effect(str,uid) ?!(str=uid) return 0 ?is(uid,"adaptive_defense") for s:string.Split(str,":",",",false) ?s="adaptive_defense" return string.Split(s,"_",false)[2] var splt=string.Split(str,":",",",false) var i=splt.IndexOf(uid) ?is(uid,"stun") return int.Parse(splt[i+2]) return int.Parse(splt[i+1]) var foe_elem="default" func get_foe_weak_elem() ?ff=aether foe_elem="aether" return "vigor" ?ff=fire foe_elem="fire" return "aether" ?ff=ice foe_elem="ice" return "fire" ?ff=poison foe_elem="poison" return "ice" ?ff=vigor foe_elem="vigor" return "poison" foe_elem="default" return "default" var all_abilities=[ "mind","hammer","bardiche","blade", "skeleton_arm","mask","fire_talisman", "cinderwisp","quarterstaff","dash","bash", ] var move_r=["quarterstaff","bash","dash"] var cooldowns=["mind",0] var abilities=["mind",false] func _prepare_abilities() for r:useable_abilities ?!all_abilities.Contains(r) panic("Unknown ability:"+r) ?!abilities.Contains(r) set(cooldowns,r,0) set(abilities,r,false) var can_mind=false func _update_abilities() for i=0 .. abilities.Count()-2 var r=abilities[i] var cd=item.GetCooldown(r) set(cooldowns,r,cd) set(abilities,r,cd<=0) ?is(r,"mind") can_mind=cd<=0 i++ func dr(ability) ?useable_abilities.Contains(ability) set(abilities,ability,false) return true func get(dict,k) var idx=dict.IndexOf(k) ?idx=-1 panic("Bad dict key:k="+k) return dict[idx+1] func try_get(dict,k,default) var idx=dict.IndexOf(k) ?idx=-1 return default return dict[idx+1] func set(dict,k,v) var idx=dict.IndexOf(k) ?idx=-1 dict.Add(k) dict.Add(v) : dict[idx+1]=v return true func is(s1,s2) ?!s1|!s2 return false return string.Equals(s1,s2) var weapon_ranges=["sword",5,"hammer",5, "quarterstaff",5,"big sword",6,"arm",6, "heavy hammer",7,"bardiche",9,"staff",10, "blade",11,"wand",20,"heavy crossbow",22, "repeating",22,"crossbow",22] var melee_range=5 var melee_aoe_range=5 var ranged_range=20 func _prepare_ranges() var a=for_melee_single_target ?a.Count()>0 melee_range=get(weapon_ranges,a[0])+1 a=for_melee_aoe ?a.Count()>0 melee_aoe_range=get(weapon_ranges,a[0])+1 a=for_ranged_aoe ?a.Count()>0 ranged_range=get(weapon_ranges,a[0])+1 func _update_lock() ?stunned set_lock("stun",0) :?lock ?is(lock,"stun")|lock_timer<=0 lock=false : lock_timer-- : lock_timer=0 var at_boss=false var low_hp=false var can_aoe=false var f=false var f_type=false var weak_elem="default" var lock=false var lock_timer=false var free_mind=false var foe_ehp=0 var ib=false var phys_immune=false var ff=foe var ll=loc var fa=0 var fc=0 var fd=0 var fh=0 var fi=0 var fm=0 var fs=0 var ft=0 var tt=0 func _update_game_state() ff=foe ll=loc fa=foe.armor fc=foe.count fd=foe.distance fh=foe.hp fi=foe.id fm=foe.maxhp fs=foe.state ft=foe.time tt=totaltime _equip_L=false _equip_R=false f=false f_type=false excluded_items=false weak_elem=get_foe_weak_elem() disable_debuffs=foe.buffs.count>0& ^(foe_buff("poena_mirror")| ^foe_buff("buff_protection")) low_hp=hp<(maxhp * low_hp_threshold) foe_ehp=fa+fh ib=(ff=boss) phys_immune=(ff=immune_to_physical) can_aoe=(fc>=aoe_threshold) func prelude() ?speedrun&(tt>loc.averageTime)& ^loc.averageTime>0 loc.Leave() _update_game_state() _update_my_effects() _update_abilities() _update_lock() func panic(e) >`20,5,#red,@e@ loc.Pause() var gray="#7A8F93" func draw_ui() var x=1 var y=23 ?ui_show_debug y=21 ?ui_show_statuses ?ui_show_debug >`@x@,@y@,#F008B2, ^? @string.Join(",",unk_effects)@ y++ >`@x@,@y@,#FE6800, ^- @string.Join(",",my_debuffs)@ >`@x@,@y+1@,#00A300, ^+ @string.Join(",",my_buffs)@ ?!ui_show_debug >`@x@,@y+2@,@gray@,@loc.stars@* ^ @time.FormatDigital(tt)@ ^/@time.FormatDigital(loc.averageTime)@ ?ui_show_cd y=6 for r:all_abilities ?!move_r.Contains(r)&r!"fire_talisman"& ^abilities.Contains(r) var cd=get_cd(r) ?is(r,"skeleton_arm") r="arm" :?is(r,"cinderwisp") r="cinder" >`@x@,@y@,#@colorize(cd)@, ^@string.Capitalize(r)@ ^ @time.FormatDigital(cd)@ y++ >`@x@,@y@, ^#@colorize(get_cd("quarterstaff"))@,QS ?abilities.Contains("bash") >`@x+2@,@y@,@gray@,/ >`@x+3@,@y@, ^#@colorize(get_cd("bash"))@,B ?abilities.Contains("dash") >`@x+4@,@y@,@gray@,/ >`@x+5@,@y@, ^#@colorize(get_cd("dash"))@,D ?ui_show_debug x=1 y=15 ?ff ?string.Size(foe.buffs.string)>0 >`@x@,@y@,@gray@,@foe.buffs.string@ >`@x@,@y+1@,@gray@,id: @fi@ >`@x@,@y+2@,@gray@,S: @fs@, ^ T: @ft@ var c=foe_debuff("debuff_chill") >`@x@,@y+3@,@gray@,Chill: @c@/@c*7@ >`@x@,@y+4@,@gray@,Dist: @fd@ >`@x@,@y+5@,@gray@,Count: @fc@ y=24 >`@x@,@y+1@,@gray@,@loc.stars@* ^ @time.FormatDigital(tt)@ ^/@time.FormatDigital(loc.averageTime)@ ^ @ff@ var _weapon=" (L)" x=screen.w-10 y=23 ?_equip_L x=x-string.Size(_equip_L) _weapon=_equip_L+_weapon >`@x@,@y@,#blue,@_weapon@ _weapon=" (R)" x=screen.w-10 ?_equip_R x=x-string.Size(_equip_R) _weapon=_equip_R+_weapon >`@x@,@y+1@,#blue,@_weapon@ func colorize(cd) ?cd>0 return "red" return "green" func brew_pot() ?ll=Mushroom|ll=mine| ^ll=halls|ll=rocky|ll=deadwood| ^ll=icy_ridge brew wood+bronze :?ll=caves|ll=temple brew stone+bronze func reset_loop() lock=false lock_timer=0 unk_effects.Clear() at_boss=false naga_step=0 last_state=0 dysan_step=-1 ?loc.begin equip_L("quest") ae_shield() _prepare_statuses() _prepare_items() _prepare_ranges() _prepare_abilities() ?use_potions_for_bosses brew_pot() :?item.potion=empty brew tar+bronze :?loc.loop ?use_potions_for_bosses brew_pot() reset_loop() prelude() ?ai.enabled&!ai.paused progress() : healwalk() draw_ui()