/************************************************************************ Realms of Aurealis James Rhone aka Vall of RoA fightmes.c Code dealing with sending the various damage messages to characters. Also contains CMOLCv0.1 (RoA) Combat Message Online Creation Based on RoAOLCv2.1 standards. Now RoAOLCable. 1/10/97 ******** Heavily modified and expanded ******** *** BE AWARE OF ALL RIGHTS AND RESERVATIONS *** ******** Heavily modified and expanded ******** All rights reserved henceforth. Please note that no guarantees are associated with any code from Realms of Aurealis. All code which has been released to the general public has been done so with an 'as is' pretense. RoA is based on both Diku and CircleMUD and ALL licenses from both *MUST* be adhered to as well as the RoA license. *** Read, Learn, Understand, Improve *** *************************************************************************/ #include "conf.h" #include "sysdep.h" #include "structures.h" #include "utils.h" #include "comm.h" #include "handler.h" #include "interpreter.h" #include "acmd.h" #include "db.h" #include "magic.h" #include "mudlimits.h" #include "roaolc.h" #include "global.h" #include "exshell.h" /* External variables / structures */ extern struct message_list fight_messages[MAX_MESSAGES]; // external functions extern char *delete_doubledollar(char *string); // internal functions void messedit_top_menu(chdata *ch, char *input_str); void messedit_confirm_message_quit(chdata *ch, char *input_str); void messedit_confirm_message_save(chdata *ch, char *input_str); void messedit_edit_message(chdata *ch, char *input_str); void messedit_confirm_quit(chdata *ch, char *input_str); void dupe_mesg_over(struct message_type *orig, struct message_type *m); struct message_type *get_mesg(struct message_type *m, int num); int count_mesgs(struct message_type *m); struct attack_hit_type { char *singular; char *plural; } attack_hit_text[] = { { "hit", "hits" }, { "pound", "pounds" }, { "pierce", "pierces" }, { "slash", "slashes" }, { "blast", "blasts" }, { "whip", "whips" }, { "pierce", "pierces" }, { "claw", "claws" }, { "bite", "bites" }, { "sting", "stings" }, { "crush", "crushes" }, { "BDEFINED", "BDEFINED"} /* Builder defined */ }; // revamped, 1/10/97, jtrhone void clear_messages(void) { int i; for (i = 0; i < MAX_MESSAGES; i++) { fight_messages[i].a_type = 0; fight_messages[i].num_mesgs = 0; fight_messages[i].msg = NULL; } } // free this particular message (part of a larger message struct) void free_this_message(struct message_type *m) { FREENULL(m->die_msg.attacker_msg); FREENULL(m->die_msg.victim_msg); FREENULL(m->die_msg.room_msg); FREENULL(m->miss_msg.attacker_msg); FREENULL(m->miss_msg.victim_msg); FREENULL(m->miss_msg.room_msg); FREENULL(m->hit_msg.attacker_msg); FREENULL(m->hit_msg.victim_msg); FREENULL(m->hit_msg.room_msg); FREENULL(m->god_msg.attacker_msg); FREENULL(m->god_msg.victim_msg); FREENULL(m->god_msg.room_msg); FREENULL(m); } // go thru each message, traverse list of each one, free em up void free_messages(void) { int i; struct message_type *m; for (i = 0; i < MAX_MESSAGES; i++) if (fight_messages[i].a_type > 0 && fight_messages[i].msg) { while (fight_messages[i].msg) { m = fight_messages[i].msg; fight_messages[i].msg = m->next; free_this_message(m); } } } // save the combat messages to file (copy over first) void save_messages(void) { FILE *fp; struct message_type *m; int i; sprintf(buf, "cp %s %s.BAK", MESS_FILE, MESS_FILE); roa_system(buf); if (!(fp = fopen(MESS_FILE, "w"))) { sprintf(buf2, "Error writing combat message file %s", MESS_FILE); perror(buf2); exit(0); } i = 0; while (fight_messages[i].a_type > 0 && i < MAX_MESSAGES) { m = fight_messages[i].msg; while (m) { fprintf(fp, "M\n %d\n", fight_messages[i].a_type); fprintf(fp, "L %d\n", m->level); fprintf(fp, "%s~\n", m->die_msg.attacker_msg); fprintf(fp, "%s~\n", m->die_msg.victim_msg); fprintf(fp, "%s~\n", m->die_msg.room_msg); fprintf(fp, "%s~\n", m->miss_msg.attacker_msg); fprintf(fp, "%s~\n", m->miss_msg.victim_msg); fprintf(fp, "%s~\n", m->miss_msg.room_msg); fprintf(fp, "%s~\n", m->hit_msg.attacker_msg); fprintf(fp, "%s~\n", m->hit_msg.victim_msg); fprintf(fp, "%s~\n", m->hit_msg.room_msg); fprintf(fp, "%s~\n", m->god_msg.attacker_msg); fprintf(fp, "%s~\n", m->god_msg.victim_msg); fprintf(fp, "%s~\n", m->god_msg.room_msg); m = m->next; } i++; } fprintf(fp, "$~\n"); fclose(fp); } // given a mesg slot and level, return ptr to appropriate mesg struct message_type *locate_appropriate_mesg(int i, int level) { int j; // to be used as a MAX_MESG_LINK check sometime struct message_type *m, *pm; for (j = 1, pm = m = fight_messages[i].msg; m; j++) { pm = m; m = m->next; if (!m || level < m->level) break; } return pm; } // allocate and insert message into appropriate slot, return ptr to new mesg struct message_type *insert_combat_message(int i, int level, int type) { struct message_type *insmesg; struct message_type *newmesg; fight_messages[i].num_mesgs++; fight_messages[i].a_type = type; CREATE(newmesg, struct message_type, 1); newmesg->level = level; // now find where to insert into, not just top anymore if (!fight_messages[i].msg) // just insert first one { fight_messages[i].msg = newmesg; newmesg->next = NULL; } else // locate a spot based on level { insmesg = locate_appropriate_mesg(i, level); newmesg->next = insmesg->next; insmesg->next = newmesg; } return newmesg; } // send a file ptr and message struct, fill it in void fill_message_data(FILE *f1, struct message_type *messages) { messages->die_msg.attacker_msg = fread_string(f1, buf2); messages->die_msg.victim_msg = fread_string(f1, buf2); messages->die_msg.room_msg = fread_string(f1, buf2); messages->miss_msg.attacker_msg = fread_string(f1, buf2); messages->miss_msg.victim_msg = fread_string(f1, buf2); messages->miss_msg.room_msg = fread_string(f1, buf2); messages->hit_msg.attacker_msg = fread_string(f1, buf2); messages->hit_msg.victim_msg = fread_string(f1, buf2); messages->hit_msg.room_msg = fread_string(f1, buf2); messages->god_msg.attacker_msg = fread_string(f1, buf2); messages->god_msg.victim_msg = fread_string(f1, buf2); messages->god_msg.room_msg = fread_string(f1, buf2); } // load the combat messages from disk void load_messages(void) { FILE *f1; int i, type, level; struct message_type *newmesg; char chk[100]; char letter; if (!(f1 = fopen(MESS_FILE, "r"))) { sprintf(buf2, "Error reading combat message file %s", MESS_FILE); perror(buf2); exit(0); } clear_messages(); fscanf(f1, " %s \n", chk); while (*chk == 'M') { fscanf(f1, " %d\n", &type); // now check for RoA message level letter=fread_letter(f1); ungetc(letter, f1); if (letter == 'L') fscanf(f1, "L %d\n",&level); else level = 0; // find the right skill/spell number to insert into for (i = 0; (i < MAX_MESSAGES) && (fight_messages[i].a_type != type) && (fight_messages[i].a_type); i++) ; if (i >= MAX_MESSAGES) { log("SYSERR: Too many combat messages."); exit(0); } newmesg = insert_combat_message(i, level, type); fill_message_data(f1, newmesg); fscanf(f1, " %s \n", chk); } fclose(f1); sprintf(buf, "SYSUPD: %d combat message slots loaded.",i); mudlog(buf, BRF, LEV_IMM, TRUE); } // basically, just free and reload messages void reload_messages(void) { free_messages(); clear_messages(); load_messages(); } ACMD(do_reload_messages) { if (IS_NPC(ch)) return; reload_messages(); send_to_char("Messages reloaded.\n\r",ch); sprintf(buf, "IMMUPD: %s reloaded combat messages.",GET_NAME(ch)); mudlog(buf, CMP, MAX(LEV_IMM, GET_INVIS_LEV(ch)), TRUE); } ACMD(do_save_messages) { if (IS_NPC(ch)) return; save_messages(); send_to_char("Messages saved.\n\r",ch); sprintf(buf, "IMMUPD: %s saved combat messages.",GET_NAME(ch)); mudlog(buf, CMP, MAX(LEV_IMM, GET_INVIS_LEV(ch)), TRUE); } // replace the strings for weapons in dam_message() (to be changed -roa) char *replace_string(char *str, char *weapon_singular, char *weapon_plural) { static char buf[256]; char *cp; cp = buf; for (; *str; str++) { if (*str == '#') { switch (*(++str)) { case 'W' : for (; *weapon_plural; *(cp++) = *(weapon_plural++)) ; break; case 'w' : for (; *weapon_singular; *(cp++) = *(weapon_singular++)) ; break; default : *(cp++) = '#'; break; } } else *(cp++) = *str; *cp = 0; } /* For */ return(buf); } // a better way? someday ill waste mind time on this... jtrhone int get_dam_msgnum(int dam) { int msgnum; if (dam == 0) msgnum = 0; else if (dam <= 2) msgnum = 1; else if (dam <= 4) msgnum = 2; else if (dam <= 6) msgnum = 3; else if (dam <= 8) msgnum = 4; else if (dam <= 10) msgnum = 5; else if (dam <= 12) msgnum = 6; else if (dam <= 14) msgnum = 7; else if (dam <= 16) msgnum = 8; else if (dam <= 18) msgnum = 9; else if (dam <= 20) msgnum = 10; else if (dam <= 23) msgnum = 11; else if (dam <= 26) msgnum = 12; else if (dam <= 30) msgnum = 13; else if (dam <= 34) msgnum = 14; else if (dam <= 37) msgnum = 15; else if (dam <= 41) msgnum = 16; else if (dam <= 47) msgnum = 17; else if (dam <= 53) msgnum = 18; else if (dam <= 59) msgnum = 19; else if (dam <= 65) msgnum = 20; else if (dam <= 71) msgnum = 21; else if (dam <= 77) msgnum = 22; else if (dam <= 85) msgnum = 23; else msgnum = 24; return msgnum; } // send a message to room/char/vict based on damage and weapon void dam_message(int dam, chdata *ch, chdata *victim, int w_type) { obdata *wield; char *buf; int msgnum; static struct dam_weapon_type { char *to_room; char *to_char; char *to_victim; } dam_weapons[] = { /* use #w for singular (i.e. "slash") and #W for plural (i.e. "slashes") */ { "$n misses $N with $s #w.", /* 0: 0 */ "You miss $N with your #w.", "$n misses you with $s #w." }, { "$n tickles $N with $s #w.", /* 1: 1..2 */ "You tickle $N as you #w $M.", "$n tickles you as $e #W you." }, { "$n barely #W $N.", /* 2: 3..4 */ "You barely #w $N.", "$n barely #W you." }, { "$n #W $N.", /* 3: 5..6 */ "You #w $N.", "$n #W you." }, { "$n nicks $N with $s #w.", /* 4: 7..8 */ "You nick $N with your #w.", "$n nicks you with $s #w." }, { "$n #W $N hard.", /* 5: 9..10 */ "You #w $N hard.", "$n #W you hard." }, { "$n #W $N very hard.", /* 6: 11..12 */ "You #w $N very hard.", "$n #W you very hard." }, { "$n #W $N extremely hard.", /* 7: 13..14 */ "You #w $N extremely hard.", "$n #W you extremely hard." }, { "$n dismembers $N with $s #w.", /* 8: 15..16 */ "You dismember $N with your #w.", "$n dismembers you with $s #w." }, { "$n shakes $N with $s #w.", /* 9: 17..18 */ "You shake $N with your #w.", "$n shakes you with $s #w." }, { "$n decomposes $N with $s #w.", /* 10: 19..20 */ "You decompose $N with your #w.", "$n decomposes you with $s #w." }, { "$n Maims $N with $s #w.", /* 11 : 21..23 */ "You Maim $N with your #w.", "$n Maims you with $s #w." }, { "$n Shreds $N with $s #w.", /* 12 : 24..26 */ "You Shred $N with your #w.", "$n Shreds you with $s #w." }, { "$n Massacres $N to small fragments with $s #w.", /* 13: 27..30 */ "You Massacre $N to small fragments with your #w.", "$n Massacres you to small fragments with $s #w." }, { "$n Obliterates $N with $s nasty #w!", /* 14: 31..34 */ "You Obliterate $N with your nasty #w!", "$n Obliterates you with $s nasty #w!" }, { "$n Implodes $N with $s nasty #w!", /* 15: 34..37 */ "You Implode $N with your nasty #w!", "$n Implodes you with $s nasty #w!" }, { "$n PULVERIZES $N with $s wicked #w!!", /* 16: 37..41 */ "You PULVERIZE $N with your wicked #w!!", "$n PULVERIZES you with $s wicked #w!!" }, { "$n DISINTEGRATES $N with $s deadly #w!!", /* 17: 42..47 */ "You DISINTEGRATE $N with your deadly #w!!", "$n DISINTEGRATES you with $s deadly #w!!" }, { "$n %BLIQUIFIES%0 $N with $s deadly #w!!", /* 18: 48..53 */ "You %BLIQUIFY%0 $N with your deadly #w!!", "$n %BLIQUIFIES%0 you with $s deadly #w!!" }, { "$n %BSUBLIMATES%0 $N with $s deadly #w!!", /* 19: 54..59 */ "You %BSUBLIMATE%0 $N with your deadly #w!!", "$n %BSUBLIMATES%0 you with $s deadly #w!!" }, { "$n %5ANNIHILATES%0 $N with $s triumphant #w!!", /* 20: 60..65 */ "You %5ANNIHILATE%0 $N with your triumphant #w!!", "$n %5ANNIHILATES%0 you with $s triumphant #w!!" }, { "$n %5ATOMIZES%0 $N with $s triumphant #w!!", /* 21: 66.. 71 */ "You %5ATOMIZE%0 $N with your triumphant #w!!", "$n %5ATOMIZES%0 you with $s triumphant #w!!" }, { "$n %5EVAPORATES%0 $N with $s triumphant #w!!", /* 22: 72..77 */ "You %5EVAPORATE%0 $N with your triumphant #w!!", "$n %5EVAPORATES%0 you with $s triumphant #w!!" }, { "$n %5ERADICATES%0 $N with $s triumphant #w!!", /* 23: 78..85 */ "You %5ERADICATE%0 $N with your triumphant #w!!", "$n %5ERADICATES%0 you with $s triumphant #w!!" }, { "$n %5%BG E T S M E D I E V A L%0 on $N with $s triumphant #w!!", /* 24: >85 */ "You %5%BG E T M E D I E V A L%0 on $N with your triumphant #w!!", "$n %5%BG E T S M E D I E V A L%0 on you with $s triumphant #w!!" } }; w_type -= TYPE_HIT; /* Change to base of table with text */ wield = EQ(ch, W_WIELD); msgnum = get_dam_msgnum(dam); /* damage message to onlookers */ if (wield && wield->weap_plur && wield->weap_sing && w_type == TYPE_BDEFINED - TYPE_HIT) buf = replace_string(dam_weapons[msgnum].to_room, wield->weap_sing, wield->weap_plur); else buf = replace_string(dam_weapons[msgnum].to_room, attack_hit_text[w_type].singular, attack_hit_text[w_type].plural); act(buf, FALSE, ch, wield, victim, TO_NOTVICT); /* damage message to damager */ if (wield && wield->weap_plur && wield->weap_sing && w_type == TYPE_BDEFINED - TYPE_HIT) buf = replace_string(dam_weapons[msgnum].to_char, wield->weap_sing, wield->weap_plur); else buf = replace_string(dam_weapons[msgnum].to_char, attack_hit_text[w_type].singular, attack_hit_text[w_type].plural); act(buf, FALSE, ch, wield, victim, TO_CHAR); /* damage message to damagee */ if (ch != victim) { if (wield && wield->weap_plur && wield->weap_sing && w_type == TYPE_BDEFINED - TYPE_HIT) buf = replace_string(dam_weapons[msgnum].to_victim, wield->weap_sing, wield->weap_plur); else buf = replace_string(dam_weapons[msgnum].to_victim, attack_hit_text[w_type].singular, attack_hit_text[w_type].plural); act(buf, FALSE, ch, wield, victim, TO_VICT); } } // send spell type message from the fight_messages[] array read in from disk void spl_message(int dam, chdata *ch, chdata *vict, int spl) { int i; struct message_type *m; for (i = 0; i < MAX_MESSAGES; i++) { if (fight_messages[i].a_type == spl) { m = locate_appropriate_mesg(i, GET_LEVEL(ch)); if (IS_IMMORTAL(vict)) { act(m->god_msg.attacker_msg, FALSE, ch, EQ(ch, W_WIELD), vict, TO_CHAR); if (ch != vict) /* why send it twice? */ act(m->god_msg.victim_msg, FALSE, ch, EQ(ch, W_WIELD), vict, TO_VICT); act(m->god_msg.room_msg, FALSE, ch, EQ(ch, W_WIELD), vict, TO_NOTVICT); } else if (dam) { if (GET_POS(vict) == POS_DEAD) { act(m->die_msg.attacker_msg, FALSE, ch, EQ(ch, W_WIELD), vict, TO_CHAR); if (ch != vict) /* why send it twice? */ act(m->die_msg.victim_msg, FALSE, ch, EQ(ch, W_WIELD), vict, TO_VICT); act(m->die_msg.room_msg, FALSE, ch, EQ(ch, W_WIELD), vict, TO_NOTVICT); } else { act(m->hit_msg.attacker_msg, FALSE, ch, EQ(ch, W_WIELD), vict, TO_CHAR); if (ch != vict) /* why send it twice? */ act(m->hit_msg.victim_msg, FALSE, ch, EQ(ch, W_WIELD), vict, TO_VICT); act(m->hit_msg.room_msg, FALSE, ch, EQ(ch, W_WIELD), vict, TO_NOTVICT); } } else if (!dam) { act(m->miss_msg.attacker_msg, FALSE, ch, EQ(ch, W_WIELD), vict, TO_CHAR); act(m->miss_msg.victim_msg, FALSE, ch, EQ(ch, W_WIELD), vict, TO_VICT); act(m->miss_msg.room_msg, FALSE, ch, EQ(ch, W_WIELD), vict, TO_NOTVICT); } } } } // use this to parse out the damage message to ppl, call from fight.c (damage()) void send_combat_messages(int dam, chdata *ch, chdata *vict, int spl) { // if its normal weapon type hit if (spl >= TYPE_HIT && spl <= TYPE_BDEFINED) { if (!EQ(ch, W_WIELD)) spl = TYPE_HIT; dam_message(dam, ch, vict, spl); } else spl_message(dam, ch, vict, spl); } // called from damage() in fight.c, will add randomness here soon void send_position_messages(int dam, chdata *ch, chdata *victim) { switch (GET_POS(victim)) { case POS_MORTALLYW: act("$n is mortally wounded, and will die soon, if not aided.", TRUE, victim, 0, 0, TO_ROOM); send_to_char("You are mortally wounded, and will die soon, if not aided.\n\r", victim); break; case POS_INCAP: act("$n is incapacitated and will slowly die, if not aided.", TRUE, victim, 0, 0, TO_ROOM); send_to_char("You are incapacitated an will slowly die, if not aided.\n\r", victim); break; case POS_STUNNED: act("$n is stunned, but will probably regain consciousness again.", TRUE, victim, 0, 0, TO_ROOM); send_to_char("You're stunned, but will probably regain consciousness again.\n\r", victim); break; case POS_DEAD: // don't send this AND death message -roa // act("$n is dead! R.I.P.", TRUE, victim, 0, 0, TO_ROOM); send_to_char("Darkness settles in as you breath your last breath...\n\r", victim); break; default: /* >= POS SLEEPING */ if (dam > (GET_MAX_HIT(victim) / 5)) act("%B%5AAAAAAHHHH%0!! That really %B%1HURT%0!!!", FALSE, victim, 0, 0, TO_CHAR); if (GET_HIT(victim) < (GET_MAX_HIT(victim) / 5)) { act("You are %1BLEEDING%0 seriously!", FALSE, victim, 0, 0, TO_CHAR); if (MOB_FLAGGED(victim, MOB_WIMPY)) do_flee(victim, "", 0, 0); } if (IS_PC(victim) && WIMP_LEVEL(victim) && victim != ch && GET_HIT(victim) <= WIMP_LEVEL(victim)) { send_to_char("You wimp out, and attempt to flee!\n\r", victim); do_flee(victim, "", 0, 0); } break; } } // RoA CMOLC V0.1 BETA Combat Message OnLine Creation version 0.1 // actual editting/creating/saving begins here ACMD(do_mess_edit) { char *argu = argument; int slot, cnt; skip_spaces(&argu); if (!*argu) { sprintf(buf, "Combat Messages\n\r---------------\n\r"); for (cnt = slot = 0; slot<MAX_MESSAGES && fight_messages[slot].a_type>0; slot++) { if (fight_messages[slot].a_type < MAX_SPELLS) strcpy(buf2, skill_names[fight_messages[slot].a_type]); else strcpy(buf2, "Out of Range"); sprintf(buf+strlen(buf), "(%%B%3d%%0) %%6%-15.15s%%0-%3d ",slot, buf2, fight_messages[slot].a_type); cnt++; if (!(cnt % 3)) str_cat(buf, "\n\r", MAX_STRING_LENGTH, "do_mess_edit"); } page_string(ch->desc, buf, 1); return; } if (!is_number(argu)) { send_to_char("Usage: mesgedit < slot number >\n\r",ch); send_to_char("No arguments for a list of slot correlations.\n\r",ch); return; } slot = atoi(argu); if (slot < 0 || slot >= MAX_MESSAGES) { send_to_char("Usage: mesgedit < slot number >\n\r",ch); send_to_char("No arguments for a list of slot correlations.\n\r",ch); return; } SET_BIT(PLR_FLAGS(ch), PLR_BUILDING); ch->pc_specials->index = slot; ch->pc_specials->index2 = 0; MENU_DEPTH(ch) = 0; ch->pc_specials->field_changed = FALSE; menu_jump(ch, messedit_top_menu); } int count_mesgs(struct message_type *m) { struct message_type *tm; int i; for (i = 0, tm = m; tm; tm = tm->next, i++) ; return i; } struct message_type *get_mesg(struct message_type *m, int num) { int i; struct message_type *tm; if (!m || num <= 0 || num > count_mesgs(m)) return NULL; for (i=1, tm=m; tm && i < num; i++, tm=tm->next) ; return tm; } // duplicate a another copy of orig into m void dupe_mesg_over(struct message_type *orig, struct message_type *m) { m->level = orig->level; FREENULL(m->die_msg.attacker_msg); m->die_msg.attacker_msg = str_dup(orig->die_msg.attacker_msg); FREENULL(m->die_msg.victim_msg); m->die_msg.victim_msg = str_dup(orig->die_msg.victim_msg); FREENULL(m->die_msg.room_msg); m->die_msg.room_msg = str_dup(orig->die_msg.room_msg); FREENULL(m->miss_msg.attacker_msg); m->miss_msg.attacker_msg = str_dup(orig->miss_msg.attacker_msg); FREENULL(m->miss_msg.victim_msg); m->miss_msg.victim_msg = str_dup(orig->miss_msg.victim_msg); FREENULL(m->miss_msg.room_msg); m->miss_msg.room_msg = str_dup(orig->miss_msg.room_msg); FREENULL(m->hit_msg.attacker_msg); m->hit_msg.attacker_msg = str_dup(orig->hit_msg.attacker_msg); FREENULL(m->hit_msg.victim_msg); m->hit_msg.victim_msg = str_dup(orig->hit_msg.victim_msg); FREENULL(m->hit_msg.room_msg); m->hit_msg.room_msg = str_dup(orig->hit_msg.room_msg); FREENULL(m->god_msg.attacker_msg); m->god_msg.attacker_msg = str_dup(orig->god_msg.attacker_msg); FREENULL(m->god_msg.victim_msg); m->god_msg.victim_msg = str_dup(orig->god_msg.victim_msg); FREENULL(m->god_msg.room_msg); m->god_msg.room_msg = str_dup(orig->god_msg.room_msg); } // confirm that user wants to quit editting a message block void messedit_confirm_message_quit(chdata *ch, char *input_str) { char buf[MAX_STRING_LENGTH]; char *p; if (!input_str) { MENU_PROMPT(ch) = "Quit editting message block (yes/NO)? "; return; } strcpy(buf, input_str); p = strtok(buf, " \n\r"); if (p && strncasecmp("yes", p, strlen(p)) == 0) menu_jump(ch, messedit_confirm_message_save); else menu_jump(ch, messedit_edit_message); } // search for null strings in message block, fill with error messages void validate_message(struct message_type *m) { if(!m->die_msg.attacker_msg) m->die_msg.attacker_msg = str_dup("Invalid message. Report immediately."); if(!m->die_msg.victim_msg) m->die_msg.victim_msg = str_dup("Invalid message. Report immediately."); if(!m->die_msg.room_msg) m->die_msg.room_msg = str_dup("Invalid message. Report immediately."); if(!m->miss_msg.attacker_msg) m->miss_msg.attacker_msg = str_dup("Invalid message. Report immediately."); if(!m->miss_msg.victim_msg) m->miss_msg.victim_msg = str_dup("Invalid message. Report immediately."); if(!m->miss_msg.room_msg) m->miss_msg.room_msg = str_dup("Invalid message. Report immediately."); if(!m->hit_msg.attacker_msg) m->hit_msg.attacker_msg = str_dup("Invalid message. Report immediately."); if(!m->hit_msg.victim_msg) m->hit_msg.victim_msg = str_dup("Invalid message. Report immediately."); if(!m->hit_msg.room_msg) m->hit_msg.room_msg = str_dup("Invalid message. Report immediately."); if(!m->god_msg.attacker_msg) m->god_msg.attacker_msg = str_dup("Invalid message. Report immediately."); if(!m->god_msg.victim_msg) m->god_msg.victim_msg = str_dup("Invalid message. Report immediately."); if(!m->god_msg.room_msg) m->god_msg.room_msg = str_dup("Invalid message. Report immediately."); } // if user wants to save, check format, dupe back over to actual, save file // else free it up, menu_pop to messedit_top void messedit_confirm_message_save(chdata *ch, char *input_str) { char buf[MAX_STRING_LENGTH]; char *p; int num = ch->pc_specials->index2; struct message_type *m = ch->pc_specials->msg_editted; struct message_type *orig, *targ; if (!input_str) { MENU_PROMPT(ch) = "Save editted message block (yes/NO)? "; return; } strcpy(buf, input_str); p = strtok(buf, " \n\r"); if (p && strncasecmp("yes", p, strlen(p)) == 0) // yes, save it { validate_message(m); orig = fight_messages[ch->pc_specials->index].msg; if (!(targ = get_mesg(orig, num))) send_to_char("Unable to find target message. Not saved.\n\r",ch); else dupe_mesg_over(m, targ); } free_this_message(m); ch->pc_specials->msg_editted = NULL; ch->pc_specials->index2 = 0; // now pop back out to messedit_top menu menu_back(ch); } void wax_doubles(struct message_type *m) { m->die_msg.attacker_msg = delete_doubledollar(m->die_msg.attacker_msg); m->die_msg.victim_msg = delete_doubledollar(m->die_msg.victim_msg); m->die_msg.room_msg = delete_doubledollar(m->die_msg.room_msg); m->miss_msg.attacker_msg = delete_doubledollar(m->miss_msg.attacker_msg); m->miss_msg.victim_msg = delete_doubledollar(m->miss_msg.victim_msg); m->miss_msg.room_msg = delete_doubledollar(m->miss_msg.room_msg); m->hit_msg.attacker_msg = delete_doubledollar(m->hit_msg.attacker_msg); m->hit_msg.victim_msg = delete_doubledollar(m->hit_msg.victim_msg); m->hit_msg.room_msg = delete_doubledollar(m->hit_msg.room_msg); m->god_msg.attacker_msg = delete_doubledollar(m->god_msg.attacker_msg); m->god_msg.victim_msg = delete_doubledollar(m->god_msg.victim_msg); m->god_msg.room_msg = delete_doubledollar(m->god_msg.room_msg); } void messedit_edit_message(chdata *ch, char *input_str) { char *p; int field; char buf[MAX_STRING_LENGTH]; struct message_type *m = ch->pc_specials->msg_editted; int slot = ch->pc_specials->index; if (!input_str) { menu_title_send("MessageEdit SubMenu", ch); if (fight_messages[slot].a_type < MAX_SPELLS) strcpy(buf2, skill_names[fight_messages[slot].a_type]); else strcpy(buf2, "Out of Range"); wax_doubles(m); sprintf(buf, "%%B%%6Skill / Spell%%0: %%5%%B%s%%0\n\r", buf2); S2C(); sprintf(buf, " 1.) %%6Message Level%%0: %%B%d%%0\n\r",m->level); S2C(); sprintf(buf, " 2.) %%6Die Msg, to Attacker%%0:\n\r%s\n\r",m->die_msg.attacker_msg); S2C(); sprintf(buf, " 3.) %%6Die Msg, to Victim %%0:\n\r%s\n\r",m->die_msg.victim_msg); S2C(); sprintf(buf, " 4.) %%6Die Msg, to Room %%0:\n\r%s\n\r",m->die_msg.room_msg); S2C(); sprintf(buf, " 5.) %%6Miss Msg, to Attacker%%0:\n\r%s\n\r",m->miss_msg.attacker_msg); S2C(); sprintf(buf, " 6.) %%6Miss Msg, to Victim %%0:\n\r%s\n\r",m->miss_msg.victim_msg); S2C(); sprintf(buf, " 7.) %%6Miss Msg, to Room %%0:\n\r%s\n\r",m->miss_msg.room_msg); S2C(); sprintf(buf, " 8.) %%6Hit Msg, to Attacker%%0:\n\r%s\n\r",m->hit_msg.attacker_msg); S2C(); sprintf(buf, " 9.) %%6Hit Msg, to Victim %%0:\n\r%s\n\r",m->hit_msg.victim_msg); S2C(); sprintf(buf, "10.) %%6Hit Msg, to Room %%0:\n\r%s\n\r",m->hit_msg.room_msg); S2C(); sprintf(buf, "11.) %%6God Msg, to Attacker%%0:\n\r%s\n\r",m->god_msg.attacker_msg); S2C(); sprintf(buf, "12.) %%6God Msg, to Victim %%0:\n\r%s\n\r",m->god_msg.victim_msg); S2C(); sprintf(buf, "13.) %%6God Msg, to Room %%0:\n\r%s\n\r",m->god_msg.room_msg); S2C(); send_to_char("\n\r", ch); MENU_PROMPT(ch) = "Enter field number to change or 0 to end: "; return; } strcpy(buf, input_str); p = strtok(buf, " \n\r"); if (p) field = atoi(p); else field = 0; switch (field) { case 0: menu_jump(ch, messedit_confirm_message_quit); break; case 1: GET_INTEGER_ARG(ch, "Enter min level of this combat message block: ", m->level, 0, LEV_IMPL); break; case 2: do_string_arg(ch, "Enter die msg to attacker:\n\r ", &m->die_msg.attacker_msg, ""); break; case 3: do_string_arg(ch, "Enter die msg to victim:\n\r ", &m->die_msg.victim_msg, ""); break; case 4: do_string_arg(ch, "Enter die msg to room:\n\r ", &m->die_msg.room_msg, ""); break; case 5: do_string_arg(ch, "Enter miss msg to attacker:\n\r ", &m->miss_msg.attacker_msg, ""); break; case 6: do_string_arg(ch, "Enter miss msg to victim:\n\r ", &m->miss_msg.victim_msg, ""); break; case 7: do_string_arg(ch, "Enter miss msg to room:\n\r ", &m->miss_msg.room_msg, ""); break; case 8: do_string_arg(ch, "Enter hit msg to attacker:\n\r ", &m->hit_msg.attacker_msg, ""); break; case 9: do_string_arg(ch, "Enter hit msg to victim:\n\r ", &m->hit_msg.victim_msg, ""); break; case 10: do_string_arg(ch, "Enter hit msg to room:\n\r ", &m->hit_msg.room_msg, ""); break; case 11: do_string_arg(ch, "Enter god msg to attacker:\n\r ", &m->god_msg.attacker_msg, ""); break; case 12: do_string_arg(ch, "Enter god msg to victim:\n\r ", &m->god_msg.victim_msg, ""); break; case 13: do_string_arg(ch, "Enter god msg to room:\n\r ", &m->god_msg.room_msg, ""); break; default: send_to_char("That field cannot be changed.\n\r", ch); break; } } void messedit_top_menu(chdata *ch, char *input_str) { char *p; int i, num, field; char buf[MAX_STRING_LENGTH]; struct message_type *m = fight_messages[ch->pc_specials->index].msg; struct message_type *tm, *ttm; int slot = ch->pc_specials->index; if (!input_str) { menu_title_send("MessageEdit Main Menu", ch); if (fight_messages[slot].a_type < MAX_SPELLS) strcpy(buf2, skill_names[fight_messages[slot].a_type]); else strcpy(buf2, "Out of Range"); sprintf(buf, "\n%%5Skill / Spell%%0: %%B%%6%s%%0\n\r", buf2); S2C(); for (i = 1, tm = m; tm; tm = tm->next, i++) { sprintf(buf, " %d.) %%6Message Lvl%%0: %2d\n\r",i, tm->level); S2C(); if (tm->level == LEV_IMPL) { sprintf(buf, "%%B%%1Note: Message number %d must be completed.\n\r",i); S2C(); } } send_to_char("\n10.) Add a message level...\n\r",ch); send_to_char("11.) Delete a message level...\n\r",ch); send_to_char("\n\r", ch); MENU_PROMPT(ch) = "Enter field number or 0 to end: "; return; } strcpy(buf, input_str); p = strtok(buf, " \n\r"); if (p) field = atoi(p); else field = 0; num = count_mesgs(m); // edit an existing one, depending on the number entered, ptr ch's editor to // the correct one in the m list if (field > 0 && field <= num) { if (!(tm = get_mesg(m, field))) { GET_INTEGER_ARG(ch, "Not a valid message block... (hit return): ", MENU_RETURN(ch), 0, 0); return; } // must create local copy so we dont alter original while // players are using them -roa CREATE(ch->pc_specials->msg_editted, struct message_type, 1); dupe_mesg_over(tm, ch->pc_specials->msg_editted); ch->pc_specials->index2 = field; // save this for later reference menu_push(ch); MENU_HANDLER_ARG(ch) = (void *) 0; menu_jump(ch, messedit_edit_message); return; } else switch (field) { case 0: menu_jump(ch, messedit_confirm_quit); break; // if we create, dupe first message block over, find last message in list // point its next to this new block, new block next = NULL case 10: CREATE(tm, struct message_type, 1); if (m) { dupe_mesg_over(m, tm); ttm = get_mesg(m, num); ttm->next = tm; tm->next = NULL; } else // empty msg block list, fill up new one { validate_message(tm); tm->next = NULL; fight_messages[ch->pc_specials->index].msg = tm; } tm->level = LEV_IMPL; send_to_char("%B%6Message added.%0\n\r",ch); (*MENU_HANDLER(ch))(ch, NULL); break; case 11: break; default: send_to_char("That field cannot be changed.\n\r", ch); break; } } void messedit_confirm_quit(chdata *ch, char *input_str) { char buf[MAX_STRING_LENGTH]; char *p; if (!input_str) { MENU_PROMPT(ch) = "Quit editting messages (yes/NO)? "; return; } strcpy(buf, input_str); p = strtok(buf, " \n\r"); if (p && strncasecmp("yes", p, strlen(p)) == 0) { sprintf(buf, "IMMUPD: %s editted message slot %d", GET_NAME(ch), ch->pc_specials->index); mudlog(buf, CMP, MAX(LEV_IMM, GET_INVIS_LEV(ch)), TRUE); ch->pc_specials->index = 0; ch->pc_specials->index2 = 0; if (ch->pc_specials->msg_editted) free_this_message(ch->pc_specials->msg_editted); ch->pc_specials->msg_editted = NULL; MENU_PROMPT(ch) = NULL; MENU_HANDLER(ch) = NULL; MENU_DEPTH(ch) = 0; REMOVE_BIT(PLR_FLAGS(ch), PLR_BUILDING); } else menu_jump(ch, messedit_top_menu); }