/* bumcheekcity's snapshot.ash v2.0 This script takes a snapshot of your character, level, stats, everything, and prints it in wikicode. Mad props to Terrabull and Zarqon for being cool. Changelog: 0.1 - Initial Implementation. Only Hobopolis done yet. 0.2 - Completed the Familiars check, including the 90/100% check. 0.3 - Added Slime Tube, Tattoos. 0.4 - Added Skill check. 0.5 - Fixed various tattoos, fixed tome skills, sped up script. 0.6 - Trophies added. Hobo Code added. Various small fixes. 0.7 - Fixed misspelt Hobo Codes. Added option for no description on trophies, war medals. Fixed tattoos, display case bug. 0.8 - Changed script massively. Few various fixes and tweaks on top of that. 0.9 - Changed script massively again. Now it's on my server. 1.0 - Minor fixes. Released script. 1.1 - If a password is set, then require the password to update your snapshot. Make tattoos use the "/" and ".gif" part of the gifname to make sure it matches the whole string. Add Slime skill strength checking. Fix familiar 90/100% run checking for those with a space in their username. Check for telescope strength. Ascension reward checking. 1.2 - Discoveries. Mr. Items. 1.3 - Bugfixing. Add multi-use discoveries. 1.4 - Bugfixing. Fixed the store/DC blue text. 2.0 - No longer need your password to update. "Misc. Rare Items" check. Frostys arm now counts in chefstaff form. Maps moved to my server. */ script "snapshot.ash"; notify bumcheekcity; if (index_of(visit_url("http://kolmafia.us/showthread.php?t=3001"), "2.0") == -1) { print("There is a new version available - go download the next version of snapshot.ash at http://kolmafia.us/showthread.php?t=3001!", "red"); } boolean debug = false; void debug(string s) { if (debug) { print(s, "blue"); } } record ItemImage { string itemname; string gifname; string a; string b; string c; string d; string e; string f; }; boolean description = true, hasallitems = false, hasdisplay = false, hashobotattoo = false, hasstore = false; int a, d, itemAmount, s, s_si, s_sh, s_sy; ItemImage [int] ascrewards, concocktail, confood, conjewel, conmeat, conmisc, consmith, coolitems, familiars, hobopolis, mritems, skills, slimetube, tattoos, trophies, warmedals; string html, htmlkoldb, htmlscope, ret; //Check for a display case. if (index_of(visit_url("/displaycollection.php?who=" + my_id()), "This player doesn't have a display case...") == -1) { //Then they have a display case. But I have to check if there's anything in there. if (index_of(visit_url("/displaycollection.php?who=" + my_id()), "This display case is currently empty.") == -1) { //Then they have at least one item in there. hasdisplay = true; debug("You have a display case with at least one item in it."); } else { debug("You have a display case, but no items in it."); } } else { debug("You have no display case."); } //Check for a store. if (index_of(visit_url("charsheet.php"), "in the Mall of Loathing") > 0) { if (index_of(visit_url("mallstore.php?whichstore="+my_id()), "This store's inventory is currently empty. Try again later.") == -1) { hasstore = true; debug("You have a store with at least one item in it."); } else { debug("You have a store, but no items in it."); } } else { debug("You have no store."); } //Now check the options set. if (index_of(visit_url("account.php"), " Hide Inventory Images") > 0) { debug("Inventory Images are Hidden."); } else { debug("Inventory Images are not Hidden."); } //Now check the options set. if (index_of(visit_url("account.php"), " Turn On One-Click Crafting") > 0) { debug("One-Click Crafting is turned off."); } else { debug("One-Click Crafting is turned on."); } //Check the slime skills. string slime_brain = visit_url ("desc_skill.php?whichskill=47&self=true"); if(index_of(slime_brain , "Slimy Synapses" )!=-1) { if(slime_brain.contains_text("Your synapses are 10% lubricated")) s_sy = 1; if(slime_brain.contains_text("Your synapses are 20% lubricated")) s_sy = 2; if(slime_brain.contains_text("Your synapses are 30% lubricated")) s_sy = 3; if(slime_brain.contains_text("Your synapses are 40% lubricated")) s_sy = 4; if(slime_brain.contains_text("Your synapses are 50% lubricated")) s_sy = 5; if(slime_brain.contains_text("Your synapses are 60% lubricated")) s_sy = 6; if(slime_brain.contains_text("Your synapses are 70% lubricated")) s_sy = 7; if(slime_brain.contains_text("Your synapses are 80% lubricated")) s_sy = 8; if(slime_brain.contains_text("Your synapses are 90% lubricated")) s_sy = 9; if(slime_brain.contains_text("Your synapses are maximally lubricated")) s_sy = 10; } string slime_hypophysis = visit_url ("desc_skill.php?whichskill=46&self=true"); if(index_of(slime_hypophysis , "Slimy Sinews" )!=-1) { if(slime_hypophysis.contains_text("Your sinews are 10% lubricated")) s_si = 1; if(slime_hypophysis.contains_text("Your sinews are 20% lubricated")) s_si = 2; if(slime_hypophysis.contains_text("Your sinews are 30% lubricated")) s_si = 3; if(slime_hypophysis.contains_text("Your sinews are 40% lubricated")) s_si = 4; if(slime_hypophysis.contains_text("Your sinews are 50% lubricated")) s_si = 5; if(slime_hypophysis.contains_text("Your sinews are 60% lubricated")) s_si = 6; if(slime_hypophysis.contains_text("Your sinews are 70% lubricated")) s_si = 7; if(slime_hypophysis.contains_text("Your sinews are 80% lubricated")) s_si = 8; if(slime_hypophysis.contains_text("Your sinews are 90% lubricated")) s_si = 9; if(slime_hypophysis.contains_text("Your sinews are maximally lubricated")) s_si = 10; } string slime_sweat = visit_url ("desc_skill.php?whichskill=48&self=true"); if(index_of(slime_sweat , "Slimy Shoulders" )!=-1) { if(slime_sweat.contains_text("Your shoulders are 10% lubricated")) s_sh = 1; if(slime_sweat.contains_text("Your shoulders are 20% lubricated")) s_sh = 2; if(slime_sweat.contains_text("Your shoulders are 30% lubricated")) s_sh = 3; if(slime_sweat.contains_text("Your shoulders are 40% lubricated")) s_sh = 4; if(slime_sweat.contains_text("Your shoulders are 50% lubricated")) s_sh = 5; if(slime_sweat.contains_text("Your shoulders are 60% lubricated")) s_sh = 6; if(slime_sweat.contains_text("Your shoulders are 70% lubricated")) s_sh = 7; if(slime_sweat.contains_text("Your shoulders are 80% lubricated")) s_sh = 8; if(slime_sweat.contains_text("Your shoulders are 90% lubricated")) s_sh = 9; if(slime_sweat.contains_text("Your shoulders are maximally lubricated")) s_sh = 10; } int i_a(string name) { item i = to_item(name); a = item_amount(i) + closet_amount(i) + equipped_amount(i) + storage_amount(i); d = 0; s = 0; if (hasdisplay) { d = display_amount(i); } if (hasstore) { s = shop_amount(i); } //Make a check for familiar equipment NOT equipped on the current familiar. foreach fam in $familiars[] { if (have_familiar(fam) && fam != my_familiar()) { if (name == to_string(familiar_equipped_equipment(fam)) && name != "none") { a = a + 1; } } } return a + d + s; } boolean load_current_map(string fname, ItemImage[int] map) { string domain = "http://bumcheekcity.com/kol/maps/"; string curr = visit_url(domain + "index.php?name=" + fname); file_to_map(fname+".txt", map); //If the map is empty or the file doesn't need updating if ((count(map) == 0) || (curr != "" && get_property(fname+".txt") != curr)) { print("Updating "+fname+".txt from '"+get_property(fname+".txt")+"' to '"+curr+"'..."); if (!file_to_map(domain + fname + ".txt", map) || count(map) == 0) { return false; } map_to_file(map, fname+".txt"); set_property(fname+".txt", curr); print("..."+fname+".txt updated."); } return true; } void hasItem(string name) { if (i_a(name) > 0) { ret = ret + "|1"; } else { ret = ret + "|"; } } void hasItem(string name, string amount) { if (i_a(name) > 0) { ret = ret + "|"+i_a(name); } else { ret = ret + "|"; } } void isIn(string name, string html) { if (length(name) > 7) { if (index_of(name, "_thumb") >= length(name) - 7) { name = substring(name, 0, length(name) - 7); } } if (index_of(html, name) != -1) { ret = ret + "|1"; } else { ret = ret + "|"; } } void regCheck(string checkthis, string html) { checkthis = replace_string(checkthis, "+", "\\+"); checkthis = replace_string(checkthis, "(0)", "\\(([0-9]+)\\)"); checkthis = replace_string(checkthis, "", "(){0,1}"); checkthis = replace_string(checkthis, " (\\s){0,1}", "(?:\\[\\w+\\])?"); matcher reg = create_matcher(checkthis, html); if (reg.find()) { ret = ret + "|1"; debug("YES --- " + checkthis); } else { ret = ret + "|"; debug("NO --- " + checkthis); } } void isInDisco(string name, string html, string a) { if (a != "none") { regCheck(a, html); } else { if (index_of(html, ">"+name+"<") != -1) { ret = ret + "|1"; } else { ret = ret + "|"; } } } void famCheck(string name, string gifname, string hatchling) { if (index_of(html, name) > 0) { if (index_of(htmlkoldb, "\"" + name + "\" /> (100.0%)") > 0) { //100% Run ret = ret + "|3"; } else if (index_of(htmlkoldb, "\"" + name + "\" /> (9") > 0) { //90% Tourguide Run ret = ret + "|4"; } else { //Have Familiar ret = ret + "|1"; } } else if (i_a(hatchling) > 0) { //Have Hatchling ret = ret + "|2"; } else { //Dont have familiar at all. ret = ret + "|"; } } void isInSkill(string name, string html, string overwrite) { if (overwrite == "none") { overwrite = ""; } if (index_of(html, ">"+name+" (HP)") != -1) { if (name == "Slimy Shoulders") { ret = ret + "|1-" + s_sh; } else if (name == "Slimy Sinews") { ret = ret + "|1-" + s_si; } else if (name == "Slimy Synapses") { ret = ret + "|1-" + s_sy; } else { ret = ret + "|1"; } } else if (length(overwrite) > 0 && index_of(html, overwrite) > 0) { ret = ret + "|1"; } else if (index_of(html, ">"+name+" (P)") != -1) { if (name == "Slimy Shoulders") { ret = ret + "|2-" + s_sh; } else if (name == "Slimy Sinews") { ret = ret + "|2-" + s_si; } else if (name == "Slimy Synapses") { ret = ret + "|2-" + s_sy; } else { ret = ret + "|2"; } } else { ret = ret + "|"; } } void tattooCheck(string outfit, string gif, string i1, string i2, string i3, string i4, string i5) { hasallitems = false; if (last_index_of(html, "/"+gif+".gif") > 0) { ret = ret + "|1"; } else { if (i5 != "none") { if (i_a(i1) > 0 && i_a(i2) > 0 && i_a(i3) > 0 && i_a(i4) > 0 && i_a(i5) > 0) { hasallitems = true; } } else if (i4 != "none") { if (i_a(i1) > 0 && i_a(i2) > 0 && i_a(i3) > 0 && i_a(i4) > 0) { hasallitems = true; } } else if (i3 != "none") { if (i_a(i1) > 0 && i_a(i2) > 0 && i_a(i3) > 0) { hasallitems = true; } } else { if (i_a(i1) > 0 && i_a(i2) > 0) { hasallitems = true; } } if (hasallitems) { ret = ret + "|2"; } else { ret = ret + "|"; } } //This is a terrible way of doing this, but the hobo tattoo goes after the salad one. if (gif == "saladtat") { if (index_of(html, "hobotat19") != -1) { ret = ret + "|19"; } else { for i from 18 to 1 { if (index_of(html, "hobotat"+i) != -1 && !hashobotattoo) { ret = ret + "|"+i; hashobotattoo = true; } } if (!hashobotattoo) { ret = ret + "|"; } } } } void main() { print("This is bumcheekcity's snapshot maker! This script takes a snapshot of your character and uploads it to my server at bumcheekcity.com", "green"); print("Updating map files...", "olive"); load_current_map("skills_descriptions", skills); load_current_map("tattoos_gifname_outfits", tattoos); load_current_map("trophies_descriptions", trophies); load_current_map("familiars_gifname_hatchlings", familiars); load_current_map("hobopolis_outfits", hobopolis); load_current_map("slimetube_equipment", slimetube); load_current_map("warmedals_gifname", warmedals); load_current_map("ascensionrewards", ascrewards); load_current_map("con_cocktail", concocktail); load_current_map("con_food", confood); load_current_map("con_jewel", conjewel); load_current_map("con_meat", conmeat); load_current_map("con_smith", consmith); load_current_map("con_misc", conmisc); load_current_map("mr_items", mritems); load_current_map("cool_items", coolitems); print("Checking skills...", "olive"); html = visit_url("charsheet.php") + visit_url("campground.php?action=bookshelf"); ret = "&skills="; foreach x in skills { isInSkill(skills[x].itemname, html, skills[x].a); } print("Checking tattoos...", "olive"); html = visit_url("account_tattoos.php"); ret = ret + "&tattoos="; foreach x in tattoos { tattooCheck(tattoos[x].itemname, tattoos[x].gifname, , tattoos[x].a, tattoos[x].b, tattoos[x].c, tattoos[x].d, tattoos[x].e); } print("Checking trophies...", "olive"); html = visit_url("trophies.php"); ret = ret + "&trophies="; foreach x in trophies { isIn(trophies[x].itemname, html); } print("Checking familiars...", "olive"); html = visit_url("familiarnames.php"); htmlkoldb = visit_url("http://www.koldb.com/player.php?name=" + url_encode(my_name()), false); ret = ret + "&familiars="; foreach x in familiars { famCheck(familiars[x].itemname, familiars[x].gifname, familiars[x].a); } print("Checking hobopolis loot and hobo codes...", "olive"); html = visit_url("questlog.php?which=5"); ret = ret + "&hobopolis="; foreach x in hobopolis { if (x >= 44) { isIn(hobopolis[x].itemname, html); } else { hasItem(hobopolis[x].itemname); } } print("Checking Slime Tube loot...", "olive"); ret = ret + "&slimetube="; foreach x in slimetube { hasItem(slimetube[x].itemname); } print("Checking War Medals...", "olive"); ret = ret + "&warmedals="; foreach x in warmedals { hasItem(warmedals[x].itemname, "amount"); } if (in_bad_moon()) { ret = ret + "&scope=9"; } else { print("Checking for Telescope", "olive"); ret = ret + "&scope="; htmlscope = visit_url("campground.php?action=telescopelow"); if (index_of(htmlscope, "Nope") == -1) { htmlscope = substring(htmlscope, index_of(htmlscope, "You peer into the eyepiece of the telescope")); htmlscope = substring(htmlscope, 0, index_of(htmlscope, "")); if (index_of(htmlscope, "sixth and final window") > 0) { ret = ret + "7"; } else if (index_of(htmlscope, "see a fifth window") > 0) { ret = ret + "6"; } else if (index_of(htmlscope, "see another window") > 0) { ret = ret + "5"; } else if (index_of(htmlscope, "see a third window") > 0) { ret = ret + "4"; } else if (index_of(htmlscope, "see a second window") > 0) { ret = ret + "3"; } else if (index_of(htmlscope, "raise the telescope a little higher") > 0) { ret = ret + "2"; } else if (index_of(htmlscope, "a strange ring of mountains") > 0) { ret = ret + "1"; } } } print("Checking for Ascension Rewards", "olive"); ret = ret + "&ascreward="; foreach x in ascrewards { hasItem(ascrewards[x].itemname, "amount"); } print("Checking for Discoveries [Cocktail]", "olive"); html = visit_url("craft.php?mode=discoveries&what=cocktail"); ret = ret + "&concocktail="; foreach x in concocktail { isInDisco(concocktail[x].itemname, html, concocktail[x].gifname); } print("Checking for Discoveries [Food]", "olive"); html = visit_url("craft.php?mode=discoveries&what=cook"); ret = ret + "&confood="; foreach x in confood { isInDisco(confood[x].itemname, html, confood[x].gifname); } print("Checking for Discoveries [Jewelery]", "olive"); html = visit_url("craft.php?mode=discoveries&what=jewelry"); ret = ret + "&conjewel="; foreach x in conjewel { isInDisco(conjewel[x].itemname, html, conjewel[x].gifname); } print("Checking for Discoveries [Meat Pasting]", "olive"); html = visit_url("craft.php?mode=discoveries&what=combine"); ret = ret + "&conmeat="; foreach x in conmeat { isInDisco(conmeat[x].itemname, html, conmeat[x].gifname); } print("Checking for Discoveries [Meatsmithing]", "olive"); html = visit_url("craft.php?mode=discoveries&what=smith"); ret = ret + "&consmith="; foreach x in consmith { isInDisco(consmith[x].itemname, html, consmith[x].gifname); } print("Checking for Discoveries [Misc]", "olive"); html = visit_url("craft.php?mode=discoveries&what=multi"); ret = ret + "&conmisc="; foreach x in conmisc { isInDisco(conmisc[x].itemname, html, conmisc[x].gifname); } print("Checking for Mr. Items", "olive"); html = visit_url("familiarnames.php") + visit_url("campground.php?action=bookshelf"); ret = ret + "&mritems="; foreach x in mritems { itemAmount = 0; switch (mritems[x].itemname) { //Bind-on-use Items case "b" : itemAmount = i_a(to_item(mritems[x].gifname)) + i_a(to_item(mritems[x].a)); break; //Familiar case "f" : if (index_of(html, mritems[x].a) > 0) { itemAmount = 1; } itemAmount = itemAmount + i_a(to_item(mritems[x].gifname)); break; //Item case "i" : itemAmount = i_a(to_item(mritems[x].gifname)); break; //Foldable case "o" : itemAmount = i_a(to_item(mritems[x].gifname)) + i_a(to_item(mritems[x].a)) + i_a(to_item(mritems[x].b)) + i_a(to_item(mritems[x].c)) + i_a(to_item(mritems[x].d)); if (mritems[x].e != "none") { itemAmount = itemAmount + i_a(to_item(mritems[x].e)); } if (mritems[x].f != "none") { itemAmount = itemAmount + i_a(to_item(mritems[x].f)); } break; //Tome, Libram, Grimore case "t" : if (index_of(html, mritems[x].a) > 0) { itemAmount = 1; } itemAmount = itemAmount + i_a(to_item(mritems[x].gifname)); break; } ret = ret + "|" + itemAmount; } print("Checking for Cool Items", "olive"); ret = ret + "&coolitems="; foreach x in coolitems { hasItem(coolitems[x].itemname, "amount"); } html = visit_url("http://bumcheekcity.com/kol/profilesave.php?username="+url_encode(my_name())+ret+"&version=2.0"); print(""); if (index_of(html, "success") > 0) { print("Successfully done. Visit the following URL to see your snapshot!", "green"); print("http://bumcheekcity.com/kol/profile.php?u="+my_name(), "red"); print("Setup your snapshot profile here:", "green"); print("http://bumcheekcity.com/kol/profilesetup.php?u="+my_name(), "red"); print(visit_url("http://bumcheekcity.com/kol/profileafter.php?version=2.0&result=success")); } else if (index_of(html, "fail") > 0) { print("The script is reporting that it failed to update.", "red"); print("This could be caused by you not setting your password correctly in the script.", "red"); print("If you have a password, please open up snapshot.ash and enter it at the top.", "red"); print("Note: Remember that capitalisation is important for both your username AND password in the ASH script.", "red"); print(""); print("It's also possible that this error is occuring because you need to update your script version.", "red"); print("Go to http://kolmafia.us/showthread.php?t=3001 and download the latest version if so.", "red"); print(visit_url("http://bumcheekcity.com/kol/profileafter.php?version=2.0&result=fail")); } else { print("For some reason, the script isn't reporting a successful update.", "orange"); print("Visit the following URL to check your snapshot.", "orange"); print("http://bumcheekcity.com/kol/profile.php?u="+my_name(), "red"); print("If it didn't work - try again later - my website may just be having some temporary downtime problems.", "orange"); print("If it worked, you can setup your snapshot profile here:", "orange"); print("http://bumcheekcity.com/kol/profilesetup.php?u="+my_name(), "red"); print(visit_url("http://bumcheekcity.com/kol/profileafter.php?u="+my_name()+"version=2.0&result=dontknow")); } }