mirror of
https://github.com/tbamud/tbamud.git
synced 2026-03-21 11:46:33 +01:00
Add 'stat shop' command for immortals
This commit is contained in:
parent
f8d9d31c1c
commit
57579be97b
2 changed files with 257 additions and 3 deletions
|
|
@ -9,7 +9,7 @@ Due to the sensitive nature of topics found in this setting, all characters and
|
|||
players are 18+. The game world is derived from several inspirational sources,
|
||||
most notably the former Armageddon MUD.
|
||||
|
||||
Roleplay is highly encouraged, but not enforced.
|
||||
Roleplay is **highly** encouraged.
|
||||
|
||||
Changes from stock tbaMUD 2025 to Cataclysm MUD v1.0.0-alpha:
|
||||
|
||||
|
|
@ -54,10 +54,10 @@ Changes in v1.1.0-alpha:
|
|||
* Renamed move to stamina in code to reflect how much energy is used for certain actions
|
||||
* Species have base hit/mana/stamina now, plus their class modifier rolls
|
||||
* Prioritized stats during character generation
|
||||
* Ability to change ldesc of PC/NPC's in some situations
|
||||
* Ability to change ldesc of PC/NPC's
|
||||
* Ability to look in certain directions to see what is 1-3 rooms away
|
||||
* PC's and NPC's can now have an age set between 18-65
|
||||
* "audit armor" command for immortals (formerly "acaudit")
|
||||
* "audit armor" and "audit melee" commands for immortals (formerly "acaudit") to check non-compliant items
|
||||
* Minor score output change to only show quest status while on a quest, PC/NPC name, sdesc, and current ldesc
|
||||
* Added ability to reroll initial stats if they are not to player's liking, and undo reroll if needed
|
||||
* Removed alignment from game - no more GOOD/EVIL flags or restrictions on shops
|
||||
|
|
@ -67,6 +67,7 @@ Changes in v1.1.0-alpha:
|
|||
Features to be implemented in the next few releases:
|
||||
|
||||
* Height and weight normalized to species
|
||||
* Stables allow for purchasing of mounts
|
||||
* Stables will take mounts and provide tickets to get them out
|
||||
* Updated door code so that it can be closed/locked/saved with rsave code
|
||||
* SECTOR/ROOM type changes to make terrain movement easier or more difficult
|
||||
|
|
|
|||
253
src/act.wizard.c
253
src/act.wizard.c
|
|
@ -30,6 +30,7 @@
|
|||
#include "genmob.h"
|
||||
#include "genolc.h"
|
||||
#include "genobj.h"
|
||||
#include "genshp.h"
|
||||
#include "fight.h"
|
||||
#include "house.h"
|
||||
#include "modify.h"
|
||||
|
|
@ -44,6 +45,7 @@ static void perform_immort_invis(struct char_data *ch, int level);
|
|||
static void do_stat_room(struct char_data *ch, struct room_data *rm);
|
||||
static void do_stat_object(struct char_data *ch, struct obj_data *j);
|
||||
static void do_stat_character(struct char_data *ch, struct char_data *k);
|
||||
static void do_stat_shop(struct char_data *ch, shop_rnum shop_nr);
|
||||
static void stop_snooping(struct char_data *ch);
|
||||
static struct obj_data *find_inventory_coin(struct char_data *ch);
|
||||
static void remove_other_coins_from_list(struct obj_data *list, struct obj_data *keep);
|
||||
|
|
@ -67,7 +69,12 @@ static const char *stat_border_line(void);
|
|||
static void stat_table_border(struct char_data *ch);
|
||||
static void stat_table_row(struct char_data *ch, const char *label, const char *value);
|
||||
static void stat_table_row_fmt(struct char_data *ch, const char *label, const char *fmt, ...) __attribute__((format(printf,3,4)));
|
||||
static void stat_table_border_buf(char *buf, size_t buf_size, size_t *len);
|
||||
static void stat_table_row_buf(char *buf, size_t buf_size, size_t *len, const char *label, const char *value);
|
||||
static void stat_table_row_fmt_buf(char *buf, size_t buf_size, size_t *len, const char *label, const char *fmt, ...) __attribute__((format(printf,5,6)));
|
||||
static void stat_appendf(char *buf, size_t buf_size, size_t *len, const char *fmt, ...) __attribute__((format(printf,4,5)));
|
||||
static void stat_append_list_item(char *buf, size_t buf_size, size_t *len, size_t *line_len, const char *item);
|
||||
static void stat_format_notrade_classes(bitvector_t flags, char *out, size_t outsz);
|
||||
static void stat_format_script_triggers(struct script_data *sc, char *buf, size_t buf_size);
|
||||
static void stat_format_script_globals(struct script_data *sc, char *buf, size_t buf_size);
|
||||
static void stat_format_script_memory(struct script_memory *mem, char *buf, size_t buf_size);
|
||||
|
|
@ -209,6 +216,60 @@ static void stat_table_row_fmt(struct char_data *ch, const char *label, const ch
|
|||
stat_table_row(ch, label, buf);
|
||||
}
|
||||
|
||||
static void stat_table_border_buf(char *buf, size_t buf_size, size_t *len)
|
||||
{
|
||||
stat_appendf(buf, buf_size, len, "%s", stat_border_line());
|
||||
}
|
||||
|
||||
static void stat_table_row_buf(char *buf, size_t buf_size, size_t *len, const char *label, const char *value)
|
||||
{
|
||||
const char *text = (value && *value) ? value : "<None>";
|
||||
bool printed = FALSE;
|
||||
|
||||
while (*text) {
|
||||
while (*text == '\r' || *text == '\n')
|
||||
text++;
|
||||
if (!*text)
|
||||
break;
|
||||
|
||||
char chunk[STAT_VALUE_WIDTH + 1];
|
||||
const char *next = stat_next_chunk(text, chunk, STAT_VALUE_WIDTH);
|
||||
|
||||
if (!*chunk) {
|
||||
text = next;
|
||||
continue;
|
||||
}
|
||||
|
||||
stat_appendf(buf, buf_size, len, "| %-*s | %-*s |\r\n",
|
||||
STAT_LABEL_WIDTH,
|
||||
printed || !label ? "" : label,
|
||||
STAT_VALUE_WIDTH,
|
||||
chunk);
|
||||
|
||||
printed = TRUE;
|
||||
text = next;
|
||||
}
|
||||
|
||||
if (!printed)
|
||||
stat_appendf(buf, buf_size, len, "| %-*s | %-*s |\r\n",
|
||||
STAT_LABEL_WIDTH,
|
||||
label ? label : "",
|
||||
STAT_VALUE_WIDTH,
|
||||
(value && *value) ? value : "<None>");
|
||||
}
|
||||
|
||||
static void stat_table_row_fmt_buf(char *buf, size_t buf_size, size_t *len, const char *label, const char *fmt, ...)
|
||||
{
|
||||
char row[MAX_STRING_LENGTH];
|
||||
va_list args;
|
||||
|
||||
va_start(args, fmt);
|
||||
vsnprintf(row, sizeof(row), fmt, args);
|
||||
va_end(args);
|
||||
|
||||
stat_table_row_buf(buf, buf_size, len, label, row);
|
||||
}
|
||||
|
||||
static void stat_appendf(char *buf, size_t buf_size, size_t *len, const char *fmt, ...)
|
||||
{
|
||||
if (*len >= buf_size)
|
||||
|
|
@ -228,6 +289,52 @@ static void stat_appendf(char *buf, size_t buf_size, size_t *len, const char *fm
|
|||
*len += wrote;
|
||||
}
|
||||
|
||||
static void stat_append_list_item(char *buf, size_t buf_size, size_t *len, size_t *line_len, const char *item)
|
||||
{
|
||||
size_t item_len = strlen(item);
|
||||
|
||||
if (*line_len && *line_len + 2 + item_len > STAT_VALUE_WIDTH) {
|
||||
stat_appendf(buf, buf_size, len, "\n");
|
||||
*line_len = 0;
|
||||
}
|
||||
|
||||
if (*line_len) {
|
||||
stat_appendf(buf, buf_size, len, ", ");
|
||||
*line_len += 2;
|
||||
}
|
||||
|
||||
stat_appendf(buf, buf_size, len, "%s", item);
|
||||
*line_len += item_len;
|
||||
}
|
||||
|
||||
static void stat_format_notrade_classes(bitvector_t flags, char *out, size_t outsz)
|
||||
{
|
||||
size_t len = 0;
|
||||
int i, found = 0;
|
||||
|
||||
if (!out || outsz == 0)
|
||||
return;
|
||||
|
||||
out[0] = '\0';
|
||||
|
||||
for (i = TRADE_CLASS_START; i < NUM_TRADERS; i++) {
|
||||
if (IS_SET(flags, 1 << i)) {
|
||||
int n = snprintf(out + len, outsz - len, "%s%s", found ? " " : "", trade_letters[i]);
|
||||
|
||||
if (n < 0 || (size_t)n >= outsz - len) {
|
||||
out[outsz - 1] = '\0';
|
||||
return;
|
||||
}
|
||||
|
||||
len += (size_t)n;
|
||||
found = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
strlcpy(out, "NOBITS", outsz);
|
||||
}
|
||||
|
||||
static void stat_format_script_triggers(struct script_data *sc, char *buf, size_t buf_size)
|
||||
{
|
||||
size_t len = 0;
|
||||
|
|
@ -1941,6 +2048,125 @@ static void do_stat_character(struct char_data *ch, struct char_data *k)
|
|||
stat_table_border(ch);
|
||||
}
|
||||
|
||||
static void do_stat_shop(struct char_data *ch, shop_rnum shop_nr)
|
||||
{
|
||||
char entry[MAX_STRING_LENGTH];
|
||||
char list[MAX_STRING_LENGTH];
|
||||
char buf[MAX_STRING_LENGTH];
|
||||
char bits[MAX_STRING_LENGTH];
|
||||
char *out;
|
||||
size_t out_size = MAX_STRING_LENGTH * 4;
|
||||
size_t len = 0;
|
||||
size_t line_len = 0;
|
||||
size_t list_len = 0;
|
||||
int i;
|
||||
|
||||
CREATE(out, char, out_size);
|
||||
out[0] = '\0';
|
||||
|
||||
stat_table_border_buf(out, out_size, &len);
|
||||
stat_table_row_fmt_buf(out, out_size, &len, "Identifiers", "VNum #%d (RNum %d)",
|
||||
SHOP_NUM(shop_nr), shop_nr);
|
||||
|
||||
if (SHOP_KEEPER(shop_nr) == NOBODY) {
|
||||
strlcpy(buf, "None", sizeof(buf));
|
||||
} else {
|
||||
snprintf(buf, sizeof(buf), "[%d] %s",
|
||||
mob_index[SHOP_KEEPER(shop_nr)].vnum,
|
||||
mob_proto[SHOP_KEEPER(shop_nr)].player.short_descr ?
|
||||
mob_proto[SHOP_KEEPER(shop_nr)].player.short_descr : "<None>");
|
||||
}
|
||||
stat_table_row_buf(out, out_size, &len, "Keeper", buf);
|
||||
|
||||
stat_table_row_fmt_buf(out, out_size, &len, "Open/Close",
|
||||
"Open1 %d Close1 %d, Open2 %d Close2 %d",
|
||||
SHOP_OPEN1(shop_nr), SHOP_CLOSE1(shop_nr),
|
||||
SHOP_OPEN2(shop_nr), SHOP_CLOSE2(shop_nr));
|
||||
|
||||
stat_table_row_fmt_buf(out, out_size, &len, "Rates",
|
||||
"Sell %1.2f, Buy %1.2f",
|
||||
SHOP_BUYPROFIT(shop_nr), SHOP_SELLPROFIT(shop_nr));
|
||||
|
||||
list[0] = '\0';
|
||||
line_len = 0;
|
||||
list_len = 0;
|
||||
for (i = 0; SHOP_ROOM(shop_nr, i) != NOWHERE; i++) {
|
||||
room_rnum rnum = real_room(SHOP_ROOM(shop_nr, i));
|
||||
if (rnum != NOWHERE)
|
||||
snprintf(entry, sizeof(entry), "#%d %s",
|
||||
GET_ROOM_VNUM(rnum), world[rnum].name);
|
||||
else
|
||||
snprintf(entry, sizeof(entry), "<UNKNOWN> (#%d)", SHOP_ROOM(shop_nr, i));
|
||||
stat_append_list_item(list, sizeof(list), &list_len, &line_len, entry);
|
||||
}
|
||||
if (!list_len)
|
||||
strlcpy(list, "None", sizeof(list));
|
||||
stat_table_row_buf(out, out_size, &len, "Rooms", list);
|
||||
|
||||
list[0] = '\0';
|
||||
list_len = 0;
|
||||
line_len = 0;
|
||||
for (i = 0; SHOP_PRODUCT(shop_nr, i) != NOTHING; i++) {
|
||||
obj_rnum rnum = SHOP_PRODUCT(shop_nr, i);
|
||||
if (rnum != NOTHING && rnum >= 0 && rnum <= top_of_objt) {
|
||||
snprintf(entry, sizeof(entry), "%s (#%d)",
|
||||
obj_proto[rnum].short_description ? obj_proto[rnum].short_description : "<None>",
|
||||
obj_index[rnum].vnum);
|
||||
} else
|
||||
snprintf(entry, sizeof(entry), "<UNKNOWN>");
|
||||
stat_append_list_item(list, sizeof(list), &list_len, &line_len, entry);
|
||||
}
|
||||
if (!list_len)
|
||||
strlcpy(list, "None", sizeof(list));
|
||||
stat_table_row_buf(out, out_size, &len, "Products", list);
|
||||
|
||||
list[0] = '\0';
|
||||
list_len = 0;
|
||||
line_len = 0;
|
||||
for (i = 0; SHOP_BUYTYPE(shop_nr, i) != NOTHING; i++) {
|
||||
const char *keyword = SHOP_BUYWORD(shop_nr, i) ? SHOP_BUYWORD(shop_nr, i) : "all";
|
||||
if (SHOP_BUYTYPE(shop_nr, i) >= 0 && SHOP_BUYTYPE(shop_nr, i) < NUM_ITEM_TYPES) {
|
||||
snprintf(entry, sizeof(entry), "%s (#%d) [%s]",
|
||||
item_types[SHOP_BUYTYPE(shop_nr, i)], SHOP_BUYTYPE(shop_nr, i), keyword);
|
||||
} else
|
||||
snprintf(entry, sizeof(entry), "Unknown (#%d) [%s]", SHOP_BUYTYPE(shop_nr, i), keyword);
|
||||
stat_append_list_item(list, sizeof(list), &list_len, &line_len, entry);
|
||||
}
|
||||
if (!list_len)
|
||||
strlcpy(list, "None", sizeof(list));
|
||||
stat_table_row_buf(out, out_size, &len, "Accept Types", list);
|
||||
|
||||
stat_format_notrade_classes(SHOP_TRADE_WITH(shop_nr), buf, sizeof(buf));
|
||||
stat_table_row_buf(out, out_size, &len, "No Trade With", buf);
|
||||
|
||||
sprintbit(SHOP_BITVECTOR(shop_nr), shop_bits, bits, sizeof(bits));
|
||||
stat_table_row_buf(out, out_size, &len, "Shop Flags", bits);
|
||||
|
||||
stat_table_row_buf(out, out_size, &len, "Keeper No Item",
|
||||
shop_index[shop_nr].no_such_item1 ? shop_index[shop_nr].no_such_item1 : "None");
|
||||
stat_table_row_buf(out, out_size, &len, "Player No Item",
|
||||
shop_index[shop_nr].no_such_item2 ? shop_index[shop_nr].no_such_item2 : "None");
|
||||
stat_table_row_buf(out, out_size, &len, "Keeper No Cash",
|
||||
shop_index[shop_nr].missing_cash1 ? shop_index[shop_nr].missing_cash1 : "None");
|
||||
stat_table_row_buf(out, out_size, &len, "Player No Cash",
|
||||
shop_index[shop_nr].missing_cash2 ? shop_index[shop_nr].missing_cash2 : "None");
|
||||
stat_table_row_buf(out, out_size, &len, "Keeper No Buy",
|
||||
shop_index[shop_nr].do_not_buy ? shop_index[shop_nr].do_not_buy : "None");
|
||||
stat_table_row_buf(out, out_size, &len, "Buy Success",
|
||||
shop_index[shop_nr].message_buy ? shop_index[shop_nr].message_buy : "None");
|
||||
stat_table_row_buf(out, out_size, &len, "Sell Success",
|
||||
shop_index[shop_nr].message_sell ? shop_index[shop_nr].message_sell : "None");
|
||||
|
||||
stat_table_border_buf(out, out_size, &len);
|
||||
|
||||
if (ch->desc)
|
||||
page_string(ch->desc, out, TRUE);
|
||||
else
|
||||
send_to_char(ch, "%s", out);
|
||||
|
||||
free(out);
|
||||
}
|
||||
|
||||
ACMD(do_stat)
|
||||
{
|
||||
char buf1[MAX_INPUT_LENGTH], buf2[MAX_INPUT_LENGTH];
|
||||
|
|
@ -2014,6 +2240,33 @@ ACMD(do_stat)
|
|||
else
|
||||
send_to_char(ch, "No such object around.\r\n");
|
||||
}
|
||||
} else if (is_abbrev(buf1, "shop")) {
|
||||
shop_rnum shop_nr = NOWHERE;
|
||||
if (!*buf2) {
|
||||
int found = FALSE;
|
||||
room_vnum rvnum = GET_ROOM_VNUM(IN_ROOM(ch));
|
||||
for (shop_nr = 0; shop_nr <= top_shop; shop_nr++) {
|
||||
for (int j = 0; SHOP_ROOM(shop_nr, j) != NOWHERE; j++) {
|
||||
if (SHOP_ROOM(shop_nr, j) == rvnum) {
|
||||
found = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found)
|
||||
break;
|
||||
}
|
||||
if (!found) {
|
||||
send_to_char(ch, "This isn't a shop.\r\n");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
shop_nr = real_shop(atoi(buf2));
|
||||
if (shop_nr == NOWHERE) {
|
||||
send_to_char(ch, "That is not a valid shop.\r\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
do_stat_shop(ch, shop_nr);
|
||||
} else if (is_abbrev(buf1, "zone")) {
|
||||
if (!*buf2) {
|
||||
print_zone(ch, zone_table[world[IN_ROOM(ch)].zone].number);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue