Working (I think pending further testing but so far seems good) I had to add an integer to the object struct to store the original attack type
Code:
ACMD(do_rune)
{
struct obj_data *weapon = NULL;
struct obj_data *obj, *next_obj;
struct affected_type af;
char weapon_name[MAX_STRING_LENGTH];
char rune_type[MAX_INPUT_LENGTH];
char buf[MAX_INPUT_LENGTH];
int found = FALSE, i, element = APPLY_NONE;
two_arguments(argument, weapon_name, rune_type);
if (!can_see_room(ch, IN_ROOM(ch))) {
send_to_char(ch, "It's too dark for you to see!\r\n");
return;
}
/* No rune while fighting */
if (IS_FIGHTING(ch)) {
send_to_char(ch, "You are too busy fighting to do that right now!\r\n");
return;
}
if (!*weapon_name || !*rune_type) {
send_to_char(ch, "Usage: rune <weapon> <element>\r\n");
return;
}
if (!*weapon_name) {
send_to_char(ch, "What do you wish to imbue?\r\n");
return;
}
// Check if the player provided a valid rune type
if (!*rune_type) {
send_to_char(ch, "What type of rune do you want to add?\r\n");
return;
}
for (obj = ch->carrying; obj; obj = next_obj) {
next_obj = obj->next_content;
if (obj == NULL)
return;
else if (!(weapon = get_obj_in_list_vis(ch->carrying, ch, weapon_name)))
continue;
else
found = TRUE;
}
if (found == FALSE) {
sprintf(buf, "You don't have %s in your inventory!\r\n", weapon_name);
send_to_char(ch, buf);
return;
}
if (found && (GET_OBJ_TYPE(weapon) != ITEM_WEAPON)) {
sprintf(buf, "It doesn't look like %s would make a good weapon...\r\n", weapon_name);
send_to_char(ch, buf);
return;
}
if (GET_OBJ_RUNED(weapon) == 1) {
send_to_char(ch, "This weapon is already imbued with runes!\r\n");
return;
}
/* Check if element is valid */
if (is_abbrev(rune_type, "fire")) {
element = 15;
} else if (is_abbrev(rune_type, "cold")) {
element = TYPE_COLD;
} else if (is_abbrev(rune_type, "electric")) {
element = TYPE_ELEC;
} else if (is_abbrev(rune_type, "acid")) {
element = TYPE_ACID;
} else if (is_abbrev(rune_type, "poison")) {
element = TYPE_POIS;
} else {
send_to_char(ch, "Invalid element!\r\n");
return;
}
// Store the original attack type
weapon->original_attack_type = GET_OBJ_VAL(weapon, 3);
GET_OBJ_RUNED(weapon) += 1; //Prevents from doing multiple runes while one is already active
GET_OBJ_VAL(weapon, 3) = element;
SET_BIT_AR(GET_OBJ_EXTRA(weapon), ITEM_MAGIC);
GET_OBJ_TIMER(weapon) = 2;
act("$n enchants $p with magical runes!", TRUE, ch, weapon, 0, TO_ROOM);
act("You enchant $p with magical runes!", FALSE, ch, weapon, 0, TO_CHAR);
}
Code:
/* Rune Ward */
if (GET_OBJ_TYPE(j) == ITEM_WEAPON) {
if (GET_OBJ_TIMER(j) > 0)
GET_OBJ_TIMER(j)--;
if (!GET_OBJ_TIMER(j)) {
if (GET_OBJ_RUNED(j) == 1) {
// Reset the weapon's attack type to its original value
// Display the message if it hasn't been displayed yet
if (j->carried_by) {
act("The magical runes on $p fade away.", FALSE, j->carried_by, j, 0, TO_CHAR);
}
if (j->worn_by) {
act("The magical runes on $p fade away.", FALSE, j->worn_by, j, 0, TO_CHAR);
}
// Display the message to the room if the item is on the ground
act("The magical runes on $p fade away.", FALSE, NULL, j, NULL, TO_ROOM);
// Set the flag to indicate that the message has been displayed
GET_OBJ_RUNED(j) = 0;
GET_OBJ_VAL(j, 3) = j->original_attack_type;
}
} else {
// Set the flag to indicate that the weapon is currently runed
GET_OBJ_RUNED(j) = 1;
}
}
Code:
struct obj_data {
obj_vnum item_number; /* Where in data-base */
room_rnum in_room; /* In what room -1 when conta/carr */
struct obj_flag_data obj_flags; /* Object information */
struct obj_affected_type affected[MAX_OBJ_AFFECT]; /* affects */
struct obj_bonus_prof_type bonus_profs[MAX_OBJ_PROF_BONUSES]; /* bonus spell/skill profs */
char *name; /* Title of object :get etc. */
char *description; /* When in room */
char *short_description; /* when worn/carry/in cont. */
char *action_description; /* What to write when used */
struct extra_descr_data *ex_description; /* extra descriptions */
struct char_data *carried_by; /* Carried by :NULL in room/conta */
struct char_data *worn_by; /* Worn by? */
sh_int worn_on; /* Worn where? */
struct obj_data *in_obj; /* In what object NULL when none */
struct obj_data *contains; /* Contains objects */
long id; /* used by DG triggers */
time_t generation; /* creation time for dupe check */
unsigned long long unique_id; /* random bits for dupe check */
struct trig_proto_list *proto_script; /* list of default triggers */
struct script_data *script; /* script info for the object */
struct obj_data *next_content; /* For 'contains' lists */
struct obj_data *next; /* For the object list */
struct char_data *sitting_here;/* who is sitting on furniture*/
int original_attack_type; // Rune Ward
};