/**************************************************************************** * [S]imulated [M]edieval [A]dventure multi[U]ser [G]ame | \\._.// * * -----------------------------------------------------------| (0...0) * * SMAUG 1.0 (C) 1994, 1995, 1996 by Derek Snider |).:.(* * -----------------------------------------------------------| {o o} * * SMAUG code team: Thoric, Altrag, Blodkai, Narn, Haus, | / ' ' \ * * Scryn, Rennard, Swordbearer, Gorog, Grishnakh and Tricops |~'~.VxvxV.~'~* * ------------------------------------------------------------------------ * * Merc 2.1 Diku Mud improvments copyright (C) 1992, 1993 by Michael * * Chastain, Michael Quan, and Mitchell Tse. * * Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, * * Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe. * * ------------------------------------------------------------------------ * * Shop and repair shop module * ****************************************************************************/ /*static char rcsid[] = "$Id: shops.c,v 1.10 2002/10/12 20:06:11 dotd Exp $";*/ #include <sys/types.h> #include <stdio.h> #include <string.h> #include <time.h> #include <math.h> #include "h/mud.h" #include "h/currency.h" #include "h/shops.h" #include "h/clans.h" /* * Local functions */ #define CD CHAR_DATA CD *find_keeper args((CHAR_DATA *ch)); CD *find_fixer args((CHAR_DATA *ch)); #define SMITH_PRODUCT 41002 int get_repaircost args((CHAR_DATA *ch, CHAR_DATA *keeper, OBJ_DATA *obj)); #undef CD void colorize_keeper(OBJ_DATA *obj, CHAR_DATA *ch); /* * Shopping commands. */ CHAR_DATA *find_keeper(CHAR_DATA *ch) { char buf[MSL]; CHAR_DATA *keeper; SHOP_DATA *pShop; int speakswell; pShop = NULL; for(keeper = ch->in_room->first_person; keeper; keeper = keeper->next_in_room) if(IS_NPC(keeper) && (pShop = keeper->pIndexData->pShop) != NULL) break; if(!pShop) { send_to_char("You can't do that here.\r\n", ch); return NULL; } /* * Invisible or hidden people. */ if(!can_see(keeper, ch)) { interpret(keeper, (char *)"say I don't trade with folks I can't see."); return NULL; } /* * Undesirables. */ if(!IS_NPC(ch) && xIS_SET(ch->act, PLR_KILLER)) { interpret(keeper, (char *)"say Killers are not welcome!"); snprintf(buf, MSL, "shout %s the KILLER is over here!\r\n", ch->name); interpret(keeper, buf); return NULL; } if(!IS_NPC(ch) && xIS_SET(ch->act, PLR_THIEF)) { interpret(keeper, (char *)"say Thieves are not welcome!"); snprintf(buf, MSL, "shout %s the THIEF is over here!\r\n", ch->name); interpret(keeper, buf); return NULL; } /* * Shop hours. */ if(time_info.hour < pShop->open_hour) { interpret(keeper, (char *)"say Sorry, come back later."); return NULL; } if(time_info.hour > pShop->close_hour) { interpret(keeper, (char *)"say Sorry, come back tomorrow."); return NULL; } speakswell = UMIN(knows_language(keeper, ch->speaking, ch), knows_language(ch, ch->speaking, keeper)); if((number_percent() % 65) > speakswell) { if(speakswell > 60) snprintf(buf, MSL, "%s Could you repeat that? I didn't quite catch it.", ch->name); else if(speakswell > 50) snprintf(buf, MSL, "%s Could you say that a little more clearly please?", ch->name); else if(speakswell > 40) snprintf(buf, MSL, "%s Sorry... What was that you wanted?", ch->name); else snprintf(buf, MSL, "%s I can't understand you.", ch->name); do_tell(keeper, buf); return NULL; } return keeper; } /* * repair commands. */ CHAR_DATA *find_fixer(CHAR_DATA *ch) { char buf[MSL]; CHAR_DATA *keeper; REPAIR_DATA *rShop; int speakswell; rShop = NULL; for(keeper = ch->in_room->first_person; keeper; keeper = keeper->next_in_room) if(IS_NPC(keeper) && (rShop = keeper->pIndexData->rShop) != NULL) break; if(!rShop) { send_to_char("You can't do that here.\r\n", ch); return NULL; } /* * Shop hours. */ if(time_info.hour < rShop->open_hour) { interpret(keeper, (char *)"say Sorry, come back later."); return NULL; } if(time_info.hour > rShop->close_hour) { interpret(keeper, (char *)"say Sorry, come back tomorrow."); return NULL; } /* * Invisible or hidden people. */ if(!can_see(keeper, ch)) { interpret(keeper, (char *)"say I don't trade with folks I can't see."); return NULL; } /* * Undesirables. */ if(!IS_NPC(ch) && xIS_SET(ch->act, PLR_KILLER)) { interpret(keeper, (char *)"say Killers are not welcome!"); snprintf(buf, MSL, "shout %s the KILLER is over here!\r\n", ch->name); interpret(keeper, buf); return NULL; } if(!IS_NPC(ch) && xIS_SET(ch->act, PLR_THIEF)) { interpret(keeper, (char *)"say Thieves are not welcome!"); snprintf(buf, MSL, "shout %s the THIEF is over here!\r\n", ch->name); interpret(keeper, buf); return NULL; } speakswell = UMIN(knows_language(keeper, ch->speaking, ch), knows_language(ch, ch->speaking, keeper)); if((number_percent() % 65) > speakswell) { if(speakswell > 60) snprintf(buf, MSL, "%s Could you repeat that? I didn't quite catch it.", ch->name); else if(speakswell > 50) snprintf(buf, MSL, "%s Could you say that a little more clearly please?", ch->name); else if(speakswell > 40) snprintf(buf, MSL, "%s Sorry... What was that you wanted?", ch->name); else snprintf(buf, MSL, "%s I can't understand you.", ch->name); do_tell(keeper, buf); return NULL; } return keeper; } bool will_buy(CHAR_DATA *keeper, OBJ_DATA *obj) { SHOP_DATA *pShop; OBJ_DATA *obj2; int itype; if(!obj || (pShop = keeper->pIndexData->pShop) == NULL) return FALSE; for(itype = 0; itype < MAX_TRADE; itype++) if(obj->item_type == pShop->buy_type[itype]) break; if(obj->item_type != pShop->buy_type[itype]) return FALSE; for(obj2 = keeper->first_carrying; obj2; obj2 = obj2->next_content) if(obj->pIndexData == obj2->pIndexData) return FALSE; return TRUE; } int get_cost(CHAR_DATA *ch, CHAR_DATA *keeper, OBJ_DATA *obj, bool fBuy) { /* * fBuy here means the player is buying - ie using profit_buy's margin */ SHOP_DATA *pShop; int cost = 0; if(!obj || (pShop = keeper->pIndexData->pShop) == NULL) return 0; if(fBuy) { /* Volk - if fBuy is TRUE, then player is buying - apply buying * * * * * margin */ cost = (obj->pIndexData->cost * pShop->profit_buy / 100); // Make cha have a affect with shops if(get_curr_cha(ch) < 11) { cost += 50; } else if(get_curr_cha(ch) > 10 && get_curr_cha(ch) < 13) { cost += 40; } else if(get_curr_cha(ch) > 12 && get_curr_cha(ch) < 14) { cost += 30; } else if(get_curr_cha(ch) > 13 && get_curr_cha(ch) < 17) { cost += 25; } else if(get_curr_cha(ch) > 16 && get_curr_cha(ch) < 21) { cost += 10; } else if(get_curr_cha(ch) > 20 && get_curr_cha(ch) < 24) { cost += 5; } else if(get_curr_cha(ch) > 23) { cost -= 1; } /* * Lets allow influence to change cost of items */ if(cost > 0 && IS_CLANNED(ch) && str_cmp(ch->pcdata->clan->name, "Halcyon")) { if(IS_INFLUENCED(ch, ch->in_room->area)) /* If their clan is * * * * * * influencing the area * * * * * * sell * it to them * cheaper */ cost -= (int)(cost * .10); else /* Ok they are clanned and not * * * halcyon so charge more */ cost += (int)(cost * .10); if(cost <= 0) cost = 1; } } else /* Volk - selling */ cost = (obj->cost * pShop->profit_sell / 100); if(obj->count > 1) cost *= obj->count; return cost; } int get_repaircost(CHAR_DATA *ch, CHAR_DATA *keeper, OBJ_DATA *obj) { REPAIR_DATA *rShop; int cost; int itype; bool found; if(!obj || (rShop = keeper->pIndexData->rShop) == NULL) return 0; cost = 0; found = FALSE; for(itype = 0; itype < MAX_FIX; itype++) { if(obj->item_type == rShop->fix_type[itype]) { cost = (int)(obj->cost * rShop->profit_fix / 1000); found = TRUE; break; } } if(!found) cost = -1; if(cost == 0) cost = 1; if(found && cost > 0) { switch (obj->item_type) { case ITEM_ARMOR: if(obj->value[0] >= obj->value[1]) cost = -2; else cost *= (obj->value[1] - obj->value[0]); break; case ITEM_WEAPON: if(INIT_WEAPON_CONDITION == obj->value[0]) cost = -2; else cost *= (INIT_WEAPON_CONDITION - obj->value[0]); break; case ITEM_WAND: case ITEM_STAFF: if(obj->value[2] >= obj->value[1]) cost = -2; else cost *= (obj->value[1] - obj->value[2]); } } /* * Lets allow influence to change cost of items */ if(cost > 0 && IS_CLANNED(ch) && str_cmp(ch->pcdata->clan->name, "Halcyon")) { if(IS_INFLUENCED(ch, ch->in_room->area)) /* If their clan is influencing * * * * * * the area * sell it to * them * * * * * cheaper */ cost -= (int)(cost * .10); else /* Ok they are clanned and not * * * halcyon so charge more */ cost += (int)(cost * .10); if(cost <= 0) cost = 1; } return cost; } /* Lets see if the character is able to afford the object */ bool can_afford(CHAR_DATA *ch, double cost, short fctype) { double has; if(fctype == CURR_GOLD) cost *= 1000; else if(fctype == CURR_SILVER) cost *= 100; else if(fctype == CURR_BRONZE) cost *= 10; has = (GET_MONEY(ch, CURR_GOLD) * 1000); has += (GET_MONEY(ch, CURR_SILVER) * 100); has += (GET_MONEY(ch, CURR_BRONZE) * 10); has += (GET_MONEY(ch, CURR_COPPER)); if(cost > has) return FALSE; return TRUE; } void convert_coins(CHAR_DATA *ch, int needed, short tctype, short fctype, int climit) { while(GET_MONEY(ch, fctype) >= climit) { GET_MONEY(ch, tctype) += 1; GET_MONEY(ch, fctype) -= climit; if(GET_MONEY(ch, tctype) >= needed) return; } } /* * We will start out seeing if they have enough of the specified type if not * then we will see if we can convert up, if not then convert down * returns true once they have enough */ bool spend_coins(CHAR_DATA *ch, CHAR_DATA *keeper, int cost, short ctype) { bool converted = FALSE; while(cost > 0) { if(ctype == CURR_GOLD) { if(GET_MONEY(ch, CURR_GOLD) >= cost) { GET_MONEY(ch, ctype) -= cost; cost -= cost; continue; } converted = TRUE; /* * Transfer everything up to gold */ convert_coins(ch, cost, CURR_GOLD, CURR_COPPER, 1000); if(GET_MONEY(ch, CURR_GOLD) >= cost) continue; convert_coins(ch, cost, CURR_GOLD, CURR_BRONZE, 100); if(GET_MONEY(ch, CURR_GOLD) >= cost) continue; convert_coins(ch, cost, CURR_GOLD, CURR_SILVER, 10); if(GET_MONEY(ch, CURR_GOLD) >= cost) continue; /* * If we still haven't gotten enough have to transfer up as we go till we do * have enough */ /* * First lets transfer copper up as much as possible */ convert_coins(ch, 1000, CURR_SILVER, CURR_COPPER, 100); convert_coins(ch, 100, CURR_BRONZE, CURR_COPPER, 10); /* * Next lets transfer up our bronze */ convert_coins(ch, 100, CURR_SILVER, CURR_BRONZE, 10); /* * Finaly lets transfer up our silver again */ convert_coins(ch, cost, CURR_GOLD, CURR_SILVER, 10); if(GET_MONEY(ch, CURR_GOLD) >= cost) continue; } else if(ctype == CURR_SILVER) { if(GET_MONEY(ch, CURR_SILVER) >= cost) { GET_MONEY(ch, ctype) -= cost; cost -= cost; continue; } converted = TRUE; /* * Transfer everything to silver */ convert_coins(ch, cost, CURR_SILVER, CURR_COPPER, 100); if(GET_MONEY(ch, CURR_SILVER) >= cost) continue; convert_coins(ch, cost, CURR_SILVER, CURR_BRONZE, 10); if(GET_MONEY(ch, CURR_SILVER) >= cost) continue; /* * If we still haven't gotten enough have to transfer up as we go till we do * have enough */ /* * First lets transfer copper up as much as possible */ convert_coins(ch, 100, CURR_BRONZE, CURR_COPPER, 10); /* * Next lets transfer up our bronze */ convert_coins(ch, 100, CURR_SILVER, CURR_BRONZE, 10); if(GET_MONEY(ch, CURR_SILVER) >= cost) continue; /* * If we made it this far we need to bring down gold */ while(GET_MONEY(ch, CURR_GOLD) > 0) { GET_MONEY(ch, CURR_GOLD) -= 1; GET_MONEY(ch, CURR_SILVER) += 10; if(GET_MONEY(ch, CURR_SILVER) >= cost) break; } } else if(ctype == CURR_BRONZE) { if(GET_MONEY(ch, CURR_BRONZE) >= cost) { GET_MONEY(ch, ctype) -= cost; cost -= cost; continue; } converted = TRUE; /* * Transfer everything to bronze */ convert_coins(ch, cost, CURR_BRONZE, CURR_COPPER, 10); if(GET_MONEY(ch, CURR_BRONZE) >= cost) continue; /* * If we made it this far we need to bring down silver */ while(GET_MONEY(ch, CURR_SILVER) > 0) { GET_MONEY(ch, CURR_SILVER) -= 1; GET_MONEY(ch, CURR_BRONZE) += 10; if(GET_MONEY(ch, CURR_BRONZE) >= cost) break; } if(GET_MONEY(ch, CURR_BRONZE) >= cost) continue; /* * If we made it this far we need to bring down gold */ while(GET_MONEY(ch, CURR_GOLD) > 0) { GET_MONEY(ch, CURR_GOLD) -= 1; GET_MONEY(ch, CURR_SILVER) += 10; /* * Now as we do this lets break down the silver */ while(GET_MONEY(ch, CURR_SILVER) > 0) { GET_MONEY(ch, CURR_SILVER) -= 1; GET_MONEY(ch, CURR_BRONZE) += 10; if(GET_MONEY(ch, CURR_BRONZE) >= cost) break; } if(GET_MONEY(ch, CURR_BRONZE) >= cost) break; } } else if(ctype == CURR_COPPER) { if(GET_MONEY(ch, CURR_COPPER) >= cost) { GET_MONEY(ch, ctype) -= cost; cost -= cost; continue; } converted = TRUE; /* * Transfer everything to copper */ while(GET_MONEY(ch, CURR_BRONZE) > 0) { GET_MONEY(ch, CURR_BRONZE) -= 1; GET_MONEY(ch, CURR_COPPER) += 10; if(GET_MONEY(ch, CURR_COPPER) >= cost) break; } if(GET_MONEY(ch, CURR_COPPER) >= cost) continue; /* * If we made it this far we need to bring down silver */ while(GET_MONEY(ch, CURR_SILVER) > 0) { GET_MONEY(ch, CURR_SILVER) -= 1; GET_MONEY(ch, CURR_BRONZE) += 10; while(GET_MONEY(ch, CURR_BRONZE) > 0) { GET_MONEY(ch, CURR_BRONZE) -= 1; GET_MONEY(ch, CURR_COPPER) += 10; if(GET_MONEY(ch, CURR_COPPER) >= cost) break; } if(GET_MONEY(ch, CURR_COPPER) >= cost) break; } if(GET_MONEY(ch, CURR_COPPER) >= cost) continue; /* * If we made it this far we need to bring down gold */ while(GET_MONEY(ch, CURR_GOLD) > 0) { GET_MONEY(ch, CURR_GOLD) -= 1; GET_MONEY(ch, CURR_SILVER) += 10; while(GET_MONEY(ch, CURR_SILVER) > 0) { GET_MONEY(ch, CURR_SILVER) -= 1; GET_MONEY(ch, CURR_BRONZE) += 10; while(GET_MONEY(ch, CURR_BRONZE) > 0) { GET_MONEY(ch, CURR_BRONZE) -= 1; GET_MONEY(ch, CURR_COPPER) += 10; if(GET_MONEY(ch, CURR_COPPER) >= cost) break; } if(GET_MONEY(ch, CURR_COPPER) >= cost) break; } if(GET_MONEY(ch, CURR_COPPER) >= cost) break; } } } return converted; } bool buy_obj(CHAR_DATA *ch, CHAR_DATA *keeper, OBJ_DATA *obj, int noi) { char buf[MSL]; const char *string; int cost; bool converted = FALSE; cost = (get_cost(ch, keeper, obj, TRUE) * noi); if(!can_afford(ch, cost, obj->currtype)) { act(AT_TELL, "$n tells you 'I'm sorry but you can't afford to buy $p.'", keeper, obj, ch, TO_VICT); ch->reply = keeper; return FALSE; } /* * Lets go ahead and handle all the coinage stuff, It doesn't give alot of info but * should at least convert them correctly */ converted = spend_coins(ch, keeper, cost, obj->currtype); if(obj->currtype == CURR_GOLD) string = "gold"; else if(obj->currtype == CURR_SILVER) string = "silver"; else if(obj->currtype == CURR_BRONZE) string = "bronze"; else string = "copper"; if(obj->pIndexData->vnum == 41002 || obj->pIndexData->vnum == 41004) { cost = obj->cost; if(obj->currtype == CURR_GOLD) string = "gold"; else if(obj->currtype == CURR_SILVER) string = "silver"; else if(obj->currtype == CURR_BRONZE) string = "bronze"; else string = "copper"; } if(noi == 1) { act(AT_ACTION, "$n buys $p.", ch, obj, NULL, TO_ROOM); if(converted) snprintf(buf, MSL, "You buy $p. You hand all your money to the shopkeeper."); else snprintf(buf, MSL, "You buy $p for %d %s coin%s.", cost, string, cost > 1 ? "s" : ""); act(AT_ACTION, buf, ch, obj, NULL, TO_CHAR); if(converted) act(AT_ACTION, "The shopkeeper quickly takes what $E needs and hands the rest back.", ch, NULL, keeper, TO_CHAR); } else if(noi > 1) { snprintf(buf, MSL, "$n buys %d of $p.", noi); act(AT_ACTION, buf, ch, obj, NULL, TO_ROOM); if(converted) snprintf(buf, MSL, "You buy %d of $p. You hand all your money to the shopkeeper.", noi); else snprintf(buf, MSL, "You buy %d of $p for %d %s coin%s.", noi, cost, string, cost > 1 ? "s" : ""); act(AT_ACTION, buf, ch, obj, NULL, TO_CHAR); act(AT_ACTION, "The shopkeeper puts them into a bag and hands it to you.", ch, NULL, NULL, TO_CHAR); if(converted) act(AT_ACTION, "The shopkeeper quickly takes what $E needs and hands the rest back.", ch, NULL, keeper, TO_CHAR); } return TRUE; } void do_buy(CHAR_DATA *ch, char *argument) { char arg[MIL]; int maxmoney, cost; CHAR_DATA *keeper; argument = one_argument(argument, arg); if(arg[0] == '\0') { send_to_char("Buy what?\r\n", ch); return; } if(IS_SET(ch->in_room->room_flags, ROOM_PET_SHOP)) { char buf[MSL]; CHAR_DATA *pet; ROOM_INDEX_DATA *pRoomIndexNext; ROOM_INDEX_DATA *in_room; if(IS_NPC(ch)) return; pRoomIndexNext = get_room_index(ch->in_room->vnum + 1); if(!pRoomIndexNext) { bug("Do_buy: bad pet shop at vnum %d.", ch->in_room->vnum); send_to_char("Sorry, you can't buy that here.\r\n", ch); return; } if((keeper = find_keeper(ch)) == NULL) return; in_room = ch->in_room; ch->in_room = pRoomIndexNext; pet = get_char_room(ch, arg); ch->in_room = in_room; if(pet == NULL || !IS_NPC(pet) || !xIS_SET(pet->act, ACT_PET)) { send_to_char("Sorry, you can't buy that here.\r\n", ch); return; } if(xIS_SET(ch->act, PLR_BOUGHT_PET)) { send_to_char("You already bought one pet at this time.\r\n", ch); return; } if(pet->level > 100) pet->level = 100; cost = (pet->level * 100); if(!can_afford(ch, cost, CURR_SILVER)) { send_to_char("You can't afford it.\r\n", ch); return; } if(ch->level < pet->level) { send_to_char("Are you kidding? That thing will take you for walks!\r\n", ch); return; } spend_coins(ch, keeper, cost, CURR_SILVER); GET_MONEY(keeper, CURR_SILVER) += cost; if(GET_MONEY(keeper, CURR_SILVER) >= 50000) { boost_economy(keeper->in_room->area, 25000, CURR_SILVER); GET_MONEY(keeper, CURR_SILVER) -= 25000; act(AT_ACTION, "$n puts some $T into a large safe.", keeper, NULL, curr_types[CURR_SILVER], TO_ROOM); } pet = create_mobile(pet->pIndexData); xSET_BIT(ch->act, PLR_BOUGHT_PET); xSET_BIT(pet->act, ACT_PET); xSET_BIT(pet->affected_by, AFF_CHARM); xSET_BIT(pet->affected_by, AFF_TRUESIGHT); argument = one_argument(argument, arg); if(arg[0] != '\0') { snprintf(buf, MSL, "%s %s", pet->name, arg); if(VLD_STR(pet->name)) STRFREE(pet->name); pet->name = STRALLOC(buf); } snprintf(buf, MSL, "%sA neck tag says 'I belong to %s'.\r\n", pet->description, ch->name); if(VLD_STR(pet->description)) STRFREE(pet->description); pet->description = STRALLOC(buf); char_to_room(pet, ch->in_room); add_follower(pet, ch); send_to_char("Enjoy your pet.\r\n", ch); act(AT_ACTION, "$n bought $N as a pet.", ch, NULL, pet, TO_ROOM); return; } else { /* not a pet shop - volk */ OBJ_DATA *obj; int cost, noi = 1; short primcurr, mnoi = 50; if(!(keeper = find_keeper(ch))) return; maxmoney = keeper->level * 50000; if(is_number(arg)) { noi = atoi(arg); argument = one_argument(argument, arg); if(noi > mnoi) { act(AT_TELL, "$n tells you 'I don't sell that many items at" " once.'", keeper, NULL, ch, TO_VICT); ch->reply = keeper; return; } } obj = get_obj_carry(keeper, arg); cost = (get_cost(ch, keeper, obj, TRUE)); if(obj && (obj->pIndexData->vnum == 41002 || obj->pIndexData->vnum == 41004)) { cost = obj->cost; } /* * The TRUE part of get_cost means playing is BUYING item, not selling - Volk */ if(cost <= 0 || !can_see_obj(ch, obj)) { act(AT_TELL, "$n tells you 'I don't sell that -- try 'list'.'", keeper, NULL, ch, TO_VICT); ch->reply = keeper; return; } if(obj->level > ch->level) { act(AT_TELL, "$n tells you 'That object is too powerful for you.. Hope you know what you're doing.", keeper, NULL, ch, TO_VICT); interpret(keeper, (char *)"shrug"); ch->reply = keeper; // return; } if(!IS_OBJ_STAT(obj, ITEM_INVENTORY) && (noi > 1)) { interpret(keeper, (char *)"laugh"); act(AT_TELL, "$n tells you 'I don't have enough of those in stock" " to sell more than one at a time.'", keeper, NULL, ch, TO_VICT); ch->reply = keeper; return; } if(xIS_SET(obj->extra_flags, ITEM_PROTOTYPE) && get_trust(ch) < LEVEL_IMMORTAL) { act(AT_TELL, "$n tells you 'This is a only a prototype! I can't sell you that...'", keeper, NULL, ch, TO_VICT); ch->reply = keeper; return; } if(ch->carry_number + get_obj_number(obj) > can_carry_n(ch)) { send_to_char("You can't carry that many items.\r\n", ch); return; } if(ch->carry_weight + (get_obj_weight(obj, FALSE) * noi) + (noi > 1 ? 2 : 0) > can_carry_w(ch)) { send_to_char("You can't carry that much weight.\r\n", ch); return; } /* * New here */ if(!buy_obj(ch, keeper, obj, noi)) return; primcurr = obj->currtype; cost *= noi; GET_MONEY(keeper, primcurr) += cost; if(GET_MONEY(keeper, primcurr) >= maxmoney) { boost_economy(keeper->in_room->area, (maxmoney / 2), primcurr); GET_MONEY(keeper, primcurr) -= (maxmoney / 2); act(AT_ACTION, "$n puts some $T into a large safe.", keeper, NULL, curr_types[primcurr], TO_ROOM); } if(IS_OBJ_STAT(obj, ITEM_INVENTORY)) { OBJ_DATA *bag; OBJ_DATA *newobj; newobj = create_object(obj->pIndexData, obj->level); if(noi > 1) { bag = create_object(get_obj_index(OBJ_VNUM_SHOPPING_BAG), 0); /* * perfect size bag ;) */ bag->value[0] = bag->weight + (newobj->weight * noi); newobj->count = noi; obj->pIndexData->count += (noi - 1); numobjsloaded += (noi - 1); obj_to_obj(newobj, bag); obj_to_char(bag, ch); } else obj_to_char(newobj, ch); } else { obj_from_char(obj); obj_to_char(obj, ch); } return; } } void do_list(CHAR_DATA *ch, char *argument) { const char *divleft = "-----------------------------------[ "; const char *divright = " ]-----------------------------------"; int lower, upper; CHAR_DATA *keeper; lower = -2; upper = -1; if(IS_SET(ch->in_room->room_flags, ROOM_PET_SHOP)) { ROOM_INDEX_DATA *pRoomIndexNext; CHAR_DATA *pet; bool found; pRoomIndexNext = get_room_index(ch->in_room->vnum + 1); if(!pRoomIndexNext) { bug("Do_list: bad pet shop at vnum %d.", ch->in_room->vnum); send_to_char("You can't do that here.\r\n", ch); return; } if((keeper = find_keeper(ch)) == NULL) return; found = FALSE; for(pet = pRoomIndexNext->first_person; pet; pet = pet->next_in_room) { if(xIS_SET(pet->act, ACT_PET) && IS_NPC(pet)) { if(!found) { found = TRUE; send_to_char("Mounts and Pets for sale:\r\n", ch); ch_printf(ch, "[Lv Price Currency] Item\r\n"); } if(pet->level > 100) pet->level = 100; ch_printf(ch, "[%2d] %4d silver - %s\r\n", pet->level, 100 * pet->level, pet->short_descr); } } if(!found) send_to_char("Sorry, we're out of pets right now.\r\n", ch); return; } else { char arg[MIL], arg2[MIL], buf[MSL]; OBJ_DATA *obj; int cost = 0; bool found, inventory = FALSE; AFFECT_DATA *paf; argument = one_argument(argument, arg); argument = one_argument(argument, arg2); if((keeper = find_keeper(ch)) == NULL) return; if(!str_cmp(arg, "stat")) { if(!arg2 || arg2[0] == '\0') { send_to_char("Syntax: list stat <object>\r\n", ch); return; } obj = get_obj_carry(keeper, arg2); if(!obj || !can_see_obj(ch, obj)) { act(AT_TELL, "$N tells you 'I dont have any object like that.'", ch, NULL, keeper, TO_CHAR); ch->reply = keeper; return; } if(IS_OBJ_STAT(obj, ITEM_INVENTORY)) { xREMOVE_BIT(obj->extra_flags, ITEM_INVENTORY); inventory = TRUE; } act(AT_CYAN, "$N takes $p down off a display.", ch, obj, keeper, TO_CHAR); act(AT_TELL, "$N tells you 'this item here is used as......'", ch, NULL, keeper, TO_CHAR); snprintf(buf, MSL, "Special properties: %s", !xIS_EMPTY(obj->extra_flags) ? ext_flag_string(&obj->extra_flags, o_flags) : "Nothing"); act(AT_LBLUE, buf, ch, obj, keeper, TO_CHAR); snprintf(buf, MSL, "It is a %s.", item_type_name(obj)); act(AT_LBLUE, buf, ch, obj, keeper, TO_CHAR); snprintf(buf, MSL, "Its weight is %d and level is %d", obj->weight, obj->level); act(AT_LBLUE, buf, ch, obj, keeper, TO_CHAR); snprintf(buf, MSL, "Item's wear locations are %s", flag_string(obj->wear_flags, w_flags)); act(AT_LBLUE, buf, ch, obj, keeper, TO_CHAR); snprintf(buf, MSL, "Size needed to wear: %s\r\n", obj_sizes[obj->size]); act(AT_LBLUE, buf, ch, obj, keeper, TO_CHAR); if(inventory) xSET_BIT(obj->extra_flags, ITEM_INVENTORY); switch (obj->item_type) { case ITEM_CONTAINER: case ITEM_KEYRING: case ITEM_QUIVER: snprintf(buf, MSL, "%s appears to %s.", capitalize(obj->short_descr), obj->value[0] < 76 ? "have a small capacity" : obj->value[0] < 150 ? "have a small to medium capacity" : obj->value[0] < 300 ? "have a medium capacity" : obj->value[0] < 500 ? "have a medium to large capacity" : obj->value[0] < 751 ? "have a large capacity" : "have a giant capacity"); act(AT_LBLUE, buf, ch, obj, keeper, TO_CHAR); break; case ITEM_PILL: case ITEM_SCROLL: case ITEM_POTION: snprintf(buf, MSL, "Level %d spells of: ", obj->value[0]); if(obj->value[1] >= 0 && obj->value[1] < top_sn) { mudstrlcat(buf, "'", MSL); mudstrlcat(buf, skill_table[obj->value[1]]->name, MSL); mudstrlcat(buf, "'", MSL); } if(obj->value[2] >= 0 && obj->value[2] < top_sn) { mudstrlcat(buf, "'", MSL); mudstrlcat(buf, skill_table[obj->value[2]]->name, MSL); mudstrlcat(buf, "'", MSL); } if(obj->value[3] >= 0 && obj->value[3] < top_sn) { mudstrlcat(buf, "'", MSL); mudstrlcat(buf, skill_table[obj->value[3]]->name, MSL); mudstrlcat(buf, "'", MSL); } act(AT_LBLUE, buf, ch, obj, keeper, TO_CHAR); break; case ITEM_SALVE: snprintf(buf, MSL, "Has %d(%d) applications of level %d", obj->value[1], obj->value[2], obj->value[0]); if(obj->value[4] >= 0 && obj->value[4] < top_sn) { mudstrlcat(buf, " '", MSL); mudstrlcat(buf, skill_table[obj->value[4]]->name, MSL); mudstrlcat(buf, "'", MSL); } act(AT_LBLUE, buf, ch, obj, keeper, TO_CHAR); break; case ITEM_WAND: case ITEM_STAFF: snprintf(buf, MSL, "Has %d(%d) charges of level %d", obj->value[1], obj->value[2], obj->value[0]); if(obj->value[3] >= 0 && obj->value[3] < top_sn) { mudstrlcat(buf, " '", MSL); mudstrlcat(buf, skill_table[obj->value[3]]->name, MSL); mudstrlcat(buf, "'", MSL); } act(AT_LBLUE, buf, ch, obj, keeper, TO_CHAR); break; case ITEM_MISSILE_WEAPON: case ITEM_WEAPON: snprintf(buf, MSL, "Damage is %d to %d (average %d)%s", obj->value[1], obj->value[2], (obj->value[1] + obj->value[2]) / 2, IS_OBJ_STAT(obj, ITEM_POISONED) ? ", and is poisonous." : "."); act(AT_LBLUE, buf, ch, obj, keeper, TO_CHAR); snprintf(buf, MSL, "Skill needed: %s", weapon_skills[obj->value[4]]); act(AT_LBLUE, buf, ch, obj, keeper, TO_CHAR); snprintf(buf, MSL, "Damage type: %s", capitalize(attack_table[obj->value[3]])); act(AT_LBLUE, buf, ch, obj, keeper, TO_CHAR); break; case ITEM_ARMOR: snprintf(buf, MSL, "Armor class is %d.", obj->value[0]); act(AT_LBLUE, buf, ch, obj, keeper, TO_CHAR); break; } bool afs = FALSE; for(paf = obj->pIndexData->first_affect; paf; paf = paf->next) { showaffect(ch, paf); afs = TRUE; } for(paf = obj->first_affect; paf; paf = paf->next) { afs = TRUE; showaffect(ch, paf); } if(afs) { mudstrlcpy(buf, "'", MSL); act(AT_LBLUE, buf, ch, obj, keeper, TO_CHAR); } ch->reply = keeper; return; } found = FALSE; for(obj = keeper->first_carrying; obj; obj = obj->next_content) { if(obj->wear_loc == WEAR_NONE && can_see_obj(ch, obj) && (cost = get_cost(ch, keeper, obj, TRUE)) || obj->pIndexData->vnum == 41002 || obj->pIndexData->vnum == 41004) { if(!found) { found = TRUE; send_to_pager("&C[&WLv Price Currency Name of Object Size&C]\r\n", ch); } if(obj->pIndexData->vnum == 41002 || obj->pIndexData->vnum == 41004) { cost = obj->cost; } if(obj->level <= upper) { pager_printf(ch, "%-3s%-11d%-40s\r\n", divleft, upper, divright); upper = -1; } if(obj->level < lower) { pager_printf(ch, "%-3s%-11d%-40s\r\n", divleft, lower, divright); lower = -1; } pager_printf(ch, "&C[%2d %7d %-11s %-40s %10s]\r\n", obj->level, cost, curr_types[obj->currtype], capitalize(obj->short_descr), obj_sizes[obj->size]); } } if(lower >= 0) { pager_printf(ch, "%-3s%-7d%-40s\r\n", divleft, lower, divright); } if(!found) { if(arg[0] == '\0') send_to_char("You can't buy anything here.\r\n", ch); else send_to_char("You can't buy that here.\r\n", ch); return; } send_to_char("\r\n&CType &WLIST STAT <&Cobject&W>&C - To find out more details.\r\n", ch); return; } } void do_sell(CHAR_DATA *ch, char *argument) { char arg[MIL]; CHAR_DATA *keeper; OBJ_DATA *obj; int cost = 0, sfor = 0; short primcurr; argument = one_argument(argument, arg); if(!arg || arg[0] == '\0') { send_to_char("Sell what?\r\n", ch); return; } if(argument && argument[0] != '\0' && is_number(argument)) { sfor = atoi(argument); if(sfor < 0) sfor = 0; } if((keeper = find_keeper(ch)) == NULL) return; if((obj = get_obj_carry(ch, arg)) == NULL) { act(AT_TELL, "$n tells you 'You don't have that item.'", keeper, NULL, ch, TO_VICT); ch->reply = keeper; return; } if(!can_see_obj(keeper, obj)) { send_to_char("What are you trying to sell me? I don't buy thin air!\r\n", ch); return; } if(!can_drop_obj(ch, obj)) { send_to_char("You can't let go of it!\r\n", ch); return; } if(obj->timer > 0) { act(AT_TELL, "$n tells you, '$p is depreciating in value too quickly...'", keeper, obj, ch, TO_VICT); return; } /* * Shopkeeper won't buy it or it is worthless */ if(!will_buy(keeper, obj) || obj->pIndexData->cost <= 0) { /* * We will allow one marked as crafthshop to buy object 41002 and 41004 */ if(!xIS_SET(keeper->act, ACT_CRAFTSHOP) || (obj->pIndexData->vnum != 41002 && obj->pIndexData->vnum != 41004)) { act(AT_ACTION, "$n looks uninterested in $p.", keeper, obj, ch, TO_VICT); return; } } primcurr = get_primary_curr(keeper->in_room); cost = (get_cost(ch, keeper, obj, FALSE)); if(sfor != 0 && sfor < cost) cost = sfor; if(GET_MONEY(keeper, CURR_GOLD) < 500 || GET_MONEY(keeper, CURR_SILVER) < 5000 || GET_MONEY(keeper, CURR_BRONZE) < 50000 || GET_MONEY(keeper, CURR_COPPER) < 50000) { GET_MONEY(keeper, CURR_GOLD) = 500; GET_MONEY(keeper, CURR_SILVER) = 5000; GET_MONEY(keeper, CURR_BRONZE) = 50000; GET_MONEY(keeper, CURR_COPPER) = 50000; } if(GET_VALUE(obj, type) == CURR_GOLD) { if(cost > 5000) { act(AT_CYAN, "$n's eyes stare at $p.", keeper, obj, ch, TO_VICT); act_printf(AT_TELL, keeper, obj, ch, TO_VICT, "$n tells you 'I don't carry %d gold on me.'", cost); ch->reply = keeper; return; } if(GET_MONEY(keeper, CURR_GOLD) < cost) { act(AT_TELL, "$n tells you 'I don't have enough gold to buy $p.'", keeper, obj, ch, TO_VICT); act_printf(AT_TELL, keeper, obj, ch, TO_VICT, "$n tells you 'I only have %d gold try coming back later.'", GET_MONEY(keeper, CURR_GOLD)); ch->reply = keeper; return; } } if(GET_VALUE(obj, type) == CURR_SILVER) { if(GET_MONEY(keeper, CURR_SILVER) < cost) { act(AT_TELL, "$n tells you 'I don't have enough silver to buy $p.'", keeper, obj, ch, TO_VICT); act_printf(AT_TELL, keeper, obj, ch, TO_VICT, "$n tells you 'The most I can give you for it is %d silver.'", GET_MONEY(keeper, CURR_SILVER)); ch->reply = keeper; return; } } if(GET_VALUE(obj, type) == CURR_BRONZE) { if(GET_MONEY(keeper, CURR_BRONZE) < cost) { act(AT_TELL, "$n tells you 'I don't have enough bronze to buy $p.'", keeper, obj, ch, TO_VICT); act_printf(AT_TELL, keeper, obj, ch, TO_VICT, "$n tells you 'The most I can give you for it is %d bronze.'", GET_MONEY(keeper, CURR_BRONZE)); ch->reply = keeper; return; } } if(GET_VALUE(obj, type) == CURR_COPPER) { if(GET_MONEY(keeper, CURR_COPPER) < cost) { act(AT_TELL, "$n tells you 'I don't have enough copper to buy $p.'", keeper, obj, ch, TO_VICT); act_printf(AT_TELL, keeper, obj, ch, TO_VICT, "$n tells you 'The most I can give you for it is %d copper.'", GET_MONEY(keeper, CURR_COPPER)); ch->reply = keeper; return; } } if(cost == 0) { cost = 1; } if(GET_VALUE(obj, type) == CURR_SILVER) { act(AT_ACTION, "$n sells $p.", ch, obj, NULL, TO_ROOM); snprintf(arg, MIL, "You sell $p for %d %s coin%s.", cost, curr_types[CURR_SILVER], cost > 1 ? "s" : ""); act(AT_ACTION, arg, ch, obj, NULL, TO_CHAR); GET_MONEY(ch, CURR_SILVER) += cost; } if(GET_VALUE(obj, type) == CURR_GOLD) { act(AT_ACTION, "$n sells $p.", ch, obj, NULL, TO_ROOM); snprintf(arg, MIL, "You sell $p for %d %s coin%s.", cost, curr_types[CURR_GOLD], cost > 1 ? "s" : ""); act(AT_ACTION, arg, ch, obj, NULL, TO_CHAR); GET_MONEY(ch, CURR_GOLD) += cost; } if(GET_VALUE(obj, type) == CURR_BRONZE) { act(AT_ACTION, "$n sells $p.", ch, obj, NULL, TO_ROOM); snprintf(arg, MIL, "You sell $p for %d %s coin%s.", cost, curr_types[CURR_BRONZE], cost > 1 ? "s" : ""); act(AT_ACTION, arg, ch, obj, NULL, TO_CHAR); GET_MONEY(ch, CURR_BRONZE) += cost; } if(GET_VALUE(obj, type) == CURR_COPPER) { act(AT_ACTION, "$n sells $p.", ch, obj, NULL, TO_ROOM); snprintf(arg, MIL, "You sell $p for %d %s coin%s.", cost, curr_types[CURR_COPPER], cost > 1 ? "s" : ""); act(AT_ACTION, arg, ch, obj, NULL, TO_CHAR); GET_MONEY(ch, CURR_COPPER) += cost; } if(obj->item_type == ITEM_TRASH) extract_obj(obj); else { obj_from_char(obj); obj_to_char(obj, keeper); } } void do_value(CHAR_DATA *ch, char *argument) { char buf[MSL]; CHAR_DATA *keeper; OBJ_DATA *obj; int cost; short primcurr; if(argument[0] == '\0') { send_to_char("Value what?\r\n", ch); return; } if((keeper = find_keeper(ch)) == NULL) return; if((obj = get_obj_carry(ch, argument)) == NULL) { act(AT_TELL, "$n tells you 'You don't have that item.'", keeper, NULL, ch, TO_VICT); ch->reply = keeper; return; } if(!can_drop_obj(ch, obj)) { send_to_char("You can't let go of it!\r\n", ch); return; } if(!will_buy(keeper, obj) || (cost = get_cost(ch, keeper, obj, FALSE)) <= 0) { act(AT_ACTION, "$n looks uninterested in $p.", keeper, obj, ch, TO_VICT); return; } primcurr = get_primary_curr(keeper->in_room); if(GET_VALUE(obj, type) == CURR_GOLD) { snprintf(buf, MSL, "$n tells you 'I'll give you %d %s coins for $p.'", cost, curr_types[primcurr]); act(AT_TELL, buf, keeper, obj, ch, TO_VICT); ch->reply = keeper; } else if(GET_VALUE(obj, type) == CURR_SILVER) { snprintf(buf, MSL, "$n tells you 'I'll give you %d silver coins for $p.'", cost); act(AT_TELL, buf, keeper, obj, ch, TO_VICT); ch->reply = keeper; } else if(GET_VALUE(obj, type) == CURR_BRONZE) { snprintf(buf, MSL, "$n tells you 'I'll give you %d bronze coins for $p.'", cost); act(AT_TELL, buf, keeper, obj, ch, TO_VICT); ch->reply = keeper; } else if(GET_VALUE(obj, type) == CURR_COPPER) { snprintf(buf, MSL, "$n tells you 'I'll give you %d copper coins for $p.'", cost); act(AT_TELL, buf, keeper, obj, ch, TO_VICT); ch->reply = keeper; } else { act(AT_ACTION, "$n looks uninterested in $p.", keeper, obj, ch, TO_VICT); return; } } /* * Repair a single object. Used when handling "repair all" - Gorog */ void repair_one_obj(CHAR_DATA *ch, CHAR_DATA *keeper, OBJ_DATA *obj, char *arg, int maxmoney, char *fixstr, char *fixstr2) { char buf[MSL]; int cost; short primcurr; primcurr = get_primary_curr(keeper->in_room); if(!can_drop_obj(ch, obj)) ch_printf(ch, "You can't let go of %s.\r\n", obj->name); else if((cost = get_repaircost(ch, keeper, obj)) < 0) { if(cost != -2) act(AT_TELL, "$n tells you, 'Sorry, I can't do anything with $p.'", keeper, obj, ch, TO_VICT); else act(AT_TELL, "$n tells you, '$p looks fine to me!'", keeper, obj, ch, TO_VICT); } else if((cost = str_cmp("all", arg) ? cost : 11 * cost / 10) && !can_afford(ch, cost, CURR_BRONZE)) { snprintf(buf, MSL, "$N tells you, 'It will cost %d coin%s of %s to %s %s...'", cost, cost == 1 ? "" : "s", curr_types[CURR_BRONZE], fixstr, obj->name); act(AT_TELL, buf, ch, NULL, keeper, TO_CHAR); act(AT_TELL, "$N tells you, 'Which I see you can't afford.'", ch, NULL, keeper, TO_CHAR); } else { snprintf(buf, MSL, "$n gives $p to $N, who quickly %s it.", fixstr2); act(AT_ACTION, buf, ch, obj, keeper, TO_ROOM); snprintf(buf, MSL, "$N charges you %d %s coin%s to %s $p.", cost, curr_types[CURR_BRONZE], cost == 1 ? "" : "s", fixstr); act(AT_ACTION, buf, ch, obj, keeper, TO_CHAR); spend_coins(ch, keeper, cost, CURR_BRONZE); GET_MONEY(keeper, CURR_BRONZE) += cost; if(GET_MONEY(keeper, CURR_BRONZE) < 0) GET_MONEY(keeper, CURR_BRONZE) = 0; else if(GET_MONEY(keeper, CURR_BRONZE) >= maxmoney) { boost_economy(keeper->in_room->area, (maxmoney / 2), CURR_BRONZE); GET_MONEY(keeper, CURR_BRONZE) -= (maxmoney / 2); act(AT_ACTION, "$n puts some $T into a large safe.", keeper, NULL, curr_types[CURR_BRONZE], TO_ROOM); } switch (obj->item_type) { default: send_to_char("For some reason, you think you got ripped off...\r\n", ch); break; case ITEM_ARMOR: obj->value[0] = obj->value[1]; break; case ITEM_WEAPON: obj->value[0] = INIT_WEAPON_CONDITION; break; case ITEM_WAND: case ITEM_STAFF: obj->value[2] = obj->value[1]; break; } oprog_repair_trigger(ch, obj); } } void do_repair(CHAR_DATA *ch, char *argument) { CHAR_DATA *keeper; OBJ_DATA *obj; const char *fixstr; const char *fixstr2; int maxmoney = 0; if(argument[0] == '\0') { send_to_char("Repair what?\r\n", ch); return; } if(!(keeper = find_fixer(ch))) return; maxmoney = keeper->level * 100000; switch (keeper->pIndexData->rShop->shop_type) { default: case SHOP_FIX: fixstr = "repair"; fixstr2 = "repairs"; break; case SHOP_RECHARGE: fixstr = "recharge"; fixstr2 = "recharges"; break; } if(!str_cmp(argument, "all")) { for(obj = ch->first_carrying; obj; obj = obj->next_content) { if(obj->wear_loc == WEAR_NONE && can_see_obj(ch, obj) && can_see_obj(keeper, obj) && (obj->item_type == ITEM_ARMOR || obj->item_type == ITEM_WEAPON || obj->item_type == ITEM_WAND || obj->item_type == ITEM_STAFF)) repair_one_obj(ch, keeper, obj, argument, maxmoney, (char *)fixstr, (char *)fixstr2); } return; } if(!(obj = get_obj_carry(ch, argument))) { act(AT_TELL, "$n tells you 'You don't have that item.'", keeper, NULL, ch, TO_VICT); ch->reply = keeper; return; } repair_one_obj(ch, keeper, obj, argument, maxmoney, (char *)fixstr, (char *)fixstr2); } void appraise_all(CHAR_DATA *ch, CHAR_DATA *keeper, char *fixstr) { OBJ_DATA *obj; char buf[MSL]; int cost = 0, total = 0; short primcurr; primcurr = get_primary_curr(keeper->in_room); for(obj = ch->first_carrying; obj != NULL; obj = obj->next_content) { if(obj->wear_loc == WEAR_NONE && can_see_obj(ch, obj) && (obj->item_type == ITEM_ARMOR || obj->item_type == ITEM_WEAPON || obj->item_type == ITEM_WAND || obj->item_type == ITEM_STAFF)) { if(!can_drop_obj(ch, obj)) ch_printf(ch, "You can't let go of %s.\r\n", obj->name); else if((cost = get_repaircost(ch, keeper, obj)) < 0) { if(cost != -2) act(AT_TELL, "$n tells you, 'Sorry, I can't do anything with $p.'", keeper, obj, ch, TO_VICT); else act(AT_TELL, "$n tells you, '$p looks fine to me!'", keeper, obj, ch, TO_VICT); } else { snprintf(buf, MSL, "$N tells you, 'It will cost %d piece%s of %s to %s %s'", cost, cost == 1 ? "" : "s", curr_types[primcurr], fixstr, obj->name); act(AT_TELL, buf, ch, NULL, keeper, TO_CHAR); total += cost; } } } if(total > 0) { send_to_char("\r\n", ch); snprintf(buf, MSL, "$N tells you, 'It will cost %d piece%s of %s in total.'", total, cost == 1 ? "" : "s", curr_types[primcurr]); act(AT_TELL, buf, ch, NULL, keeper, TO_CHAR); act(AT_TELL, "$N tells you, 'Remember there is a 10% surcharge for repair all.'", ch, NULL, keeper, TO_CHAR); } } void do_appraise(CHAR_DATA *ch, char *argument) { char buf[MSL]; char arg[MIL]; CHAR_DATA *keeper; OBJ_DATA *obj; int cost; const char *fixstr; one_argument(argument, arg); if(arg[0] == '\0') { send_to_char("Appraise what?\r\n", ch); return; } if((keeper = find_fixer(ch)) == NULL) return; switch (keeper->pIndexData->rShop->shop_type) { default: case SHOP_FIX: fixstr = "repair"; break; case SHOP_RECHARGE: fixstr = "recharge"; break; } if(!str_cmp(arg, "all")) { appraise_all(ch, keeper, (char *)fixstr); return; } if((obj = get_obj_carry(ch, arg)) == NULL) { act(AT_TELL, "$n tells you 'You don't have that item.'", keeper, NULL, ch, TO_VICT); ch->reply = keeper; return; } if(!can_drop_obj(ch, obj)) { send_to_char("You can't let go of it.\r\n", ch); return; } if((cost = get_repaircost(ch, keeper, obj)) < 0) { if(cost != -2) act(AT_TELL, "$n tells you, 'Sorry, I can't do anything with $p.'", keeper, obj, ch, TO_VICT); else act(AT_TELL, "$n tells you, '$p looks fine to me!'", keeper, obj, ch, TO_VICT); return; } snprintf(buf, MSL, "$N tells you, 'It will cost %d piece%s of bronze to %s that...'", cost, cost == 1 ? "" : "s", fixstr); act(AT_TELL, buf, ch, NULL, keeper, TO_CHAR); if(cost > GET_MONEY(ch, CURR_BRONZE)) act(AT_TELL, "$N tells you, 'Which I see you can't afford.'", ch, NULL, keeper, TO_CHAR); return; } /* ------------------ Shop Building and Editing Section ----------------- */ void do_makeshop(CHAR_DATA *ch, char *argument) { SHOP_DATA *shop; int vnum; MOB_INDEX_DATA *mob; if(!argument || argument[0] == '\0') { send_to_char("Usage: makeshop <mobvnum>\r\n", ch); return; } vnum = atoi(argument); if((mob = get_mob_index(vnum)) == NULL) { send_to_char("Mobile not found.\r\n", ch); return; } if(!can_medit(ch, mob)) return; if(mob->pShop) { send_to_char("This mobile already has a shop.\r\n", ch); return; } CREATE(shop, SHOP_DATA, 1); LINK(shop, first_shop, last_shop, next, prev); shop->keeper = vnum; shop->profit_buy = 120; shop->profit_sell = 90; shop->open_hour = 0; shop->close_hour = 23; mob->pShop = shop; send_to_char("Done.\r\n", ch); return; } void do_shopset(CHAR_DATA *ch, char *argument) { SHOP_DATA *shop; MOB_INDEX_DATA *mob, *mob2; char arg1[MIL]; char arg2[MIL]; int vnum, value; argument = one_argument(argument, arg1); argument = one_argument(argument, arg2); if(arg1[0] == '\0' || arg2[0] == '\0') { send_to_char("Usage: shopset <mob vnum> <field> value\r\n", ch); send_to_char("\r\nField being one of:\r\n", ch); send_to_char(" buy0 buy1 buy2 buy3 buy4 buy sell open close keeper\r\n", ch); return; } vnum = atoi(arg1); if((mob = get_mob_index(vnum)) == NULL) { send_to_char("Mobile not found.\r\n", ch); return; } if(!can_medit(ch, mob)) return; if(!mob->pShop) { send_to_char("This mobile doesn't keep a shop.\r\n", ch); return; } shop = mob->pShop; value = atoi(argument); if(!str_cmp(arg2, "buy0")) { if(!is_number(argument)) value = get_otype(argument); if(value < 0 || value > MAX_ITEM_TYPE) { send_to_char("Invalid item type!\r\n", ch); return; } shop->buy_type[0] = value; send_to_char("Done.\r\n", ch); return; } if(!str_cmp(arg2, "buy1")) { if(!is_number(argument)) value = get_otype(argument); if(value < 0 || value > MAX_ITEM_TYPE) { send_to_char("Invalid item type!\r\n", ch); return; } shop->buy_type[1] = value; send_to_char("Done.\r\n", ch); return; } if(!str_cmp(arg2, "buy2")) { if(!is_number(argument)) value = get_otype(argument); if(value < 0 || value > MAX_ITEM_TYPE) { send_to_char("Invalid item type!\r\n", ch); return; } shop->buy_type[2] = value; send_to_char("Done.\r\n", ch); return; } if(!str_cmp(arg2, "buy3")) { if(!is_number(argument)) value = get_otype(argument); if(value < 0 || value > MAX_ITEM_TYPE) { send_to_char("Invalid item type!\r\n", ch); return; } shop->buy_type[3] = value; send_to_char("Done.\r\n", ch); return; } if(!str_cmp(arg2, "buy4")) { if(!is_number(argument)) value = get_otype(argument); if(value < 0 || value > MAX_ITEM_TYPE) { send_to_char("Invalid item type!\r\n", ch); return; } shop->buy_type[4] = value; send_to_char("Done.\r\n", ch); return; } if(!str_cmp(arg2, "buy")) { if(value <= (shop->profit_sell + 5) || value > 1000) { send_to_char("Out of range.\r\n", ch); return; } shop->profit_buy = value; send_to_char("Done.\r\n", ch); return; } if(!str_cmp(arg2, "sell")) { if(value < 0 || value >= (shop->profit_buy - 5)) { send_to_char("Out of range.\r\n", ch); return; } shop->profit_sell = value; send_to_char("Done.\r\n", ch); return; } if(!str_cmp(arg2, "open")) { if(value < 0 || value > 23) { send_to_char("Out of range.\r\n", ch); return; } shop->open_hour = value; send_to_char("Done.\r\n", ch); return; } if(!str_cmp(arg2, "close")) { if(value < 0 || value > 23) { send_to_char("Out of range.\r\n", ch); return; } shop->close_hour = value; send_to_char("Done.\r\n", ch); return; } if(!str_cmp(arg2, "keeper")) { if((mob2 = get_mob_index(vnum)) == NULL) { send_to_char("Mobile not found.\r\n", ch); return; } if(!can_medit(ch, mob)) return; if(mob2->pShop) { send_to_char("That mobile already has a shop.\r\n", ch); return; } mob->pShop = NULL; mob2->pShop = shop; shop->keeper = value; send_to_char("Done.\r\n", ch); return; } do_shopset(ch, (char *)""); return; } void do_shopstat(CHAR_DATA *ch, char *argument) { SHOP_DATA *shop; MOB_INDEX_DATA *mob; int vnum; if(argument[0] == '\0') { send_to_char("Usage: shopstat <keeper vnum>\r\n", ch); return; } vnum = atoi(argument); if((mob = get_mob_index(vnum)) == NULL) { send_to_char("Mobile not found.\r\n", ch); return; } if(!mob->pShop) { send_to_char("This mobile doesn't keep a shop.\r\n", ch); return; } shop = mob->pShop; ch_printf(ch, "Keeper: %d %s\r\n", shop->keeper, mob->short_descr); ch_printf(ch, "buy0 [%s] buy1 [%s] buy2 [%s] buy3 [%s] buy4 [%s]\r\n", o_types[shop->buy_type[0]], o_types[shop->buy_type[1]], o_types[shop->buy_type[2]], o_types[shop->buy_type[3]], o_types[shop->buy_type[4]]); ch_printf(ch, "Profit: buy %3d%% sell %3d%%\r\n", shop->profit_buy, shop->profit_sell); ch_printf(ch, "Hours: open %2d close %2d\r\n", shop->open_hour, shop->close_hour); return; } void do_shops(CHAR_DATA *ch, char *argument) { SHOP_DATA *shop; if(!first_shop) { send_to_char("There are no shops.\r\n", ch); return; } set_pager_color(AT_NOTE, ch); for(shop = first_shop; shop; shop = shop->next) pager_printf(ch, "Keeper: %5d Buy: %3d Sell: %3d Open: %2d Close: %2d Buy: %2d %2d %2d %2d %2d\r\n", shop->keeper, shop->profit_buy, shop->profit_sell, shop->open_hour, shop->close_hour, shop->buy_type[0], shop->buy_type[1], shop->buy_type[2], shop->buy_type[3], shop->buy_type[4]); return; } /* -------------- Repair Shop Building and Editing Section -------------- */ void do_makerepair(CHAR_DATA *ch, char *argument) { REPAIR_DATA *repair; int vnum; MOB_INDEX_DATA *mob; if(!argument || argument[0] == '\0') { send_to_char("Usage: makerepair <mobvnum>\r\n", ch); return; } vnum = atoi(argument); if((mob = get_mob_index(vnum)) == NULL) { send_to_char("Mobile not found.\r\n", ch); return; } if(!can_medit(ch, mob)) return; if(mob->rShop) { send_to_char("This mobile already has a repair shop.\r\n", ch); return; } CREATE(repair, REPAIR_DATA, 1); LINK(repair, first_repair, last_repair, next, prev); repair->keeper = vnum; repair->profit_fix = 100; repair->shop_type = SHOP_FIX; repair->open_hour = 0; repair->close_hour = 23; mob->rShop = repair; send_to_char("Done.\r\n", ch); return; } void do_repairset(CHAR_DATA *ch, char *argument) { REPAIR_DATA *repair; MOB_INDEX_DATA *mob, *mob2; char arg1[MIL]; char arg2[MIL]; int vnum, value; argument = one_argument(argument, arg1); argument = one_argument(argument, arg2); if(arg1[0] == '\0' || arg2[0] == '\0') { send_to_char("Usage: repairset <mob vnum> <field> value\r\n", ch); send_to_char("\r\nField being one of:\r\n", ch); send_to_char(" fix0 fix1 fix2 profit type open close keeper\r\n", ch); return; } vnum = atoi(arg1); if((mob = get_mob_index(vnum)) == NULL) { send_to_char("Mobile not found.\r\n", ch); return; } if(!can_medit(ch, mob)) return; if(!mob->rShop) { send_to_char("This mobile doesn't keep a repair shop.\r\n", ch); return; } repair = mob->rShop; value = atoi(argument); if(!str_cmp(arg2, "fix0")) { if(!is_number(argument)) value = get_otype(argument); if(value < 0 || value > MAX_ITEM_TYPE) { send_to_char("Invalid item type!\r\n", ch); return; } repair->fix_type[0] = value; send_to_char("Done.\r\n", ch); return; } if(!str_cmp(arg2, "fix1")) { if(!is_number(argument)) value = get_otype(argument); if(value < 0 || value > MAX_ITEM_TYPE) { send_to_char("Invalid item type!\r\n", ch); return; } repair->fix_type[1] = value; send_to_char("Done.\r\n", ch); return; } if(!str_cmp(arg2, "fix2")) { if(!is_number(argument)) value = get_otype(argument); if(value < 0 || value > MAX_ITEM_TYPE) { send_to_char("Invalid item type!\r\n", ch); return; } repair->fix_type[2] = value; send_to_char("Done.\r\n", ch); return; } if(!str_cmp(arg2, "profit")) { if(value < 1 || value > 1000) { send_to_char("Out of range.\r\n", ch); return; } repair->profit_fix = value; send_to_char("Done.\r\n", ch); return; } if(!str_cmp(arg2, "type")) { if(value < 1 || value > 2) { send_to_char("Out of range.\r\n", ch); return; } repair->shop_type = value; send_to_char("Done.\r\n", ch); return; } if(!str_cmp(arg2, "open")) { if(value < 0 || value > 23) { send_to_char("Out of range.\r\n", ch); return; } repair->open_hour = value; send_to_char("Done.\r\n", ch); return; } if(!str_cmp(arg2, "close")) { if(value < 0 || value > 23) { send_to_char("Out of range.\r\n", ch); return; } repair->close_hour = value; send_to_char("Done.\r\n", ch); return; } if(!str_cmp(arg2, "keeper")) { if((mob2 = get_mob_index(vnum)) == NULL) { send_to_char("Mobile not found.\r\n", ch); return; } if(!can_medit(ch, mob)) return; if(mob2->rShop) { send_to_char("That mobile already has a repair shop.\r\n", ch); return; } mob->rShop = NULL; mob2->rShop = repair; repair->keeper = value; send_to_char("Done.\r\n", ch); return; } do_repairset(ch, (char *)""); return; } void do_repairstat(CHAR_DATA *ch, char *argument) { REPAIR_DATA *repair; MOB_INDEX_DATA *mob; int vnum; if(argument[0] == '\0') { send_to_char("Usage: repairstat <keeper vnum>\r\n", ch); return; } vnum = atoi(argument); if((mob = get_mob_index(vnum)) == NULL) { send_to_char("Mobile not found.\r\n", ch); return; } if(!mob->rShop) { send_to_char("This mobile doesn't keep a repair shop.\r\n", ch); return; } repair = mob->rShop; ch_printf(ch, "Keeper: %d %s\r\n", repair->keeper, mob->short_descr); ch_printf(ch, "fix0 [%s] fix1 [%s] fix2 [%s]\r\n", o_types[repair->fix_type[0]], o_types[repair->fix_type[1]], o_types[repair->fix_type[2]]); ch_printf(ch, "Profit: %3d%% Type: %d\r\n", repair->profit_fix, repair->shop_type); ch_printf(ch, "Hours: open %2d close %2d\r\n", repair->open_hour, repair->close_hour); return; } void do_repairshops(CHAR_DATA *ch, char *argument) { REPAIR_DATA *repair; if(!first_repair) { send_to_char("There are no repair shops.\r\n", ch); return; } set_char_color(AT_NOTE, ch); for(repair = first_repair; repair; repair = repair->next) ch_printf(ch, "Keeper: %5d Profit: %3d Type: %d Open: %2d Close: %2d Fix: %2d %2d %2d\r\n", repair->keeper, repair->profit_fix, repair->shop_type, repair->open_hour, repair->close_hour, repair->fix_type[0], repair->fix_type[1], repair->fix_type[2]); return; }