// skill types
// 0 - passive not castable
// 1 - summon castable, oft limited, 1st pref
// 2 - restore not used here
// 3 - char-only buff castable, 2nd pref
// 4 - buff castable, 3rd pref
// 5 - combat not castable
int max_castable(skill sk) { // returns how many times you can possibly cast a given skill (NOT based on current MP)
switch (sk) {
case $skill[Advanced Cocktailcrafting]: return 3 + 2*to_int(have_skill($skill[superhuman cocktailcrafting])) - to_int(get_property("cocktailSummons"));
case $skill[Pastamastery]: return 3 + 2*to_int(have_skill($skill[transcendental noodlecraft])) - to_int(get_property("noodleSummons"));
case $skill[Advanced Saucecrafting]: return 3 + 2*to_int(have_skill($skill[the way of sauce])) - to_int(get_property("reagentSummons"));
case $skill[Rainbow Gravitation]: return 3 - to_int(get_property("prismaticSummons"));
case $skill[Summon Hilarious Objects]: return to_int(get_property("grimoire1Summons") == "0");
case $skill[Summon Tasteful Items]: return to_int(get_property("grimoire2Summons") == "0");
case $skill[Summon Alice Army Cards]: return to_int(get_property("grimoire3Summons") == "0");
case $skill[Summon Snowcones]:
case $skill[Summon Stickers]:
case $skill[Summon Sugar Sheets]: return 3 - to_int(get_property("tomeSummons"));
case $skill[Summon Crimbo Candy]: return to_int(get_property("_candySummons") == "0");
// candyHeartSummons??
}
if (mp_cost(sk) == 0) return 0;
return floor(my_maxmp() / mp_cost(sk));
}
// build list of castable skills
record tskill {
skill nome;
int type;
int irr; int ele; int vent;
};
tskill[int] skills;
file_to_map("classskills.txt",skills);
print("Your castable skills:","blue");
foreach i,s in skills {
if (!have_skill(s.nome) || (s.nome.combat || s.type < 1 || s.type == 2) || // only types 1,3,4 that you have
max_castable(s.nome) == 0 || $ints[45,90,1025,3101,3102,3103,3104,3105,3106,] contains i || // casting limits, skip flavours, deep dark visions, rage gland
(s.type > 2 && to_effect(s.nome) != $effect[none] && have_effect(to_effect(s.nome)) > 2000)) { // skip buffs you have too much of
remove skills[i]; continue;
}
print(i+": "+s.nome + " ("+mp_cost(s.nome)+" MP) -- "+to_effect(s.nome));
}
int rest_mp() { // calculate resting MP
int[item] campgear = get_campground();
if (numeric_modifier("Base Resting MP") < 40 && item_amount($item[Frobozz Real-Estate Company Instant House (TM)]) > 0 && use(1,$item[Frobozz Real-Estate Company Instant House (TM)])) {}
if (numeric_modifier("Base Resting MP") < 10 && retrieve_item(1,$item[Newbiesport™ tent]) && use(1,$item[Newbiesport™ tent])) {}
if (!have_bartender()) print("You could get a bartender for an additional 15 MP/rest.","olive");
if (!(campgear contains $item[beanbag chair])) print("You could get a beanbag chair for an additional 30 MP/rest.","olive");
if (!(campgear contains $item[feng shui for big dumb idiots])) print("You could get some good Feng Shui for an additional 7 MP/rest.","olive");
return numeric_modifier("Base Resting MP") * (100+numeric_modifier("Resting MP Percent"))/100.0 + numeric_modifier("Bonus Resting MP");
}
int restmp = rest_mp();
print("Resting MP: "+restmp,"blue");
int next_restore(boolean doit) { // returns MP gained from next available free restore method, 0 if no methods available
if (item_amount($item[platinum yendorian express card]) > 0 && !get_property("expressCardUsed").to_boolean()) {
if (doit) use(1,$item[platinum yendorian express card]);
return my_maxmp();
}
if (item_amount($item[license to chill]) > 0 && !get_property("_licenseToChillUsed").to_boolean()) {
if (doit) use(1,$item[license to chill]);
return my_maxmp();
}
if (my_level() > 11 && get_property("sidequestNunsCompleted") == "fratboy" && to_int(get_property("nunsVisits")) < 3) {
if (doit) cli_execute("nuns mp");
return min(1000,my_maxmp());
}
if (item_amount($item[clan vip lounge key]) > 0 && !get_property("_aprilShower").to_boolean() && which_shower() == "hot") {
if (doit) cli_execute("shower hot");
return min(1000,my_maxmp());
}
if ((have_skill($skill[disco nap]) ||
have_skill($skill[adventurer of leisure]) ||
have_skill($skill[executive narcolepsy]) ||
have_skill($skill[food coma]) ||
have_skill($skill[dog tired]) ||
get_property("chateauAvailable").to_boolean() ||
have_familiar($familiar[unconscious collective])) && contains_text(visit_url("campground.php"),"_free.gif")) { // free rest remains
if (doit) cli_execute("rest");
return min(restmp,my_maxmp());
}
return 0;
}
boolean burn_to(int target) { // only returns true if burning occurred!
target = minmax(target,0,max(0,my_maxmp() - restmp));
if (my_mp() <= target) return false;
print("Burning down to "+target+" MP...");
int init = my_mp();
if (my_class() == $class[accordion thief]) record_songs();
cli_execute("burn extra -"+target);
if (my_mp() <= target) return true;
int mpflag;
repeat {
mpflag = my_mp();
foreach i,s in skills {
if (i > 6000 && i < 6028 && (have_effect(to_effect(s.nome)) == 0 || // skip AT buffs you don't have or have too much of
have_effect(to_effect(s.nome)) > 2000)) continue;
if (!s.nome.song && max_castable(s.nome) > 0 && my_mp() >= mp_cost(s.nome))
use_skill(count(skills) == 1 ? min(max_castable(s.nome),ceil((my_mp() - target)/mp_cost(s.nome))) : 1, s.nome);
if (my_mp() <= target) return true;
}
} until (mpflag == my_mp());
return (my_mp() != init);
}
boolean burn_everything() {
if (my_path() == "Zombie Slayer") return true;
if ((count(skills) > 0 || have_item($item[the trickster trikitixa]) > 0) && next_restore(false) > 0) {
maximize("-1000 mana cost, 2 mp, 1 hp",false);
// maximize("adv, switch disembodied hand, -tie",true);
burn_to(min(numeric_modifier("_spec","Buffed MP Maximum"),my_maxmp()) - next_restore(false));
while (next_restore(true) > 0 && burn_to(my_maxmp() - next_restore(false))) {}
}
print("No more free MP restores left.");
maximize("adv, switch disembodied hand, -tie",false);
if (count(skills) == 0) return true;
return burn_to(900000);
}