Update audit command for melee weapons, add helpfile entry

This commit is contained in:
kinther 2025-12-31 08:27:33 -08:00
parent a765351be9
commit f8d9d31c1c
3 changed files with 148 additions and 76 deletions

View file

@ -57,7 +57,7 @@ Changes in v1.1.0-alpha:
* Ability to change ldesc of PC/NPC's in some situations
* 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 ac" command for immortals (formerly "acaudit"), allowing for further audit commands in the future
* "audit armor" command for immortals (formerly "acaudit")
* 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

View file

@ -315,29 +315,35 @@ Situational: cover (+2/+5), spells (Shield, Haste, etc.)
See Also: SCORE
#0
AUDIT AC AUDIT-AC ACAUDIT ARMOR-AUDIT AUDIT-ARMOR IMMORTAL
AUDIT ARMOR AUDIT-ARMOR AUDIT AC AUDIT-AC ACAUDIT AUDIT MELEE AUDIT-MELEE IMMORTAL
Summary: Imm-only tool that scans all ITEM\_ARMOR prototypes and reports
per-piece fields against slot caps. Use this to catch outliers and quickly
rebalance items to the Light/Medium/Heavy targets.
Summary: Imm-only tool that scans armor and weapons for invalid config.
Usage:
audit ac
audit armor|melee
If you omit the option, you'll be prompted with "Audit what?"
What it does:
What auditing armor does:
Scans prototypes for armor slots (head, body, legs, arms, hands, feet) and
prints one line per item:
\[#VNUM] <name> slot=<slot> ac=\<piece\_ac> bulk=<bulk> mag=+<magic> flags=<mask>
[#VNUM] <name> sl=<slot> ac=<piece_ac> b=<bulk> m=<magic> sd=<0/1> str=<req>
Markers:
OVER : value exceeds the slots hard cap (e.g., piece AC > slot max, or
magic > slot max)
WARN : value outside 0..3 (invalid for piece AC, bulk, or magic)
(STEALTHDISADV): flag is set (the piece imposes Stealth Disadvantage)
R! : value exceeds the slots hard cap (e.g., piece AC > slot max, or
magic > slot max)
Y? : value outside 0..3 (invalid for piece AC, bulk, or magic)
sd=1 : piece imposes Stealth Disadvantage
What auditing melee weapons does:
Scans melee weapon prototypes and reports attack type, damage (1d4/1d6/1d8/
1d10/1d12), and weight.
Melee markers:
R! : attack type is missing/invalid or damage is not 1d4/1d6/1d8/1d10/1d12
Y? : weight is 0 or less
Notes:
@ -358,7 +364,7 @@ Medium : AC \~1418
Heavy : AC \~1620
See Also: ARMOR PIECES, BULK, SHIELDS, MAGIC CAPS, SCORE, OEDIT ARMOR
#32
#2
ACRONYMS TERMINOLOGY VOCABULARY
Here are some common terms used in building, and TBA zone:
@ -9822,7 +9828,7 @@ redit 34800
q
y
See Also: TBA-STAFF, TBA-ZONES
#32
#2
TBA-ADVERTISING
Mud Created: 2000
@ -12568,7 +12574,7 @@ Examples:
>; @ - shows all gods that are on and visible to you.
- also shows if the gods who are visible to you are writing.
>;#<level> <text> - sends text to everyone <level> and above.
- ;#32 only God and above will see this.
- ;#2 only God and above will see this.
See also: NOWIZ
#2

View file

@ -6183,14 +6183,20 @@ ACMD(do_audit)
{
int found = 0, warned = 0;
char arg[MAX_INPUT_LENGTH];
bool do_armor = FALSE;
bool do_weapons = FALSE;
one_argument(argument, arg);
if (!*arg) {
send_to_char(ch, "Audit what?\r\n");
return;
}
if (!is_abbrev(arg, "ac")) {
send_to_char(ch, "Usage: audit ac\r\n");
if (is_abbrev(arg, "armor"))
do_armor = TRUE;
else if (is_abbrev(arg, "melee"))
do_weapons = TRUE;
else {
send_to_char(ch, "Usage: audit armor | audit melee\r\n");
return;
}
@ -6218,75 +6224,135 @@ ACMD(do_audit)
len += (size_t)snprintf(out + len, cap - len, __VA_ARGS__); \
} while (0)
/* Header (short so it wont wrap) */
APPEND_FMT("\r\n\tY[Armor Audit]\tn ITEM_ARMOR scan\r\n");
APPEND_FMT("Legend: \tR!\tn over-cap, \tY?\tn warn, S stealth-disadv\r\n");
if (do_armor) {
/* Header (short so it wont wrap) */
APPEND_FMT("\r\n\tY[Armor Audit]\tn ITEM_ARMOR scan\r\n");
APPEND_FMT("Legend: \tR!\tn over-cap, \tY?\tn warn, S stealth-disadv\r\n");
for (obj_rnum r = 0; r <= top_of_objt; r++) {
struct obj_data *obj = &obj_proto[r];
char namebuf[128] = {0};
int idx, vnum, piece_ac, bulk, magic, stealth, strreq;
for (obj_rnum r = 0; r <= top_of_objt; r++) {
struct obj_data *obj = &obj_proto[r];
char namebuf[128] = {0};
int idx, vnum, piece_ac, bulk, magic, stealth, strreq;
if (GET_OBJ_TYPE(obj) != ITEM_ARMOR)
continue;
if (GET_OBJ_TYPE(obj) != ITEM_ARMOR)
continue;
/* Identify slot (skip shields here) */
idx = armor_slot_index_from_wear(obj);
if (idx == -2) continue; /* shield handled in AC; skip */
if (idx < 0) continue; /* not a supported armor slot */
/* Identify slot (skip shields here) */
idx = armor_slot_index_from_wear(obj);
if (idx == -2) continue; /* shield handled in AC; skip */
if (idx < 0) continue; /* not a supported armor slot */
vnum = GET_OBJ_VNUM(obj);
piece_ac = GET_OBJ_VAL(obj, VAL_ARMOR_PIECE_AC);
bulk = GET_OBJ_VAL(obj, VAL_ARMOR_BULK);
magic = GET_OBJ_VAL(obj, VAL_ARMOR_MAGIC_BONUS);
stealth = GET_OBJ_VAL(obj, VAL_ARMOR_STEALTH_DISADV); /* 1/0, yes or no */
strreq = GET_OBJ_VAL(obj, VAL_ARMOR_STR_REQ); /* 0 or 13/15/16 typically */
vnum = GET_OBJ_VNUM(obj);
piece_ac = GET_OBJ_VAL(obj, VAL_ARMOR_PIECE_AC);
bulk = GET_OBJ_VAL(obj, VAL_ARMOR_BULK);
magic = GET_OBJ_VAL(obj, VAL_ARMOR_MAGIC_BONUS);
stealth = GET_OBJ_VAL(obj, VAL_ARMOR_STEALTH_DISADV); /* 1/0, yes or no */
strreq = GET_OBJ_VAL(obj, VAL_ARMOR_STR_REQ); /* 0 or 13/15/16 typically */
/* Display name (trim to keep line width < ~78 cols) */
if (obj->short_description)
snprintf(namebuf, sizeof(namebuf), "%s", obj->short_description);
else if (obj->name)
snprintf(namebuf, sizeof(namebuf), "%s", obj->name);
else
snprintf(namebuf, sizeof(namebuf), "object");
/* Display name (trim to keep line width < ~78 cols) */
if (obj->short_description)
snprintf(namebuf, sizeof(namebuf), "%s", obj->short_description);
else if (obj->name)
snprintf(namebuf, sizeof(namebuf), "%s", obj->name);
else
snprintf(namebuf, sizeof(namebuf), "object");
/* Slot caps */
const int max_piece_ac = armor_slots[idx].max_piece_ac;
const int max_magic = armor_slots[idx].max_magic;
/* Slot caps */
const int max_piece_ac = armor_slots[idx].max_piece_ac;
const int max_magic = armor_slots[idx].max_magic;
/* Validations */
bool over_ac = (piece_ac > max_piece_ac);
bool over_magic = (magic > max_magic);
bool bad_ac = (piece_ac < 0 || piece_ac > 3);
bool bad_bulk = (bulk < 0 || bulk > 3);
bool bad_magic = (magic < 0 || magic > 3);
/* Validations */
bool over_ac = (piece_ac > max_piece_ac);
bool over_magic = (magic > max_magic);
bool bad_ac = (piece_ac < 0 || piece_ac > 3);
bool bad_bulk = (bulk < 0 || bulk > 3);
bool bad_magic = (magic < 0 || magic > 3);
found++;
found++;
/* Compact, non-wrapping row (~70 cols worst case) */
APPEND_FMT("\tc[#%5d]\tn %-24.24s sl=%-5.5s ac=%2d%s b=%d%s m=%+d%s sd=%d str=%d\r\n",
vnum,
namebuf,
slot_name_from_index(idx),
piece_ac, over_ac ? " \tR!\tn" : (bad_ac ? " \tY?\tn" : ""),
bulk, bad_bulk ? " \tY?\tn" : "",
magic, over_magic ? " \tR!\tn" : (bad_magic? " \tY?\tn" : ""),
stealth, strreq);
/* Compact, non-wrapping row (~70 cols worst case) */
APPEND_FMT("\tc[#%5d]\tn %-24.24s sl=%-5.5s ac=%2d%s b=%d%s m=%+d%s sd=%d str=%d\r\n",
vnum,
namebuf,
slot_name_from_index(idx),
piece_ac, over_ac ? " \tR!\tn" : (bad_ac ? " \tY?\tn" : ""),
bulk, bad_bulk ? " \tY?\tn" : "",
magic, over_magic ? " \tR!\tn" : (bad_magic? " \tY?\tn" : ""),
stealth, strreq);
if (over_ac || over_magic || bad_ac || bad_bulk || bad_magic)
warned++;
if (over_ac || over_magic || bad_ac || bad_bulk || bad_magic)
warned++;
}
if (!found) {
free(out);
send_to_char(ch, "No ITEM_ARMOR prototypes found for the audited slots.\r\n");
return;
}
/* Footer */
APPEND_FMT("\r\nScanned: %d items, %d with issues. Armor magic cap +%d (shield separate).\r\n",
found, warned, MAX_TOTAL_ARMOR_MAGIC);
} else if (do_weapons) {
APPEND_FMT("\r\n\tY[Weapon Audit]\tn ITEM_WEAPON scan\r\n");
APPEND_FMT("Legend: \tR!\tn error, \tY?\tn warn, dmg=1d4/1d6/1d8/1d10/1d12\r\n");
for (obj_rnum r = 0; r <= top_of_objt; r++) {
struct obj_data *obj = &obj_proto[r];
char namebuf[128] = {0};
int vnum, ndice, sdice, atype, weight;
bool bad_type, bad_dmg, bad_weight;
const char *atype_name;
if (GET_OBJ_TYPE(obj) != ITEM_WEAPON)
continue;
vnum = GET_OBJ_VNUM(obj);
ndice = GET_OBJ_VAL(obj, 0);
sdice = GET_OBJ_VAL(obj, 1);
atype = GET_OBJ_VAL(obj, 2);
weight = GET_OBJ_WEIGHT(obj);
/* Display name (trim to keep line width < ~78 cols) */
if (obj->short_description)
snprintf(namebuf, sizeof(namebuf), "%s", obj->short_description);
else if (obj->name)
snprintf(namebuf, sizeof(namebuf), "%s", obj->name);
else
snprintf(namebuf, sizeof(namebuf), "object");
bad_type = (atype < 0 || atype >= NUM_ATTACK_TYPES);
bad_dmg = !(ndice == 1 &&
(sdice == 4 || sdice == 6 || sdice == 8 || sdice == 10 || sdice == 12));
bad_weight = (weight <= 0);
if (bad_type)
atype_name = "invalid";
else
atype_name = attack_hit_text[atype].singular;
found++;
APPEND_FMT("\tc[#%5d]\tn %-24.24s at=%-7.7s%s dmg=%dd%d%s wt=%d%s\r\n",
vnum,
namebuf,
atype_name, bad_type ? " \tR!\tn" : "",
ndice, sdice, bad_dmg ? " \tR!\tn" : "",
weight, bad_weight ? " \tY?\tn" : "");
if (bad_type || bad_dmg || bad_weight)
warned++;
}
if (!found) {
free(out);
send_to_char(ch, "No ITEM_WEAPON prototypes found.\r\n");
return;
}
APPEND_FMT("\r\nScanned: %d items, %d with issues.\r\n", found, warned);
}
if (!found) {
free(out);
send_to_char(ch, "No ITEM_ARMOR prototypes found for the audited slots.\r\n");
return;
}
/* Footer */
APPEND_FMT("\r\nScanned: %d items, %d with issues. Armor magic cap +%d (shield separate).\r\n",
found, warned, MAX_TOTAL_ARMOR_MAGIC);
/* Page it (copy mode) and try to force 25-line pages */
if (ch->desc) {
int old_len = 0; bool changed = false;