[Feature]: Lucky! megatile
uthuluc opened this issue · 2 comments
uthuluc commented
What's the request?
Same formatting as Sneak megatile
clovers 3/day bankable
AED limited
optimal dog 1/day
lucky lindy 3/day
pill keeper X/day
scepter clover 1/day
april sax 3/day
Account State
All account states would benefit equally!
Your current TourGuide version
No response
uthuluc commented
NOT COMPLETE, DOES NOT DISPLAY
BOTTOM SECTION UNCHANGED
MISSING: OPTIMAL DOG, LUCKY LINDY, ETC
MISSING: CLOVER ADV RECOMMENDATIONS
record LuckySource {
string sourceName;
string url;
string imageLookupName;
boolean LuckyCondition;
int LuckyCount;
string tileDescription;
};
RegisterResourceGenerationFunction("LuckyDayGenerator");
void LuckyDayGenerator(ChecklistEntry [int] resource_entries)
{
// Saving some useful variables for use in the calculations.
int spleenRemaining = spleen_limit() - my_spleen_use();
int stomachLeft = availableFullness();
LuckySource getAstralEnergy() {
LuckySource final;
final.sourceName = "Astral Energy Drink";
final.url = "inventory.php?ftext=astral+energy+drink";
final.imageLookupName = "__item astral energy drink";
// calculate possible spleen-based Luckys
int spleenLuckys = floor(spleenRemaining / 5);
// usable if we have pill keeper plus free Luckys or spleen Luckys available
final.LuckyCondition = available_amount($item[[10883]astral energy drink]) > 0 && (spleenLuckys > 0);
final.LuckyCount = spleenLuckys;
final.tileDescription = final.tileDescription + `<b>{spleenLuckys}x AED</b> for 5 spleen each`;
return final;
}
LuckySource getLuckyisol() {
LuckySource final;
final.sourceName = "Surprise Element pills";
final.url = "main.php?eowkeeper=1";
final.imageLookupName = "__item Eight Days a Week Pill Keeper";
// see # of free pillkeeepers remaining
int freeLuckyLeft = get_property_boolean("_freePillKeeperUsed") ? 0 : 1;
// calculate possible spleen-based Luckys
int spleenLuckys = floor(spleenRemaining / 3);
// usable if we have pill keeper plus free Luckys or spleen Luckys available
final.LuckyCondition = __iotms_usable[lookupItem("Eight Days a Week Pill Keeper")] && (freeLuckyLeft + spleenLuckys > 0);
final.LuckyCount = freeLuckyLeft + spleenLuckys;
final.tileDescription = get_property_boolean("_freePillKeeperUsed") ? "" : `<b>1x free Lucky, </b>`;
final.tileDescription = final.tileDescription + `<b>{spleenLuckys}x Luckys</b> for 3 spleen each`;
return final;
}
LuckySource getClovers() {
LuckySource final;
final.sourceName = "11-Leaf Clover";
final.url = "inventory.php?ftext=11-leaf+clover";
final.imageLookupName = "__item 11-leaf clover";
// usable if we have pill keeper plus free Luckys or spleen Luckys available
int cloverLuckys = available_amount($item[11-leaf clover]);
final.LuckyCount = cloverLuckys;
final.tileDescription = final.tileDescription + `<b>{cloverLuckys}x 11-leaf clover</b>`;
return final;
}
LuckySource getSaxes() {
LuckySource final;
final.sourceName = 'Apriling saxes';
final.url = "inventory.php?ftext=apriling+band+sax";
final.imageLookupName = "__item apriling band sax";
int saxosLeft = clampi(3 - get_property_int("_aprilBandSaxUses"), 0, 3);
final.LuckyCondition = ($item[apriling band saxophone].available_amount() > 0 && (saxosLeft > 0));
final.LuckyCount = saxosLeft;
final.tileDescription = `<b>{saxosLeft}x Apriling sax blows</b> left`;
return final;
}
LuckySource getScepters() {
LuckySource final;
final.sourceName = "August scepter";
final.url = "inventory.php?ftext=august+scepter";
final.imageLookupName = "__item august scepter";
final.LuckyCondition = __iotms_usable[lookupItem("august scepter")] && !get_property_boolean("_aug2Cast");
final.LuckyCount = get_property_boolean("_aug2Cast") ? 0 : 1;
final.tileDescription = "<b>{final.LuckyCount}x August Scepter</b> holiday left";
return final;
}
// Having generated these, we now get to generate a tile that combines them.
LuckySource [string] LuckySources;
LuckySources["saxo"] = getSaxes();
LuckySources["scepto"] = getScepters();
LuckySources["clovo"] = getClovers();
LuckySources["pillo"] = getLuckyisol();
LuckySources["AEDo"] = getAstralEnergy();
LuckySources["doggo"] = getOptimalDogs();
LuckySources["lindo"] = getLuckyLindys();
// Making it use the order we want; almost most recent to oldest, but pills on the bottom.
string [int] LuckyOrder = listMake("saxo","scepto","pillo","AEDo","clovo");
ChecklistEntry entry;
entry.url = "";
entry.image_lookup_name = "__effect Feeling Lucky";
entry.tags.id = "Lucky sources available";
entry.importance_level = -2;
string [int] description;
int totalLuckys = 0;
string line = HTMLGenerateSpanOfClass("Get a Lucky adventure!", "r_bold r_element_stench_desaturated");
foreach it, LuckyType in LuckyOrder
{
LuckySource Luckyer = LuckySources[LuckyType];
if (Luckyer.LuckyCount > 0 && Luckyer.LuckyCondition) {
totalLuckys += Luckyer.LuckyCount;
entry.url = Luckyer.url;
line += "|*"+Luckyer.tileDescription; //"
}
}
if (totalLuckys == 0) return;
// Append all the lines to a description
description.listAppend(line);
// Store the base description within the mouseover subentries
entry.subentries_on_mouse_over.listAppend(ChecklistSubentryMake(pluralise(totalLuckys, "Lucky usable", "Luckys usable"), "", description));
// Add a description that falls away when you hoverover
entry.subentries.listAppend(ChecklistSubentryMake(pluralise(totalLuckys, "Lucky usable", "Luckys usable"), "", description));
// OK, now we're going to make a big table with the NC recommendations. Yeesh.
// This tile is complicated, dude! First, start by initializing variables.
// Ezan's table creators are formatted as string[int][int], where the first
// is the row and the second is the column... I think?
int totalNCsRemaining = 0;
string [int][int] table;
// In the synth tile, Ezan populates table_lines and builds out from there. I
// am doing the same because I don't fully understand the syntax.
string [int] tableLines;
// This is a function that generates the right format for the table. Basically,
// it ingests the table title + a separated list of all Lucky opportunities in
// that summarized title.
string populateLuckyTable(string title, string [int] desc) {
string finalDesc = "";
// If nothing got added, just add an "all done!" to make the user feel better
if (desc.count() == 0) finalDesc = "All done!";
// Have to add line breaks here.
foreach k, d in desc {
finalDesc += d+"<br>";
}
// Finally, generate a little sub-tile that looks like this:
// NAME OF LuckyS
// 1 Luckysource
// 1 Luckysource
// Where the name is bold and the Luckysources are tiny. In some future world,
// it might be nice to have coloring that grays those that are not available
// yet, but that is too much for this first implementation.
return HTMLGenerateSpanOfClass(title, "r_bold") + "<br>" + HTMLGenerateSpanOfStyle(finalDesc, "font-size:0.8em");
}
// We aren't going to do a loop here; we're just going to populate table_lines
// semi-manually, using logic that is roughly correct in each case.
// START = DELAY LuckyS
// 1x hidden apartment
// 1x hidden office
// Initialize your string-int array of the Luckys.
string [int] LuckyDelay;
// You want to use prefs when possible to isolate that the user can use that Lucky, then append to LuckyDelay
if (get_property_int("hiddenApartmentProgress") < 7) LuckyDelay.listAppend("1 hidden apartment");
if (get_property_int("hiddenOfficeProgress") < 7) LuckyDelay.listAppend("1 hidden office");
// Populate the Luckyy table.
tableLines[1] = populateLuckyTable("Delay Zones", LuckyDelay);
// Add the detected NCs to your total NCs remaining.
totalNCsRemaining += LuckyDelay.count();
// NEXT = 95% COMBAT LuckyS
// 12x friars NCs (-1 w/ carto)
// 1x castle basement
// 1x castle top
string [int] Lucky95;
// Ripping some code from the friars tile to count NCs encountered. First, names of the relevant NCs.
boolean [string] necks_known_ncs = $strings[How Do We Do It? Quaint and Curious Volume!,Strike One!,Olive My Love To You\, Oh.,Dodecahedrariffic!];
boolean [string] heart_known_ncs = $strings[Moon Over the Dark Heart,Running the Lode,I\, Martin,Imp Be Nimble\, Imp Be Quick];
boolean [string] elbow_known_ncs = $strings[Deep Imp Act,Imp Art\, Some Wisdom,A Secret\, But Not the Secret You're Looking For,Butter Knife? I'll Take the Knife];
// Then, a tiny function to count the NCs found by zone for friars.
int countFriarNCs(boolean [string] known_ncs, location place) {
int ncs_found = 0;
if (known_ncs.count() > 0) {
string [int] location_ncs = place.locationSeenNoncombats();
foreach key, s in location_ncs
{
if (known_ncs contains s) ncs_found += 1;
}
}
return ncs_found;
}
// You can remove one from the needed NCs if they have carto in their run.
int cartoAdjustment = lookupSkill("Comprehensive Cartography").have_skill() ? 1 : 0;
// Right now I think the raw logic off; I noted in the discord that we are having some small issues with
// it showing extra NCs in a few places. Not really sure what's up with that? An easy fix is to
// just set all of these to 0 in the event that questL06Friar = 'finished' -- I've implemented
// this fix, but I do think it's worth solving this at some point.
int questPropMin = get_property('questL06Friar') == 'finished' ? 0 : 4;
int necksNCsLeft = min(4 - countFriarNCs(necks_known_ncs, $location[The Dark Neck of the Woods]) - cartoAdjustment, questPropMin);
int heartNCsLeft = min(4 - countFriarNCs(heart_known_ncs, $location[The Dark Heart of the Woods]), questPropMin);
int elbowNCsLeft = min(4 - countFriarNCs(elbow_known_ncs, $location[The Dark Elbow of the Woods]), questPropMin);
// Also correcting total NCs left here; we are using a "count" for this, and thus we only get 1
// out of however many NCs actually are left in these zones, because it just counts the elements
// in the list rather than the # prepending the element in the list.
if (necksNCsLeft > 0) {
Lucky95.listAppend(`{necksNCsLeft} Dark Neck`);
totalNCsRemaining += necksNCsLeft-1;
}
if (heartNCsLeft > 0) {
Lucky95.listAppend(`{heartNCsLeft} Dark Heart`);
totalNCsRemaining += heartNCsLeft-1;
}
if (elbowNCsLeft > 0) {
Lucky95.listAppend(`{elbowNCsLeft} Dark Elbow`);
totalNCsRemaining += elbowNCsLeft-1;
}
// If the pref is any of these, you can still Lucky the basement.
boolean [string] canLuckyBasement = $strings[unstarted,started,step1,step2,step3,step4,step5,step6,step7];
if (canLuckyBasement contains get_property("questL10Garbage")) Lucky95.listAppend("1 castle basement");
// If the quest is unfinished, you can Lucky the top floor.
if (get_property("questL10Garbage")!= "finished") Lucky95.listAppend("1 castle top floor");
tableLines[2] = populateLuckyTable("95% Combat", Lucky95);
totalNCsRemaining += Lucky95.count();
// NEXT = 90% COMBAT LuckyS
// 1x spookyraven bedroom
// 1x spookyraven bathroom
string [int] Lucky90;
// I don't really think I need to import this but I'm tired and copy/pasting logic from the spookyraven tile seems fine.
QuestState dance_quest_state;
QuestStateParseMafiaQuestProperty(dance_quest_state, "questM21Dance");
if ($item[Lady Spookyraven's powder puff].available_amount() == 0 && dance_quest_state.mafia_internal_step < 4) Lucky90.listAppend("1 spookyraven bathroom");
if ($item[Lady Spookyraven's dancing shoes].available_amount() == 0 && dance_quest_state.mafia_internal_step < 4) Lucky90.listAppend("1 spookyraven gallery");
tableLines[3] = populateLuckyTable("90% Combat", Lucky90);
totalNCsRemaining += Lucky90.count();
// Here is how Ezan built the lines into a table. It's kind of cute. First, make a placeholder "builder" line.
string [int] building_line;
foreach key in tableLines
{
// For each key, you append it to the empty building lines.
building_line.listAppend(tableLines[key]);
// However, if the key is even, you append to the table. This works, because you are appending a two-element
// item into the table, so it creates a string [int] that creates a row in the table.
if (key % 2 == 1)
{
table.listAppend(building_line);
// Then, you clear out the building line, to reset the next table row
building_line = listMakeBlankString();
}
}
// Then, at the end, you append the remainder to the table.
if (building_line.count() > 0)
table.listAppend(building_line);
// Having done this, you now append the NCs remaining subentry to the end of the core entry, with an on_mouse_over bit as well.
// However, I am going to be lazy, and not append either of these in the event the user is in CS/GG.
if (my_path().id != PATH_COMMUNITY_SERVICE && my_path().id != PATH_GREY_GOO) {
entry.subentries.listAppend(ChecklistSubentryMake(pluralise(totalNCsRemaining, "NC remaining","NCs remaining"), "", HTMLGenerateSpanOfClass("Mouse over for the best Luckys!", "r_bold r_element_spooky_desaturated")));
entry.subentries_on_mouse_over.listAppend(ChecklistSubentryMake(pluralise(totalNCsRemaining, "NC remaining","NCs remaining"), "", table.HTMLGenerateSimpleTableLines(false)));
}
if (entry.subentries.count() > 0) resource_entries.listAppend(entry);
}