/*
* command5.cpp
* Command handling/parsing routines.
* ____ _
* | _ \ ___ __ _| |_ __ ___ ___
* | |_) / _ \/ _` | | '_ ` _ \/ __|
* | _ < __/ (_| | | | | | | \__ \
* |_| \_\___|\__,_|_|_| |_| |_|___/
*
* 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 "login.h"
#include "commands.h"
#include "guilds.h"
#include "web.h"
#include "calendar.h"
//*********************************************************************
// who
//*********************************************************************
// This function outputs a list of all the players who are currently
// logged into the game.
int cmdWho(Player* player, cmd* cmnd) {
int cClass=0, chaos=0, clan=0, pledge=0;
int race=0, cls=0, law=0, guild=0;
bool found=false;
player->clearFlag(P_AFK);
if(player->isBraindead()) {
player->print("You are brain-dead. You can't do that.\n");
return(0);
}
if(player->isBlind()) {
player->printColor("^CYou're blind!\n");
return(0);
}
if(cmnd->num > 1) {
lowercize(cmnd->str[1],0);
switch (cmnd->str[1][0]) {
case 'a':
switch (cmnd->str[1][1]) {
case 'd':
cClass = -2;
break;
case 's':
cClass = ASSASSIN;
break;
default:
player->print("Parameter not unique.\n");
return(0);
break;
}
break;
break;
case 'b':
switch (cmnd->str[1][3]) {
case 'b':
race = BARBARIAN;
break;
case 's':
cClass = BERSERKER;
break;
case 'd':
cClass = BARD;
break;
default:
player->print("Parameter not unique.\n");
return(0);
break;
}
break;
case 'c':
switch (cmnd->str[1][1]) {
case 'a':
switch(cmnd->str[1][2]) {
case 'm':
race = CAMBION;
break;
case 'r':
if(!player->isCt()) {
player->print("You do not currently have that privilege.\n");
return(0);
} else
cClass = CARETAKER;
break;
default:
player->print("Parameter not unique.\n");
return(0);
break;
}
break;
case 'h':
chaos = 1;
break;
case 'l':
switch (cmnd->str[1][2]) {
case 'e':
cClass = CLERIC;
break;
case 'a':
switch(cmnd->str[1][3]) {
case 's':
cClass = player->getClass();
break;
case 'n':
clan = 1;
break;
}
break;
default:
player->print("Parameter not unique.\n");
return(0);
break;
}
break;
default:
player->print("Parameter not unique.\n");
return(0);
break;
}
break;
case 'd':
switch(cmnd->str[1][1]) {
case 'a':
race = DARKELF;
break;
case 'e':
cClass = DEATHKNIGHT;
break;
case 'r':
cClass = DRUID;
break;
case 'w':
race = DWARF;
break;
case 'u':
if(!player->isDm()) {
player->print("You do not currently have that privilege.\n");
return(0);
} else
cClass = DUNGEONMASTER;
break;
default:
player->print("Parameter not unique.\n");
return(0);
break;
}
break;
case 'e':
race = ELF;
break;
case 'f':
cClass = FIGHTER;
break;
case 'g':
switch(cmnd->str[1][1]) {
case 'n':
race = GNOME;
break;
case 'o':
race = GOBLIN;
break;
case 'u':
guild = 1;
break;
default:
player->print("Parameter not unique.\n");
return(0);
break;
}
break;
case 'h':
switch(cmnd->str[1][1]) {
case 'u':
race = HUMAN;
break;
case 'a':
switch(cmnd->str[1][4]) {
case 'e':
race = HALFELF;
break;
case 'g':
race = HALFGIANT;
break;
case 'l':
race = HALFLING;
break;
case 'o':
race = HALFORC;
break;
default:
player->print("Parameter not unique.\n");
return(0);
break;
}
break;
default:
player->print("Parameter not unique.\n");
return(0);
break;
}
break;
case 'k':
switch(cmnd->str[1][1]) {
case 'a':
race = KATARAN;
break;
case 'o':
race = KOBOLD;
break;
default:
player->print("Parameter not unique.\n");
return(0);
break;
}
break;
case 'l':
switch(cmnd->str[1][1]) {
case 'a':
law = 1;
break;
case 'i':
cClass = LICH;
break;
default:
player->print("Parameter not unique.\n");
return(0);
break;
}
break;
case 'm':
switch(cmnd->str[1][1]) {
case 'a':
cClass = MAGE;
break;
case 'i':
race = MINOTAUR;
break;
case 'o':
cClass = MONK;
break;
default:
player->print("Unknown parameter.\n");
return(0);
break;
}
break;
case 'o':
switch(cmnd->str[1][1]) {
case 'g':
race = OGRE;
break;
case 'r':
race = ORC;
break;
default:
player->print("Unknown parameter.\n");
return(0);
break;
}
break;
case 'p':
switch(cmnd->str[1][1]) {
case 'a':
cClass = PALADIN;
break;
case 'l':
pledge = 1;
break;
default:
player->print("Parameter not unique.\n");
return(0);
break;
}
break;
case 'r':
switch(cmnd->str[1][1]) {
case 'a':
cClass = RANGER;
break;
case 'o':
cClass = ROGUE;
break;
default:
player->print("Parameter not unique.\n");
return(0);
break;
}
break;
case 's':
race = SERAPH;
break;
case 't':
switch(cmnd->str[1][1]) {
case 'h':
cClass = THIEF;
break;
case 'r':
race = TROLL;
break;
case 'i':
race = TIEFLING;
break;
default:
player->print("Parameter not unique.\n");
return(0);
break;
}
break;
case 'v':
switch (cmnd->str[1][1]) {
case 'a':
cClass = PUREBLOOD;
break;
case 'e':
cClass = -3;
break;
default:
player->print("Parameter not unique.\n");
return(0);
break;
}
break;
break;
case 'w':
switch(cmnd->str[1][1]) {
case 'a':
cClass = -1;
break;
case 'e':
cClass = WEREWOLF;
break;
default:
player->print("Parameter not unique.\n");
return(0);
break;
}
break;
case '.':
cls = 1;
break;
default:
player->print("Parameter not unique.\n");
return(0);
break;
}// end main switch
} // end if cmnd->num > 1
std::ostringstream whoStr;
bstring curStr;
whoStr << "\n^BPlayers currently online:\n";
whoStr << "-------------------------------------------------------------------------------^x\n";
Player* target=0;
for(std::pair<bstring, Player*> p : gServer->players) {
target = p.second;
if(!target->isConnected())
continue;
if(!player->canSee(target))
continue;
if(cls == 1)
if(target->getClass() != player->getClass())
continue;
if(clan == 1)
if(!target->getClan())
continue;
if(guild == 1)
if(player->getGuild() && target->getGuild() != player->getGuild())
continue;
if(chaos == 1)
if(!target->flagIsSet(P_CHAOTIC))
continue;
if(law == 1)
if(target->flagIsSet(P_CHAOTIC))
continue;
if(pledge == 1)
if((target->getClan() && target->getClan() == player->getClan()) || !target->getClan())
continue;
if(race > 0)
if((player->willIgnoreIllusion() ? target->getRace() : target->getDisplayRace()) != race)
continue;
if(cClass == -1)
if(!target->isPublicWatcher())
continue;
if(cClass == -2)
if(!target->flagIsSet(P_ADULT))
continue;
if(cClass == -3)
if(!target->flagIsSet(P_VETERAN))
continue;
if(cClass > 0)
if(target->getClass() != cClass)
continue;
if(target->isEffected("mist") && !player->isEffected("true-sight") && !player->isCt() )
continue;
if(target->isInvisible() && !player->isEffected("detect-invisible") && !player->isCt() )
continue;
if(target->flagIsSet(P_GLOBAL_GAG) && player != target && !player->isCt())
continue;
found = true;
curStr = target->getWhoString(false, true, player->willIgnoreIllusion());
whoStr << curStr;
}
if(!found)
player->print("Nobody found!\n");
else {
curStr = whoStr.str();
player->printColor("%s\n", curStr.c_str());
}
return(0);
}
//*********************************************************************
// classwho
//*********************************************************************
// This function outputs a list of all the players who are currently
// logged into the game which are the same class as the player doing
// the command.
int cmdClasswho(Player* player, cmd* cmnd) {
cmnd->num = 2;
strcpy(cmnd->str[0], "who");
strcpy(cmnd->str[1], "class");
return(cmdWho(player, cmnd));
}
//*********************************************************************
// cmdWhois
//*********************************************************************
// The whois function displays a selected player's name, class, level
// title, age and gender
int cmdWhois(Player* player, cmd* cmnd) {
Player *target=0;
player->clearFlag(P_AFK);
if(player->isBraindead()) {
player->print("You are brain-dead. You can't do that.\n");
return(0);
}
if(cmnd->num < 2) {
player->print("Whois who?\n");
return(0);
}
lowercize(cmnd->str[1], 1);
target = gServer->findPlayer(cmnd->str[1]);
if(!target || !player->canSee(target)) {
player->print("That player is not logged on.\n");
return(0);
}
player->printColor("%s", target->getWhoString(true, true, player->willIgnoreIllusion()).c_str());
return(0);
}
//*********************************************************************
// cmdSuicide
//*********************************************************************
// This function is called whenever the player explicitly asks to
// commit suicide.
int cmdSuicide(Player* player, cmd* cmnd) {
if(!player->ableToDoCommand())
return(0);
if(player->getProxyName() != "") {
player->print("You are unable to suicide a proxied character.\n");
return(0);
}
if(player->flagIsSet(P_NO_SUICIDE)) {
player->print("You cannot suicide right now. You are in a 24 hour cooling-off period.\n");
return(0);
}
// Prevents players from suiciding in jail
if(player->inJail()) {
player->print("You attempt to kill yourself and fail. It sure hurts though!\n");
broadcast(player->getSock(), player->getParent(),"%M tries to kill %sself.", player, player->himHer());
return(0);
}
if(cmnd->num < 2 || strcasecmp(cmnd->str[1], "yes")) {
player->printColor("^rWARNING:^x This will completely erase your character!\n");
player->print("To prevent accidental suicides you must confirm you want to suicide;\nto do so type 'suicide yes'\n");
if(player->getGuild() && player->getGuildRank() == GUILD_MASTER)
player->printColor("^yNote:^x if you want to control who takes over your guild after you suicide,\nbe sure to abdicate leadership first.\n");
return(0);
}
//if(player->getLevel() > 2 && !player->isStaff())
broadcast("### %s committed suicide! We'll miss %s dearly.", player->getCName(), player->himHer());
//else
// broadcast(isWatcher, "^C### %s committed suicide! We'll miss %s dearly.", player->getCName(), player->himHer());
logn("log.suicide", "%s(%s)-%d (%s)\n", player->getCName(), player->getPassword().c_str(), player->getLevel(), player->getSock()->getHostname().c_str());
deletePlayer(player);
updateRecentActivity();
return(0);
}
//*********************************************************************
// deletePlayer
//*********************************************************************
// Does a true delete of a player and their files
void deletePlayer(Player* player) {
char file[80];
bool hardcore = player->isHardcore();
// cache the name because we will be deleting the player object
bstring name = player->getName();
gConfig->deleteUniques(player);
gServer->clearAsEnemy(player);
// remove minions before backup, since this affects other players as well
player->clearMinions();
// they are no longer the owner of any effects they have created
gServer->removeEffectsOwner(player);
// unassociate
if(player->getForum() != "") {
player->setForum("");
webUnassociate(name);
}
// take the player out of any guilds
updateGuild(player, GUILD_REMOVE);
// save a backup - this will be the only copy of the player!
if(player->getLevel() >= 7)
player->save(false, LS_BACKUP);
if(player->flagIsSet(P_CREATING_GUILD)) {
// If they are the founder, this will return text, and we
// need go no further. Otherwise, they are a supporter, and we
// have to search for them.
if(gConfig->removeGuildCreation(name) != "") {
std::list<GuildCreation*>::iterator gcIt;
for(gcIt = gConfig->guildCreations.begin(); gcIt != gConfig->guildCreations.end(); gcIt++) {
// they were supporting this guild - stop
if((*gcIt)->removeSupporter(name))
break;
}
gConfig->saveGuilds();
}
}
// this deletes the player object
Socket* sock = player->getSock();
player->uninit();
free_crt(player,true);
//gServer->clearPlayer(name);
sock->setPlayer(NULL);
// get rid of any files the player was using
sprintf(file, "%s/%s.xml", Path::Player, name.c_str());
unlink(file);
sprintf(file, "%s/%s.txt", Path::Bank, name.c_str());
unlink(file);
sprintf(file, "%s/%s.txt", Path::Post, name.c_str());
unlink(file);
sprintf(file, "%s/%s.txt", Path::History, name.c_str());
unlink(file);
// handle removing and property this player owned
gConfig->destroyProperties(name);
if(hardcore)
sock->reconnect(true);
else
sock->disconnect();
}
//*********************************************************************
// cmdQuit
//*********************************************************************
// This function checks to see if a player is allowed to quit yet. It
// checks to make sure the player isn't in the middle of combat, and if
// so, the player is not allowed to quit (and 0 is returned).
int cmdQuit(Player* player, cmd* cmnd) {
long i=0, t=0;
if(!player->ableToDoCommand())
return(0);
t = time(0);
if(player->inCombat())
i = player->getLTAttack() + 20;
else
i = player->getLTAttack() + 2;
if(t < i) {
player->pleaseWait(i-t);
return(0);
}
if(player->inCombat())
i = LT(player, LT_SPELL) + 20;
else
i = LT(player, LT_SPELL) + 2;
if(t < i) {
player->pleaseWait(i-t);
return(0);
}
player->update();
return(DISCONNECT);
}
//*********************************************************************
// changeStats
//*********************************************************************
int cmdChangeStats(Player* player, cmd* cmnd) {
player->print("Disabled\n");
return(0);
player->changeStats();
return(0);
}
void Player::changeStats() {
int a=0;
if(!flagIsSet(P_CAN_CHANGE_STATS) && !isCt()) {
print("You cannot change your stats at this time.\n");
return;
} else {
for(a=0;a<5;a++) {
tnum[a] = 0;
tstat.num[a] = 0;
}
tstat.hp = 0;
tstat.mp = 0;
tstat.pp = 0;
tstat.rp = 0;
tstat.race = 0;
tstat.cls = 0;
tstat.cls2 = 0;
tstat.level = 0;
broadcast(::isCt, "^y### %s is choosing new stats.", getCName());
printColor("^yPlease enter a new set of initial stats (56 points):\n");
getSock()->setState(CON_CHANGING_STATS);
}
}
//********************************************************************
// changingStats
//********************************************************************
// This function allows a player to change their stats
void changingStats(Socket* sock, bstring str) {
sock->getPlayer()->changingStats(str);
}
void Player::changingStats(bstring str) {
int a, n, i, k, l, sum=0;
int vnum[5];
vstat nstat, sendStat;
switch(getSock()->getState()) {
case CON_CHANGING_STATS:
n = str.length();
l = 0;
k = 0;
for(i=0; i<=n; i++) {
if(str[i]==' ' || str[i]==0) {
str[i] = 0;
//bstring tmp = str.substr(l);
vnum[k++] = atoi(&str[l]);
l = i+1;
}
if(k>4)
break;
}
if(k<5) {
print("Please enter all 5 numbers.\n");
print("Aborted.\n");
getSock()->setState(CON_PLAYING);
return;
}
sum = 0;
for(i=0; i<5; i++) {
if(vnum[i] < 3 || vnum[i] > 18) {
print("No stats < 3 or > 18 please.\n");
print("Aborted.\n");
getSock()->setState(CON_PLAYING);
return;
}
sum += vnum[i];
}
if(sum != 56) {
print("Stat total must equal 56 points.\n");
print("Aborted.\n");
getSock()->setState(CON_PLAYING);
return;
}
for(a=0;a<5;a++)
tnum[a] = vnum[a];
if(race == HUMAN) {
print("Raise which stat?:\n[A] Strength, [B] Dexterity, [C] Constitution, [D] Intelligence, or [E] Piety.\n");
getSock()->setState(CON_CHANGING_STATS_RAISE);
return;
}
print("Your stats have been calculated.\n");
print("Please press [ENTER].\n");
getSock()->setState(CON_CHANGING_STATS_CALCULATE);
return;
break;
case CON_CHANGING_STATS_CALCULATE:
for(a=0;a<5;a++) {
sendStat.num[a] = tnum[a];
}
calcStats(sendStat, &nstat);
print("Your resulting stats will be as follows:\n");
print("STR: %d DEX: %d CON: %d INT: %d PIE: %d\n", nstat.num[0], nstat.num[1], nstat.num[2], nstat.num[3], nstat.num[4]);
print("Hit Points: %d\n", nstat.hp);
print("Are these the stats you want? (Y/N)\n");
for(a=0; a<5; a++)
tstat.num[a] = nstat.num[a];
tstat.hp = nstat.hp;
getSock()->setState(CON_CHANGING_STATS_CONFIRM);
// confirm y/n
break;
case CON_CHANGING_STATS_CONFIRM:
if(low(str[0]) == 'y') {
broadcast(::isCt, "^y### %s has chosen %s stats.", getCName(), hisHer());
print("New stats set.\n");
strength.setCur((short)tstat.num[0]);
dexterity.setCur((short)tstat.num[1]);
constitution.setCur((short)tstat.num[2]);
intelligence.setCur((short)tstat.num[3]);
piety.setCur((short)tstat.num[4]);
hp.setMax(tstat.hp);
clearFlag(P_CAN_CHANGE_STATS);
getSock()->setState(CON_PLAYING);
return;
} else {
broadcast(::isCt,"^y### %s aborted choosing new stats.", getCName());
print("Aborted.\n");
getSock()->setState(CON_PLAYING);
return;
}
break;
case CON_CHANGING_STATS_RAISE:
switch (low(str[0])) {
case 'a':
tnum[0]++;
break;
case 'b':
tnum[1]++;
break;
case 'c':
tnum[2]++;
break;
case 'd':
tnum[3]++;
break;
case 'e':
tnum[4]++;
break;
default:
print("\nPlease choose one.\n");
return;
break;
}
print("Lower which stat?:\n[A] Strength, [B] Dexterity, [C] Constitution, [D] Intelligence, or [E] Piety.\n");
getSock()->setState(CON_CHANGING_STATS_LOWER);
return;
break;
case CON_CHANGING_STATS_LOWER:
switch (low(str[0])) {
case 'a':
tnum[0]--;
tnum[0] = MAX(1, tnum[0]);
break;
case 'b':
tnum[1]--;
tnum[1] = MAX(1, tnum[1]);
break;
case 'c':
tnum[2]--;
tnum[2] = MAX(1, tnum[2]);
break;
case 'd':
tnum[3]--;
tnum[3] = MAX(1, tnum[3]);
break;
case 'e':
tnum[4]--;
tnum[4] = MAX(1, tnum[4]);
break;
default:
print("\nPlease choose one.");
return;
break;
}
print("Your stats have been calculated.\n");
print("Please press [ENTER].\n");
getSock()->setState(CON_CHANGING_STATS_CALCULATE);
break;
}
}
//*********************************************************************
// timestr
//*********************************************************************
char *timestr(long t) {
static char buf[BUFSIZ];
if(t >= 60) {
sprintf(buf, "%01ld:%02ld", t / 60, t % 60);
} else {
sprintf(buf, "%ld seconds", t);
}
return(buf);
}
#define TIMELEFT(name,ltflag) \
tmp = MAX(0,(LT(player, (ltflag)) - t)); \
player->print("Time left on current %s: %s.\n", name, timestr(tmp));
#define TIMEUNTIL(name,ltflag,time) \
u = (time) - t + player->lasttime[(ltflag)].ltime;\
if(u < 0) u = 0;\
player->print("Time left before next %s: %s.\n", name, timestr(u));
//*********************************************************************
// showAbility
//*********************************************************************
void showAbility(Player* player, const char *skill, const char *display, int lt, int tu, int flag = -1) {
long t = time(0), u=0, tmp=0;
if(player->knowsSkill(skill)) {
if(flag != -1 && player->flagIsSet(flag)) {
TIMELEFT(display, lt);
} else {
TIMEUNTIL(display, lt, tu);
}
}
}
//*********************************************************************
// cmdTime
//*********************************************************************
// This function outputs the time of day (realtime) to the player.
int cmdTime(Player* player, cmd* cmnd) {
long t = time(0), u=0, tmp=0, i=0;
const CatRefInfo* cri = gConfig->getCatRefInfo(player->getRoomParent(), 1);
bstring world = "";
if(cri && cri->getWorldName() != "") {
world += " of ";
world += cri->getWorldName();
}
player->clearFlag(P_AFK);
if(player->isBraindead()) {
player->print("You are brain-dead. You can't do that.\n");
return(0);
}
player->printColor("^cThe current time in the world%s:\n", world.c_str());
gConfig->getCalendar()->printtime(player);
if(gConfig->getCalendar()->isBirthday(player))
player->printColor("^yToday is your birthday!\n");
if(player->flagIsSet(P_PTESTER))
player->print("Tick Interval: %d.\n", player->lasttime[LT_TICK].interval);
if(cmnd->num < 2) {
// for ceris/aramon when they resurrect dead people
tmp = MAX(0,(LT(player, LT_NOMPTICK) - t));
if(tmp > 0)
player->print("Time until vitality is restored: %s.\n", timestr(tmp));
// CT+ doesn't need to see all this info
if(!player->isCt()) {
if(player->getClass() == BARD && player->getLevel() >= 4) {
TIMEUNTIL("bard song", LT_SING, player->lasttime[LT_SING].interval);
}
showAbility(player, "barkskin", "barkskin", LT_BARKSKIN, 600);
showAbility(player, "berserk", "berserk", LT_BERSERK, 600);
showAbility(player, "bite", "bite", LT_PLAYER_BITE, player->lasttime[LT_PLAYER_BITE].interval);
showAbility(player, "bloodsac", "blood sacrifice", LT_BLOOD_SACRIFICE, 600);
showAbility(player, "commune", "commune", LT_PRAY, 45);
showAbility(player, "charm", "charm", LT_HYPNOTIZE, player->lasttime[LT_HYPNOTIZE].interval);
showAbility(player, "creeping-doom", "creeping-doom", LT_SMOTHER, player->lasttime[LT_SMOTHER].interval);
showAbility(player, "disarm", "disarm", LT_DISARM, player->lasttime[LT_DISARM].interval);
showAbility(player, "drain", "drain life", LT_DRAIN_LIFE, player->lasttime[LT_DRAIN_LIFE].interval);
showAbility(player, "smother", "earth-smother", LT_SMOTHER, player->lasttime[LT_SMOTHER].interval);
showAbility(player, "enthrall", "enthrall", LT_HYPNOTIZE, player->lasttime[LT_HYPNOTIZE].interval);
showAbility(player, "focus", "focus", LT_FOCUS, 600, P_FOCUSED);
showAbility(player, "frenzy", "frenzy", LT_FRENZY, 600);
showAbility(player, "harm", "harm touch", LT_LAY_HANDS, player->lasttime[LT_LAY_HANDS].interval);
showAbility(player, "holyword", "holyword", LT_SMOTHER, player->lasttime[LT_SMOTHER].interval);
showAbility(player, "howl", "howl", LT_HOWLS, 240);
showAbility(player, "hypnotize", "hypnotize", LT_HYPNOTIZE, player->lasttime[LT_HYPNOTIZE].interval);
if( player->knowsSkill("identify") ||
player->canBuildObjects()
) {
TIMEUNTIL("identify", LT_IDENTIFY, player->lasttime[LT_IDENTIFY].interval);
}
showAbility(player, "hands", "lay on hands", LT_LAY_HANDS, player->lasttime[LT_LAY_HANDS].interval);
showAbility(player, "maul", "maul", LT_KICK, player->lasttime[LT_KICK].interval);
showAbility(player, "meditate", "meditate", LT_MEDITATE, 90);
showAbility(player, "mistbane", "mistbane", LT_FOCUS, 600, P_MISTBANE);
showAbility(player, "poison", "poison", LT_DRAIN_LIFE, player->lasttime[LT_DRAIN_LIFE].interval);
showAbility(player, "pray", "pray", LT_PRAY, 600);
showAbility(player, "regenerate", "regenerate", LT_REGENERATE, player->lasttime[LT_REGENERATE].interval);
showAbility(player, "renounce", "renounce", LT_RENOUNCE, player->lasttime[LT_RENOUNCE].interval);
showAbility(player, "touch", "touch of death", LT_TOUCH_OF_DEATH, player->lasttime[LT_TOUCH_OF_DEATH].interval);
showAbility(player, "turn", "turn undead", LT_TURN, player->lasttime[LT_TURN].interval);
showAbility(player, "scout", "scout", LT_SCOUT, player->lasttime[LT_SCOUT].interval);
}
if(player->flagIsSet(P_OUTLAW)) {
i = LT(player, LT_OUTLAW);
player->print("Outlaw time remaining: ");
if(i - t > 3600)
player->print("%02d:%02d:%02d more hours.\n",(i - t) / 3600L, ((i - t) % 3600L) / 60L, (i - t) % 60L);
else if((i - t > 60) && (i - t < 3600))
player->print("%d:%02d more minutes.\n", (i - t) / 60L, (i - t) % 60L);
else
player->print("%d more seconds.\n", MAX((i - t),0));
}
if(player->flagIsSet(P_JAILED)) {
if( player->inUniqueRoom() &&
player->getUniqueRoomParent()->flagIsSet(R_MOB_JAIL)
)
i = LT(player, LT_MOB_JAILED);
else
i = LT(player, LT_JAILED);
player->print("NOTE: 0 Seconds means you're out any second.\n");
player->print("Jailtime remaining(Approx): ");
if(i - t > 3600)
player->print("%02d:%02d:%02d more hours.\n",(i - t) / 3600L, ((i - t) % 3600L) / 60L, (i - t) % 60L);
else if((i - t > 60) && (i - t < 3600))
player->print("%d:%02d more minutes.\n", (i - t) / 60L, (i - t) % 60L);
else
player->print("%d more seconds.\n", MAX((i - t),0));
}
// All those confusing defines, i'll make up my own code
i = 0;
for(Monster* pet : player->pets) {
if(pet->isMonster() && pet->isPet()) {
i = 1;
if(pet->isUndead())
player->print("Time left before creature following you leaves/fades: %s\n",
timestr(pet->lasttime[LT_ANIMATE].ltime+pet->lasttime[LT_ANIMATE].interval-t));
else
player->print("Time left before creature following you leaves/fades: %s\n",
timestr(pet->lasttime[LT_INVOKE].ltime+pet->lasttime[LT_INVOKE].interval-t));
//TIMEUNTIL("hire",LT_INVOKE,player->lasttime[LT_INVOKE].interval);
}
}
// only show how long until next if they don't have a pet already
if(!i) {
if( player->getClass() == DRUID ||
(player->getClass() == CLERIC && player->getDeity() == GRADIUS))
{
TIMEUNTIL("conjure", LT_INVOKE, player->lasttime[LT_INVOKE].interval);
}
if( player->getClass() == CLERIC &&
player->getDeity() == ARAMON &&
player->getAdjustedAlignment() <= REDDISH)
{
TIMEUNTIL("animate dead", LT_ANIMATE, player->lasttime[LT_ANIMATE].interval);
}
}
}
return(0);
}
//*********************************************************************
// cmdSave
//*********************************************************************
// This is the function that is called when a players types save
// It calls save() (the real save function) and then tells the user
// the player was saved. See save() for more details.
int cmdSave(Player* player, cmd* cmnd) {
ASSERTLOG( player );
player->clearFlag(P_AFK);
if(player->isBraindead()) {
player->print("You are brain-dead. You can't do that.\n");
return(0);
}
player->save(true);
// Save storage rooms
if(player->inUniqueRoom() && player->getUniqueRoomParent()->info.isArea("stor"))
gConfig->resaveRoom(player->getUniqueRoomParent()->info);
player->print("Player saved.\n");
return(0);
}