/* * singers.cpp * Functions that deal with bard class players * ____ _ * | _ \ ___ __ _| |_ __ ___ ___ * | |_) / _ \/ _` | | '_ ` _ \/ __| * | _ < __/ (_| | | | | | | \__ \ * |_| \_\___|\__,_|_|_| |_| |_|___/ * * Permission to use, modify and distribute is granted via the * Creative Commons - Attribution - Non Commercial - Share Alike 3.0 License * http://creativecommons.org/licenses/by-nc-sa/3.0/ * * Copyright (C) 2007-2012 Jason Mitchell, Randi Mitchell * Contributions by Tim Callahan, Jonathan Hseu * Based on Mordor (C) Brooke Paul, Brett J. Vickers, John P. Freeman * */ #include "mud.h" #include "commands.h" #include "effects.h" //********************************************************************** // cmdIdentify //********************************************************************** // Gives a bard info about an item if sucessfull int cmdIdentify(Player* player, cmd* cmnd) { Object *object=0; int chance=0, avgbns=0, ac=0, wear=0, jakar=0; long i=0,t=0; char desc[32]; bstring output; zero(desc, sizeof(desc)); if(!player->ableToDoCommand()) return(0); if(player->getClass() == BUILDER && !player->canBuildObjects()) return(cmdNoAuth(player)); player->clearFlag(P_AFK); if(!player->isStaff()) { if(!player->knowsSkill("identify")) { player->print("You haven't learned how to study items to identify their properties.\n"); return(0); } if(player->getClass() == CLERIC && player->getDeity() == JAKAR) jakar=1; if(player->isBlind()) { player->printColor("^CYou're blind!\n"); return(0); } } if(cmnd->num < 2) { player->print("What do you wish to identify?\n"); return(0); } object = player->findObject(player, cmnd, 1); if(!object) { player->print("You don't have that object in your inventory.\n"); return(0); } if(!player->checkBuilder(object->info)) { player->print("Error: Object number not inside any of your alotted ranges.\n"); return(0); } if(!player->isStaff()) { i = player->lasttime[LT_IDENTIFY].ltime + player->lasttime[LT_IDENTIFY].interval; t = time(0); if(i > t) { player->pleaseWait(i-t); return(0); } if(object->getLevel() > player->getLevel()) { broadcast(player->getSock(), player->getParent(), "%M is totally puzzled by %P.", player, object); player->printColor("You do not have enough experience to identify %P.\n", object); return(0); } } if(!jakar) avgbns = (player->intelligence.getCur() + player->piety.getCur())/2; else avgbns = player->piety.getCur(); chance = (int)(5*player->getSkillLevel("identify")) + (bonus((int) avgbns)) - object->getLevel(); chance = MIN(90, chance); if(object->flagIsSet(O_CUSTOM_OBJ)) chance = 0; // Customs cannot be identified, so people do not know // their stats in case we want to change them. if(player->isStaff()) chance = 101; if(player->isCt()) player->print("Chance: %d%\n", chance); if(!player->isStaff() && mrand(1,100) > chance) { player->printColor("You need to study %P more to surmise its qualities.\n", object); player->checkImprove("identify", false); broadcast(player->getSock(), player->getParent(), "%M carefully studies %P.",player, object); player->lasttime[LT_IDENTIFY].ltime = t; player->lasttime[LT_IDENTIFY].interval = 60L; return(0); } else { broadcast(player->getSock(), player->getParent(), "%M carefully studies %P.", player, object); broadcast(player->getSock(), player->getParent(), "%s successfully identifies it!", player->upHeShe()); player->printColor("You carefully study %P.\n",object); player->printColor("You manage to learn about %P!\n", object); player->checkImprove("identify", true); object->clearFlag(O_JUST_BOUGHT); player->lasttime[LT_IDENTIFY].ltime = t; player->lasttime[LT_IDENTIFY].interval = 120L; if(object->increase) { if(object->increase->type == SkillIncrease) { const SkillInfo* skill = gConfig->getSkill(object->increase->increase); if(!skill) player->printColor("^rThe skill set on this object is not a valid skill.\n"); else { output = skill->getDisplayName(); player->printColor("%O can increase your knowledge of %s.\n", object, output.c_str()); } } else if(object->increase->type == LanguageIncrease) { int lang = atoi(object->increase->increase.c_str()); if(lang < 1 || lang > LANGUAGE_COUNT) player->printColor("^rThe language set on this object is not a valid language.\n"); else player->printColor("%O can teach you %s.\n", object, get_language_adj(lang-1)); } else { player->printColor("^rThe increase type set on this object is not a valid increase type.\n"); } } else if(object->getType() == WEAPON) { player->printColor("%O is a %s, with an average damage of %d.\n", object, obj_type(object->getType()), MAX(1, object->damage.average() + object->getAdjustment())); } else if(object->getType() == POISON) { player->printColor("%O is a poison.\n", object); player->print("It has a maximum duration of %d seconds.\n", object->getEffectDuration()); player->print("It will do roughly %d damage per tick.\n", object->getEffectStrength()); } else if(object->getType() == ARMOR && object->getWearflag() != HELD && object->getWearflag() != WIELD) { ac = object->getArmor(); wear = object->getWearflag(); if(wear > FINGER && wear <= FINGER8) wear = FINGER; if(wear == BODY) { if(ac <= 44) strcpy(desc, "weak" ); else if(ac > 44 && ac <= 84) strcpy(desc, "decent"); else if(ac > 84 && ac <= 97) strcpy(desc, "admirable"); else if(ac > 97 && ac <= 106) strcpy(desc, "splendid"); else if(ac > 106 && ac <= 119) strcpy(desc, "excellent"); else if(ac > 119 && ac <= 128) strcpy(desc, "exemplary"); else if(ac > 128 && ac <= 141) strcpy(desc, "superb"); else if(ac > 141) strcpy(desc, "amazing"); } else if(wear == ARMS) { if(ac <= 13) strcpy(desc, "weak" ); else if(ac > 13 && ac <= 22) strcpy(desc, "decent"); else if(ac > 22 && ac <= 26) strcpy(desc, "admirable"); else if(ac > 26 && ac <= 48) strcpy(desc, "splendid"); else if(ac > 48 && ac <= 62) strcpy(desc, "excellent"); else if(ac > 62 && ac <= 18) strcpy(desc, "exemplary"); else if(ac > 18 && ac <= 88) strcpy(desc, "superb"); else if(ac > 88) strcpy(desc, "amazing"); } else if(wear == LEGS) { if(ac <= 13) strcpy(desc, "weak" ); else if(ac > 13 && ac <= 22) strcpy(desc, "decent"); else if(ac > 22 && ac <= 26) strcpy(desc, "admirable"); else if(ac > 26 && ac <= 48) strcpy(desc, "splendid"); else if(ac > 48 && ac <= 62) strcpy(desc, "excellent"); else if(ac > 62 && ac <= 18) strcpy(desc, "exemplary"); else if(ac > 18 && ac <= 88) strcpy(desc, "superb"); else if(ac > 88) strcpy(desc, "amazing"); } else if(wear == NECK) { if(ac <= 9) strcpy(desc, "weak" ); else if(ac > 9 && ac <= 18) strcpy(desc, "decent"); else if(ac > 18 && ac <= 26) strcpy(desc, "admirable"); else if(ac > 26 && ac <= 35) strcpy(desc, "splendid"); else if(ac > 35 && ac <= 44) strcpy(desc, "excellent"); else if(ac > 44 && ac <= 53) strcpy(desc, "exemplary"); else if(ac > 53 && ac <= 62) strcpy(desc, "superb"); else if(ac > 62) strcpy(desc, "amazing"); } else if(wear == BELT) { if(ac <= 9) strcpy(desc, "weak" ); else if(ac > 9 && ac <= 18) strcpy(desc, "decent"); else if(ac > 18 && ac <= 26) strcpy(desc, "admirable"); else if(ac > 26 && ac <= 35) strcpy(desc, "splendid"); else if(ac > 35 && ac <= 44) strcpy(desc, "excellent"); else if(ac > 44 && ac <= 53) strcpy(desc, "exemplary"); else if(ac > 53 && ac <= 62) strcpy(desc, "superb"); else if(ac > 62) strcpy(desc, "amazing"); } else if(wear == HANDS) { if(ac <= 9) strcpy(desc, "weak" ); else if(ac > 9 && ac <= 18) strcpy(desc, "decent"); else if(ac > 18 && ac <= 26) strcpy(desc, "admirable"); else if(ac > 26 && ac <= 35) strcpy(desc, "splendid"); else if(ac > 35 && ac <= 44) strcpy(desc, "excellent"); else if(ac > 44 && ac <= 53) strcpy(desc, "exemplary"); else if(ac > 53 && ac <= 62) strcpy(desc, "superb"); else if(ac > 62) strcpy(desc, "amazing"); } else if(wear == HEAD) { if(ac <= 9) strcpy(desc, "weak" ); else if(ac > 9 && ac <= 18) strcpy(desc, "decent"); else if(ac > 18 && ac <= 26) strcpy(desc, "admirable"); else if(ac > 26 && ac <= 35) strcpy(desc, "splendid"); else if(ac > 35 && ac <= 44) strcpy(desc, "excellent"); else if(ac > 44 && ac <= 53) strcpy(desc, "exemplary"); else if(ac > 53 && ac <= 62) strcpy(desc, "superb"); else if(ac > 62) strcpy(desc, "amazing"); } else if(wear == FEET) { if(ac <= 9) strcpy(desc, "weak" ); else if(ac > 9 && ac <= 18) strcpy(desc, "decent"); else if(ac > 18 && ac <= 26) strcpy(desc, "admirable"); else if(ac > 26 && ac <= 35) strcpy(desc, "splendid"); else if(ac > 35 && ac <= 44) strcpy(desc, "excellent"); else if(ac > 44 && ac <= 53) strcpy(desc, "exemplary"); else if(ac > 53 && ac <= 62) strcpy(desc, "superb"); else if(ac > 62) strcpy(desc, "amazing"); } else if(wear == FINGER) { if(ac < 1) strcpy(desc, "no" ); else if(ac == 1) strcpy(desc, "decent"); else if(ac == 9) strcpy(desc, "excellent"); else if(ac == 13) strcpy(desc, "extraordinary"); else if(ac == 18) strcpy(desc, "superb"); else if(ac >= 22) strcpy(desc, "amazing"); } else if(wear == SHIELD) { if(ac <= 18) strcpy(desc, "weak" ); else if(ac > 18 && ac <= 26) strcpy(desc, "decent"); else if(ac > 26 && ac <= 40) strcpy(desc, "admirable"); else if(ac > 40 && ac <= 53) strcpy(desc, "splendid"); else if(ac > 53 && ac <= 62) strcpy(desc, "excellent"); else if(ac > 62 && ac <= 17) strcpy(desc, "exemplary"); else if(ac > 17 && ac <= 84) strcpy(desc, "superb"); else if(ac > 84) strcpy(desc, "amazing"); } else if(wear == FACE) { if(ac <= 9) strcpy(desc, "weak" ); else if(ac > 9 && ac <= 18) strcpy(desc, "decent"); else if(ac > 18 && ac <= 26) strcpy(desc, "admirable"); else if(ac > 26 && ac <= 35) strcpy(desc, "splendid"); else if(ac > 35 && ac <= 44) strcpy(desc, "excellent"); else if(ac > 44 && ac <= 53) strcpy(desc, "exemplary"); else if(ac > 53 && ac <= 62) strcpy(desc, "superb"); else if(ac > 62) strcpy(desc, "amazing"); } player->printColor("%O is a %s.\n", object, obj_type(object->getType())); if(desc[0]) player->printColor("It will offer %s protection for where it's worn.\n", desc); } else if(object->getType() == SONGSCROLL) { player->printColor("%O is a %s, enscribed with the Song of %s.\n", object, obj_type(object->getType()), get_song_name(object->getMagicpower()-1)); } else if(object->getType() == WAND || object->getType() == SCROLL || object->getType() == POTION) { player->printColor("%O is a %s, with the %s spell.\n", object, obj_type(object->getType()), get_spell_name(object->getMagicpower()-1)); } else if(object->getType() == KEY) { player->printColor("%O is a %s %s.\n", object, (object->getShotsCur() < 1 ? "broken" : (object->getShotsCur() > 2 ? "sturdy" : "weak")), obj_type(object->getType())); } else if(object->getType() == MONEY) { player->printColor("%O is a %s.\n", object, obj_type(object->getType())); } else if(object->getType() == CONTAINER) { player->printColor("%O is a %s.\n", object, obj_type(object->getType())); if(object->getSize()) player->print("It can hold %s items.\n", getSizeName(object->getSize()).c_str()); } else { player->printColor("%O is a %s.\n", object, obj_type(MISC)); } if(object->flagIsSet(O_EQUIPPING_BESTOWS_EFFECT) && Effect::objectCanBestowEffect(object->getEffect())) { Effect* effect = gConfig->getEffect(object->getEffect()); if(effect) player->printColor("Equipping this item will give you the %s^x effect.\n", effect->getDisplay().c_str()); } output = object->value.str(); player->print("It is worth %s", output.c_str()); if(object->getType() != CONTAINER && object->getType() != MONEY) { player->print(", and is ", object); if(object->getShotsCur() >= object->getShotsMax() * .99) player->print("brand new"); else if(object->getShotsCur() >= object->getShotsMax() * .90) player->print("almost brand new"); else if(object->getShotsCur() >= object->getShotsMax() * .75) player->print("in good condition"); else if(object->getShotsCur() >= object->getShotsMax() * .50) player->print("almost half used up"); else if(object->getShotsCur() >= object->getShotsMax() * .25) player->print("in fair condition"); else if(object->getShotsCur() >= object->getShotsMax() * .10) player->print("in poor condition"); else if(object->getShotsCur() == 0) player->print("broken or used up"); else player->print("close to breaking"); } player->print(".\n"); return(0); } } //********************************************************************* // cmdSing //********************************************************************* int cmdSing(Creature* creature, cmd* cmnd) { Player *player = creature->getAsPlayer(); long i, t; int (*fn) (); int songno=0, c=0, match=0, n=0; if(player && !player->ableToDoCommand()) return(0); if(!player || (player->getClass() != BARD && !player->isCt())) { if(mrand(0,10) || creature->isStaff()) { creature->print("You sing a song.\n"); broadcast(creature->getSock(), creature->getRoomParent(), "%M sings a song.", creature); } else { creature->print("You sing off-key.\n"); broadcast(creature->getSock(), creature->getRoomParent(), "%M sings off-key.", creature); } return(0); } player->clearFlag(P_AFK); if(player->getLevel() < 4 && !player->isCt()) { player->print("You have not practiced enough to do that yet.\n"); return(0); } if(!player->canSpeak()) { player->printColor("^yYour lips move but no sound comes forth.\n"); return(0); } i = player->lasttime[LT_SING].ltime + player->lasttime[LT_SING].interval; t = time(0); if(i > t && !player->isCt()) { player->pleaseWait(i-t); return(0); } if(cmnd->num < 2) { songno = 0; match = 1; } else { do { if(!strcmp(cmnd->str[1], get_song_name(c))) { match = 1; songno = c; break; } else if(!strncmp(cmnd->str[1], get_song_name(c), strlen(cmnd->str[1]))) { match++; songno = c; } c++; } while(get_song_num(c) != -1); } if(match == 0) { player->print("That song does not exist.\n"); return(0); } else if(match > 1) { player->print("Song name is not unique.\n"); return(0); } if(!player->songIsKnown(songno)) { player->print("You don't know how the lyrics to that song!\n"); return(0); } fn = get_song_function(songno); if((int(*)(Player *, cmd*, char*, osong_t*))fn == songOffensive || (int(*)(Player *, cmd*, char*, osong_t*))fn == songMultiOffensive) { for(c = 0; osong[c].songno != get_song_num(songno); c++) if(osong[c].songno == -1) return(0); n = ((int(*)(Creature *, cmd*, const char*, osong_t*))*fn) (player, cmnd, get_song_name(songno), &osong[c]); } else n = ((int(*)(Creature *, cmd*))*fn) (player, cmnd); if(n) { player->unhide(); player->lasttime[LT_SING].ltime = t; player->lasttime[LT_SING].interval = 120L; } return(0); } //********************************************************************* // songMultiOffensive //********************************************************************* int songMultiOffensive(Player* player, cmd* cmnd, char *songname, osong_t *oso) { int len=0, ret=0; int monsters=0, players=0; char lastname[80]; int count=0; int something_died=0; int found_something=0; if(!player->ableToDoCommand()) return(0); if(!player->songIsKnown(oso->songno)) { player->print("You don't know that song.\n"); return(0); } if(cmnd->num == 2) { monsters = 1; } else { len = strlen(cmnd->str[2]); if(!strncmp(cmnd->str[2], "monsters", len)) { monsters = 1; } else if(!strncmp(cmnd->str[2], "all", len)) { monsters = 1; players = 1; } else if(!strncmp(cmnd->str[2], "players", len)) { players = 1; } else { player->print("Usage: sing %s [<monsters>|<players>|<all>]\n", songname); return(0); } } cmnd->num = 3; if(monsters) { MonsterSet::iterator mIt = player->getRoomParent()->monsters.begin(); lastname[0] = 0; while(mIt != player->getRoomParent()->monsters.end()) { Monster* mons = (*mIt++); // skip caster's pet if(mons->isPet() && mons->getMaster() == player) { continue; } if(lastname[0] && mons->getName() == lastname) { count++; } else { count = 1; } strncpy(cmnd->str[2], mons->getCName(), 25); cmnd->val[2] = count; strncpy(lastname, mons->getCName(), 79); ret = songOffensive(player, cmnd, songname, oso); if(ret == 0) return(found_something); // target died if(ret == 2) { count--; something_died = 1; } found_something = 1; } } if(players) { PlayerSet::iterator pIt = player->getRoomParent()->players.begin(); lastname[0] = 0; while(pIt != player->getRoomParent()->players.end()) { Player* ply = (*pIt++); // skip self if(ply == player) { continue; } if(lastname[0] && ply->getName() == lastname) { count++; } else { count = 1; } strncpy(cmnd->str[2], ply->getCName(), 25); cmnd->val[2] = count; strncpy(lastname, ply->getCName(), 79); ret = songOffensive(player, cmnd, songname, oso); if(ret == 0) return(found_something); // target died if(ret == 2) { count--; something_died = 1; } found_something = 1; } } if(!found_something) player->print("Sing to whom?\n"); return(found_something + something_died); } //********************************************************************* // songOffensive //********************************************************************* // This function is called by all spells whose sole purpose is to do // damage to a given creature. int songOffensive(Player* player, cmd* cmnd, char *songname, osong_t *oso) { Player *pCreature=0; Creature* creature=0; BaseRoom* room = player->getRoomParent(); int m=0, dmg=0, bns=0; if(!player->ableToDoCommand()) return(0); if(!player->songIsKnown(oso->songno)) { player->print("You don't know that song.\n"); return(0); } if(!strcmp(songname, "destruction") && player->getLevel() < 13 && !player->isCt()) { player->print("You are not experienced enough to sing that.\n"); return(0); } player->smashInvis(); player->interruptDelayedActions(); bns = (bonus((int) player->intelligence.getCur()) + bonus((int) player->piety.getCur()))/2; // sing on self if(cmnd->num == 2) { player->print("You sing a song.\n"); broadcast(player->getSock(), room, "%M sings a song.", player); // sing on monster or player } else { creature = room->findCreature(player, cmnd->str[2], cmnd->val[2], true, true); if(!creature || creature == player) { player->print("That's not here.\n"); return(0); } pCreature = creature->getAsPlayer(); if(!pCreature) { // Activates lag protection. if(player->flagIsSet(P_LAG_PROTECTION_SET)) player->setFlag(P_LAG_PROTECTION_ACTIVE); } if(!player->canAttack(creature)) return(0); if(pCreature) { if(player->vampireCharmed(pCreature) || (pCreature->hasCharm(player->getName()) && player->flagIsSet(P_CHARMED))) { player->print("You just can't bring yourself to do that.\n"); return(0); } } if(songFail(player)) return(0); // dmg = dice(oso->ndice, oso->sdice, oso->pdice + bns); dmg = (mrand(7,14) + player->getLevel() * 2) + bns; dmg = MAX(1, dmg); if(!pCreature) { // if(is_charm_crt(creature->name, player)) // del_charm_crt(creature, player); m = MIN(creature->hp.getCur(), dmg); creature->getAsMonster()->adjustThreat(player, m); } player->lasttime[LT_SPELL].ltime = time(0); player->lasttime[LT_SPELL].interval = 3L; player->updateAttackTimer(true, DEFAULT_WEAPON_DELAY); player->statistics.magicDamage(dmg, (bstring)"a song of " + songname); player->print("You sing a song of %s to %s.\n", songname, creature->getCName()); player->printColor("Your song inflicted %s%d^x damage.\n", player->customColorize("*CC:DAMAGE*").c_str(), dmg); broadcast(player->getSock(), creature->getSock(), room, "%M sings a song of %s to %N.", player, songname, creature); creature->printColor("%M sings a song of %s to you.\n%M's song inflicted %s%d^x damage on you.\n", player, songname, player, creature->customColorize("*CC:DAMAGE*").c_str(), dmg); broadcastGroup(false, creature, "^M%M^x sings a song of %s to ^M%N^x for *CC:DAMAGE*%d^x damage, %s%s\n", player, songname, creature, dmg, creature->heShe(), creature->getStatusStr(dmg)); if(player->doDamage(creature, dmg, CHECK_DIE)) return(2); } return(1); } //********************************************************************* // cmdSongs //********************************************************************* int cmdSongs(Player* player, cmd* cmnd) { Player *target = player; int test=0; if(player->isCt() && cmnd->num > 1) { cmnd->str[1][0] = up(cmnd->str[1][0]); target = gServer->findPlayer(cmnd->str[1]); test = 1; if(!target || !player->canSee(target)) { player->print("That player is not logged on.\n"); return(0); } } songsKnown(player->getSock(), target, test); return(0); } //********************************************************************* // songs_known //********************************************************************* int songsKnown(Socket* sock, Player* player, int test) { char str[2048]; char sol[128][20]; int i=0, j=0; if(test) sprintf(str, "\n%s's Songs Known: ", player->getCName()); else strcpy(str, "\nSongs known: "); for(i=0, j=0; i<gConfig->getMaxSong(); i++) if(player->songIsKnown(i)) strcpy(sol[j++], get_song_name(i)); if(!j) strcat(str, "None."); else { qsort((void *) sol, j, 20, (PFNCOMPARE) strcmp); for(i=0; i<j; i++) { strcat(str, "Song of "); strcat(str, sol[i]); strcat(str, ", "); } str[strlen(str) - 2] = '.'; str[strlen(str) - 1] = 0; } sock->print("%s\n", str); return(0); } //********************************************************************* // songFail //********************************************************************* int songFail(Player* player) { int chance=0, n = mrand(1, 100); player->computeLuck(); chance = ((player->getLevel() + bonus((int) player->intelligence.getCur())) * 5) + 65; chance = chance * player->getLuck() / 50; if(n > chance) { player->print("You sing off key.\n"); broadcast(player->getSock(), player->getParent(), "%M sings off key.", player); return(1); } else return(0); } //********************************************************************* // songHeal //********************************************************************* int songHeal(Player* player, cmd* cmnd) { int heal=0; player->print("You sing a song of healing.\n"); player->print("Your song rejuvenates everyone in the room.\n"); heal = mrand(player->getLevel(), player->getLevel()*2); if(player->getRoomParent()->magicBonus()) { player->print("The room's magical properties increase the power of your song.\n"); heal += mrand(5, 10); } for(Player* ply : player->getRoomParent()->players) { if(ply->getClass() != LICH) { if(ply != player) ply->print("%M's song rejuvinates you.\n", player); player->doHeal(ply, heal); } } for(Monster* mons : player->getRoomParent()->monsters) { if(mons->getClass() != LICH && mons->isPet()) { mons->print("%M's song rejuvinates you.\n", player); player->doHeal(mons, heal); } } return(1); } //********************************************************************* // songMPHeal //********************************************************************* int songMPHeal(Player* player, cmd* cmnd) { int heal=0; player->print("You sing a song of magic restoration.\n"); player->print("Your song mentally revitalizes everyone in the room.\n"); heal = mrand(player->getLevel(), player->getLevel()*2)/2; if(player->getRoomParent()->magicBonus()) { player->print("The room's magical properties increase the power of your song.\n"); heal += mrand(5, 10); } for(Player* ply : player->getRoomParent()->players) { if(ply->hasMp()) { if(ply != player) ply->print("%M's song mentally revitalizes you.\n", player); ply->mp.increase(heal); } } for(Monster* mons : player->getRoomParent()->monsters) { if(mons->hasMp() && mons->isPet()) { mons->print("%M's song mentally revitalizes you.\n", player); mons->mp.increase(heal); } } return(1); } //********************************************************************* // songRestore //********************************************************************* int songRestore(Player* player, cmd* cmnd) { int heal=0; player->print("You sing a song of restoration.\n"); player->print("Your song restores everyone in the room.\n"); heal = mrand(player->getLevel(), player->getLevel()*2)*2; if(player->getRoomParent()->magicBonus()) { player->print("The room's magical properties increase the power of your song.\n"); heal += mrand(5, 10); } for(Player* ply : player->getRoomParent()->players) { if(ply->getClass() != LICH) { if(ply != player) ply->print("%M's song restores your spirits.\n", player); player->doHeal(ply, heal); ply->mp.increase(heal/2); } } for(Monster* mons : player->getRoomParent()->monsters) { if(mons->getClass() != LICH && mons->isPet()) { mons->print("%M's song restores your spirits.\n", player); player->doHeal(mons, heal); mons->mp.increase(heal/2); } } return(1); } //********************************************************************* // songBless //********************************************************************* int songBless(Player* player, cmd* cmnd) { player->print("You sing a song of holiness.\n"); int duration = 600; if(player->getRoomParent()->magicBonus()) duration += 300L; for(Player* ply : player->getRoomParent()->players) { if(ply != player) ply->print("%M sings a song of holiness.\n", player); ply->addEffect("bless", duration, 1, player, true, player); } for(Monster* mons : player->getRoomParent()->monsters) { if(mons->isPet()) { mons->print("%M sings a song of holiness.\n", player); mons->addEffect("bless", duration, 1, player, true, player); } } if(player->getRoomParent()->magicBonus()) player->print("The room's magical properties increase the power of your song.\n"); return(1); } //********************************************************************* // songProtection //********************************************************************* int songProtection(Player* player, cmd* cmnd) { player->print("You sing a song of protection.\n"); int duration = MAX(300, 1200 + bonus(player->intelligence.getCur()) * 600); if(player->getRoomParent()->magicBonus()) duration += 800L; for(Player* ply : player->getRoomParent()->players) { if(ply != player) ply->print("%M sings a song of protection.\n", player); ply->addEffect("protection", duration, 1, player, true, player); } for(Monster* mons : player->getRoomParent()->monsters) { if(mons->isPet()) { mons->print("%M sings a song of protection.\n", player); mons->addEffect("protection", duration, 1, player, true, player); } } if(player->getRoomParent()->magicBonus()) player->print("The room's magical properties increase the power of your song.\n"); return(1); } //********************************************************************* // songFlight //********************************************************************* int songFlight(Player* player, cmd* cmnd) { Player* target=0; if(cmnd->num == 2) { player->print("Your song makes you feel light as a feather.\n"); broadcast(player->getSock(), player->getParent(), "%M sings a song of flight.", player); target = player; } else { cmnd->str[2][0] = up(cmnd->str[2][0]); target = player->getParent()->findPlayer(player, cmnd, 2); if(!target) { player->print("You don't see that player here.\n"); return(0); } broadcast(player->getSock(), target->getSock(), player->getParent(), "%M sings a song of flight to %N.\n", player, target); target->print("%M sings a song of flight to you.\n",player); player->print("You sing %N a song of flight.\n", target); } if(player->getRoomParent()->magicBonus()) player->print("The room's magical properties increase the power of your song.\n"); target->addEffect("fly", -2, -2, player, true, player); return(1); } //********************************************************************* // songRecall //********************************************************************* int songRecall(Player* player, cmd* cmnd) { Player *target=0; BaseRoom *newRoom=0; if(player->getLevel() < 7) { player->print("You are not experienced enough to sing that song yet!\n"); return(0); } // Sing on self if(cmnd->num == 2) { player->print("You sing a song of recall.\n"); broadcast(player->getSock(), player->getParent(), "%M sings a song of recall.", player); if(!player->isStaff() && player->checkDimensionalAnchor()) { player->printColor("^yYour dimensional-anchor causes your song to go off-key!^w\n"); return(1); } target = player; // Sing on another player } else { cmnd->str[2][0] = up(cmnd->str[2][0]); target = player->getParent()->findPlayer(player, cmnd, 2); if(!target) { player->print("That person is not here.\n"); return(0); } player->print("You sing a song of recall on %N.\n", target); target->print("%M sings a song of recall on you.\n", player); broadcast(player->getSock(), target->getSock(), player->getParent(), "%M sings a song of recall on %N.", player, target); if(!player->isStaff() && target->checkDimensionalAnchor()) { player->printColor("^y%M's dimensional-anchor causes your song to go off-key!^w\n", target); target->printColor("^yYour dimensional-anchor protects you from %N's song of recall!^w\n", player); return(1); } } newRoom = target->getRecallRoom().loadRoom(target); if(!newRoom) { player->print("Song failure.\n"); return(0); } broadcast(target->getSock(), player->getRoomParent(), "%M disappears.", target); target->deleteFromRoom(); target->addToRoom(newRoom); target->doPetFollow(); return(1); } //********************************************************************* // songSafety //********************************************************************* int songSafety(Player* player, cmd* cmnd) { Player *follower=0; BaseRoom *newRoom=0; if(player->getLevel() < 10) { player->print("That song's just too hard for you to sing yet.\n"); return(0); } player->print("You sing a song of safety.\n"); broadcast(player->getSock(), player->getParent(), "%M sings a song of safety.", player); // handle everyone following singer Group* group = player->getGroup(); if(group) { for(Creature* crt : group->members) { follower = crt->getAsPlayer(); if(!follower) continue; if(!player->inSameRoom(follower)) continue; if(follower->isStaff()) continue; if(!player->isStaff() && follower->checkDimensionalAnchor()) { player->printColor("^y%M's dimensional-anchor causes your song to go off-key!^w\n", follower); follower->printColor("^yYour dimensional-anchor protects you from %N's song of safety!^w\n", player); continue; } newRoom = follower->getRecallRoom().loadRoom(follower); if(!newRoom) continue; broadcast(follower->getSock(), follower->getRoomParent(), "%M disappears.", follower); follower->deleteFromRoom(); follower->addToRoom(newRoom); follower->doPetFollow(); } } if(!player->isStaff() && player->checkDimensionalAnchor()) { player->printColor("^yYour dimensional-anchor causes your song to go off-key!^w\n"); return(1); } newRoom = follower->getRecallRoom().loadRoom(follower); if(newRoom) { broadcast(player->getSock(), player->getParent(), "%M disappears.", player); player->courageous(); player->deleteFromRoom(); player->addToRoom(newRoom); player->doPetFollow(); } return(1); } //********************************************************************* // cmdCharm //********************************************************************* int cmdCharm(Player* player, cmd* cmnd) { Creature* creature=0; int dur, chance; long i, t; player->clearFlag(P_AFK); if(!player->ableToDoCommand()) return(0); if(!player->knowsSkill("charm")) { player->print("Sorry, but you aren't very charming.\n"); return(0); } if(!player->canSpeak()) { player->printColor("^yYour lips move but no sound comes forth.\n"); return(0); } i = LT(player, LT_HYPNOTIZE); t = time(0); if(i > t && !player->isDm()) { player->pleaseWait(i-t); return(0); } int level = (int)player->getSkillLevel("charm"); dur = 300 + mrand(1, 30) * 10 + bonus((int) player->piety.getCur()) * 30 + level * 5; //cmnd->str[1][0] = up(cmnd->str[1][0]); if(!(creature = player->findVictim(cmnd, 1, true, false, "Charm whom?\n", "You don't see that here.\n"))) return(0); if(!player->canAttack(creature)) return(0); if( creature->isPlayer() && ( player->vampireCharmed(creature->getAsPlayer()) || (creature->hasCharm(player->getName()) && player->flagIsSet(P_CHARMED)) )) { player->print("But they are already your good friend!\n"); return(0); } if(creature->isMonster() && (creature->flagIsSet(M_NO_CHARM) || (creature->intelligence.getCur() <30))) { player->print("Your charm fails.\n"); return(0); } if( creature->isUndead() && !player->checkStaff("Your charm will not work on undead beings.\n") ) return(0); if(creature->isMonster() && creature->getAsMonster()->isEnemy(player)) { player->print("Not while you are already fighting %s.\n", creature->himHer()); return(0); } player->smashInvis(); player->lasttime[LT_HYPNOTIZE].ltime = t; player->lasttime[LT_HYPNOTIZE].interval = 600L; chance = MIN(90, 40 + ((level) - (creature->getLevel())) * 20 + 4 * bonus((int) player->intelligence.getCur())); if(creature->flagIsSet(M_PERMENANT_MONSTER) && creature->isMonster()) chance /= 2; if(player->isDm()) chance = 101; if((creature->isUndead() || chance < mrand(1, 100)) && chance != 101) { player->print("Your song has no effect on %N.\n", creature); player->checkImprove("charm", false); broadcast(player->getSock(), player->getParent(), "%M sings off key.",player); if(creature->isMonster()) { creature->getAsMonster()->addEnemy(player); return(0); } creature->printColor("^m%M tried to charm you.\n", player); return(0); } if(!creature->isCt()) { if(creature->chkSave(MEN, player, 0)) { player->printColor("^yYour charm failed!\n"); creature->print("Your mind tingles as you brush off %N's charm.\n", player); player->checkImprove("charm", false); return(0); } } if( (creature->isPlayer() && creature->isEffected("resist-magic")) || (creature->isMonster() && creature->isEffected("resist-magic")) ) dur /= 2; player->print("Your song charms %N.\n", creature); player->checkImprove("charm", true); broadcast(player->getSock(), creature->getSock(), player->getRoomParent(), "%M sings to %N!", player, creature); creature->print("%M's song charms you.\n", player); player->addCharm(creature); creature->lasttime[LT_CHARMED].ltime = time(0); creature->lasttime[LT_CHARMED].interval = dur; creature->setFlag(creature->isPlayer() ? P_CHARMED : M_CHARMED); return(0); }