#include "h/mud.h" #include <string.h> #include <ctype.h> #include <time.h> #include "h/files.h" #include "h/currency.h" void free_bank_to_chars(BANK_DATA * bank); CHAR_DATA *find_banker(CHAR_DATA *ch) { CHAR_DATA *banker = NULL; for(banker = ch->in_room->first_person; banker; banker = banker->next_in_room) if(IS_NPC(banker) && xIS_SET(banker->act, ACT_BANKER)) break; return banker; } /* Quick function for immortals/staff to list all bankers in the world */ void do_bankers(CHAR_DATA *ch, char *argument) { CHAR_DATA *mob; for(mob = first_char; mob; mob = mob->next) { if(IS_NPC(mob)) { if(xIS_SET(mob->pIndexData->act, ACT_BANKER)) ch_printf(ch, "&R[%d] Banker '%s', level %d : in room [%d] - %s..\n\r", mob->pIndexData->vnum, mob->short_descr, mob->level, mob->in_room->vnum, mob->in_room->area->name); else if(xIS_SET(mob->act, ACT_BANKER)) ch_printf(ch, "&W[%d] Banker '%s', level %d : in room [%d] - %s..\n\r", mob->pIndexData->vnum, mob->short_descr, mob->level, mob->in_room->vnum, mob->in_room->area->name); } } send_to_char("&wMobs in &Wwhite &ware current, &Rred &ware proto.\n\r", ch); return; } void unlink_bank(BANK_DATA * bank) { BANK_DATA *tmp, *tmp_next; int hash; if(!bank) { bug("Unlink_bank: NULL bank"); return; } if(bank->name[0] < 'a' || bank->name[0] > 'z') hash = 0; else hash = (bank->name[0] - 'a') + 1; if(bank == (tmp = bank_index[hash])) { bank_index[hash] = tmp->next; return; } for(; tmp; tmp = tmp_next) { tmp_next = tmp->next; if(bank == tmp_next) { tmp->next = tmp_next->next; return; } } } void free_bank(BANK_DATA * bank) { if(bank->name) STRFREE(bank->name); if(bank->password) STRFREE(bank->password); DISPOSE(bank); } void free_banks(void) { BANK_DATA *bank, *bank_next; int hash; for(hash = 0; hash < 126; hash++) { for(bank = bank_index[hash]; bank; bank = bank_next) { bank_next = bank->next; unlink_bank(bank); free_bank(bank); } } } void add_bank(BANK_DATA * bank) { int hash, x; BANK_DATA *tmp, *prev; if(!bank) { bug("Add_bank: NULL bank"); return; } if(!bank->name) { bug("Add_bank: NULL bank->name"); return; } if(!bank->password) { bug("Add_bank: NULL bank->password"); return; } for(x = 0; bank->name[x] != '\0'; x++) bank->name[x] = LOWER(bank->name[x]); if(bank->name[0] < 'a' || bank->name[0] > 'z') hash = 0; else hash = (bank->name[0] - 'a') + 1; if((prev = tmp = bank_index[hash]) == NULL) { bank->next = bank_index[hash]; bank_index[hash] = bank; return; } for(; tmp; tmp = tmp->next) { if((x = strcmp(bank->name, tmp->name)) == 0) { bug("Add_bank: trying to add duplicate name to bucket %d", hash); free_bank(bank); return; } else if(x < 0) { if(tmp == bank_index[hash]) { bank->next = bank_index[hash]; bank_index[hash] = bank; return; } prev->next = bank; bank->next = tmp; return; } prev = tmp; } /* * add to end */ prev->next = bank; bank->next = NULL; return; } // Volk Jan-16: Quick command to merge two accounts void do_merge(CHAR_DATA *ch, char *argument) { BANK_DATA *bank, *bank2; CHAR_DATA *banker; char arg1[MIL], arg2[MIL], arg3[MIL], arg4[MIL]; char buf[MSL]; if(!(banker = find_banker(ch))) { send_to_char("You're not in a bank!\r\n", ch); return; } if(IS_NPC(ch)) { snprintf(buf, MSL, "say Sorry, %s, we don't do business with mobs.", ch->name); interpret(banker, buf); return; } if(argument[0] == '\0') { send_to_char("Syntax: merge (name) (password) (name2) (password2)\r\n", ch); send_to_char(" using the name and password of the first account, then the second.\r\n", ch); send_to_char("The first account will be kept, with the funds from both accounts. The second will be deleted.\r\n", ch); interpret(banker, (char *)"say If you need help type &WHELP BANK&D."); return; } argument = one_argument(argument, arg1); argument = one_argument(argument, arg2); argument = one_argument(argument, arg3); argument = one_argument(argument, arg4); bank = find_bank(arg1); bank2 = find_bank(arg3); if(!bank) { ch_printf(ch, "There is no account by the name of '%s'.\r\n", arg1); return; } if(!bank2) { ch_printf(ch, "There is no account by the name of '%s'.\r\n", arg3); return; } if(strcmp(sha256_crypt(arg2), bank->password)) { ch_printf(ch, "Invalid password for account '%s'.\r\n", arg1); return; } if(strcmp(sha256_crypt(arg4), bank2->password)) { ch_printf(ch, "Invalid password for account '%s'.\r\n", arg3); return; } ch_printf(ch, "Moving %d gold to account '%s' (previously had %d gold).\r\n", bank2->gold, arg1, bank->gold); bank->gold += bank2->gold; bank2->gold = 0; ch_printf(ch, "Moving %d silver to account '%s' (previously had %d silver).\r\n", bank2->silver, arg1, bank->silver); bank->silver += bank2->silver; bank2->silver = 0; ch_printf(ch, "Moving %d bronze to account '%s' (previously had %d bronze).\r\n", bank2->bronze, arg1, bank->bronze); bank->bronze += bank2->bronze; bank2->bronze = 0; ch_printf(ch, "Moving %d copper to account '%s' (previously had %d copper).\r\n", bank2->copper, arg1, bank->copper); bank->copper += bank2->copper; bank2->copper = 0; bank->lastused = current_time; ch_printf(ch, "Deleting... (%s)\r\n", bank2->name); free_bank_to_chars(bank2); unlink_bank(bank2); free_bank(bank2); save_bank(); if(ch->pcdata && ch->pcdata->account) STRFREE(ch->pcdata->account); ch_printf(ch, "Account '%s' has successfully been deleted.\r\n", arg3); send_to_char("Please reselect your active account using the 'ACCOUNT' command.\r\n", ch); return; } void do_account(CHAR_DATA *ch, char *argument) { BANK_DATA *bank; CHAR_DATA *banker; char arg1[MIL], arg2[MIL], arg3[MIL]; int amount = 0, currtime = time(0); int type = DEFAULT_CURR; char buf[MSL], *pwdnew; if(!(banker = find_banker(ch))) { send_to_char("You're not in a bank!\r\n", ch); return; } if(IS_NPC(ch)) { snprintf(buf, MSL, "say Sorry, %s, we don't do business with mobs.", ch->name); interpret(banker, buf); return; } if(argument[0] == '\0') { send_to_char("Syntax: account name password create/delete\r\n", ch); send_to_char(" account name password - to switch accounts\r\n", ch); interpret(banker, (char *)"say If you need help type &WHELP BANK&D."); return; } argument = one_argument(argument, arg1); argument = one_argument(argument, arg2); argument = one_argument(argument, arg3); bank = find_bank(arg1); // account saved to pfile if(str_cmp(arg3, "create") && str_cmp(arg3, "delete")) { // add check here for correct password if(!bank) { interpret(banker, (char *)"say There is no account with that name. Please use the correct name, or create a new account."); send_to_char("&wTo learn more, type &WHELP BANK&w.\r\n", ch); return; } if(strcmp(sha256_crypt(arg2), bank->password)) { send_to_char("Invalid password.\r\n", ch); return; } if(ch->pcdata->account) { if(str_cmp(ch->pcdata->account, arg1)) { ch_printf(ch, "You switch bank account from '%s' to '%s'.\r\n", ch->pcdata->account, arg1); STRFREE(ch->pcdata->account); ch->pcdata->account = STRALLOC(arg1); } else ch_printf(ch, "Account '%s' is already selected.\r\n", arg1); } else { ch_printf(ch, "Account '%s' has been selected.\r\n", arg1); ch->pcdata->account = STRALLOC(arg1); } return; } if(!str_cmp(arg3, "create") && (arg2)) { if(strlen(arg1) < 4) { send_to_char("Account name must be at least 4 characters.\r\n", ch); return; } if(strlen(arg2) < 5) { send_to_char("Invalid Password. Must be at least 5 characters in length.\r\n", ch); return; } if(arg2[0] == '!') { send_to_char("Password cannot begin with the '!' character.\r\n", ch); return; } if(bank) { send_to_char("There is already an account with that name!\r\n", ch); return; } if((currtime - ch->pcdata->lastaccountcreated) < 3600 && get_trust(ch) < LEVEL_AJ_LT) { send_to_char("Please wait at least one hour from previous creation time to make a new account.\r\n", ch); return; } pwdnew = sha256_crypt(arg2); CREATE(bank, BANK_DATA, 1); bank->lastused = current_time; bank->name = STRALLOC(arg1); bank->password = STRALLOC(pwdnew); bank->bronze = 0; bank->copper = 0; bank->gold = 0; bank->silver = 0; add_bank(bank); save_bank(); ch->pcdata->lastaccountcreated = currtime; if(ch->pcdata->account) STRFREE(ch->pcdata->account); ch->pcdata->account = STRALLOC(arg1); save_char_obj(ch); saving_char = NULL; send_to_char("Your account has been added.\r\n", ch); return; } if(!str_cmp(arg3, "delete") && (arg2)) { if(!bank) { send_to_char("There is no account with that name to delete!\r\n", ch); return; } if(strcmp(sha256_crypt(arg2), bank->password)) { send_to_char("Invalid password.\r\n", ch); return; } GET_MONEY(ch, CURR_GOLD) += bank->gold; GET_MONEY(ch, CURR_SILVER) += bank->silver; GET_MONEY(ch, CURR_BRONZE) += bank->bronze; GET_MONEY(ch, CURR_COPPER) += bank->copper; ch_printf(ch, "Deleting... (%s)\r\n", bank->name); free_bank_to_chars(bank); unlink_bank(bank); free_bank(bank); save_bank(); ch->pcdata->lastaccountcreated = 0; if(ch->pcdata->account) STRFREE(ch->pcdata->account); save_char_obj(ch); saving_char = NULL; send_to_char("Your account has successfully been deleted.\r\n", ch); return; } } void do_deposit(CHAR_DATA *ch, char *argument) { BANK_DATA *bank; CHAR_DATA *banker; char arg1[MIL]; char arg2[MIL]; int amount = 0, currtime = time(0); int type = DEFAULT_CURR; char buf[MSL], *pwdnew; if(!(banker = find_banker(ch))) { send_to_char("You're not in a bank!\r\n", ch); return; } if(IS_NPC(ch)) { snprintf(buf, MSL, "say Sorry, %s, we don't do business with mobs.", ch->name); interpret(banker, buf); return; } if(argument[0] == '\0') { send_to_char("Syntax: deposit amount currency\r\n", ch); interpret(banker, (char *)"say if you need help type &WHELP BANK&D."); return; } argument = one_argument(argument, arg1); argument = one_argument(argument, arg2); bank = find_bank(ch->pcdata->account); // account saved to pfile if(is_number(arg1)) { amount = atoi(arg1); } if(!bank) { send_to_char("There is no account by that name, use the account command to create a new account.\r\n", ch); return; } if(!is_number(arg1)) { send_to_char("You can only deposit coins.\r\n", ch); return; } else { amount = atoi(arg1); } if(arg2) type = get_currency_type(arg2); if(type == CURR_NONE) { send_to_char("You don't have any of that kind of coin.\r\n", ch); return; } if(amount <= 0) { send_to_char("You can't do that.\r\n", ch); return; } if(amount > GET_MONEY(ch, type)) { send_to_char("You don't have that much.\r\n", ch); return; } if(type != CURR_BRONZE && type != CURR_COPPER && type != CURR_GOLD && type != CURR_SILVER) { send_to_char("No such currency.\r\n", ch); return; } GET_MONEY(ch, type) -= amount; ch_printf(ch, "You put %d %s coins in the bank.\r\n", amount, curr_types[type]); if(type == CURR_BRONZE) { bank->bronze += amount; ch_printf(ch, "This brings your account's bronze balance to %d.\r\n", bank->bronze); } else if(type == CURR_COPPER) { bank->copper += amount; ch_printf(ch, "This brings your account's copper balance to %d.\r\n", bank->copper); } else if(type == CURR_GOLD) { bank->gold += amount; ch_printf(ch, "This brings your account's gold balance to %d.\r\n", bank->gold); } else if(type == CURR_SILVER) { bank->silver += amount; ch_printf(ch, "This brings your account's silver balance to %d.\r\n", bank->silver); } save_char_obj(ch); bank->lastused = current_time; save_bank(); return; } void do_withdraw(CHAR_DATA *ch, char *argument) { BANK_DATA *bank; CHAR_DATA *banker; char arg1[MIL]; char arg2[MIL]; int amount = 0, currtime = time(0); int type = DEFAULT_CURR; char buf[MSL], *pwdnew; if(!(banker = find_banker(ch))) { send_to_char("You're not in a bank!\r\n", ch); return; } if(IS_NPC(ch)) { snprintf(buf, MSL, "say Sorry, %s, we don't do business with mobs.", ch->name); interpret(banker, buf); return; } if(argument[0] == '\0') { send_to_char("Syntax: withrdaw amount currency\r\n", ch); interpret(banker, (char *)"say if you need help type &WHELP BANK&D."); return; } argument = one_argument(argument, arg1); argument = one_argument(argument, arg2); bank = find_bank(ch->pcdata->account); // account saved to pfile if(is_number(arg1)) { amount = atoi(arg1); } if(!bank) { send_to_char("There is no account by that name, use the account command to create a new account.\r\n", ch); return; } if(!is_number(arg1)) { send_to_char("You can only withdraw coins.\r\n", ch); return; } else { amount = atoi(arg1); } if(arg2) type = get_currency_type(arg2); if(type == CURR_NONE) { send_to_char("You don't have any of that kind of coin.\r\n", ch); return; } if(amount <= 0) { send_to_char("You can't do that.\r\n", ch); return; } if(type == CURR_BRONZE) { if(amount > bank->bronze) { ch_printf(ch, "You don't have that much %s in the bank.\r\n", curr_types[type]); return; } bank->bronze -= amount; ch_printf(ch, "This brings your account bronze balance to %d.\r\n", bank->bronze); } else if(type == CURR_COPPER) { if(amount > bank->copper) { ch_printf(ch, "You don't have that much %s in the bank.\r\n", curr_types[type]); return; } bank->copper -= amount; ch_printf(ch, "This brings your account copper balance to %d.\r\n", bank->copper); } else if(type == CURR_GOLD) { if(amount > bank->gold) { ch_printf(ch, "You don't have that much %s in the bank.\r\n", curr_types[type]); return; } bank->gold -= amount; ch_printf(ch, "This brings your account gold balance to %d.\r\n", bank->gold); } else if(type == CURR_SILVER) { if(amount > bank->silver) { ch_printf(ch, "You don't have that much %s in the bank.\r\n", curr_types[type]); return; } bank->silver -= amount; ch_printf(ch, "This brings your account silver balance to %d.\r\n", bank->silver); } else { send_to_char("No such currency.\r\n", ch); return; } GET_MONEY(ch, type) += amount; ch_printf(ch, "You took %d %s coins from the bank.\r\n", amount, curr_types[type]); bank->lastused = current_time; save_bank(); save_char_obj(ch); return; } void free_bank_to_chars(BANK_DATA * bank) { CHAR_DATA *ch; if(!bank) return; for(ch = first_char; ch; ch = ch->next) { if(!ch || !ch->pcdata || !ch->pcdata->bank) continue; if(ch->pcdata->bank != bank) continue; ch_printf(ch, "%s account no longer exist.\r\n", bank->name); ch->pcdata->bank = NULL; } } void do_transfer(CHAR_DATA *ch, char *argument) { BANK_DATA *bank; BANK_DATA *victim_bank; CHAR_DATA *banker; char arg1[MIL], arg2[MIL], arg3[MIL]; int amount = 0, currtime = time(0); int type = DEFAULT_CURR; char buf[MSL], *pwdnew; if(!(banker = find_banker(ch))) { send_to_char("You're not in a bank!\r\n", ch); return; } if(IS_NPC(ch)) { snprintf(buf, MSL, "say Sorry, %s, we don't do business with mobs.", ch->name); interpret(banker, buf); return; } if(argument[0] == '\0') { send_to_char("Syntax: transfer amount currency destination\r\n", ch); interpret(banker, (char *)"say if you need help type &WHELP BANK&D."); return; } argument = one_argument(argument, arg1); argument = one_argument(argument, arg2); argument = one_argument(argument, arg3); bank = find_bank(ch->pcdata->account); // account saved to pfile if(is_number(arg1)) { amount = atoi(arg1); } if(!bank) { send_to_char("There is no account by that name, use the account command to create a new account.\r\n", ch); return; } if(!is_number(arg1)) { send_to_char("You can only transfer coins.\r\n", ch); return; } else { amount = atoi(arg1); } if(arg1 && arg2) type = get_currency_type(arg2); if(type == CURR_NONE) { send_to_char("You don't have any of that kind of coin.\r\n", ch); return; } if(amount <= 0) { send_to_char("You can't do that.\r\n", ch); return; } victim_bank = find_bank(arg3); if(!victim_bank) { sprintf(buf, "%s There is no account by that name here.", ch->name); do_tell(banker, buf); return; } if(type == CURR_BRONZE) { if(amount > bank->bronze) { ch_printf(ch, "You don't have that much %s in the bank.\r\n", curr_types[type]); return; } bank->bronze -= amount; victim_bank->bronze += amount; } else if(type == CURR_COPPER) { if(amount > bank->copper) { ch_printf(ch, "You don't have that much %s in the bank.\r\n", curr_types[type]); return; } bank->copper -= amount; victim_bank->copper += amount; } else if(type == CURR_GOLD) { if(amount > bank->gold) { ch_printf(ch, "You don't have that much %s in the bank.\r\n", curr_types[type]); return; } bank->gold -= amount; victim_bank->gold += amount; } else if(type == CURR_SILVER) { if(amount > bank->silver) { ch_printf(ch, "You don't have that much %s in the bank.\r\n", curr_types[type]); return; } bank->silver -= amount; victim_bank->silver += amount; } ch_printf(ch, "You transfer %d %s coins from your account to theirs.\r\n", amount, curr_types[type]); bank->lastused = current_time; save_bank(); return; }