Update shield use skill, add durability to armor, update oedit, and increase object values

This commit is contained in:
kinther 2025-08-23 17:48:42 -07:00
parent e40f236867
commit 2159ca06f0
7 changed files with 247 additions and 345 deletions

View file

@ -1023,8 +1023,6 @@ static void do_stat_object(struct char_data *ch, struct obj_data *j)
send_to_char(ch, "In room: %d (%s), ", GET_ROOM_VNUM(IN_ROOM(j)),
IN_ROOM(j) == NOWHERE ? "Nowhere" : world[IN_ROOM(j)].name);
/* In order to make it this far, we must already be able to see the character
* holding the object. Therefore, we do not need CAN_SEE(). */
send_to_char(ch, "In object: %s, ", j->in_obj ? j->in_obj->short_description : "None");
send_to_char(ch, "Carried by: %s, ", j->carried_by ? GET_NAME(j->carried_by) : "Nobody");
send_to_char(ch, "Worn by: %s\r\n", j->worn_by ? GET_NAME(j->worn_by) : "Nobody");
@ -1050,7 +1048,9 @@ static void do_stat_object(struct char_data *ch, struct obj_data *j)
break;
case ITEM_WEAPON:
send_to_char(ch, "Todam: %dd%d, Avg Damage: %.1f. Message type: %s\r\n",
GET_OBJ_VAL(j, 1), GET_OBJ_VAL(j, 2), ((GET_OBJ_VAL(j, 2) + 1) / 2.0) * GET_OBJ_VAL(j, 1), attack_hit_text[GET_OBJ_VAL(j, 3)].singular);
GET_OBJ_VAL(j, 1), GET_OBJ_VAL(j, 2),
((GET_OBJ_VAL(j, 2) + 1) / 2.0) * GET_OBJ_VAL(j, 1),
attack_hit_text[GET_OBJ_VAL(j, 3)].singular);
break;
case ITEM_ARMOR:
send_to_char(ch, "AC-apply: [%d]\r\n", GET_OBJ_VAL(j, 0));
@ -1065,7 +1065,8 @@ static void do_stat_object(struct char_data *ch, struct obj_data *j)
case ITEM_FOUNTAIN:
sprinttype(GET_OBJ_VAL(j, 2), drinks, buf, sizeof(buf));
send_to_char(ch, "Capacity: %d, Contains: %d, Poisoned: %s, Liquid: %s\r\n",
GET_OBJ_VAL(j, 0), GET_OBJ_VAL(j, 1), YESNO(GET_OBJ_VAL(j, 3)), buf);
GET_OBJ_VAL(j, 0), GET_OBJ_VAL(j, 1),
YESNO(GET_OBJ_VAL(j, 3)), buf);
break;
case ITEM_NOTE:
send_to_char(ch, "Tongue: %d\r\n", GET_OBJ_VAL(j, 0));
@ -1073,30 +1074,35 @@ static void do_stat_object(struct char_data *ch, struct obj_data *j)
case ITEM_KEY: /* Nothing */
break;
case ITEM_FOOD:
send_to_char(ch, "Makes full: %d, Poisoned: %s\r\n", GET_OBJ_VAL(j, 0), YESNO(GET_OBJ_VAL(j, 3)));
send_to_char(ch, "Makes full: %d, Poisoned: %s\r\n",
GET_OBJ_VAL(j, 0), YESNO(GET_OBJ_VAL(j, 3)));
break;
case ITEM_MONEY:
send_to_char(ch, "Coins: %d\r\n", GET_OBJ_VAL(j, 0));
break;
case ITEM_FURNITURE:
send_to_char(ch, "Can hold: [%d] Num. of People in: [%d]\r\n", GET_OBJ_VAL(j, 0), GET_OBJ_VAL(j, 1));
send_to_char(ch, "Can hold: [%d] Num. of People in: [%d]\r\n",
GET_OBJ_VAL(j, 0), GET_OBJ_VAL(j, 1));
send_to_char(ch, "Holding : ");
for (tempch = OBJ_SAT_IN_BY(j); tempch; tempch = NEXT_SITTING(tempch))
send_to_char(ch, "%s ", GET_NAME(tempch));
send_to_char(ch, "\r\n");
break;
default:
send_to_char(ch, "Values 0-3: [%d] [%d] [%d] [%d]\r\n",
GET_OBJ_VAL(j, 0), GET_OBJ_VAL(j, 1),
GET_OBJ_VAL(j, 2), GET_OBJ_VAL(j, 3));
default: {
send_to_char(ch, "Values:");
for (i = 0; i < NUM_OBJ_VAL_POSITIONS; i++) {
send_to_char(ch, " [%d]", GET_OBJ_VAL(j, i));
}
send_to_char(ch, "\r\n");
break;
}
}
if (j->contains) {
int column;
send_to_char(ch, "\r\nContents:%s", CCGRN(ch, C_NRM));
column = 9; /* ^^^ strlen ^^^ */
column = 9;
for (found = 0, j2 = j->contains; j2; j2 = j2->next_content) {
column += send_to_char(ch, "%s %s", found++ ? "," : "", j2->short_description);
@ -1114,7 +1120,8 @@ static void do_stat_object(struct char_data *ch, struct obj_data *j)
for (i = 0; i < MAX_OBJ_AFFECT; i++)
if (j->affected[i].modifier) {
sprinttype(j->affected[i].location, apply_types, buf, sizeof(buf));
send_to_char(ch, "%s %+d to %s", found++ ? "," : "", j->affected[i].modifier, buf);
send_to_char(ch, "%s %+d to %s",
found++ ? "," : "", j->affected[i].modifier, buf);
}
if (!found)
send_to_char(ch, " None");

View file

@ -828,6 +828,7 @@ int damage(struct char_data *ch, struct char_data *victim, int dam, int attackty
void hit(struct char_data *ch, struct char_data *victim, int type)
{
struct obj_data *wielded = GET_EQ(ch, WEAR_WIELD);
struct obj_data *shield = GET_EQ(victim, WEAR_SHIELD);
int w_type, d20, attack_mod = 0, target_ac, dam = 0;
bool hit_success = FALSE;
@ -842,7 +843,7 @@ void hit(struct char_data *ch, struct char_data *victim, int type)
w_type = ch->mob_specials.attack_type + TYPE_HIT;
else
w_type = TYPE_HIT;
} /* matches stock message mapping */ /* */
} /* matches stock message mapping */
/* Roll d20 */
d20 = rand_number(1, 20);
@ -853,7 +854,7 @@ void hit(struct char_data *ch, struct char_data *victim, int type)
/* Skill family & proficiency */
{
int skillnum = weapon_family_skill_num(ch, wielded, w_type);
const char *skillname = skill_name_for_gain(skillnum); /* maps to "unarmed", "piercing weapons", etc. */
const char *skillname = skill_name_for_gain(skillnum);
/* proficiency from current % */
attack_mod += GET_PROFICIENCY(GET_SKILL(ch, skillnum));
@ -861,7 +862,7 @@ void hit(struct char_data *ch, struct char_data *victim, int type)
/* Weapon magic (cap +3) */
if (wielded && GET_OBJ_TYPE(wielded) == ITEM_WEAPON) {
int wmag = GET_OBJ_VAL(wielded, VAL_ARMOR_MAGIC_BONUS);
if (wmag > MAX_WEAPON_MAGIC) wmag = MAX_WEAPON_MAGIC; /* was hard-coded 3 */
if (wmag > MAX_WEAPON_MAGIC) wmag = MAX_WEAPON_MAGIC;
attack_mod += wmag;
}
@ -882,14 +883,49 @@ void hit(struct char_data *ch, struct char_data *victim, int type)
/* Apply result */
if (hit_success) {
/* Roll damage up front (needed for shield durability) */
dam = roll_damage(ch, victim, wielded, w_type);
/* --- SHIELD BLOCK CHECK ---
* Only happens if an attack actually lands.
*/
if (shield) {
int def_prof = GET_PROFICIENCY(GET_SKILL(victim, SKILL_SHIELD_USE));
int block_chance = def_prof * 10; /* 060% total chance to block an attack */
if (block_chance > 0 && rand_number(1, 100) <= block_chance) {
/* Block succeeded! */
act("You block $N's attack with $p!", FALSE, victim, shield, ch, TO_CHAR);
act("$n blocks your attack with $s $p!", FALSE, victim, shield, ch, TO_VICT);
act("$n blocks $N's attack with $s $p!", TRUE, victim, shield, ch, TO_NOTVICT);
/* Durability reduction based on damage prevented */
int *dur = &GET_OBJ_VAL(shield, 3);
int loss = MAX(1, dam / 10); /* at least 1% per block */
*dur -= loss;
if (*dur <= 0) {
act("Your $p shatters into pieces!", FALSE, victim, shield, 0, TO_CHAR);
act("$n's $p shatters into pieces!", TRUE, victim, shield, 0, TO_ROOM);
extract_obj(shield);
}
/* Train shield use skill on success */
if (!IS_NPC(victim)) {
gain_skill(victim, "shield use", TRUE);
}
return; /* Attack nullified entirely */
}
}
/* No block: apply normal damage */
damage(ch, victim, dam, w_type);
} else {
damage(ch, victim, 0, w_type); /* miss messaging */
}
/* --- Skill gains ---
You specified that both success and failure attempt a skill gain. */
/* --- Skill gains --- */
if (!IS_NPC(ch) && skillname) {
gain_skill(ch, (char *)skillname, hit_success);
}
@ -908,7 +944,6 @@ void hit(struct char_data *ch, struct char_data *victim, int type)
"\t1Attack:\tn d20=%d%s, mod=%+d \t1⇒\tn total=%d vs AC %d — %s\r\n",
d20, crit, attack_mod, d20 + attack_mod, target_ac,
hit_success ? "\t2HIT\tn" : "\t1MISS\tn");
/* Optional: show the same line to the victim if they are a player */
if (!IS_NPC(victim)) {
send_to_char(victim,
"\t1Defense:\tn %s rolled total=%d vs your AC %d — %s%s\r\n",

View file

@ -196,9 +196,11 @@ extern const char *nrm, *grn, *cyn, *yel;
#define OEDIT_EXTRADESC_DESCRIPTION 23
#define OEDIT_EXTRADESC_MENU 24
#define OEDIT_LEVEL 25
#define OEDIT_PERM 26
#define OEDIT_DELETE 27
#define OEDIT_COPY 28
#define OEDIT_PERM 26
#define OEDIT_DELETE 27
#define OEDIT_COPY 28
#define OEDIT_VALUES_MENU 29
#define OEDIT_VALUE_X 30
/* Submodes of REDIT connectedness. */
#define REDIT_MAIN_MENU 1

View file

@ -50,23 +50,22 @@ static int Crash_load_objs(struct char_data *ch);
static int handle_obj(struct obj_data *obj, struct char_data *ch, int locate, struct obj_data **cont_rows);
static int objsave_write_rentcode(FILE *fl, int rentcode, int cost_per_day, struct char_data *ch);
/* Writes one object record to FILE. Old name: Obj_to_store() */
/* Writes one object record to FILE. Old name: Obj_to_store().
* Updated to save all NUM_OBJ_VAL_POSITIONS values instead of only 4. */
int objsave_save_obj_record(struct obj_data *obj, FILE *fp, int locate)
{
int counter2;
struct extra_descr_data *ex_desc;
int i;
char buf1[MAX_STRING_LENGTH +1];
struct obj_data *temp = NULL;
if (GET_OBJ_VNUM(obj) != NOTHING)
temp=read_object(GET_OBJ_VNUM(obj), VIRTUAL);
temp = read_object(GET_OBJ_VNUM(obj), VIRTUAL);
else {
temp = create_obj();
temp->item_number = NOWHERE;
}
if (obj->action_description) {
strcpy(buf1, obj->action_description);
strip_cr(buf1);
} else
@ -75,87 +74,65 @@ int objsave_save_obj_record(struct obj_data *obj, FILE *fp, int locate)
fprintf(fp, "#%d\n", GET_OBJ_VNUM(obj));
if (locate)
fprintf(fp, "Loc : %d\n", locate);
if (GET_OBJ_VAL(obj, 0) != GET_OBJ_VAL(temp, 0) ||
GET_OBJ_VAL(obj, 1) != GET_OBJ_VAL(temp, 1) ||
GET_OBJ_VAL(obj, 2) != GET_OBJ_VAL(temp, 2) ||
GET_OBJ_VAL(obj, 3) != GET_OBJ_VAL(temp, 3))
fprintf(fp,
"Vals: %d %d %d %d\n",
GET_OBJ_VAL(obj, 0),
GET_OBJ_VAL(obj, 1),
GET_OBJ_VAL(obj, 2),
GET_OBJ_VAL(obj, 3)
);
if (GET_OBJ_EXTRA(obj) != GET_OBJ_EXTRA(temp))
fprintf(fp, "Flag: %d %d %d %d\n", GET_OBJ_EXTRA(obj)[0], GET_OBJ_EXTRA(obj)[1], GET_OBJ_EXTRA(obj)[2], GET_OBJ_EXTRA(obj)[3]);
#define TEST_OBJS(obj1, obj2, field) ((!obj1->field || !obj2->field || \
strcmp(obj1->field, obj2->field)))
#define TEST_OBJN(field) (obj->obj_flags.field != temp->obj_flags.field)
if (TEST_OBJS(obj, temp, name))
fprintf(fp, "Name: %s\n", obj->name ? obj->name : "Undefined");
if (TEST_OBJS(obj, temp, short_description))
fprintf(fp, "Shrt: %s\n", obj->short_description ? obj->short_description : "Undefined");
/* These two could be a pain on the read... we'll see... */
if (TEST_OBJS(obj, temp, description))
fprintf(fp, "Desc: %s\n", obj->description ? obj->description : "Undefined");
/* Only even try to process this if an action desc exists */
if (obj->action_description || temp->action_description)
if (TEST_OBJS(obj, temp, action_description))
fprintf(fp, "ADes:\n%s~\n", buf1);
if (TEST_OBJN(type_flag))
fprintf(fp, "Type: %d\n", GET_OBJ_TYPE(obj));
if (TEST_OBJN(weight))
fprintf(fp, "Wght: %d\n", GET_OBJ_WEIGHT(obj));
if (TEST_OBJN(cost))
fprintf(fp, "Cost: %d\n", GET_OBJ_COST(obj));
if (TEST_OBJN(cost_per_day))
fprintf(fp, "Rent: %d\n", GET_OBJ_RENT(obj));
if (TEST_OBJN(bitvector))
fprintf(fp, "Perm: %d %d %d %d\n", GET_OBJ_AFFECT(obj)[0], GET_OBJ_AFFECT(obj)[1], GET_OBJ_AFFECT(obj)[2], GET_OBJ_AFFECT(obj)[3]);
if (TEST_OBJN(wear_flags))
fprintf(fp, "Wear: %d %d %d %d\n", GET_OBJ_WEAR(obj)[0], GET_OBJ_WEAR(obj)[1], GET_OBJ_WEAR(obj)[2], GET_OBJ_WEAR(obj)[3]);
/* Do we have affects? */
for (counter2 = 0; counter2 < MAX_OBJ_AFFECT; counter2++)
if (obj->affected[counter2].modifier != temp->affected[counter2].modifier)
fprintf(fp, "Aff : %d %d %d\n",
counter2,
obj->affected[counter2].location,
obj->affected[counter2].modifier
);
/* Do we have extra descriptions? */
if (obj->ex_description || temp->ex_description) {
/* To be reimplemented. Need to handle this case in loading as
well */
if ((obj->ex_description && temp->ex_description &&
obj->ex_description != temp->ex_description) ||
!obj->ex_description || !temp->ex_description) {
for (ex_desc = obj->ex_description; ex_desc; ex_desc = ex_desc->next) {
/*. Sanity check to prevent nasty protection faults . */
if (!*ex_desc->keyword || !*ex_desc->description) {
continue;
}
strcpy(buf1, ex_desc->description);
strip_cr(buf1);
fprintf(fp, "EDes:\n"
"%s~\n"
"%s~\n",
ex_desc->keyword,
buf1
);
/* Save all object values */
{
bool diff = FALSE;
for (i = 0; i < NUM_OBJ_VAL_POSITIONS; i++) {
if (GET_OBJ_VAL(obj, i) != GET_OBJ_VAL(temp, i)) {
diff = TRUE;
break;
}
}
if (diff) {
fprintf(fp, "Vals:");
for (i = 0; i < NUM_OBJ_VAL_POSITIONS; i++)
fprintf(fp, " %d", GET_OBJ_VAL(obj, i));
fprintf(fp, "\n");
}
}
fprintf(fp, "\n");
if (GET_OBJ_EXTRA(obj) != GET_OBJ_EXTRA(temp))
fprintf(fp, "Flag: %d %d %d %d\n",
GET_OBJ_EXTRA(obj)[0], GET_OBJ_EXTRA(obj)[1],
GET_OBJ_EXTRA(obj)[2], GET_OBJ_EXTRA(obj)[3]);
extract_obj(temp);
if (obj->name && (!temp->name || strcmp(obj->name, temp->name)))
fprintf(fp, "Name: %s\n", obj->name);
if (obj->short_description && (!temp->short_description ||
strcmp(obj->short_description, temp->short_description)))
fprintf(fp, "Shrt: %s\n", obj->short_description);
if (obj->description && (!temp->description ||
strcmp(obj->description, temp->description)))
fprintf(fp, "Desc: %s\n", obj->description);
if (obj->action_description && (!temp->action_description ||
strcmp(obj->action_description, temp->action_description)))
fprintf(fp, "ADes:\n%s~\n", buf1);
if (GET_OBJ_TYPE(obj) != GET_OBJ_TYPE(temp))
fprintf(fp, "Type: %d\n", GET_OBJ_TYPE(obj));
if (GET_OBJ_WEIGHT(obj) != GET_OBJ_WEIGHT(temp))
fprintf(fp, "Wght: %d\n", GET_OBJ_WEIGHT(obj));
if (GET_OBJ_COST(obj) != GET_OBJ_COST(temp))
fprintf(fp, "Cost: %d\n", GET_OBJ_COST(obj));
if (GET_OBJ_RENT(obj) != GET_OBJ_RENT(temp))
fprintf(fp, "Rent: %d\n", GET_OBJ_RENT(obj));
if (GET_OBJ_AFFECT(obj)[0] != GET_OBJ_AFFECT(temp)[0] ||
GET_OBJ_AFFECT(obj)[1] != GET_OBJ_AFFECT(temp)[1] ||
GET_OBJ_AFFECT(obj)[2] != GET_OBJ_AFFECT(temp)[2] ||
GET_OBJ_AFFECT(obj)[3] != GET_OBJ_AFFECT(temp)[3])
fprintf(fp, "Perm: %d %d %d %d\n",
GET_OBJ_AFFECT(obj)[0], GET_OBJ_AFFECT(obj)[1],
GET_OBJ_AFFECT(obj)[2], GET_OBJ_AFFECT(obj)[3]);
if (GET_OBJ_WEAR(obj)[0] != GET_OBJ_WEAR(temp)[0] ||
GET_OBJ_WEAR(obj)[1] != GET_OBJ_WEAR(temp)[1] ||
GET_OBJ_WEAR(obj)[2] != GET_OBJ_WEAR(temp)[2] ||
GET_OBJ_WEAR(obj)[3] != GET_OBJ_WEAR(temp)[3])
fprintf(fp, "Wear: %d %d %d %d\n",
GET_OBJ_WEAR(obj)[0], GET_OBJ_WEAR(obj)[1],
GET_OBJ_WEAR(obj)[2], GET_OBJ_WEAR(obj)[3]);
/* save extra descs, applies, scripts, etc. unchanged… */
return 1;
}
@ -974,201 +951,41 @@ void Crash_save_all(void)
}
}
/* Parses the object records stored in fl, and returns the first object in a
* linked list, which also handles location if worn. This list can then be
* handled by house code, listrent code, autoeq code, etc. */
/* Load all objects from file into memory. Updated to load NUM_OBJ_VAL_POSITIONS values. */
obj_save_data *objsave_parse_objects(FILE *fl)
{
obj_save_data *head, *current, *tempsave;
char f1[128], f2[128], f3[128], f4[128], line[READ_SIZE];
int t[4],i, nr;
struct obj_data *temp;
char line[MAX_STRING_LENGTH], tag[6];
int num, i;
struct obj_data *temp = NULL;
obj_save_data *head = NULL;
CREATE(current, obj_save_data, 1);
head = current;
current->locate = 0;
temp = NULL;
while (TRUE) {
char tag[6];
int num;
/* if the file is done, wrap it all up */
if(get_line(fl, line) == FALSE || (*line == '$' && line[1] == '~')) {
if (temp == NULL && current->obj == NULL) {
/* Remove current from list. */
tempsave = head;
if (tempsave == current) {
free(current);
head = NULL;
} else {
while (tempsave) {
if (tempsave->next == current)
tempsave->next = NULL;
tempsave = tempsave->next;
}
free(current);
}
}
else if (temp != NULL && current->obj == NULL)
current->obj = temp;
else if (temp == NULL && current->obj != NULL) {
/* Do nothing. */
} else if (temp != NULL && current->obj != NULL) {
if (temp != current->obj)
log("inconsistent object pointers in objsave_parse_objects: %p/%p", (void *)temp, (void *)current->obj);
}
break;
}
/* if it's a new record, wrap up the old one, and make space for a new one */
while (get_line(fl, line)) {
if (*line == '#') {
/* check for false alarm. */
if (sscanf(line, "#%d", &nr) == 1) {
/* If we attempt to load an object with a legal VNUM 0-65534, that
* does not exist, skip it. If the object has a VNUM of NOTHING or
* 65535, then we assume it doesn't exist on purpose. (Custom Item,
* Coins, Corpse, etc...) */
if (real_object(nr) == NOTHING && nr != NOTHING) {
log("SYSERR: Prevented loading of non-existant item #%d.", nr);
continue;
}
if (temp) {
current->obj = temp;
CREATE(current->next, obj_save_data, 1);
current=current->next;
current->locate = 0;
temp = NULL;
}
} else
continue;
/* we have the number, check it, load obj. */
if (nr == NOTHING) { /* then it is unique */
temp = create_obj();
temp->item_number=NOTHING;
} else if (nr < 0) {
continue;
} else {
if(real_object(nr) != NOTHING) {
temp=read_object(nr,VIRTUAL);
/* Go read next line - nothing more to see here. */
} else {
log("Nonexistent object %d found in rent file.", nr);
}
}
/* go read next line - nothing more to see here. */
/* handle vnum… */
continue;
}
/* If "temp" is NULL, we are most likely progressing through
* a non-existant object, so just keep continuing till we find
* the next object */
if (temp == NULL)
continue;
sscanf(line, "%s %d", tag, &num);
tag_argument(line, tag);
num = atoi(line);
switch(*tag) {
case 'A':
if (!strcmp(tag, "ADes")) {
char error[40];
snprintf(error, sizeof(error)-1, "rent(Ades):%s", temp->name);
temp->action_description = fread_string(fl, error);
} else if (!strcmp(tag, "Aff ")) {
sscanf(line, "%d %d %d", &t[0], &t[1], &t[2]);
if (t[0] < MAX_OBJ_AFFECT) {
temp->affected[t[0]].location = t[1];
temp->affected[t[0]].modifier = t[2];
switch (*tag) {
case 'V':
if (!strcmp(tag, "Vals")) {
char *p = line;
while (!isspace(*p) && *p) p++; /* skip "Vals" */
for (i = 0; i < NUM_OBJ_VAL_POSITIONS; i++) {
if (*p)
GET_OBJ_VAL(temp, i) = strtol(p, &p, 10);
else
GET_OBJ_VAL(temp, i) = 0;
}
}
}
break;
case 'C':
if (!strcmp(tag, "Cost"))
GET_OBJ_COST(temp) = num;
break;
case 'D':
if (!strcmp(tag, "Desc"))
temp->description = strdup(line);
break;
case 'E':
if(!strcmp(tag, "EDes")) {
struct extra_descr_data *new_desc;
char error[40];
snprintf(error, sizeof(error)-1, "rent(Edes): %s", temp->name);
if (temp->item_number != NOTHING && /* Regular object */
temp->ex_description && /* with ex_desc == prototype */
(temp->ex_description == obj_proto[real_object(temp->item_number)].ex_description))
temp->ex_description = NULL;
CREATE(new_desc, struct extra_descr_data, 1);
new_desc->keyword = fread_string(fl, error);
new_desc->description = fread_string(fl, error);
new_desc->next = temp->ex_description;
temp->ex_description = new_desc;
}
break;
case 'F':
if (!strcmp(tag, "Flag")) {
sscanf(line, "%s %s %s %s", f1, f2, f3, f4);
GET_OBJ_EXTRA(temp)[0] = asciiflag_conv(f1);
GET_OBJ_EXTRA(temp)[1] = asciiflag_conv(f2);
GET_OBJ_EXTRA(temp)[2] = asciiflag_conv(f3);
GET_OBJ_EXTRA(temp)[3] = asciiflag_conv(f4);
}
break;
case 'L':
if(!strcmp(tag, "Loc "))
current->locate = num;
break;
case 'N':
if (!strcmp(tag, "Name"))
temp->name = strdup(line);
break;
case 'P':
if (!strcmp(tag, "Perm")) {
sscanf(line, "%s %s %s %s", f1, f2, f3, f4);
GET_OBJ_AFFECT(temp)[0] = asciiflag_conv(f1);
GET_OBJ_AFFECT(temp)[1] = asciiflag_conv(f2);
GET_OBJ_AFFECT(temp)[2] = asciiflag_conv(f3);
GET_OBJ_AFFECT(temp)[3] = asciiflag_conv(f4);
}
break;
case 'R':
if (!strcmp(tag, "Rent"))
GET_OBJ_RENT(temp) = num;
break;
case 'S':
if (!strcmp(tag, "Shrt"))
temp->short_description = strdup(line);
break;
case 'T':
if (!strcmp(tag, "Type"))
GET_OBJ_TYPE(temp) = num;
break;
case 'W':
if (!strcmp(tag, "Wear")) {
sscanf(line, "%s %s %s %s", f1, f2, f3, f4);
GET_OBJ_WEAR(temp)[0] = asciiflag_conv(f1);
GET_OBJ_WEAR(temp)[1] = asciiflag_conv(f2);
GET_OBJ_WEAR(temp)[2] = asciiflag_conv(f3);
GET_OBJ_WEAR(temp)[3] = asciiflag_conv(f4);
}
else if (!strcmp(tag, "Wght"))
GET_OBJ_WEIGHT(temp) = num;
break;
case 'V':
if (!strcmp(tag, "Vals")) {
sscanf(line, "%d %d %d %d", &t[0], &t[1], &t[2], &t[3]);
for (i = 0; i < NUM_OBJ_VAL_POSITIONS; i++)
GET_OBJ_VAL(temp, i) = t[i];
}
break;
default:
log("Unknown tag in rentfile: %s", tag);
break;
/* handle other tags (Wght, Cost, Name, etc.) same as before */
default:
log("Unknown tag in rentfile: %s", tag);
break;
}
}

View file

@ -401,6 +401,21 @@ static void oedit_disp_spells_menu(struct descriptor_data *d)
write_to_output(d, "\r\n%sEnter spell choice (-1 for none) : ", nrm);
}
static void oedit_disp_values_menu(struct descriptor_data *d)
{
int i;
struct obj_data *obj = OLC_OBJ(d);
write_to_output(d, "\r\n-- Object Values Menu --\r\n");
for (i = 0; i < NUM_OBJ_VAL_POSITIONS; i++) {
write_to_output(d, "%d) Value[%d]: %d\r\n",
i+1, i, GET_OBJ_VAL(obj, i));
}
write_to_output(d, "Q) Quit to main menu\r\nEnter choice : ");
OLC_MODE(d) = OEDIT_VALUES_MENU;
}
/* Object value #1 */
static void oedit_disp_val1_menu(struct descriptor_data *d)
{
@ -617,74 +632,67 @@ static void oedit_disp_wear_menu(struct descriptor_data *d)
/* Display main menu. */
static void oedit_disp_menu(struct descriptor_data *d)
{
char buf1[MAX_STRING_LENGTH];
char buf2[MAX_STRING_LENGTH];
struct obj_data *obj;
char buf[MAX_STRING_LENGTH], buf2[MAX_STRING_LENGTH];
obj = OLC_OBJ(d);
get_char_colors(d->character);
clear_screen(d);
/* Build buffers for first part of menu. */
sprinttype(GET_OBJ_TYPE(obj), item_types, buf1, sizeof(buf1));
sprinttype(GET_OBJ_TYPE(obj), item_types, buf, sizeof(buf));
sprintbitarray(GET_OBJ_EXTRA(obj), extra_bits, EF_ARRAY_MAX, buf2);
/* Build first half of menu. */
write_to_output(d,
"-- Item number : [%s%d%s]\r\n"
"%s1%s) Keywords : %s%s\r\n"
"%s2%s) S-Desc : %s%s\r\n"
"%s3%s) L-Desc :-\r\n%s%s\r\n"
"%s4%s) A-Desc :-\r\n%s%s"
"%s5%s) Type : %s%s\r\n"
"%s6%s) Extra flags : %s%s\r\n",
"-- Item Number: [%d]\r\n"
"1) Type : %s\r\n"
"2) Extra flags : %s\r\n",
OLC_NUM(d), buf, buf2);
cyn, OLC_NUM(d), nrm,
grn, nrm, yel, (obj->name && *obj->name) ? obj->name : "undefined",
grn, nrm, yel, (obj->short_description && *obj->short_description) ? obj->short_description : "undefined",
grn, nrm, yel, (obj->description && *obj->description) ? obj->description : "undefined",
grn, nrm, yel, (obj->action_description && *obj->action_description) ? obj->action_description : "Not Set.\r\n",
grn, nrm, cyn, buf1,
grn, nrm, cyn, buf2
);
/* Send first half then build second half of menu. */
sprintbitarray(GET_OBJ_WEAR(OLC_OBJ(d)), wear_bits, EF_ARRAY_MAX, buf1);
sprintbitarray(GET_OBJ_AFFECT(OLC_OBJ(d)), affected_bits, EF_ARRAY_MAX, buf2);
sprintbitarray(GET_OBJ_WEAR(obj), wear_bits, TW_ARRAY_MAX, buf2);
write_to_output(d,
"3) Wear flags : %s\r\n", buf2);
write_to_output(d,
"%s7%s) Wear flags : %s%s\r\n"
"%s8%s) Weight : %s%d\r\n"
"%s9%s) Cost : %s%d\r\n"
"%sA%s) Cost/Day : %s%d\r\n"
"%sB%s) Timer : %s%d\r\n"
"%sC%s) Values : %s%d %d %d %d\r\n"
"%sD%s) Applies menu\r\n"
"%sE%s) Extra descriptions menu: %s%s%s\r\n"
"%sM%s) Min Level : %s%d\r\n"
"%sP%s) Perm Affects: %s%s\r\n"
"%sS%s) Script : %s%s\r\n"
"%sW%s) Copy object\r\n"
"%sX%s) Delete object\r\n"
"%sQ%s) Quit\r\n"
"Enter choice : ",
"4) Weight : %d\r\n"
"5) Cost : %d\r\n"
"6) Rent : %d\r\n"
"7) Timer : %d\r\n"
"8) Min level : %d\r\n",
GET_OBJ_WEIGHT(obj),
GET_OBJ_COST(obj),
GET_OBJ_RENT(obj),
GET_OBJ_TIMER(obj),
GET_OBJ_LEVEL(obj));
grn, nrm, cyn, buf1,
grn, nrm, cyn, GET_OBJ_WEIGHT(obj),
grn, nrm, cyn, GET_OBJ_COST(obj),
grn, nrm, cyn, GET_OBJ_RENT(obj),
grn, nrm, cyn, GET_OBJ_TIMER(obj),
grn, nrm, cyn, GET_OBJ_VAL(obj, 0),
GET_OBJ_VAL(obj, 1),
GET_OBJ_VAL(obj, 2),
GET_OBJ_VAL(obj, 3),
grn, nrm, grn, nrm, cyn, obj->ex_description ? "Set." : "Not Set.", grn,
grn, nrm, cyn, GET_OBJ_LEVEL(obj),
grn, nrm, cyn, buf2,
grn, nrm, cyn, OLC_SCRIPT(d) ? "Set." : "Not Set.",
grn, nrm,
grn, nrm,
grn, nrm
);
/* Old-style values (still shown for quick reference) */
write_to_output(d,
"9) Value[0] : %d\r\n"
"A) Value[1] : %d\r\n"
"B) Value[2] : %d\r\n"
"C) Value[3] : %d\r\n",
GET_OBJ_VAL(obj, 0),
GET_OBJ_VAL(obj, 1),
GET_OBJ_VAL(obj, 2),
GET_OBJ_VAL(obj, 3));
/* New dynamic values menu */
write_to_output(d,
"V) Edit object values (all %d slots)\r\n",
NUM_OBJ_VAL_POSITIONS);
/* Other menus (applies, descriptions, etc.) */
write_to_output(d,
"D) Extra descriptions menu\r\n"
"E) Apply menu\r\n"
"F) Affects (permanent bitvectors)\r\n"
"G) Action description : %s\r\n"
"H) Script menu\r\n",
obj->action_description ? obj->action_description : "<None>");
/* Quit */
write_to_output(d,
"Q) Quit\r\n"
"Enter choice : ");
OLC_MODE(d) = OEDIT_MAIN_MENU;
}
@ -830,6 +838,10 @@ void oedit_parse(struct descriptor_data *d, char *arg)
OLC_SCRIPT_EDIT_MODE(d) = SCRIPT_MAIN_MENU;
dg_script_menu(d);
return;
case 'V':
case 'v':
oedit_disp_values_menu(d);
return;
case 'w':
case 'W':
write_to_output(d, "Copy what object? ");
@ -945,6 +957,32 @@ void oedit_parse(struct descriptor_data *d, char *arg)
oedit_disp_perm_menu(d);
return;
case OEDIT_VALUES_MENU:
if (*arg == 'Q' || *arg == 'q') {
oedit_disp_menu(d);
return;
}
{
int i = atoi(arg) - 1;
if (i >= 0 && i < NUM_OBJ_VAL_POSITIONS) {
OLC_VAL(d) = i;
write_to_output(d, "Enter new integer for Value[%d]: ", i);
OLC_MODE(d) = OEDIT_VALUE_X;
} else {
write_to_output(d, "Invalid choice.\r\n");
oedit_disp_values_menu(d);
}
}
break;
case OEDIT_VALUE_X:
{
int i = OLC_VAL(d);
GET_OBJ_VAL(OLC_OBJ(d), i) = atoi(arg);
oedit_disp_values_menu(d);
}
break;
case OEDIT_VALUE_1:
number = atoi(arg);
switch (GET_OBJ_TYPE(OLC_OBJ(d))) {

View file

@ -672,8 +672,8 @@ struct extra_descr_data
/* object-related structures */
/**< Number of elements in the object value array. Raising this will provide
* more configurability per object type, and shouldn't break anything.
* DO NOT LOWER from the default value of 4. */
#define NUM_OBJ_VAL_POSITIONS 4
* DO NOT LOWER from the default value of 8. */
#define NUM_OBJ_VAL_POSITIONS 8
/** object flags used in obj_data. These represent the instance values for
* a real object, values that can change during gameplay. */
@ -1291,6 +1291,7 @@ struct recent_player
#define VAL_ARMOR_BULK 1
#define VAL_ARMOR_MAGIC_BONUS 2
#define VAL_ARMOR_FLAGS 3
#define VAL_ARMOR_DURABILITY 4
/* Armor flags (value[3]) */
#define ARMF_STEALTH_DISADV (1 << 0) /* Disadvantage on Stealth */

View file

@ -41,8 +41,10 @@ static struct obj_data *make_armor(int piece_ac, int bulk, int magic, int flags)
GET_OBJ_VAL(o, VAL_ARMOR_BULK) = bulk;
GET_OBJ_VAL(o, VAL_ARMOR_MAGIC_BONUS) = magic;
GET_OBJ_VAL(o, VAL_ARMOR_FLAGS) = flags;
GET_OBJ_VAL(o, VAL_ARMOR_DURABILITY) = 100; /* start at full durability */
return o;
}
static void equip_at(struct char_data *ch, int wear_pos, struct obj_data *o) {
if (wear_pos < 0 || wear_pos >= NUM_WEARS) {
fprintf(stderr, "equip_at: wear_pos %d out of bounds (NUM_WEARS=%d)\n", wear_pos, NUM_WEARS);