/*************************************************************** Money.c - by Muerte of CrodoMud (telnet://crodomud.crodo.com 4000) ****************************************************************/ #include "conf.h" #include "sysdep.h" #include "structs.h" #include "utils.h" #include "comm.h" #include "handler.h" #include "interpreter.h" #include "db.h" #include "spells.h" #include "screen.h" #include "constants.h" #include "dg_scripts.h" #include "money.h" /* External Structures/Variables */ extern struct room_data *world; /* Functions */ void add_cash_to_char(struct char_data *ch, int amount, int type) { struct obj_data *obj, *next_obj; int cur_amount = amount; /* Search through carried items for coins of proper type */ for (obj = ch->carrying; obj; obj = next_obj) { next_obj = obj->next_content; if ((GET_OBJ_TYPE(obj) == ITEM_MONEY) && (GET_OBJ_VAL(obj, type) > 0)) { cur_amount += GET_OBJ_VAL(obj, type); GET_OBJ_VAL(obj, type) += amount; restring_money_obj(obj, cur_amount, type); break; } } /* No money of this type found, create a new one */ if (obj == NULL) { obj = create_money(cur_amount, type); obj_to_eoi(obj, ch); } GET_GOLD(ch) += value_in_copper(amount, type); } void sub_cash_from_char(struct char_data *ch, int amount, int type) { struct obj_data *obj, *next_obj; int cur_amount = 0; /* Search through carried items for coins of proper type */ for (obj = ch->carrying; obj; obj = next_obj) { next_obj = obj->next_content; if ((GET_OBJ_TYPE(obj) == ITEM_MONEY) && (GET_OBJ_VAL(obj, type) > 0)) { cur_amount = (GET_OBJ_VAL(obj, type) - amount); GET_OBJ_VAL(obj, type) = cur_amount; if (cur_amount > 0) restring_money_obj(obj, cur_amount, type); break; } } /* Emptied out this type of currency */ if (cur_amount < 1) extract_obj(obj); GET_GOLD(ch) -= value_in_copper(amount, type); /* Went negative (Immoratls loading into inv, then dropping) */ if (GET_GOLD(ch) < 0) { log("SYSERR: Char %s went negative. coins: %d room: %d", GET_NAME(ch), GET_GOLD(ch), GET_ROOM_VNUM(IN_ROOM(ch))); GET_GOLD(ch) = 0; } } struct obj_data *create_money(int amount, int type) { struct obj_data *obj; obj_rnum r_num; if (amount < 1) { log("SYSERR: Try to create negative or 0 money. (%d)", amount); return (NULL); } r_num = real_object(7); obj = read_object(r_num, REAL); restring_money_obj(obj, amount, type); GET_OBJ_TYPE(obj) = ITEM_MONEY; GET_OBJ_WEAR(obj) = ITEM_WEAR_TAKE; GET_OBJ_VAL(obj, type) = amount; GET_OBJ_COST(obj) = amount; GET_OBJ_WEIGHT(obj) = amount * coin_weight[type]; return (obj); } char *money_desc(int amount, int type) { static char buf[128]; if (amount <= 0) { log("SYSERR: Try to create negative or 0 money (%d).", amount); return (NULL); } if (amount == 1) sprintf(buf, "a %s coin", coin_types[type]); else if (amount <= 10) sprintf(buf, "a tiny pile of %s coins", coin_types[type]); else if (amount <= 20) sprintf(buf, "a handful of %s coins", coin_types[type]); else if (amount <= 75) sprintf(buf, "a little pile of %s coins", coin_types[type]); else if (amount <= 200) sprintf(buf, "a small pile of %s coins", coin_types[type]); else if (amount <= 1000) sprintf(buf, "a pile of %s coins", coin_types[type]); else if (amount <= 5000) sprintf(buf, "a big pile of %s coins", coin_types[type]); else if (amount <= 10000) sprintf(buf, "a large heap of %s coins", coin_types[type]); else if (amount <= 20000) sprintf(buf, "a huge mound of %s coins", coin_types[type]); else if (amount <= 75000) sprintf(buf, "an enormous mound of %s coins", coin_types[type]); else if (amount <= 150000) sprintf(buf, "a small mountain of %s coins", coin_types[type]); else if (amount <= 250000) sprintf(buf, "a mountain of %s coins", coin_types[type]); else if (amount <= 500000) sprintf(buf, "a huge mountain of %s coins", coin_types[type]); else if (amount <= 1000000) sprintf(buf, "an enormous mountain of %s coins", coin_types[type]); else sprintf(buf, "an absolutely colossal mountain of %s coins", coin_types[type]); return (buf); } int get_money(struct char_data *ch, int type) { struct obj_data *obj, *next_obj; int cur_amount = 0; /* Search through carried items for coins of proper type */ for (obj = ch->carrying; obj; obj = next_obj) { next_obj = obj->next_content; if ((GET_OBJ_TYPE(obj) == ITEM_MONEY) && (GET_OBJ_VAL(obj, type) > 0)) cur_amount = GET_OBJ_VAL(obj, type); } return(cur_amount); } /* give an object to the end of a char's inventory */ void obj_to_eoi(struct obj_data *object, struct char_data *ch) { struct obj_data *last_obj; if (!object || !ch) return; /* Not carrying anything? */ if (ch->carrying == NULL) { obj_to_char(object, ch); return; } /* Get last object in char's inventory */ last_obj = ch->carrying; while (last_obj->next_content) { last_obj = last_obj->next_content; } last_obj->next_content = object; object->next_content = NULL; object->carried_by = ch; object->in_room = NOWHERE; IS_CARRYING_W(ch) += GET_OBJ_WEIGHT(object); IS_CARRYING_N(ch)++; /* set flag for crash-save system, but not on mobs! */ if (!IS_NPC(ch)) SET_BIT(PLR_FLAGS(ch), PLR_CRASH); } int value_in_copper(int amount, int type) { int modifier = 0; switch (type) { case COIN_COPPER: modifier = COPPER_VALUE; break; case COIN_SILVER: modifier = SILVER_VALUE; break; case COIN_ELECTRUM: modifier = ELECTRUM_VALUE; break; case COIN_GOLD: modifier = GOLD_VALUE; break; case COIN_PLAT: modifier = PLAT_VALUE; break; default: /* Illegal coin type passed */ return (0); break; } return (amount * modifier); } void add_cash_from_copper(struct char_data *ch, int copper) { int plat = 0, gold = 0, electrum = 0, silver = 0, remainder = 0; if (copper <= 0) return; remainder = copper; plat = (remainder / PLAT_VALUE); if (plat > 0) { remainder -= (plat * PLAT_VALUE); add_cash_to_char(ch, plat, COIN_PLAT); } if (remainder > 0) gold = (remainder / GOLD_VALUE); if (gold > 0) { remainder -= (gold * GOLD_VALUE); add_cash_to_char(ch, gold, COIN_GOLD); } if (remainder > 0) electrum = (remainder / ELECTRUM_VALUE); if (electrum > 0) { remainder -= (electrum * ELECTRUM_VALUE); add_cash_to_char(ch, electrum, COIN_ELECTRUM); } if (remainder > 0) silver = (remainder / SILVER_VALUE); if (silver > 0) { remainder -= (silver * SILVER_VALUE); add_cash_to_char(ch, silver, COIN_SILVER); } if (remainder > 0) add_cash_to_char(ch, remainder, COIN_COPPER); } void sub_cash_from_copper(struct char_data *ch, int copper) { int plat = 0, gold = 0, elec = 0, silv = 0, copp = 0, total = 0; if (copper <= 0) return; total = GET_GOLD(ch); plat = get_money(ch, COIN_PLAT); if (plat > 0) sub_cash_from_char(ch, plat, COIN_PLAT); gold = get_money(ch, COIN_GOLD); if (gold > 0) sub_cash_from_char(ch, gold, COIN_GOLD); elec = get_money(ch, COIN_ELECTRUM); if (elec > 0) sub_cash_from_char(ch, elec, COIN_ELECTRUM); silv = get_money(ch, COIN_SILVER); if (silv > 0) sub_cash_from_char(ch, silv, COIN_SILVER); copp = get_money(ch, COIN_COPPER); if (copp > 0) sub_cash_from_char(ch, copp, COIN_COPPER); total -= copper; add_cash_from_copper(ch, total); } int money_obj_value(struct obj_data *obj) { int copper = 0; copper = (value_in_copper(GET_OBJ_VAL(obj, COIN_COPPER), COIN_COPPER) + value_in_copper(GET_OBJ_VAL(obj, COIN_SILVER), COIN_SILVER) + value_in_copper(GET_OBJ_VAL(obj, COIN_ELECTRUM), COIN_ELECTRUM) + value_in_copper(GET_OBJ_VAL(obj, COIN_GOLD), COIN_GOLD) + value_in_copper(GET_OBJ_VAL(obj, COIN_PLAT), COIN_PLAT)); return (copper); } int char_cash_in_copper(struct char_data *ch) { int copper; copper = (value_in_copper(get_money(ch, COIN_COPPER), COIN_COPPER) + value_in_copper(get_money(ch, COIN_SILVER), COIN_SILVER) + value_in_copper(get_money(ch, COIN_ELECTRUM), COIN_ELECTRUM) + value_in_copper(get_money(ch, COIN_GOLD), COIN_GOLD) + value_in_copper(get_money(ch, COIN_PLAT), COIN_PLAT) ); return (copper); } int get_money_type(struct obj_data *obj) { int type = -1; int mixed = -1; if (GET_OBJ_TYPE(obj) != ITEM_MONEY) return -1; if (GET_OBJ_VAL(obj, COIN_COPPER) > 0) { type = 0; mixed++; } if (GET_OBJ_VAL(obj, COIN_SILVER) > 0) { type = 1; mixed++; } if (GET_OBJ_VAL(obj, COIN_ELECTRUM) > 0) { type = 2; mixed++; } if (GET_OBJ_VAL(obj, COIN_GOLD) > 0) { type = 3; mixed++; } if (GET_OBJ_VAL(obj, COIN_PLAT) > 0) { type = 4; mixed++; } if (mixed > 0) type = 5; return (type); } char *expand_copper(int copper, int brief) { static char buffer[128]; int plat = 0, gold = 0, electrum = 0, silver = 0, remainder = 0; *buffer = '\0'; remainder = copper; plat = (remainder / PLAT_VALUE); remainder -= (plat * PLAT_VALUE); if (remainder > 0) gold = (remainder / GOLD_VALUE); remainder -= (gold * GOLD_VALUE); if (remainder > 0) electrum = (remainder / ELECTRUM_VALUE); remainder -= (electrum * ELECTRUM_VALUE); if (remainder > 0) silver = (remainder / SILVER_VALUE); remainder -= (silver * SILVER_VALUE); if (brief == 1) { if (plat > 0) sprintf(buffer + strlen(buffer), " %dp", plat); if (gold > 0) sprintf(buffer + strlen(buffer), " %dg", gold); if (electrum > 0) sprintf(buffer + strlen(buffer), " %de", electrum); if (silver > 0) sprintf(buffer + strlen(buffer), " %ds", silver); if (remainder > 0) sprintf(buffer + strlen(buffer), " %dc", remainder); } else { if (plat > 0) sprintf(buffer + strlen(buffer), " %d platinum", plat); if (gold > 0) sprintf(buffer + strlen(buffer), " %d gold", gold); if (electrum > 0) sprintf(buffer + strlen(buffer), " %d electrum", electrum); if (silver > 0) sprintf(buffer + strlen(buffer), " %d silver", silver); if (remainder > 0) sprintf(buffer + strlen(buffer), " %d copper", remainder); } return (buffer); } int parse_cash_type(const char *currency) { int type = -1; if (!strcmp(currency, "platinum") || is_abbrev(currency, "platinum")) type = COIN_PLAT; else if (!strcmp(currency, "gold") || is_abbrev(currency, "gold")) type = COIN_GOLD; else if (!strcmp(currency, "electrum") || is_abbrev(currency, "electrum")) type = COIN_ELECTRUM; else if (!strcmp(currency, "silver") || is_abbrev(currency, "silver")) type = COIN_SILVER; else if (!strcmp(currency, "copper") || is_abbrev(currency, "copper")) type = COIN_COPPER; return (type); } struct obj_data *get_pile_in_list(struct obj_data *list) { struct obj_data *pile; for (pile = list; pile; pile = pile->next_content) { if (GET_OBJ_TYPE(pile) == ITEM_MONEY) return (pile); } return NULL; } void add_money_to_pile(struct obj_data *money, struct obj_data *pile) { int value[NUM_COIN_TYPES], i, type, amount; /* Store value of currency going into the pile */ for (i = 0; i < NUM_COIN_TYPES; i++) value[i] = GET_OBJ_VAL(money, i); /* Add it to the current pile */ for (i = 0; i < NUM_COIN_TYPES; i++) GET_OBJ_VAL(pile, i) += value[i]; /* Grab the new currency type */ type = get_money_type(pile); /* And it's value */ amount = money_obj_value(pile); /* Update the pile's strings */ restring_money_obj(pile, amount, type); /* Discard the money going in */ extract_obj(money); } void restring_money_obj(struct obj_data *obj, int amount, int type) { char buf[200]; /* Allocate extra description space if needed (new obj) */ if (obj->ex_description == NULL) { CREATE(obj->ex_description, struct extra_descr_data, 1); obj->ex_description->next = NULL; } if (amount == 1) { sprintf(buf, "coin coins %s", coin_types[type]); obj->name = str_dup(buf); sprintf(buf, "%s %s coin", type != COIN_ELECTRUM ? "a" : "an" , coin_types[type]); obj->short_description = str_dup(buf); sprintf(buf, "One miserable %s coin is lying here.", coin_types[type]); obj->description = str_dup(buf); sprintf(buf, "coin coins %s", coin_types[type]); obj->ex_description->keyword = str_dup(buf); sprintf(buf, "It's just one miserable little %s coin.", coin_types[type]); obj->ex_description->description = str_dup(buf); } else { sprintf(buf, "coin coins %s", coin_types[type]); obj->name = str_dup(buf); obj->short_description = str_dup(money_desc(amount, type)); sprintf(buf, "%s is lying here.", money_desc(amount, type)); obj->description = str_dup(CAP(buf)); sprintf(buf, "coins %s", coin_types[type]); obj->ex_description->keyword = str_dup(buf); if (amount < 10) { sprintf(buf, "There are %d %s coins.", amount, coin_types[type]); obj->ex_description->description = str_dup(buf); } else if (amount < 100) { sprintf(buf, "There are about %d %s coins.", 10 * (amount / 10), coin_types[type]); obj->ex_description->description = str_dup(buf); } else if (amount < 1000) { sprintf(buf, "It looks to be about %d %s coins.", 100 * (amount / 100), coin_types[type]); obj->ex_description->description = str_dup(buf); } else if (amount < 100000) { sprintf(buf, "You guess there are, maybe, %d %s coins.", 1000 * ((amount / 1000) + number(0, (amount / 1000))), coin_types[type]); obj->ex_description->description = str_dup(buf); } else obj->ex_description->description = str_dup("There are a LOT of coins."); } } void sub_money_from_pile(struct obj_data *pile, int amount, int type) { int cur_amount; GET_OBJ_VAL(pile, type) -= amount; /* Grab the new currency type */ type = get_money_type(pile); /* And it's value */ cur_amount = money_obj_value(pile); /* Did we empty the pile out? */ if (cur_amount == 0) { extract_obj(pile); return; } /* Update the pile's strings */ restring_money_obj(pile, amount, type); }