Aggro Part II

I discussed last time the idea of an aggressive mob function.  The function (at least a bare-bones type) wasn’t difficult to implement, but I ran into a couple of difficulties along the way.

First, one sub-function that is now called in mobact.c (aggressive_mob_on_a_leash()) checks whether the mob is charmed and whether the mob’s master can control it.

Unfortunately, since I put my function (check_aggressive()) in handler.c, and aggressive_mob_on_a_leash is a locally declared function (which I should make a note of to discuss at a later date), I had to do some shifting around.

I initially added a call to check_aggressive() in char_to_room(), but once I implemented the function, I realized that a character would move into a room, get attacked, and then look to see what’s around.

Sub-optimal to be sure.  Code after the jump.

Here’s the full code of the function “check_aggressive()” which I added in handler.c:

void check_aggressive(struct char_data *ch)
{
 struct char_data *i;

bool found = FALSE;
struct char_data *target;

/* If an aggressive NPC moved, check for PCs in the room */
if (IS_NPC(ch) && (MOB_FLAGGED(ch, MOB_AGGRESSIVE) || MOB_FLAGGED(ch, MOB_AGGR_EVIL) ||
MOB_FLAGGED(ch, MOB_AGGR_NEUTRAL) || MOB_FLAGGED(ch, MOB_AGGR_GOOD))) {

for (i = ch; i && !found; i = i->next_in_room) {
if ((ch != i) && (!IS_NPC(i))) { /* Found a character */
if ((MOB_FLAGGED(ch, MOB_AGGR_EVIL) && IS_EVIL(i)) ||
(MOB_FLAGGED(ch, MOB_AGGR_NEUTRAL) && IS_NEUTRAL(i)) ||
(MOB_FLAGGED(ch, MOB_AGGR_GOOD   ) && IS_GOOD(i))) {
target = i;
found = TRUE;
}
else if (MOB_FLAGGED(ch, MOB_AGGRESSIVE)) {
target = i;
found = TRUE;
}
} /* end of if !IS_NPC */
}  /* end of FOR */
}  /* end of IF IS_NPC */

if (!IS_NPC(ch)) {
for (i = ch; i && !found; i = i->next_in_room) {
if ((ch != i) && IS_NPC(i)) { /* Found a mob */
if (MOB_FLAGGED(i, MOB_AGGRESSIVE) ||     /* is it aggressive? */
(MOB_FLAGGED(i, MOB_AGGR_EVIL   ) && IS_EVIL(ch)) ||
(MOB_FLAGGED(i, MOB_AGGR_NEUTRAL) && IS_NEUTRAL(ch)) ||
(MOB_FLAGGED(i, MOB_AGGR_GOOD   ) && IS_GOOD(ch))) {
target = ch;
ch = i;
found = TRUE;
} /* end of IF AGGRO */
}   /* end of IF (IS_NPC) */
}  /* end of FOR */
}    /* end of else_if (!IS_NPC) */

if (found) {
if (GET_LEVEL(target) >= LVL_IMMORT)
return;
if (MOB_FLAGGED(ch, MOB_WIMPY) && AWAKE(target))/* wimpy mobs won't hit an awake character */
return;
if (aggressive_mob_on_a_leash(ch, ch->master, target)) /* charmed aggressive mobs */
return;
if (IS_NPC(target) || !CAN_SEE(ch, target) || PRF_FLAGGED(target, PRF_NOHASSLE))
return;
if (skill_check(target, SKILL_FIRST_STRIKE, 0))
hit(target, ch, SKILL_FIRST_STRIKE);
else
hit(ch, target, TYPE_UNDEFINED);
}
}
In addition to adding this bit of code, we need to add a few lines to handler.h so that we don’t get any errors.

In handler.h, under the /* characters */ comment, add the following:

void  check_aggressive(struct char_data *ch);

And while you’re there, under /* prototypes from mobact.c */:

bool aggressive_mob_on_a_leash(struct char_data *slave, struct char_data *master, struct char_data *attack);

Now, move to mobact.c and change:

struct bool aggressive_mob_on_a_leash(struct char_data *slave, struct char_data *master, struct char_data *attack)

to

bool aggressive_mob_on_a_leash(struct char_data *slave, struct char_data *master, struct char_data *attack)

And from the voice of experience, don’t forget those ;s at the end of the line in handler.h, forgetting them in the .h file makes for some interesting errors.

Well, this post is getting long, so I’ll put in the check information in another post.

Leave a comment