Hello all,
I just got back into coding and found a nice base to start from ,QuickMUD, which is a cleaned up version of Rom2.4b6 with some basic additions. I also applied some bug fixes. In any event, I am working on redoing the fight code. Starting from the top of fight.c, I cleaned up the check_assist() function. I wanted to run it by you all to see if I foobared anything in the process. I found some issues with the stock code and hopefully made it more efficient as well as put in some comments for future reference.
Here is what I've got:
/*
* for auto assisting
* Commented, adjusted, and modified by Rapture (30Aug2010)
*/
void check_assist (CHAR_DATA * ch, CHAR_DATA * victim)
{
CHAR_DATA *rch, *rch_next;
/* rch = next person in the room with ch */
for (rch = ch->in_room->people; rch != NULL; rch = rch_next)
{
rch_next = rch->next_in_room;
/*
* Don't make victim to attempt to attack themselves OR
* Skip rch if they are already fighting
*/
if ( rch_next == victim || rch->fighting != NULL )
continue;
/* Skip rch if they are sleeping or blind */
if ( !IS_AWAKE(rch) || IS_AFFECTED (rch, AFF_BLIND) )
continue;
/* quick check for ASSIST_PLAYER */
/*
* If ch is a PLAYER and
* rch is a MOBILE, is set to assist players, and the MOBILE's level is 7+ levels over the victim
* then the MOBILE(rch) will attack the victim
* For example, city guards
* skip rest of loop and check next person in room
*/
if ( !IS_NPC (ch) && ( IS_NPC (rch) && IS_SET(rch->off_flags, ASSIST_PLAYERS) && (rch->level + 6 > victim->level) ) )
{
do_function (rch, &do_emote, "screams and attacks!");
multi_hit (rch, victim, TYPE_UNDEFINED);
continue;
}
/* PCs next */
/*
* If ch is a PLAYER or ch is a MOBILE and is charmed
*/ //who has charmed ch????
if ( !IS_NPC (ch) || IS_AFFECTED (ch, AFF_CHARM) )
{
/*
* If rch is a PLAYER and is set to auto-assist players OR rch is a MOBILE and is charmed AND
* rch is in the same group as ch, and can attack the victim
* then rch will attack the victim
* skip the rest of loop and check next person in room
*/
if ( ( ( !IS_NPC (rch) && IS_SET (rch->act, PLR_AUTOASSIST) ) || IS_AFFECTED (rch, AFF_CHARM) )
&& is_same_group (ch, rch) && !is_safe (rch, victim) )
{
multi_hit (rch, victim, TYPE_UNDEFINED);
}
continue;
} // end if (!IS_NPC (ch) || IS_AFFECTED (ch, AFF_CHARM))
/* now check the NPC cases */
/*
* If ch is a MOBILE and is not charmed AND
* if rch is a MOBILE
*/
if ( IS_NPC (ch) && !IS_AFFECTED (ch, AFF_CHARM) && IS_NPC(rch) )
{
/*
* if rch is set to assist all OR
* if rch is in the same group as ch OR
* if rch is the same race as ch and is set to assist same race as ch OR
* if rch is set to assist same alignment and alignment is same as ch OR
* if rch is the same mobile VNUM as ch and rch is set to assist same VNUM
*/
if ( IS_SET (rch->off_flags, ASSIST_ALL) || ( rch->group && rch->group == ch->group ) ||
( rch->race == ch->race && IS_SET (rch->off_flags, ASSIST_RACE) ) ||
( IS_SET (rch->off_flags, ASSIST_ALIGN) &&
( ( IS_GOOD (rch) && IS_GOOD (ch) ) || ( IS_EVIL (rch) && IS_EVIL (ch) ) ||
( IS_NEUTRAL (rch) && IS_NEUTRAL (ch) ) ) ) ||
( rch->pIndexData == ch->pIndexData && IS_SET (rch->off_flags, ASSIST_VNUM) ) )
{
CHAR_DATA *vch;
CHAR_DATA *target;
int number;
/*
* Flip a coin to see if MOBILE(rch) is going to actually do something
* otherwise, skip the rest of the loop and go on to next person in room.
*/
if (number_bits (1) == 0)
{
continue;
}
target = NULL;
number = 0;
/* Now, we are going to loop through all the people in the room again */
for (vch = ch->in_room->people; vch; vch = vch->next)
{
/*
* If MONSTER(rch) can see next person (vch) in room AND
* if vch is in the same group as victim AND
* MONSTER(rch) has picked this person's random number
* then set MONSTER(rch)'s target as vch then repeat this
* until we get through all the people in the room.
* NOTE: The first person in the victim's group is always the victim!
*/
if (can_see (rch, vch)
&& is_same_group (vch, victim)
&& number_range (0, number) == 0)
{
target = vch;
number++;
}
}
/* If MONSTER(rch) was able to pick someone then attack them! Go to next person in room. */
if (target != NULL)
{
do_function (rch, &do_emote, "screams and attacks!");
multi_hit (rch, target, TYPE_UNDEFINED);
}
}
}
}
}
The only part of this function I haven't messed with is the last for loop which picks a random person in the victim's group to attack. I'm not too confident in the original coder's choice of randomness, but I didn't want to introduce another for loop into the mix.
Does everything look copasetic? |