void shHero::payMelnorme (shMonster *trader) { if (trader->isHostile ()) { int result; shMenu *amends = I->newMenu ("Make amends:", 0); amends->addIntItem ('a', "Apologize", 1, 1); amends->addIntItem ('p', "Pay reparations", 2, 1); amends->getIntResult (&result); delete amends; switch (result) { case -1: return; case 1: if (trader->mHP == trader->mMaxHP) { if (tryToTranslate (trader)) { I->p ("\"We believe you.\""); } else { I->p ("%s mumbles soothingly.", THE (trader)); } pacifyMelnorme (trader); } else { if (tryToTranslate (trader)) { I->p ("\"It is not enough.\""); } else { I->p ("%s mumbles stalwartly.", THE (trader)); } } return; case 2: { int demand = (trader->mMaxHP - trader->mHP) * 10; demand = maxi (50, demand); if (demand <= countMoney ()) { if (I->yn ("Pay %s %d buckazoids?", THE (trader), demand)) { I->p ("%s accepts the money.", THE (trader)); pacifyMelnorme (trader); loseMoney (demand); trader->gainMoney (demand); } } else { I->p ("%s demands %d buckazoids but you don't" " have that much.", THE (trader), demand); } } } return; } static int (shObject::*tests[])(void) = { &shObject::isBugginessKnown, &shObject::isChargeKnown, &shObject::isEnhancementKnown, &shObject::isAppearanceKnown }; static void (shObject::*actions[])(void) = { &shObject::setBugginessKnown, &shObject::setChargeKnown, &shObject::setEnhancementKnown, &shObject::setAppearanceKnown }; int (shObject::*test) (void); void (shObject::*action) (void); reorganizeInventory (); shMenu *menu = I->newMenu ("Melnorme Services Menu", 0); char buf[200]; shObjectVector v; int price = 1000, services = 0; int price1 = 40 - Hero.mAbil.mPsi; /* Bugginess. */ int price2 = 225 - 5 * Hero.mAbil.mPsi; /* Knowledge. */ int price3 = price1 / 2; /* Remaining. */ if (!trader->is (kGenerous)) { /* Ward against drinking a lot of nano cola. */ price1 = maxi (10, price1); price2 = maxi (100, price2); price3 = maxi (10, price3); } else { price1 = 10; price2 = 100; price3 = 10; } if (tryToTranslate (trader)) { /* Make all services known. */ for (int i = 0; i < kMelnMaxService; ++i) { MelnormeServiceData[i].mNameKnown = 1; } } char letter = 'a'; for (int i = 0; i < kMelnMaxService; ++i) { int serv = trader->mMelnorme.mPermute[i]; /* Offer only eligible services. */ if (serv == kMelnRandomIdentify) { if (trader->mMelnorme.mKnowledgeExhausted or !hasTranslation ()) continue; price = price2; ++services; } else if (serv >= kMelnRevealBugginess and serv <= kMelnRevealAppearance) { test = tests[serv - kMelnRevealBugginess]; v.reset (); unselectObjectsByFunction (&v, Hero.mInventory, test); if (!v.count ()) continue; if (serv == kMelnRevealBugginess) { price = price1; } else { price = price3; } ++services; } snprintf (buf, sizeof (buf), "%s ($%d)", MelnormeServiceData[serv].mNameKnown ? MelnormeServiceNames[serv] : MelnormeServiceData[serv].mDesc, price); menu->addIntItem (letter++, buf, serv); } if (!services) { if (tryToTranslate (trader)) { I->p ("Unfortunately I cannot help you at the moment."); } else { I->p ("%s mumbles something in sad voice.", THE (trader)); } return; } int choice; if (!menu->getIntResult (&choice)) return; delete menu; price = choice == kMelnRandomIdentify ? price2 : choice == kMelnRevealBugginess ? price1 : price3; if (countMoney () < price) { I->p ("You don't have enough money for that."); return; } loseMoney (price); trader->gainMoney (price); shObject *obj = NULL; if (choice == kMelnRandomIdentify) { int n = kObjNumIlks; int tries = 10; int success = 0; while (tries--) { int i = RNG (n); shObjectIlk *ilk = &AllIlks[i]; if (!(ilk->mFlags & kIdentified) and ilk->mProbability != ABSTRACT) { char *buf = GetBuf (); strncpy (buf, ilk->mReal.mName, SHBUFLEN); makePlural (buf, SHBUFLEN); ilk->mFlags |= kIdentified; I->p ("%s tells you how to recognize %s.", THE (trader), buf); success = 1; break; } } if (!success) { I->p ("%s offers you several facts but you know all of them.", THE (trader)); I->p ("\"It seems you know all I do.\""); trader->mMelnorme.mKnowledgeExhausted = 1; I->p ("%s returns your money."); trader->loseMoney (price); gainMoney (price); } MelnormeServiceData[choice].mNameKnown = 1; } else if (choice >= kMelnRevealBugginess and choice <= kMelnRevealAppearance) { v.reset (); test = tests[choice - kMelnRevealBugginess]; unselectObjectsByFunction (&v, Hero.mInventory, test); obj = quickPickItem (&v, "perform service on", 0); if (obj) { if (hasTranslation () or RNG (4)) { /* 75% - lets be generous. */ action = actions[choice - kMelnRevealBugginess]; (obj->*action) (); if (!hasTranslation ()) { I->p ("You manage to understand %s.", THE (trader)); } MelnormeServiceData[choice].mNameKnown = 1; I->p ("%c - %s", obj->mLetter, obj->inv ()); } else { I->p ("This time you fail to understand %s.", THE (trader)); } } } I->drawSideWin (); }
/* Replace substrings within asterisks. */ const char * processLoreLine (const char *src, const char *arg = NULL) { const char *what; const char *with; do { with = NULL; if ((what = strstr (src, "*arg*"))) { with = arg; } else if ((what = strstr (src, "*Arg*"))) { char *tmp = GetBuf (); strncpy (tmp, arg, SHBUFLEN); tmp[0] = toupper (tmp[0]); with = tmp; } else if ((what = strstr (src, "*args*"))) { char *tmp = GetBuf (); strncpy (tmp, arg, SHBUFLEN); makePlural (tmp, SHBUFLEN); with = tmp; } else if ((what = strstr (src, "*Args*"))) { char *tmp = GetBuf (); strncpy (tmp, arg, SHBUFLEN); tmp[0] = toupper (tmp[0]); makePlural (tmp, SHBUFLEN); with = tmp; } else if ((what = strstr (src, "*randomrace*"))) { with = randomRace (); } else if ((what = strstr (src, "*randomworld*"))) { with = randomWorld (); } else if ((what = strstr (src, "*profession*"))) { with = Hero.mProfession->mName; } else if ((what = strstr (src, "*heroname*"))) { with = Hero.cr ()->mName; } if (what) { char *buf = GetBuf (); char *line = GetBuf (); int length = (what - src); strncpy (buf, src, length); buf[length] = '\0'; /* Buf might have had contents. */ ++what; while (*what != '*') ++what; ++what; snprintf (line, SHBUFLEN, "%s%s%s", buf, with, what); src = line; } } while (what); return src; }
void fakeProgramLore (shMenu *lore, const char *ilkname) { /* Inspired by BOSS floppy disk labels. */ static const char *noun[] = { "Programs","Routines","Subroutines","Functions","Procedures", "Libraries","Modules","Classes","Binaries","Units","Systems","Addons", "Patches","Packages","Software","Executables","Commands","Scripts" }; const int numnouns = sizeof (noun) / sizeof (char *); static const char *verb[] = { "annihilate","analyze","assemble","augment","avoid","build","cleanse", "compile","construct","copy","crack","create","delete","detect", "derezz","destroy","elude","enhance","enslave","empower","extract", "fool","fork","generate","kill","probe","scan","sneak past","spawn", "subjugate","summon","survive","terrify","tickle","torture","transform", "transport","trash","terminate","unpack","verify" }; const int numverbs = sizeof (verb) / sizeof (char *); static const char *numeral[] = { "a bunch of","a pack of","a lot of","a few","several","some","many", "lots of","two","three","four","five","ten","dozens of","tens of", "horde of","multitude of" }; const int numnumerals = sizeof (numeral) / sizeof (char *); static const char *adjective[] = { "addictive","alien","amazing","beautiful","bloodthirsty","chaotic", "confused","curious","cute","deadly","elite","entrenched","evil", "famous","fortified","fresh","friendly","golden","gorgeous","hostile", "indifferent","lame","loathsome","lost","meek","molecular","new", "obsolete","outdated","peaceful","post-warranty","powerful", "radioactive","rainbow","super","tame","unidentified","unwilling", "vile","wary","wild" }; const int numadjectives = sizeof (adjective) / sizeof (char *); char *buf = GetBuf (); char *plural = GetBuf (); snprintf (buf, SHBUFLEN, "Download CRACKED software for your %s!", ilkname); lore->addText (buf); lore->addText (""); for (int i = 0; i < 6; ++i) { const char *name = NULL; if (RNG (2)) { int id = RNG (kObjEnergyCell, kObjWreck); shObjectIlk *obj = &AllIlks[id]; if (obj) { name = !RNG (20) ? obj->mVague.mName : RNG (2) ? obj->mAppearance.mName : obj->mReal.mName; } else { debug.log ("Error picking a random item (id:%d)", id); } } else { int id = RNG (kMonEarthling, kMonShodan); shMonsterIlk *mon = &MonIlks[id]; if (mon) { name = mon->mName; if (id == kMonCreepingCredits) { /* Name already in plural. */ char *tmp = GetBuf (); strncpy (tmp, name, SHBUFLEN); tmp[15] = '\0'; /* Delete 's'. */ name = tmp; } } else { debug.log ("Error picking a random monster (id:%d)", id); } } if (!name) continue; /* Skip a line on error. */ snprintf (plural, SHBUFLEN, "%s", name); makePlural (plural, SHBUFLEN); if (RNG (2)) { snprintf (buf, SHBUFLEN, "%s %s %s %s %s %s.", noun [RNG (numnouns)], RNG (2) ? "to" : "that", verb [RNG (numverbs)], numeral [RNG (numnumerals)], adjective [RNG (numadjectives)], plural); } else { snprintf (buf, SHBUFLEN, "%s %s %s %s %s.", noun [RNG (numnouns)], RNG (2) ? "to" : "that", verb [RNG (numverbs)], adjective [RNG (numadjectives)], plural); } if (strlen (buf) > 75) { --i; /* Retry. */ } else { lore->addText (buf); } } lore->addText (""); lore->addText ("(All software provided as is)"); }