Difference for server/attack.c from version 1.91 to 1.92


version 1.91 version 1.92
Line 1
 
Line 1
 /*  /*
  * static char *rcsid_attack_c =   * static char *rcsid_attack_c =
  *   "$Id: attack.c,v 1.91 2003/09/04 06:25:32 temitchell Exp $";   *   "$Id: attack.c,v 1.92 2003/09/13 05:02:07 mwedel Exp $";
  */   */
 /*  /*
     CrossFire, A Multiplayer game for X-windows      CrossFire, A Multiplayer game for X-windows
Line 42
 
Line 42
   
 /*#define ATTACK_DEBUG*/  /*#define ATTACK_DEBUG*/
   
   /* cancels object *op.  Cancellation basically means an object loses
    * its magical benefits.
    */
   void cancellation(object *op)
   {
       object *tmp;
      
       if (QUERY_FLAG (op, FLAG_ALIVE) || op->type == CONTAINER  || op->type == THROWN_OBJ) {
    /* Recur through the inventory */
    for(tmp=op->inv;tmp!=NULL;tmp=tmp->below)
    if (!did_make_save_item(tmp, AT_CANCELLATION,op))
        cancellation(tmp);
       }
       else if(FABS(op->magic)<=(rndm(0, 5))) {
    /* Nullify this object. This code could probably be more complete */
    /* in what abilities it should cancel */
    op->magic=0;
    CLEAR_FLAG(op, FLAG_DAMNED);
    CLEAR_FLAG(op, FLAG_CURSED);
    CLEAR_FLAG(op, FLAG_KNOWN_MAGICAL);
    CLEAR_FLAG(op, FLAG_KNOWN_CURSED);
    if (op->env && op->env->type == PLAYER) {
        esrv_send_item (op->env, op);
    }
       }
   }
   
   
   
 /* did_make_save_item just checks to make sure the item actually  /* did_make_save_item just checks to make sure the item actually
  * made its saving throw based on the tables.  It does not take   * made its saving throw based on the tables.  It does not take
  * any further action (like destroying the item).   * any further action (like destroying the item).
Line 194
 
Line 223
         if ((tmp = present_arch(at,op->map,op->x,op->y)) == NULL) {          if ((tmp = present_arch(at,op->map,op->x,op->y)) == NULL) {
           tmp = arch_to_object(at);            tmp = arch_to_object(at);
           tmp->x=op->x,tmp->y=op->y;            tmp->x=op->x,tmp->y=op->y;
        SET_SLOW_PENALTY(tmp, 0);
           insert_ob_in_map(tmp,op->map,originator,0);            insert_ob_in_map(tmp,op->map,originator,0);
         }          }
         if ( ! QUERY_FLAG (op, FLAG_REMOVED))          if ( ! QUERY_FLAG (op, FLAG_REMOVED))
Line 367
 
Line 397
    found++;     found++;
    break;     break;
        }         }
  } else if (USING_SKILL(hitter, SK_BOXING)) {   } else if (USING_SKILL(hitter, SK_PUNCHING)) {
           for (i=0; i < MAXATTACKMESS && attack_mess[ATM_PUNCH][i].level != -1;            for (i=0; i < MAXATTACKMESS && attack_mess[ATM_PUNCH][i].level != -1;
         i++)          i++)
        if (dam < attack_mess[ATM_PUNCH][i].level) {         if (dam < attack_mess[ATM_PUNCH][i].level) {
Line 501
 
Line 531
  new_draw_info(NDI_BLACK, 0, hitter, buf);   new_draw_info(NDI_BLACK, 0, hitter, buf);
     } else if(get_owner(hitter)!=NULL&&hitter->owner->type==PLAYER) {      } else if(get_owner(hitter)!=NULL&&hitter->owner->type==PLAYER) {
       /* look for stacked spells and start reducing the message chances */        /* look for stacked spells and start reducing the message chances */
         if (hitter->type == FBALL || hitter->type == FBULLET ||          if (hitter->type == SPELL_EFFECT &&
      hitter->type == CONE) {       (hitter->subtype == SP_EXPLOSION ||
         hitter->subtype == SP_BULLET ||
         hitter->subtype == SP_CONE)) {
     i=4;      i=4;
     map = hitter->map;      map = hitter->map;
     if (out_of_map(map, hitter->x, hitter->y))      if (out_of_map(map, hitter->x, hitter->y))
Line 510
 
Line 542
     next = get_map_ob(map, hitter->x, hitter->y);      next = get_map_ob(map, hitter->x, hitter->y);
     if (next)      if (next)
         while(next) {          while(next) {
     if (next->type == FBALL || next->type == FBULLET ||      if (next->type == SPELL_EFFECT &&
         next->type == CONE)          (next->subtype == SP_EXPLOSION || next->subtype==SP_BULLET ||
           next->subtype == SP_CONE))
         i*=3;          i*=3;
     tmp = next;      tmp = next;
     next = tmp->above;      next = tmp->above;
Line 673
 
Line 706
     if(roll==20 || op->stats.ac>=base_wc-roll) {      if(roll==20 || op->stats.ac>=base_wc-roll) {
  int hitdam = base_dam;   int hitdam = base_dam;
  if (settings.casting_time == TRUE) {   if (settings.casting_time == TRUE) {
      if ((hitter->type == PLAYER)&&(hitter->casting > -1)){       if ((hitter->type == PLAYER)&&(hitter->casting_time > -1)){
  hitter->casting = -1;   hitter->casting_time = -1;
  hitter->spell_state = 1;  
  new_draw_info(NDI_UNIQUE, 0,hitter,"You attacked and lost "   new_draw_info(NDI_UNIQUE, 0,hitter,"You attacked and lost "
      "your spell!");       "your spell!");
      }       }
      if ((op->casting > -1)&&(hitdam > 0)){       if ((op->casting_time > -1)&&(hitdam > 0)){
  op->casting = -1;   op->casting_time = -1;
  op->spell_state = 1;  
  if (op->type == PLAYER)  {   if (op->type == PLAYER)  {
      new_draw_info(NDI_UNIQUE, 0,op,"You were hit and lost "       new_draw_info(NDI_UNIQUE, 0,op,"You were hit and lost "
  "your spell!");   "your spell!");
Line 1161
 
Line 1192
       * Move the wiz check up here - before, the hitter wouldn't gain exp        * Move the wiz check up here - before, the hitter wouldn't gain exp
       * exp, but the wiz would still lose exp!  If drainee is a wiz,        * exp, but the wiz would still lose exp!  If drainee is a wiz,
       * nothing happens.        * nothing happens.
         * Try to credit the owner.  We try to display player -> player drain
         * attacks, hence all the != PLAYER checks.
       */        */
      if (!op_on_battleground(hitter, NULL, NULL) && !QUERY_FLAG(op,FLAG_WAS_WIZ)) {       if (!op_on_battleground(hitter, NULL, NULL) && !QUERY_FLAG(op,FLAG_WAS_WIZ)) {
  object *owner = get_owner(hitter), *old_skill;   object *owner = get_owner(hitter);
   
  /* Try to find the owner of the thing doing the drain - thus, if  
  * you summon vampires, you get some exp.  Most of this code  
  * below is taken directly from kill_object  
  */  
  if (owner && owner != hitter) {   if (owner && owner != hitter) {
      old_skill = owner->chosen_skill;  
      owner->chosen_skill = hitter->chosen_skill;  
      owner->exp_obj=hitter->exp_obj;  
   
      /* Not sure if this will happen or not - I'm think it could with  
       * summoned pets - they may use a skill and thus the chosen_skill  
       * gets updated to something they have.  
       */  
      if (owner->chosen_skill && owner->chosen_skill->env != owner) {  
  LOG(llevDebug,"kill_object: chosen skill doesn't belong to owner? (%s, %s)\n",  
      owner->chosen_skill->name, owner->name);  
  owner->chosen_skill = NULL;  
      }  
      if (owner->exp_obj && owner->exp_obj->env != owner) {  
  LOG(llevDebug,"kill_object: exp_obj doesn't belong to owner? (%s, %s)\n",  
      owner->exp_obj->name, owner->name);  
  owner->exp_obj = NULL;  
      }  
      if (op->type != PLAYER || owner->type != PLAYER)        if (op->type != PLAYER || owner->type != PLAYER)
  add_exp(owner,op->stats.exp/(rate*2));   change_exp(owner, op->stats.exp/(rate*2),
      owner->chosen_skill = old_skill;         hitter->chosen_skill? hitter->chosen_skill->skill:NULL, SK_EXP_TOTAL);
  } else {   } else if (op->type != PLAYER || hitter->type != PLAYER) {
      if (op->type != PLAYER || hitter->type != PLAYER)        change_exp(hitter, op->stats.exp/(rate*2),
  add_exp(hitter,op->stats.exp/(rate*2));         hitter->chosen_skill->skill, 0);
  }   }
  add_exp(op,-op->stats.exp/rate);   change_exp(op,-op->stats.exp/rate, NULL, 0);
      }        }
      dam = 1; /* Drain is an effect.  Still return 1 - otherwise, if you have pure       dam = 1; /* Drain is an effect.  Still return 1 - otherwise, if you have pure
  * drain attack, you won't know that you are actually sucking out EXP,   * drain attack, you won't know that you are actually sucking out EXP,
Line 1305
 
Line 1316
  */   */
 int kill_object(object *op,int dam, object *hitter, int type)  int kill_object(object *op,int dam, object *hitter, int type)
 {  {
     char buf[MAX_BUF];      char buf[MAX_BUF], *skill;
     int maxdam=0;      int maxdam=0;
     int battleg=0;    /* true if op standing on battleground */      int battleg=0;    /* true if op standing on battleground */
     int killed_script_rtn = 0;      int killed_script_rtn = 0;
     object *owner=NULL, *old_skill;      object *owner=NULL;
     int evtid;      int evtid;
     CFParm CFP;      CFParm CFP;
       object *skop=NULL;
     event *evt;      event *evt;
   
     if (op->stats.hp>=0)      if (op->stats.hp>=0)
Line 1342
 
Line 1354
             killed_script_rtn = *(int *)(CFR->Value[0]);              killed_script_rtn = *(int *)(CFR->Value[0]);
             if (killed_script_rtn)              if (killed_script_rtn)
                 return 0;                  return 0;
         };          }
     }      }
     /* GROS: Handle for the global kill event */      /* GROS: Handle for the global kill event */
     evtid = EVENT_GKILL;      evtid = EVENT_GKILL;
Line 1367
 
Line 1379
     }      }
     if(QUERY_FLAG (op, FLAG_FRIENDLY) && op->type != PLAYER) {      if(QUERY_FLAG (op, FLAG_FRIENDLY) && op->type != PLAYER) {
  remove_friendly_object(op);   remove_friendly_object(op);
  if (get_owner (op) != NULL && op->owner->type == PLAYER)   if (get_owner (op) != NULL && op->owner->type == PLAYER &&
      op->owner->contr->golem=NULL;       op->owner->contr->ranges[range_golem] == op) {
        op->owner->contr->ranges[range_golem]=NULL;
        op->owner->contr->golem_count=0;
    }
  else   else
      LOG (llevError, "BUG: hit_player(): Encountered golem without owner.\n");       LOG (llevError, "BUG: hit_player(): Encountered golem without owner.\n");
   
Line 1437
 
Line 1452
  */   */
  if(op->type == PLAYER && hitter != op && !battleg)   if(op->type == PLAYER && hitter != op && !battleg)
      change_luck(owner, -1);       change_luck(owner, -1);
   
    /* This code below deals with finding the appropriate skill
    * to credit exp to.  This is a bit problematic - we should
            * probably never really have to look at current_weapon->skill
    */
    if (hitter->skill && hitter->type!=PLAYER) skill = hitter->skill;
    else if (owner->chosen_skill) {
        skill = owner->chosen_skill->skill;
        skop = owner->chosen_skill;
    }
    else if (QUERY_FLAG(owner, FLAG_READY_WEAPON)) skill=owner->current_weapon->skill;
    else
        LOG(llevError,"kill_object - unable to find skill that killed monster\n");
   
    /* We have the skill we want to credit to - now find the object this goes
    * to.
    */
    if (!skop && skill) {
        int i;
   
        for (i=0; i<NUM_SKILLS; i++)
                   if (owner->contr->last_skill_ob[i] &&
      !strcmp(owner->contr->last_skill_ob[i]->skill, skill)) {
        skop = owner->contr->last_skill_ob[i];
        break;
    }
    }
     } /* Was it a player that hit somethign */      } /* Was it a player that hit somethign */
   
   
Line 1444
 
Line 1486
     if(owner != hitter ) {      if(owner != hitter ) {
  (void) sprintf(buf,"%s killed %s with %s%s.",owner->name,   (void) sprintf(buf,"%s killed %s with %s%s.",owner->name,
         query_name(op),query_name(hitter), battleg? " (duel)":"");          query_name(op),query_name(hitter), battleg? " (duel)":"");
  owner->exp_obj=hitter->exp_obj;  
     }      }
     else      else {
  (void) sprintf(buf,"%s killed %s%s.",hitter->name,op->name,   (void) sprintf(buf,"%s killed %s%s.",hitter->name,op->name,
         battleg? " (duel)":"");          battleg? " (duel)":"");
       }
       /* These may have been set in the player code section above */
       if (!skop) skop = hitter->chosen_skill;
       if (!skill && skop) skill=skop->skill;
   
     new_draw_info(NDI_ALL, op->type==PLAYER?1:10, NULL, buf);      new_draw_info(NDI_ALL, op->type==PLAYER?1:10, NULL, buf);
   
   
     /* If you didn't kill yourself, and your not the wizard */      /* If you didn't kill yourself, and your not the wizard */
     if(hitter!=op&&!QUERY_FLAG(op, FLAG_WAS_WIZ)) {      if(hitter!=op&&!QUERY_FLAG(op, FLAG_WAS_WIZ)) {
  int exp=op->stats.exp;   int exp;
   
  if(!settings.simple_exp && hitter->level>op->level)  
      exp=(exp*(op->level+1))/MAX(hitter->level+1, 1);  
   
  if (owner != hitter) {  
      old_skill = owner->chosen_skill;  
      owner->chosen_skill = hitter->chosen_skill;  
      owner->exp_obj=hitter->exp_obj;  
   
      /* Not sure if this will happen or not - I'm think it could with  
       * summoned pets - they may use a skill and thus the chosen_skill  
       * gets updated to something they have.  
       */  
      if (owner->chosen_skill && owner->chosen_skill->env != owner) {  
  LOG(llevDebug,"kill_object: chosen skill doesn't belong to owner? (%s, %s)\n",  
      owner->chosen_skill->name, owner->name);  
  owner->chosen_skill = NULL;  
      }  
      if (owner->exp_obj && owner->exp_obj->env != owner) {  
  LOG(llevDebug,"kill_object: exp_obj doesn't belong to owner? (%s, %s)\n",  
      owner->exp_obj->name, owner->name);  
  owner->exp_obj = NULL;  
      }  
  }  
   
  exp = calc_skill_exp(owner,op);   exp = calc_skill_exp(owner,op, skop);
   
  /* Really don't give much experience for killing other players */   /* Really don't give much experience for killing other players */
  if (op->type==PLAYER) {   if (op->type==PLAYER) {
Line 1505
 
Line 1527
  if (battleg) exp = 0;   if (battleg) exp = 0;
   
  if(owner->type!=PLAYER || owner->contr->party_number<=0) {   if(owner->type!=PLAYER || owner->contr->party_number<=0) {
      add_exp(owner,exp);       change_exp(owner,exp, skill, 0);
  }   }
  else {   else {
      int shares=0,count=0;       int shares=0,count=0;
Line 1523
 
Line 1545
  }   }
      }       }
      if(count==1 || shares>exp)       if(count==1 || shares>exp)
  add_exp(owner,exp);   change_exp(owner,exp, skill, SK_EXP_TOTAL);
      else {       else {
  int share=exp/shares,given=0,nexp;   int share=exp/shares,given=0,nexp;
  for(pl=first_player;pl!=NULL;pl=pl->next) {   for(pl=first_player;pl!=NULL;pl=pl->next) {
      if(pl->ob->contr->party_number==no && on_same_map(pl->ob, owner)) {       if(pl->ob->contr->party_number==no && on_same_map(pl->ob, owner)) {
  nexp=(pl->ob->level+4)*share;   nexp=(pl->ob->level+4)*share;
  add_exp(pl->ob,nexp);   change_exp(pl->ob,nexp, skop->skill, SK_EXP_TOTAL);
  given+=nexp;   given+=nexp;
      }       }
  }   }
  exp-=given;   exp-=given;
  add_exp(owner,exp); /* give any remainder to the player */   /* give any remainder to the player */
    change_exp(owner,exp, skill, SK_EXP_ADD_SKILL);
      }       }
  } /* else part of a party */   } /* else part of a party */
   
  /* set this back after we have added the experience */  
  if (owner != hitter) owner->chosen_skill = old_skill;  
   
     } /* end if person didn't kill himself */      } /* end if person didn't kill himself */
   
     if(op->type!=PLAYER) {      if(op->type!=PLAYER) {
Line 1591
 
Line 1611
  if(hitter->type == PLAYER && hitter->contr->peaceful == 1)   if(hitter->type == PLAYER && hitter->contr->peaceful == 1)
  return 1;   return 1;
            
  if(owner = get_owner(hitter)){   if((owner = get_owner(hitter))!=NULL) {
  if(owner->type == PLAYER && owner->contr->peaceful == 1)   if(owner->type == PLAYER && owner->contr->peaceful == 1)
  friendlyfire = 2;   friendlyfire = 2;
  }   }
    
  if(hitter->type == CONE || hitter->type == FBALL  || hitter->type == FIREWALL   if (hitter->type == SPELL || hitter->type == POISONING ||
  || hitter->type == SWARM_SPELL || hitter->type == POISONCLOUD        hitter->type == DISEASE || hitter->type == RUNE)
  || hitter->type == POISONING || hitter->type == DISEASE || hitter->type == RUNE)  
    
  friendlyfire = 0;    friendlyfire = 0;
     }      }
    
  return friendlyfire;   return friendlyfire;
 }  }
   
Line 1923
 
Line 1940
     object *tmp;      object *tmp;
     int maxduration;      int maxduration;
          
     tmp = present_in_ob(CONFUSION,op);      tmp = present_in_ob_by_name(FORCE,"confusion", op);
     if(!tmp) {      if(!tmp) {
       tmp = get_archetype("confusion");   tmp = get_archetype("force");
       tmp = insert_ob_in_ob(tmp,op);        tmp = insert_ob_in_ob(tmp,op);
     }      }
          
     /* Duration added per hit and max. duration of confusion both depend      /* Duration added per hit and max. duration of confusion both depend
        on the player's resistance */       *  on the player's resistance
     tmp->stats.food += MAX(1, 5*(100-op->resist[ATNR_CONFUSION])/100);       */
       tmp->speed = 0.05;
       tmp->subtype = FORCE_CONFUSION;
       tmp->duration = 8 + MAX(1, 5*(100-op->resist[ATNR_CONFUSION])/100);
       if (tmp->name) free_string(tmp->name);
       tmp->name = add_string("confusion");
     maxduration = MAX(2, 30*(100-op->resist[ATNR_CONFUSION])/100);      maxduration = MAX(2, 30*(100-op->resist[ATNR_CONFUSION])/100);
     if( tmp->stats.food > maxduration)      if( tmp->duration > maxduration)
       tmp->stats.food = maxduration;   tmp->duration = maxduration;
          
     if(op->type == PLAYER && !QUERY_FLAG(op,FLAG_CONFUSED))      if(op->type == PLAYER && !QUERY_FLAG(op,FLAG_CONFUSED))
       new_draw_info(NDI_UNIQUE, 0,op,"You suddenly feel very confused!");        new_draw_info(NDI_UNIQUE, 0,op,"You suddenly feel very confused!");
Line 2006
 
Line 2028
 }  }
   
   
 /* Attempts to kill 'op'.  hitter is the attack object, dam i  /* Attempts to kill 'op'.  hitter is the attack object, dam is
  * the computed damaged.   * the computed damaged.
  */   */
 void deathstrike_player(object *op, object *hitter, int *dam)   void deathstrike_player(object *op, object *hitter, int *dam)
 {    /*  The intention of a death attack is to kill outright things  {
       /*  The intention of a death attack is to kill outright things
     **  that are a lot weaker than the attacker, have a chance of killing      **  that are a lot weaker than the attacker, have a chance of killing
     **  things somewhat weaker than the caster, and no chance of      **  things somewhat weaker than the caster, and no chance of
     **  killing something equal or stronger than the attacker.      **  killing something equal or stronger than the attacker.
Line 2030
 
Line 2053
              op->arch->name, op->name);               op->arch->name, op->name);
         def_lev = 1;          def_lev = 1;
     }      }
     atk_lev = SK_level (hitter) / 2;      atk_lev = (hitter->chosen_skill?hitter->chosen_skill->level:hitter->level) / 2;
     /* LOG(llevDebug,"Deathstrike - attack level %d, defender level %d\n",      /* LOG(llevDebug,"Deathstrike - attack level %d, defender level %d\n",
        atk_lev, def_lev); */         atk_lev, def_lev); */
   
Line 2161
 
Line 2184
 /* determine if the object is an 'aimed' missile */  /* determine if the object is an 'aimed' missile */
 int is_aimed_missile ( object *op) {  int is_aimed_missile ( object *op) {
   
   if(op&&QUERY_FLAG(op,FLAG_FLYING)&&       /* I broke what used to be one big if into a few nested
      (op->type==ARROW||op->type==THROWN_OBJ       * ones so that figuring out the logic is at least possible.
        ||op->type==FBULLET||op->type==FBALL))        */
       if (op && QUERY_FLAG(op,FLAG_FLYING)) {
    if (op->type==ARROW || op->type==THROWN_OBJ)
     return 1;      return 1;
    else if (op->type==SPELL_EFFECT && (op->subtype == SP_BULLET ||
          op->subtype == SP_EXPLOSION))
        return 1;
       }
   return 0;    return 0;
 }  }
   


Legend:
line(s) removed in v.1.91 
line(s) changed
 line(s) added in v.1.92

File made using version 1.98 of cvs2html by leaf at 2011-07-21 17:24