everything works EXCEPT when the mob's DEX is higher than the attacker's dex - then the fight happens. what am I missing?
EDIT: At first glance my suggestion would be to use a trigger type 6 (DEATH) so on death you echo the message 'Looks like you couldn't finish the job... they regroup to fight you with renewed vigor.' and set the mob's hp to 100%. Triggers can do most things except solve my problem. But after reading a few posts down it looks like we have the same issue - stopping a fight before it starts but not with the NPC NO_KILL (option 18) flag. Which is weird, because just use the flag... unless you have my issue.
My issue was I wanted a few high level (late game importance) mobs to be wandering around a lower-level zone but I want to protect my newbies and let them kill (or try to) whatever they want and not worry about getting 1-hit. At the same time, I want to preserve these mobs for higher-levels to fight when they progress later in the game AND there really wasn't a solid trigger to stop the fight before it starts.
The mob fight trigger type 11 (FIGHT) happens after each round of fighting so that really won't be an effective gate against noob insta-kills and NO_KILL flag means the mob can never be killed. I wanted something flexible and in between, so it's time to go deeper...
I made a special mob stat called atklevel (attack level) which would be the player's minimum level necessary to attack a mob.
defined in utils.h
Code:
#define GET_ATKLEVEL(ch) ((ch)->mob_specials.atklevel)
and in structs.h under struct mob_special_data
and in oasis.h
Code:
#define MEDIT_ATKLEVEL 40
writing to mobile record in genmob.c
Code:
fprintf(fd, "%d %d %d %d %d %d %d %d %d E\n"
"%d %d %d %dd%d+%d %dd%d+%d %d\n",
MOB_FLAGS(mob)[0], MOB_FLAGS(mob)[1],
MOB_FLAGS(mob)[2], MOB_FLAGS(mob)[3],
AFF_FLAGS(mob)[0], AFF_FLAGS(mob)[1],
AFF_FLAGS(mob)[2], AFF_FLAGS(mob)[3],
GET_ALIGNMENT(mob),
GET_LEVEL(mob), 20 - GET_HITROLL(mob), GET_AC(mob) / 10, GET_HIT(mob),
GET_MANA(mob), GET_MOVE(mob), GET_NDD(mob), GET_SDD(mob),
GET_DAMROLL(mob),GET_ATKLEVEL(mob));
adding it to be grabbed on load in db.c
Code:
if (sscanf(line, " %d %d %d %dd%d+%d %dd%d+%d %d",
t, t + 1, t + 2, t + 3, t + 4, t + 5, t + 6, t + 7, t + 8, t + 9) != 10) {
log("SYSERR: Format error in mob #%d, first line after S flag\n"
"...expecting line of form '# # # #d#+# #d#+# #'", nr);
exit(1);
}
GET_LEVEL(mob_proto + i) = t[0];
GET_HITROLL(mob_proto + i) = 20 - t[1];
GET_AC(mob_proto + i) = 10 * t[2];
/* max hit = 0 is a flag that H, M, V is xdy+z */
GET_MAX_HIT(mob_proto + i) = 0;
GET_HIT(mob_proto + i) = t[3];
GET_MANA(mob_proto + i) = t[4];
GET_MOVE(mob_proto + i) = t[5];
GET_MAX_MANA(mob_proto + i) = 10;
GET_MAX_MOVE(mob_proto + i) = 50;
mob_proto[i].mob_specials.damnodice = t[6];
mob_proto[i].mob_specials.damsizedice = t[7];
GET_DAMROLL(mob_proto + i) = t[8];
GET_ATKLEVEL(mob_proto + i) = t[9];
over to medit to make it accessible and pretty
Code:
/* Top section - standard stats */
write_to_output(d,
"-- Mob Number: %s[%s%d%s]%s\r\n"
"(%s1%s) Level: %s[%s%4d%s]%s\r\n"
"(%s2%s) %sAuto Set Stats (based on level)%s\r\n\r\n"
"Hit Points (xdy+z): Bare Hand Damage (xdy+z): \r\n"
"(%s3%s) HP NumDice: %s[%s%5d%s]%s (%s6%s) BHD NumDice: %s[%s%5d%s]%s\r\n"
"(%s4%s) HP SizeDice: %s[%s%5d%s]%s (%s7%s) BHD SizeDice: %s[%s%5d%s]%s\r\n"
"(%s5%s) HP Addition: %s[%s%5d%s]%s (%s8%s) DamRoll: %s[%s%2d%s]%s\r\n"
"%-*s(range %s%d%s to %s%d%s)\r\n\r\n"
"(%sA%s) Armor Class: %s[%s%4d%s]%s (%sD%s) Hitroll: %s[%s%5d%s]%s\r\n"
"(%sB%s) Exp Points: %s[%s%10d%s]%s (%sE%s) Alignment: %s[%s%5d%s]%s\r\n"
"(%sC%s) Gold: %s[%s%10d%s]%s (%sZ%s) Min Attack Level: %s[%s%2d%s]%s\r\n\r\n",
cyn, yel, OLC_NUM(d), cyn, nrm,
cyn, nrm, cyn, yel, GET_LEVEL(mob), cyn, nrm,
cyn, nrm, cyn, nrm,
cyn, nrm, cyn, yel, GET_HIT(mob), cyn, nrm, cyn, nrm, cyn, yel, GET_NDD(mob), cyn, nrm,
cyn, nrm, cyn, yel, GET_MANA(mob), cyn, nrm, cyn, nrm, cyn, yel, GET_SDD(mob), cyn, nrm,
cyn, nrm, cyn, yel, GET_MOVE(mob), cyn, nrm, cyn, nrm, cyn, yel, GET_DAMROLL(mob), cyn, nrm,
count_color_chars(buf)+28, buf,
yel, GET_NDD(mob) + GET_DAMROLL(mob), nrm,
yel, (GET_NDD(mob) * GET_SDD(mob)) + GET_DAMROLL(mob), nrm,
cyn, nrm, cyn, yel, GET_AC(mob), cyn, nrm, cyn, nrm, cyn, yel, GET_HITROLL(mob), cyn, nrm,
cyn, nrm, cyn, yel, GET_EXP(mob), cyn, nrm, cyn, nrm, cyn, yel, GET_ALIGNMENT(mob), cyn, nrm,
cyn, nrm, cyn, yel, GET_GOLD(mob), cyn, nrm, cyn, nrm, cyn, yel, GET_ATKLEVEL(mob), cyn, nrm
);
added the case for the stats menu
Code:
case 'z':
case 'Z':
OLC_MODE(d) = MEDIT_ATKLEVEL;
i++;
break;
added the function lower with the rest of the functions
Code:
case MEDIT_ATKLEVEL:
GET_ATKLEVEL(OLC_MOB(d)) = LIMIT(i, 0, 50); /*I have 50 levels */
OLC_VAL(d) = TRUE;
medit_disp_stats_menu(d);
return;
lastly, set it to default in the init_mobile function so level 1 can always attack
Code:
GET_ATKLEVEL(mob) = 0;
have it show up in just the mob stat from act.wizard.c in fancy red
Code:
if (IS_NPC(k))
send_to_char(ch, " Minimum Player level to attack: %s%d%s\r\n", CBRED(ch,C_NRM), GET_ATKLEVEL(k),CCNRM(ch,C_NRM));
then over to fight.c - in damage function right under peace room check
Code:
/* less than or equal to attack level */
if (GET_ATKLEVEL(victim) > GET_LEVEL(ch) ) {
send_to_char(ch, "You're not ready for this kind of fight...\r\n");
return (0);
}
I think that's it - I'm learning C as I go and am always open for comments/corrections/questions. This was inspired by the kill count snippet. Would this be useful for everyone? Sort of like the object level gate but for mobs? If you'd like to add to the next release please just give credit (IDK I thought it would be cool to contribute).
This works to prevent all offensive actions, skills, spells, hits, etc.