[CODE]permanent mob affects in mag_affects

From: Mike Breuer (mbreuer@new.rr.com)
Date: 07/31/01


The truly observant will have noticed by now that I am redoing the magic
system on my MUD.  Something I came across recently is the following code in
mag_affects (magic.c) that checks whether a mob has been permanently assign an
affect before allowing a spell to assign the same affect.  As explained in the
comment, this prevents players from casting a spell on a mob and then waiting
for it to wear off as a way of removing permanent affects from mobs.

This code presents a slight problem on my MUD in that I do not always have a 1
to 1 relationship between affects and spells.  Some affects can be caused by
multiple spells.  This code will fail a spell erroneously if a mob is affected
by the same affect from an earlier spell.  I wrote the following code to
prevent this situation:

mag_affects, in magic.c:
  const char *to_vict = NULL, *to_room = NULL;
  int i;
+ long /*bitvector_t*/ all_affects = 0;

  case SPELL_WATERWALK:
    af[0].duration = 24;
    af[0].bitvector = AFF_WATERWALK;
    accum_duration = TRUE;
    to_vict = "You feel webbing between your toes.";
    break;
  }
+
+ for (i = 0; i < MAX_SPELL_AFFECTS; i++)
+   all_affects |= af[i].bitvector;

- if (IS_NPC(victim) && !affected_by_spell(victim, spellnum))
+ if (IS_NPC(victim))
-   for (i = 0; i < MAX_SPELL_AFFECTS; i++)
-     if (AFF_FLAGGED(victim, af[i].bitvector)) {
+     if (permanent_affect(victim, all_affects)) {
        send_to_char(NOEFFECT, ch);
        return;
      }

  /*
   * If the victim is already affected by this spell, and the spell does
   * not have an accumulative effect, then fail the spell.
   */
- if (affected_by_spell(victim,spellnum) && !(accum_duration||accum_affect)) {
+ if (AFF_FLAGGED(victim, all_affects) && !(accum_duration || accum_affect)) {
    send_to_char(NOEFFECT, ch);
    return;
  }

in handler.h:
+bool permanent_affect( const struct char_data *ch, long /*bitvector_t*/
bitvector);

in handler.c:
/* Returns true if any of the affects in bitvector are permanent */
+bool permanent_affect( const struct char_data *ch, long /*bitvector_t*/
bitvector) {
+  const struct affected_type *aff = ch->affected;
+  long /*bitvector_t*/ ret = bitvector & AFF_FLAGS(ch);
+
+  while (ret && aff) {
+    ret ^= ret & aff->bitvector;
+
+    aff = aff->next;
+  }
+
+  return (bool)ret;
+}

If you're using 64-bit bitvectors, replace "long" with "bitvector_t".  Also
note that, with this change, you can still prevent the second spell from
working by setting accum_affect to FALSE.

Mike

--
   +---------------------------------------------------------------+
   | FAQ: http://qsilver.queensu.ca/~fletchra/Circle/list-faq.html |
   | Archives: http://post.queensu.ca/listserv/wwwarch/circle.html |
   +---------------------------------------------------------------+



This archive was generated by hypermail 2b30 : 12/06/01 PST