X-Git-Url: https://jfr.im/git/irc/gameservirc.git/blobdiff_plain/bb668fcf666c70130d77a458e7d3d805e1694b70..6f727d4c9eb5c886f14598577f40da583577444e:/gameserv/gameserv.cpp diff --git a/gameserv/gameserv.cpp b/gameserv/gameserv.cpp index e0a9b66..164a90c 100644 --- a/gameserv/gameserv.cpp +++ b/gameserv/gameserv.cpp @@ -10,6 +10,7 @@ using std::ifstream; using std::ofstream; +using std::ios; #if defined(HAVE_CRYPT_H) @@ -21,7 +22,13 @@ using std::ofstream; #endif -List players; +// this will be hash.cpp start +// thank you wcampbel +unsigned long sHASH(const unsigned char *name); +unsigned long iHASH(const unsigned char *name); +List players[U_TABLE_SIZE]; +// this will be hash.cpp end + Monster *monsters[LEVELS][MONSTERS]; // Monsters per level. Total = MONSTERS * LEVELS Monster boss; // The boss monster @@ -41,7 +48,6 @@ int stricmp(const char *s1, const char *s2); int strnicmp(const char *s1, const char *s2, size_t len); // String Functions - /********** Password functions **********/ bool passcmp(char *encrypted, char *plaintext); // Compares an encrypted pass with a plain text one @@ -53,6 +59,11 @@ bool check_password(char *name, char *plaintext); // Finds a password for the gi /********** GameServ Booleans **********/ +bool shuttingdown; +bool timedOut(Player *p); +void updateTS(Player *p); +void timeOutEvent(Player *p); + bool is_playing(char *u); // True if the given nickname in the clients list is playing. bool is_playing(aClient *user); @@ -79,6 +90,7 @@ long int stringtoint(char *number); char *spaces(int len, char *seperator); void refresh(Player *p); void refreshall(); +void updateTS(Player *p); void reset(Player *p); void init_masters(); void init_monsters(); @@ -97,6 +109,7 @@ void do_inventory(char *u); void do_refresh(char *u); void do_register(char *u); void do_list(char *u); +void do_logout(char *u); void do_master(char *u); void do_play(char *u); void do_quitg(char *u); @@ -108,6 +121,7 @@ void do_tavern(char *u); void do_use(char *u); void see_master(char *u); +void logout(aClient *user); void showstats(const char *u, const char *nick); void showinventory(aClient *from, aClient *to); void showBankBalance(const char *u); @@ -126,8 +140,8 @@ char *armors[WNA] = { "Nothing", "Clothes", "Leather Vest", "Chain Mail", "Plate int prices[WNA - 1] = {200, 1000, 3000, 10000, 30000, 100000, 150000, 200000, 400000, 1000000, 4000000, 10000000, 40000000, 100000000, 400000000}; -int webonus[WNA] = {0, 10, 15, 25, 35, 45, 65, 85, 125, 185, 255, 355, 505, 805, 1205, 1805}; -int arbonus[WNA] = {0, 1, 3, 10, 15, 25, 35, 50, 75, 100, 150, 225, 300, 400, 600, 1000}; +int webonus[WNA] = {1, 10, 15, 25, 35, 45, 65, 85, 125, 185, 255, 355, 505, 805, 1205, 1805}; +int arbonus[WNA] = {1, 2, 4, 10, 15, 25, 35, 50, 75, 100, 150, 225, 300, 400, 600, 1000}; int hpbonus[11] = {10, 15, 20, 30, 50, 75, 125, 185, 250, 350, 550}; int strbonus[11] = {5, 7, 10, 12, 20, 35, 50, 75, 110, 150, 200}; @@ -135,14 +149,15 @@ int defbonus[11] = {2, 3, 5, 10, 15, 22, 35, 60, 80, 120, 150}; void gameserv(char *source, char *buf) { - char *cmd; + char *cmd, z; cmd = strtok(buf, " "); #ifndef P10 source++; // Get rid of that : at the beginning of a :Nick privmsg Gameserv :text #endif - if (cmd[0] == ':') + z = cmd[0]; + if (z == ':') cmd++; // Get rid of that : at the beginning of the :text (command) #ifdef DEBUGMODE @@ -160,7 +175,7 @@ void gameserv(char *source, char *buf) { refreshall(); day = curday; - save_day(); + save_day(); // here i come to save the day! } if (strnicmp(cmd, "\1PING", 6) == 0) @@ -169,7 +184,7 @@ void gameserv(char *source, char *buf) ts = strtok(NULL, "\1"); notice(s_GameServ, source, "\1PING %s\1", ts); } else if (stricmp(cmd, "\1VERSION\1") == 0) { - notice(s_GameServ, source, "\1VERSION %s %s +devel\1", PACKAGE, VERSION); + notice(s_GameServ, source, "\1VERSION %s %s\1", PACKAGE, VERSION); } else if (stricmp(cmd, "SEARCH") == 0) { cmd = strtok(NULL, " "); @@ -206,13 +221,8 @@ void gameserv(char *source, char *buf) do_tavern(source); } else if (stricmp(cmd, "LIST") == 0) { do_list(source); - #ifdef DEBUGMODE - } else if (stricmp(cmd, "PRINT") == 0) { - cout << "Printing the clients list:" << endl; - clients.print(); - cout << "\nPrinting the players list:" << endl; - players.print(); - #endif + } else if (stricmp(cmd, "LOGOUT") == 0) { + do_logout(source); } else if (stricmp(cmd, "REGISTER") == 0) { do_register(source); } else if (stricmp(cmd, "IDENTIFY") == 0) { @@ -241,6 +251,7 @@ void gameserv(char *source, char *buf) #else raw("SQUIT %s :leaving: %s used the Shutdown command.", servername, source); #endif + shuttingdown = true; } } else if (stricmp(cmd, "SAVE") == 0) { aClient *user; @@ -286,6 +297,7 @@ void gameserv(char *source, char *buf) else display_help(source, cmd); } + #ifdef DEBUGMODE } else if (stricmp(cmd, "RAW") == 0) { aClient *user; @@ -303,12 +315,29 @@ void gameserv(char *source, char *buf) char *rest = strtok(NULL, ""); raw("%s", rest); } + #endif } else { - notice(s_GameServ, source, "Unknown command \002%s\002. Type /msg %S \002HELP\002 to get a list of commands.", cmd); + aClient *user; + if ((user = find(source))) + { + if (isIgnore(user)) + { + #ifdef DEBUGMODE + log("Ignoring %s.", user->getNick()); + #endif + } + else + { + notice(s_GameServ, source, "Unknown command \002%s\002. Type /msg %S \002HELP\002 to get a list of commands.", cmd); + } + } } - source--; // Bring the ':' back so we don't leak memory - cmd--; // Same thing :) + #ifndef P10 + source--; // Bring the ':' back so we don't leak memory + #endif + if (z == ':') + cmd--; // Same thing :) } int stricmp(const char *s1, const char *s2) @@ -434,6 +463,22 @@ void notice(const char *source, const char *dest, const char *fmt, ...) if (fmt[0] == '\0') return; + char *commanduse; + commanduse = new char[16]; + + #ifdef P10 + if (isUsePrivmsg()) + strcpy(commanduse, "P"); + else + strcpy(commanduse, "N"); + #else + + if (isUsePrivmsg()) + strcpy(commanduse, "PRIVMSG"); + else + strcpy(commanduse, "NOTICE"); + #endif + va_list args; char *input; const char *t = fmt; @@ -444,9 +489,9 @@ void notice(const char *source, const char *dest, const char *fmt, ...) dest++; #if !defined(P10) - sprintf(input, ":%s NOTICE %s :", source, dest); + sprintf(input, ":%s %s %s :", source, commanduse, dest); #else - sprintf(input, "%s O %s :", gsnum, dest); + sprintf(input, "%s %s %s :", gsnum, commanduse, dest); #endif dest--; @@ -454,9 +499,9 @@ void notice(const char *source, const char *dest, const char *fmt, ...) else { #if !defined(P10) - sprintf(input, ":%s NOTICE %s :", source, dest); + sprintf(input, ":%s %s %s :", source, commanduse, dest); #else - sprintf(input, "%s O %s :", gsnum, dest); + sprintf(input, "%s %s %s :", gsnum, commanduse, dest); #endif } @@ -484,6 +529,7 @@ void notice(const char *source, const char *dest, const char *fmt, ...) #endif sprintf(input, "%s%s", input, "\r\n"); sock_puts(sock, input); + delete [] commanduse; delete [] input; va_end(args); } @@ -529,14 +575,34 @@ char *strtok(char *str, const char *delim) void do_list(char *u) { + aClient *user; + if (!(user = find(u))) + { + log("Fatal Error: Couldn't find %s in the client list", u); + return; + } + else if (isIgnore(user)) + { + #ifdef DEBUGMODE + log("Ignoring %s. Command LIST", user->getNick()); + #endif + return; + } + ListNode *temp; - temp = players.First(); - if (!players.isEmpty()) + bool header = false; + for (unsigned long x = 0; x < U_TABLE_SIZE; x++) + { + temp = players[x].First(); + if (!players[x].isEmpty()) { - notice(s_GameServ, u, "People Playing:"); + if (!header) + { + notice(s_GameServ, u, "People Playing:"); + header = true; + } while(temp) { - #ifdef P10 notice(s_GameServ, u, "IRC: %s Game: %s", temp->getData()->getRealNick(), temp->getData()->stats->name); @@ -547,16 +613,104 @@ void do_list(char *u) temp = temp->Next(); } + } + } + if (!header) + notice(s_GameServ, u, "No one is playing"); + else notice(s_GameServ, u, "End of List"); + +} + +void do_logout(char *u) +{ + aClient *user; + if (!(user = find(u))) + { + notice(s_GameServ, u, "Fatal error. Cannot find aClient. "\ + "Buf: %s LOGOUT", u); + log("Could not find aClient Buf: %s LOGOUT", + u); + } + else if (isIgnore(user)) + { + #ifdef DEBUGMODE + log("Ignoring %s.", user->getNick()); + #endif + return; + } + else if (!is_playing(user)) + { + notice(s_GameServ, u, "You're not logged in!"); + } + else if (is_fighting(user)) + { + notice(s_GameServ, u, "You can't logout while fighting!"); } else - notice(s_GameServ, u, "No one is playing"); + { + notice(s_GameServ, u, "You have left the fields. You have lived to kill another day!"); + logout(user); + } +} + +void logout(aClient *user) +{ + if (is_playing(user)) + { + ListNode *it; + aClient *temp; + unsigned long hv = iHASH((unsigned char *) user->stats->name); + it = players[hv].Find(user); + + if (!it) + { + notice(s_GameServ, user->getNick(), "Fatal error. Contact "\ + "%S Admin. Cannot find you in the players list."); + log("Error on logout(). Can't find %s in the players list", + #ifdef P10 + user->getRealNick() + #else + user->getNick() + #endif + ); + return; + } + + temp = new aClient; + temp->stats = new Player; + temp->stats->setData(user->stats); + user->stats->client = NULL; + + if (player_fight(user)) + user->stats->battle->stats->battle = NULL; + + delete user->stats; + user->stats = NULL; + temp->stats->client = NULL; + #ifdef P10 + temp->setRealNick("Not Playing"); + #endif + temp->setNick("Not Playing"); + + it->setNewPtr(temp); + #ifdef DEBUGMODE + log("Logged out player %s", + #ifdef P10 + user->getRealNick() + #else + user->getNick() + #endif + ); + #endif + } + clearPlaying(user); } void do_register(char *u) { char *password, *name; - aClient *user, *p; + aClient *user; name = strtok(NULL, " "); password = strtok(NULL, " "); @@ -575,19 +729,41 @@ void do_register(char *u) { notice(s_GameServ, u, "SYNTAX: /msg %S REGISTER NAME PASSWORD"); } - else if ((user = find(u))) + else if ((user = findplayer(name))) + { + notice(s_GameServ, u, "%s is already registered!", name); + notice(s_GameServ, u, "Choose another name!"); + } + else if (!(user = find(u))) + { + log("Fatal Error: Couldn't find %s in the clients list", u); + } + else if (isIgnore(user)) { - p = findplayer(u); - if (!user->stats && !p) + #ifdef DEBUGMODE + log("Ignoring %s.", user->getNick()); + #endif + return; + } + else + { + if (!is_playing(user)) { + ListNode *temp; user->stats = new Player(user); - user->stats->user = user; // Set the backwards pointer - strcpy(user->stats->password, crypt(password, salt)); - strcpy(user->stats->name, name); - players.insertAtBack(user); + user->stats->client = user; // Set the backwards pointer + user->stats->reset(); // set the user up + strncpy(user->stats->password, crypt(password, salt), 255); + strncpy(user->stats->name, name, 255); + unsigned long hv = iHASH((unsigned char *) name); + updateTS(user->stats); + temp = players[hv].insertAtBack_RLN(user); + temp->setPtr(user); // This is an extra step, but necessary for now + notice(s_GameServ, u, "Player %s registered with password %s.", user->stats->name, password); notice(s_GameServ, u, "Write this password down. If you lose it, there is no way to retrieve it!"); log("Nickname %s registered player %s.", u, user->stats->name); + setPlaying(user); // set the playing flag } else { @@ -602,58 +778,64 @@ void do_identify(char *u) aClient *user, *p; name = strtok(NULL, " "); password = strtok(NULL, " "); - user = find(u); if (!password || !name) { notice(s_GameServ, u, "SYNTAX: /msg %S IDENTIFY NAME PASSWORD"); } - else if (!user) + else if (!(user = find(u))) { notice(s_GameServ, u, "Fatal error. Cannot find aClient. Buf: %s", strtok(NULL, "")); log("Error: aClient not found: %s", u); } + else if (isIgnore(user)) + { + #ifdef DEBUGMODE + log("Ignoring %s.", user->getNick()); + #endif + return; + } else if (!(p = findplayer(name)) || !p->stats) notice(s_GameServ, u, "Player %s not found", name); + else if (is_playing(user)) + { + notice(s_GameServ, u, "You are already playing!"); + } + else if (p->stats->client != NULL && !isAdmin(user)) + { + notice(s_GameServ, u, "That player has already identified."); + } else if (!check_password(name, password) && !isAdmin(user)) { notice(s_GameServ, u, "Password incorrect"); } - else - { - if (p->stats->user && !isAdmin(user)) + else { + ListNode *temp; + unsigned long hv = iHASH((unsigned char *) p->stats->name); + temp = players[hv].Find(p); + if (!temp) { - notice(s_GameServ, u, "That player has already identified."); + notice(s_GameServ, u, "Fatal error. Contact %S Admin. Buf: %s", + strtok(NULL, "")); return; } - if (!user->stats) - { - ListNode *temp; - temp = players.Find(p); - if (!temp) - { - notice(s_GameServ, u, "Fatal error. Contact %S Admin. Buf: %s", - strtok(NULL, "")); - return; - } - user->stats = new Player(p->stats->name); - #ifdef DEBUGMODE - log("Setting data for identified"); - #endif - user->stats->setData(p->stats); + user->stats = new Player(p->stats->name); + #ifdef DEBUGMODE + log("Setting data for identified"); + #endif + user->stats->setData(p->stats); + user->stats->client = user; + updateTS(user->stats); - #ifdef DEBUGMODE - log("Player Identified"); - #endif - temp->setPtr(user); + #ifdef DEBUGMODE + log("Player %s IRC: %s Identified", user->stats->name, + user->getNick()); + #endif - notice(s_GameServ, u, "Password Accepted. Identified."); + setPlaying(user); // set the playing flag - } - else - { - notice(s_GameServ, u, "Already identified. Contact a %S admin for help."); - } + temp->setPtr(user); + notice(s_GameServ, u, "Password Accepted. Identified."); } } @@ -664,25 +846,35 @@ void do_stats(char *u) nick = strtok(NULL, " "); - if (!nick) + if (!(user = find(u))) { - if (!(user = find(u))) - { - notice(s_GameServ, u, "Fatal Error in do_stats(). Contact a %S admin for help!"); - log("Error: aClient not found: %s", u); - return; - } - else if (!is_playing(user)) + log("Fatal Error: %s not found in client list", u); + return; + } + else if (isIgnore(user)) + { + #ifdef DEBUGMODE + log("Ignoring %s.", user->getNick()); + #endif + return; + } + else if (!nick) + { + if (!is_playing(user)) { notice(s_GameServ, u, "You're not playing, so you have no stats!"); return; } else + { + updateTS(user->stats); showstats(u, user->stats->name); + } } else showstats(u, nick); } + void init_masters() { #ifdef DEBUGMODE @@ -700,7 +892,7 @@ void init_masters() strcpy(masters[0]->name, "Old Bones"); strcpy(masters[0]->weapon, "Dull Sword Cane"); - masters[0]->strength = 15; + masters[0]->strength = 25; masters[0]->gold = 0; masters[0]->exp = 0; masters[0]->maxhp = 30; @@ -709,7 +901,7 @@ void init_masters() strcpy(masters[1]->name, "Master Chang"); strcpy(masters[1]->weapon, "Nanchaku"); - masters[1]->strength = 30; + masters[1]->strength = 35; masters[1]->gold = 0; masters[1]->exp = 0; masters[1]->maxhp = 40; @@ -718,7 +910,7 @@ void init_masters() strcpy(masters[2]->name, "Chuck Norris"); strcpy(masters[2]->weapon, "Ranger Kick"); - masters[2]->strength = 85; + masters[2]->strength = 95; masters[2]->gold = 0; masters[2]->exp = 0; masters[2]->maxhp = 70; @@ -728,7 +920,7 @@ void init_masters() strcpy(masters[3]->name, "Mr. Miagi"); strcpy(masters[3]->weapon, "Petrified Bonsai"); - masters[3]->strength = 120; + masters[3]->strength = 130; masters[3]->gold = 0; masters[3]->exp = 0; masters[3]->maxhp = 120; @@ -737,7 +929,7 @@ void init_masters() strcpy(masters[4]->name, "Jackie Chan"); strcpy(masters[4]->weapon, "Kung Fu Kick"); - masters[4]->strength = 135; + masters[4]->strength = 145; masters[4]->gold = 0; masters[4]->exp = 0; masters[4]->maxhp = 200; @@ -746,7 +938,7 @@ void init_masters() strcpy(masters[5]->name, "Jet Li"); strcpy(masters[5]->weapon, "Motorcycle"); - masters[5]->strength = 160; + masters[5]->strength = 170; masters[5]->gold = 0; masters[5]->exp = 0; masters[5]->maxhp = 400; @@ -756,7 +948,7 @@ void init_masters() strcpy(masters[6]->name, "Muhammad Ali"); strcpy(masters[6]->weapon, "Quick Jab"); - masters[6]->strength = 185; + masters[6]->strength = 195; masters[6]->gold = 0; masters[6]->exp = 0; masters[6]->maxhp = 600; @@ -765,7 +957,7 @@ void init_masters() strcpy(masters[7]->name, "Li Mu Bai"); strcpy(masters[7]->weapon, "Green Destiny"); - masters[7]->strength = 210; + masters[7]->strength = 220; masters[7]->gold = 0; masters[7]->exp = 0; masters[7]->maxhp = 800; @@ -775,7 +967,7 @@ void init_masters() strcpy(masters[8]->name, "Jimmy Wang Yu"); strcpy(masters[8]->weapon, "Flying Guillotine"); - masters[8]->strength = 275; + masters[8]->strength = 285; masters[8]->gold = 0; masters[8]->exp = 0; masters[8]->maxhp = 1200; @@ -784,7 +976,7 @@ void init_masters() strcpy(masters[9]->name, "Wong Fei Hung"); strcpy(masters[9]->weapon, "Drunken Boxing"); - masters[9]->strength = 360; + masters[9]->strength = 375; masters[9]->gold = 0; masters[9]->exp = 0; masters[9]->maxhp = 1800; @@ -793,7 +985,7 @@ void init_masters() strcpy(masters[10]->name, "Bruce Lee"); strcpy(masters[10]->weapon, "Fists of fury"); - masters[10]->strength = 575; + masters[10]->strength = 590; masters[10]->gold = 0; masters[10]->exp = 0; masters[10]->maxhp = 2500; @@ -847,21 +1039,15 @@ void display_monster(char *u) void display_players(char *u) { - if (is_playing(u)) + aClient *user; + if (!(user = find(u))) { - aClient *ni = find(u); - - aClient *battle = ni->stats->battle; - - notice(s_GameServ, u, "Your Hitpoints: %d", ni->stats->hp); - notice(s_GameServ, u, "%s's Hitpoints: %d", battle->stats->name, - battle->stats->hp); - notice(s_GameServ, u, "Here are your commands:"); - notice(s_GameServ, u, "/msg %S attack"); - notice(s_GameServ, u, "/msg %S run"); - notice(s_GameServ, u, "What will you do?"); + log("Fatal error in display_players(): Couldn't find %s", u); } + else + display_players(user); } + void display_players(aClient *user) { char *u = user->getNick(); @@ -882,18 +1068,27 @@ bool is_playing(char *u) { aClient *user; if (!(user = find(u))) - { return false; - } else - { - return user->stats != NULL; - } + return is_playing(user); } bool is_playing(aClient *user) { - return user->stats != NULL && (stricmp(user->getNick(), "!NULL!") != 0); + if (user->stats == NULL) + { + return false; + } + else if (user->stats->client == NULL) + { + return false; + } + else if (!FL_is_playing(user)) + { + return false; + } + else + return true; } bool is_fighting(char *u) @@ -901,23 +1096,17 @@ bool is_fighting(char *u) aClient *user; if (!(user = find(u))) - { return false; - } - else if (user->stats) - { - return user->stats->fight != NULL || user->stats->battle != NULL - || user->stats->master != NULL; - } else - return false; + return is_fighting(user); } + bool is_fighting(aClient *user) { if (!is_playing(user)) return false; else - return (user->stats->fight != NULL || user->stats->battle != NULL || user->stats->master != NULL); + return player_fight(user) || master_fight(user) || user->stats->fight != NULL; } bool player_fight(char *u) @@ -926,14 +1115,13 @@ bool player_fight(char *u) if (!(user = find(u))) return false; - else if (user->stats) - return user->stats->battle != NULL; - else - return false; + else + return player_fight(user); } + bool player_fight(aClient *user) { - if (!is_fighting(user)) + if (!is_playing(user)) return false; else return user->stats->battle != NULL; @@ -945,11 +1133,10 @@ bool master_fight(char *u) if (!(user = find(u))) return false; - else if (user->stats) - return user->stats->master != NULL; else - return false; + return master_fight(user); } + bool master_fight(aClient *user) { if (!is_playing(user)) @@ -967,15 +1154,18 @@ void do_fight(char *u) if (!nick) { notice(s_GameServ, u, "SYNTAX: /msg %S FIGHT PLAYER"); + return; } else if (!(ni = find(u))) { notice(s_GameServ, u, "Fatal error. Contact a(n) %S admin. buf: %s", strtok(NULL, "")); return; } - else if (!(battle = findbyrealnick(nick))) + else if (isIgnore(ni)) { - notice(s_GameServ, u, "You can't attack %s while they aren't playing!", nick); + #ifdef DEBUGMODE + log("Ignoring %s.", ni->getNick()); + #endif return; } else if (!is_playing(ni)) @@ -983,6 +1173,27 @@ void do_fight(char *u) notice(s_GameServ, u, "You are not playing!"); return; } + + updateTS(ni->stats); + + if (ni->stats->player_fights <= 0) + { + ni->stats->player_fights = 0; // just to be safe + notice(s_GameServ, u, "You are out of player fights for the "\ + "day. You have to wait until tomorrow!"); + } + else if (!(battle = findplayer(nick))) + { + notice(s_GameServ, u, "Player %s not found!", nick); + } + else if (!isAlive(ni->stats)) + { + notice(s_GameServ, u, "You are dead. Wait until tomorrow to fight others!"); + } + else if (!is_playing(battle)) + { + notice(s_GameServ, u, "You can't attack %s while they aren't playing!", nick); + } /* * Offline fighting not implemented yet. * else if (!(fight = finduser(nick))) @@ -996,41 +1207,64 @@ void do_fight(char *u) * display_players(u); * } */ - else if (!isAlive(ni->stats)) + else if (stricmp(ni->stats->name, battle->stats->name) == 0) { - notice(s_GameServ, u, "You are dead. Wait until tomorrow to fight others!"); - return; + notice(s_GameServ, u, "Are you trying to commit suicide!?"); + } + else if (!isAlive(battle->stats)) + { + notice(s_GameServ, u, "They are dead. Cannot fight dead players!"); } else if (player_fight(battle)) { notice(s_GameServ, u, "%s is fighting %s already!", battle->stats->name, battle->stats->battle->stats->name); - return; + } + else if (master_fight(battle)) + { + notice(s_GameServ, u, "%s is fighting their master!", battle->stats->name); } else if (is_fighting(battle)) { notice(s_GameServ, u, "%s is fighting %s already!", battle->stats->name, battle->stats->fight->name); - return; } - else if (is_playing(ni) && is_playing(battle) && stricmp(ni->stats->name, battle->stats->name) != 0) + else if (ni->stats->level - battle->stats->level > maxbfightdistance) + { + // You can't fight someone below you by more than X level(s) + // level 12 can fight level (12 - X) but not < (12 - X) + notice(s_GameServ, u, "You may not fight %s. You're too strong!", + battle->stats->name); + } + else if (battle->stats->level - ni->stats->level > maxafightdistance) + { + // You can't fight someone above you by more than X level(S) + // level 1 can fight level (1 + X), but not > (1 + X) + notice(s_GameServ, u, "%s, do you really have a death wish? Try the forest you "\ + "weakling!", ni->stats->name); + } + else { // Set your battle pointer to the other player ni->stats->battle = battle; // Set the other player's battle pointer to you - battle->stats->battle = ni; + ni->stats->battle->stats->battle = ni; // The initiator gets the first move (perhaps this should be 50/50) setYourTurn(ni->stats); clearYourTurn(battle->stats); // Initiate Battle sequence! + ni->stats->player_fights -= 1; + notice(s_GameServ, u, "You challenge %s to an online duel!", battle->stats->name); notice(s_GameServ, battle->getNick(), "%s has challenged you to an online duel!", ni->stats->name); - notice(s_GameServ, battle->getNick(), "%s gets to go first because he initiated!", ni->stats->name); + notice(s_GameServ, battle->getNick(), "%s gets to go first "\ + "because they initiated!", ni->stats->name); notice(s_GameServ, battle->getNick(), "Please wait while %s decides what to do.", ni->stats->name); - display_players(u); + display_players(ni); } } + void do_use(char *u) { aClient *user; @@ -1049,12 +1283,21 @@ void do_use(char *u) notice(s_GameServ, u, "Fatal Error in do_use. Contact a(n) %S Admin"); return; } + else if (isIgnore(user)) + { + #ifdef DEBUGMODE + log("Ignoring %s.", user->getNick()); + #endif + return; + } else if (!is_playing(user)) { notice(s_GameServ, u, "You must be playing to use items!"); return; } + updateTS(user->stats); + p = &user->stats->inventory; if (stricmp(item, "HEALTH") == 0) @@ -1081,7 +1324,7 @@ void do_use(char *u) int oldstrength = user->stats->strength; notice(s_GameServ, u, "As you grip the flask containing pure power, you feel adrenaline coarse through your veins!"); notice(s_GameServ, u, "In one swallow you drink the potion and feel your muscle fibers bulging andgrowing!"); - user->stats->strength += 1 + rand() % 2; // 1 - 2 Strength Added + user->stats->strength += 1 + (rand() % 10 >= 8 ? 1 : 0); // 1-2 notice(s_GameServ, u, "You gain %d Strength points!", user->stats->strength - oldstrength); p->decStrength(); } @@ -1095,7 +1338,7 @@ void do_use(char *u) int olddefense = user->stats->defense; notice(s_GameServ, u, "You drink the foul tasting viscous liquid while pinching your nose in disgust."); notice(s_GameServ, u, "It tasted bad, but you feel like you are unbeatable!"); - user->stats->defense += 1 + rand() % 2; // 1 - 2 Defense Added + user->stats->defense += 1 + (rand() % 10 >= 8 ? 1 : 0); // 1-2 notice(s_GameServ, u, "You gain %d Defense points!", user->stats->defense - olddefense); p->decDefense(); } @@ -1108,7 +1351,9 @@ void do_use(char *u) } int oldHP = user->stats->maxhp; notice(s_GameServ, u, "You feel your life growing longer as you drink the green glowing liquid."); - user->stats->maxhp += 1 + rand() % 5; // 1 - 5 Maxhp + user->stats->maxhp += 4 + + (rand() % 100 > 50 ? (rand() % 6) : (rand() % 2) ); + notice(s_GameServ, u, "You gain %d Maximum hit points!", user->stats->maxhp - oldHP); p->decHP(); } @@ -1130,13 +1375,20 @@ void do_run(char *u) notice(s_GameServ, u, "Couldn't find you. Error. Contact a %S admin"); return; } - + else if (isIgnore(user)) + { + #ifdef DEBUGMODE + log("Ignoring %s.", user->getNick()); + #endif + return; + } else if (!is_playing(user)) { - notice(s_GameServ, u, "You must be playing to use items!"); + notice(s_GameServ, u, "You must be playing to run!"); return; } + updateTS(user->stats); p = user->stats; if (p->battle) @@ -1261,6 +1513,13 @@ void do_attack(char *u) notice(s_GameServ, u, "Fatal error in do_attack. Contact a(n) %S admin for help."); return; } + else if (isIgnore(ni)) + { + #ifdef DEBUGMODE + log("Ignoring %s.", ni->getNick()); + #endif + return; + } else if (!is_playing(ni)) { notice(s_GameServ, u, "You're not playing!"); @@ -1283,6 +1542,7 @@ void do_attack(char *u) // One has to be !NULL based on the previous else if // We wouldn't be here if they were all NULL } + updateTS(ni->stats); if (!player_fight(ni)) { @@ -1515,7 +1775,7 @@ void do_attack(char *u) weapons[ni->stats->weapon], hit); clearYourTurn(ni->stats); setYourTurn(battle->stats); - display_players(battle->getNick()); + display_players(battle); } else { @@ -1523,7 +1783,7 @@ void do_attack(char *u) notice(s_GameServ, battle->getNick(), "%s misses you completely!", ni->stats->name); clearYourTurn(ni->stats); setYourTurn(battle->stats); - display_players(battle->getNick()); + display_players(battle); } if (hit >= battle->stats->hp) { @@ -1594,12 +1854,20 @@ void do_heal(char *u) if (!amount) { notice(s_GameServ, u, "SYNTAX: /msg %S HEAL {ALL | #}"); + return; } else if (!(ni = find(u))) { notice(s_GameServ, u, "Fatal error. Contact a(n) %S admin. buf: %s", strtok(NULL, "")); return; } + else if (isIgnore(ni)) + { + #ifdef DEBUGMODE + log("Ignoring %s.", ni->getNick()); + #endif + return; + } else if (!is_playing(ni)) { notice(s_GameServ, u, "You aren't playing!"); @@ -1613,12 +1881,16 @@ void do_heal(char *u) else if (is_fighting(ni)) { notice(s_GameServ, u, "You can't heal in battle!"); + return; } else if (ni->stats->hp >= ni->stats->maxhp) { notice(s_GameServ, u, "You don't need healing!"); + return; } - else if (stricmp(amount, "ALL") == 0) + + updateTS(ni->stats); + if (stricmp(amount, "ALL") == 0) { price = ni->stats->level * 3; if (ni->stats->gold < (ni->stats->maxhp - ni->stats->hp) * price) @@ -1719,7 +1991,7 @@ long int chartoint(char ch) int save_gs_dbase() { - ListNode *ptr = players.First(); + ListNode *ptr; Player *it; ofstream outfile; @@ -1731,9 +2003,13 @@ int save_gs_dbase() return 0; } + for (unsigned long x = 0; x < U_TABLE_SIZE; x++) + { + ptr = players[x].First(); while(ptr) { it = ptr->getData()->stats; + clearYourTurn(it); outfile << it->name << ' ' << it->level << ' ' << it->exp << ' ' << it->gold << ' ' << it->bank << ' ' << it->hp << ' ' << it->maxhp << ' ' << it->strength << ' ' << it->defense << ' ' << it->armor << ' ' << it->weapon << ' ' @@ -1742,6 +2018,7 @@ int save_gs_dbase() << ' ' << it->inventory.Strength() << ' ' << it->inventory.Defense() << ' ' << it->inventory.HP() << endl; ptr = ptr->Next(); } + } outfile.close(); return 1; } @@ -1785,9 +2062,9 @@ int load_gs_dbase() password = strtok(NULL, " "); strcpy(p->password, password); - temp->setNick("!NULL!"); + temp->setNick("Not Playing"); #ifdef P10 - temp->setRealNick("!NULL!"); + temp->setRealNick("Not Playing"); #endif p->inventory.reset(); // Set inventory to all 0s @@ -1809,8 +2086,10 @@ int load_gs_dbase() tempname = strtok(NULL, " "); if (tempname) p->inventory.setHP(stringtoint(tempname)); + unsigned long hv = iHASH((unsigned char *) temp->stats->name); - players.insertAtBack(temp); + temp->stats->client = NULL; + players[hv].insertAtBack(temp); delete temp; } delete [] buf; @@ -1867,15 +2146,33 @@ void do_store(char *u) notice(s_GameServ, u, "SYNTAX: STORE LIST {ARMOR | WEAPONS}"); notice(s_GameServ, u, " STORE SELL {ARMOR | WEAPON}"); notice(s_GameServ, u, " STORE BUY {ARMOR | WEAPON} NUMBER"); + return; + } + else if (!(user = find(u))) + { + log("Fatal Error: could not find %s in client list", u); + return; } - else if (!(user = find(u)) || !is_playing(user)) + else if (isIgnore(user)) + { + #ifdef DEBUGMODE + log("Ignoring %s.", user->getNick()); + #endif + return; + } + else if (!is_playing(user)) + { notice(s_GameServ, u, "You must be playing to use the store!"); + return; + } else if (!isAlive(user->stats)) { notice(s_GameServ, u, "You are dead. Wait until tomorrow to purchase weapons and armor!"); return; } - else if (stricmp(cmd, "LIST") == 0) + updateTS(user->stats); + + if (stricmp(cmd, "LIST") == 0) { if (stricmp(item, "WEAPONS") == 0) { @@ -2039,11 +2336,19 @@ void do_inventory(char *u) notice(s_GameServ, u, "Fatal Error. Contact a %S admin!"); return; } + else if (isIgnore(user)) + { + #ifdef DEBUGMODE + log("Ignoring %s.", user->getNick()); + #endif + return; + } else if (!is_playing(user)) { notice(s_GameServ, u, "You must be playing to check your inventory!"); return; } + updateTS(user->stats); showinventory(user, user); } void showinventory(aClient *from, aClient *to) @@ -2074,6 +2379,13 @@ void do_tavern(char *u) notice(s_GameServ, u, "Fatal Error. See a %S admin for help"); return; } + else if (isIgnore(user)) + { + #ifdef DEBUGMODE + log("Ignoring %s.", user->getNick()); + #endif + return; + } else if (!is_playing(user)) { notice(s_GameServ, u, "You must be playing to go to the Tavern"); @@ -2084,7 +2396,10 @@ void do_tavern(char *u) notice(s_GameServ, u, "You cannot go to the Tavern during a fight!"); return; } + + updateTS(user->stats); p = user->stats; + if (!cmd) { notice(s_GameServ, u, "Welcome to Boot Liquors Mystic Apothecary"); @@ -2095,10 +2410,10 @@ void do_tavern(char *u) else if (stricmp(cmd, "LIST") == 0) { notice(s_GameServ, u, "Here is a list of what we have to offer:"); - notice(s_GameServ, u, "1. Healing Potions for %ld Gold", 1000 * p->level + (p->exp / 10)); - notice(s_GameServ, u, "2. Strength Potions for %ld Gold", 2050 * p->level + (p->exp / 10)); - notice(s_GameServ, u, "3. Defense Potions for %ld Gold", 2000 * p->level + (p->exp / 10)); - notice(s_GameServ, u, "4. HP Potions for %ld Gold", 2300 * p->level + (p->exp / 10)); + notice(s_GameServ, u, "1. Healing Potions for %ld Gold", 100 * p->level + (p->exp / 10)); + notice(s_GameServ, u, "2. Strength Potions for %ld Gold", 205 * p->level + (p->exp / 10)); + notice(s_GameServ, u, "3. Defense Potions for %ld Gold", 200 * p->level + (p->exp / 10)); + notice(s_GameServ, u, "4. HP Potions for %ld Gold", 230 * p->level + (p->exp / 10)); notice(s_GameServ, u, "To buy a potion, type /msg %S TAVERN BUY #"); notice(s_GameServ, u, "Example: /msg %S TAVERN BUY 1 buys a healing potion!"); notice(s_GameServ, u, "By something will ya!"); @@ -2118,10 +2433,10 @@ void do_tavern(char *u) { notice(s_GameServ, u, "Invalid Choice!"); notice(s_GameServ, u, "Here is a list of what we have to offer:"); - notice(s_GameServ, u, "1. Healing Potions for %ld Gold", 1000 * p->level + (p->exp / 10)); - notice(s_GameServ, u, "2. Strength Potions for %ld Gold", 2050 * p->level + (p->exp / 10)); - notice(s_GameServ, u, "3. Defense Potions for %ld Gold", 2000 * p->level + (p->exp / 10)); - notice(s_GameServ, u, "4. HP Potions for %ld Gold", 2300 * p->level + (p->exp / 10)); + notice(s_GameServ, u, "1. Healing Potions for %ld Gold", 100 * p->level + (p->exp / 10)); + notice(s_GameServ, u, "2. Strength Potions for %ld Gold", 205 * p->level + (p->exp / 10)); + notice(s_GameServ, u, "3. Defense Potions for %ld Gold", 200 * p->level + (p->exp / 10)); + notice(s_GameServ, u, "4. HP Potions for %ld Gold", 230 * p->level + (p->exp / 10)); notice(s_GameServ, u, "To buy a potion, type /msg %S TAVERN BUY #"); notice(s_GameServ, u, "Example: /msg %S TAVERN BUY 1 buys a healing potion!"); return; @@ -2129,7 +2444,7 @@ void do_tavern(char *u) switch(num) { case 1: - price = (1000 * p->level) + (p->exp / 10); + price = (100 * p->level) + (p->exp / 10); if (p->gold >= price) { notice(s_GameServ, u, "One healing potion coming right up!"); @@ -2140,7 +2455,7 @@ void do_tavern(char *u) notice(s_GameServ, u, "You don't have enough gold!"); break; case 2: - price = (2050 * p->level) + (p->exp / 10); + price = (205 * p->level) + (p->exp / 10); if (p->gold >= price) { notice(s_GameServ, u, "One strength boost coming right up!"); @@ -2151,7 +2466,7 @@ void do_tavern(char *u) notice(s_GameServ, u, "You don't have enough gold!"); break; case 3: - price = (2000 * p->level) + (p->exp / 10); + price = (200 * p->level) + (p->exp / 10); if (p->gold >= price) { notice(s_GameServ, u, "One defense boost coming right up!"); @@ -2162,7 +2477,7 @@ void do_tavern(char *u) notice(s_GameServ, u, "You don't have enough gold!"); break; case 4: - price = (2300 * p->level) + (p->exp / 10); + price = (230 * p->level) + (p->exp / 10); if (p->gold >= price) { notice(s_GameServ, u, "One HP Potion coming right up!"); @@ -2199,14 +2514,28 @@ void do_bank(char *u) notice (s_GameServ, u, "BANK BALANCE"); return; } - - user = find(u); - if (!is_playing(user)) + else if (!(user = find(u))) + { + notice(s_GameServ, u, "Fatal Error. Couldn't find your aClient. Contact a(n) %S "\ + " admin for help"); + log("Fatal Error. Couldn't find %s while executing do_bank()", u); + return; + } + else if (isIgnore(user)) + { + #ifdef DEBUGMODE + log("Ignoring %s.", user->getNick()); + #endif + return; + } + else if (!is_playing(user)) { notice(s_GameServ, u, "You must be playing to use the bank!"); return; } - else if (stricmp(cmd, "BALANCE") == 0) + + updateTS(user->stats); + if (stricmp(cmd, "BALANCE") == 0) { showBankBalance(u); return; @@ -2332,13 +2661,20 @@ void do_bank(char *u) void do_master(char *u) { aClient *user; - user = find(u); - if (!user) + + if (!(user = find(u))) { notice(s_GameServ, u, "Fatal error. Contact a(n) %S admin. buf: %s", strtok(NULL, "")); return; } + else if (isIgnore(user)) + { + #ifdef DEBUGMODE + log("Ignoring %s.", user->getNick()); + #endif + return; + } else if (is_fighting(user)) { notice(s_GameServ, u, "You're in the middle of a fight! Pay attention!"); @@ -2354,7 +2690,8 @@ void do_master(char *u) notice(s_GameServ, u, "You must be playing to see your master!"); return; } - + + updateTS(user->stats); char *cmd = strtok(NULL, " "); Player *p = user->stats; long int need = 0; @@ -2483,8 +2820,9 @@ void refreshall() { ListNode *it; Player *p; - - it = players.First(); + for (unsigned long x = 0; x < U_TABLE_SIZE; x++) + { + it = players[x].First(); while (it) { @@ -2492,6 +2830,7 @@ void refreshall() refresh(p); it = it->Next(); } + } } void refresh(Player *p) @@ -2518,6 +2857,13 @@ void do_refresh(char *u) log("Error: aClient not found: %s", u); return; } + else if (isIgnore(user)) + { + #ifdef DEBUGMODE + log("Ignoring %s.", user->getNick()); + #endif + return; + } else if (!isAdmin(user)) { notice(s_GameServ, u, "You must be a %S admin to use this command!"); @@ -2533,7 +2879,7 @@ void do_refresh(char *u) notice(s_GameServ, u, "Refreshing everyone's stats!"); refreshall(); } - else if ((user = findbyrealnick(nick))) + else if ((user = findplayer(nick))) { if (is_playing(user)) { @@ -2566,7 +2912,9 @@ void resetall() ListNode *it; Player *p; - it = players.First(); + for (unsigned long x = 0; x < U_TABLE_SIZE; x++) + { + it = players[x].First(); while (it) { @@ -2574,6 +2922,7 @@ void resetall() reset(p); it = it->Next(); } + } } void reset(Player *p) @@ -2584,6 +2933,130 @@ void reset(Player *p) p->reset(); } +void updateTS(Player *p) +{ + if (!p) + return; + + #ifdef DEBUGMODE + log("Old timestamp for %s: %ld", p->name, p->lastcommand); + #endif + p->lastcommand = time(NULL); + #ifdef DEBUGMODE + log("New timestamp for %s: %ld", p->name, p->lastcommand); + #endif + +} + +bool timedOut(Player *p) +{ + if (!p) + return false; + else if (p->lastcommand == 0) + return false; + else + { + if ((time(NULL) - p->lastcommand) >= maxidletime) + return true; + + return false; + } +} + +void timeOutEvent(Player *p) +{ + aClient *user = findplayer(p->name); + + if (!user || !p->client) // then they're not playing + return; + + char *nick = user->getNick(); + + if (player_fight(user) && isYourTurn(p)) + { + // Check to see if they were the idler or if it was the other + // person + if (p->lastcommand != p->battle->stats->lastcommand) + { + // This person's last command was given earlier, + // so this person is the idler + notice(s_GameServ, nick, "You timed out "\ + "during a fight. You lose your turn!"); + notice(s_GameServ, p->battle->getNick(), + "%s hesitated for too long. Your move.", p->name); + clearYourTurn(p); + setYourTurn(p->battle->stats); + + // Update the TS for both players to give them another + // Chance to wake up, but if the other player doesn't + // Attack now, they both get logged out. + updateTS(p); + p->battle->stats->lastcommand = p->lastcommand; + display_players(p->battle); + return; + } + else + { + notice(s_GameServ, p->battle->getNick(), + "You and %s timed out at the same time."\ + " Don't fight if you're just going to "\ + "sit there!", p->name); + notice(s_GameServ, user->getNick(), + "You and %s timed out at the same time."\ + " Don't fight if you're just going to "\ + "sit there!", p->battle->stats->name); + logout(p->battle); + logout(user); + return; + } + } + else if (!player_fight(user)) + { + // Place fun stuff here :) + int randnum = 1 + rand() % 100; // 1-100 + #define GSN(s) notice(s_GameServ, nick, s) + #define GSN2(s, f) notice(s_GameServ, nick, s, f) + + if (randnum < 50) + { + // 35-100% of your gold goes pffft - kain + int stolen = (35 + (rand() % 66)) * user->stats->gold / 100; + + GSN("You stop for a moment to rest on the "\ + "street corner. All of a sudden, you "\ + "are ambushed from all sides by a hoarde "\ + "of knife wielding thugs."); + GSN2("The thugs beat you into utter submission "\ + "and steal %d gold from you!", stolen); + user->stats->gold -= stolen; + } + else if (randnum >= 50 && randnum < 75) + { + // 25-65% of your gold goes pffft - kain + int stolen = (25 + (rand() % 41)) * user->stats->gold / 100; + GSN("While dilly dallying around, you lose "\ + "your sense of time. Little did you know, "\ + "but thieves lifted your gold while you "\ + "weren't watching."); + GSN2("Better luck next time... you lose %d gold", stolen); + user->stats->gold -= stolen; + } + else if (randnum >= 75) + { + // 25-75% of your gold goes pffft - kain + int stolen = (25 + (rand() % 51)) * user->stats->gold / 100; + GSN("Good grief! A gaggle of gooey green ghostlike "\ + "goblins grabbed your gold!"); + GSN2("They stole %d gold from you!", stolen); + user->stats->gold -= stolen; + } + + + // Always log out the user + logout(user); + } +} + void do_reset(char *u) { char *nick = strtok(NULL, " "); @@ -2600,6 +3073,7 @@ void do_reset(char *u) notice(s_GameServ, u, "You must be a %S admin to use this command!"); return; } + if (!nick) { notice(s_GameServ, u, "SYNTAX: RESET {ALL | NICK}"); @@ -2711,6 +3185,7 @@ void do_admin(char *u) notice(s_GameServ, u, "Error: aClient not found. Contact %S admin."); return; } + if (!pass) { notice(s_GameServ, u, "SYNTAX: ADMIN password"); @@ -2782,3 +3257,35 @@ bool load_monsters() delete [] buf; return true; } + +// this will be hash.cpp start +// thank you wcampbel +unsigned long sHASH(const unsigned char *name) +{ + unsigned long h = 0, g; + + while (*name) + { + h = (h << 4) + (*name++); // Case sensitive for numerics + if ((g = (h & 0xF0000000))) + h ^= g >> 24; + h &= ~g; + } + return h % U_TABLE_SIZE; +} + +unsigned long iHASH(const unsigned char *name) +{ + unsigned long h = 0, g; + + while (*name) + { + h = (h << 4) + tolower(*name++); + if ((g = (h & 0xF0000000))) + h ^= g >> 24; + h &= ~g; + } + return h % U_TABLE_SIZE; +} + +// this will be hash.cpp end