Difference for common/living.c from version 1.36 to 1.37


version 1.36 version 1.37
Line 1
 
Line 1
 /*  /*
  * static char *rcsid_living_c =   * static char *rcsid_living_c =
  *   "$Id: living.c,v 1.36 2002/03/14 22:16:14 avogl Exp $";   *   "$Id: living.c,v 1.37 2002/07/15 04:57:11 mwedel Exp $";
  */   */
   
 /*  /*
     CrossFire, A Multiplayer game for X-windows      CrossFire, A Multiplayer game for X-windows
   
     Copyright (C) 2000 Mark Wedel      Copyright (C) 2002 Mark Wedel & Crossfire Development Team
     Copyright (C) 1992 Frank Tore Johansen      Copyright (C) 1992 Frank Tore Johansen
   
     This program is free software; you can redistribute it and/or modify      This program is free software; you can redistribute it and/or modify
Line 23
 
Line 23
     along with this program; if not, write to the Free Software      along with this program; if not, write to the Free Software
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
   
     The author can be reached via e-mail to mwedel@scruz.net      The authors can be reached via e-mail at crossfire-devel@real-time.com
 */  */
   
 #include <global.h>  #include <global.h>
Line 132
 
Line 132
    Both come in handy at least in function add_exp()     Both come in handy at least in function add_exp()
 */  */
   
 #define MAXLEVEL      110  
 #define MAX_EXPERIENCE  levels[MAXLEVEL]  #define MAX_EXPERIENCE  levels[MAXLEVEL]
   
 /* because exp_obj sum to make the total score,  /* because exp_obj sum to make the total score,
Line 225
 
Line 224
   "life stealing"    "life stealing"
 };  };
   
 static char *drain_msg[7] = {  static char *drain_msg[NUM_STATS] = {
   "Oh no! You are weakened!",    "Oh no! You are weakened!",
   "You're feeling clumsy!",    "You're feeling clumsy!",
   "You feel less healthy",    "You feel less healthy",
Line 234
 
Line 233
   "Watch out, your mind is going!",     "Watch out, your mind is going!",
   "Your spirit feels drained!"    "Your spirit feels drained!"
 };  };
 char *restore_msg[7] = {  char *restore_msg[NUM_STATS] = {
   "You feel your strength return.",    "You feel your strength return.",
   "You feel your agility return.",    "You feel your agility return.",
   "You feel your health return.",    "You feel your health return.",
Line 243
 
Line 242
   "You feel your memory return.",     "You feel your memory return.",
   "You feel your spirits return."    "You feel your spirits return."
 };  };
 char *gain_msg[7] = {  char *gain_msg[NUM_STATS] = {
  "You feel stronger.",   "You feel stronger.",
  "You feel more agile.",   "You feel more agile.",
  "You feel healthy.",   "You feel healthy.",
Line 252
 
Line 251
  "You feel smarter.",    "You feel smarter.",
  "You feel more potent."   "You feel more potent."
 };  };
 char *lose_msg[7] = {  char *lose_msg[NUM_STATS] = {
  "You feel weaker!",   "You feel weaker!",
  "You feel clumsy!",   "You feel clumsy!",
  "You feel less healthy!",   "You feel less healthy!",
Line 262
 
Line 261
  "You feel less potent!"   "You feel less potent!"
 };  };
   
 char *statname[7] = {  char *statname[NUM_STATS] = {
   "strength", "dexterity", "constitution", "wisdom", "charisma", "intelligence","power"     "strength", "dexterity", "constitution", "wisdom", "charisma", "intelligence","power"
 };  };
   
 char *short_stat_name[7] = {  char *short_stat_name[NUM_STATS] = {
   "Str", "Dex", "Con", "Wis", "Cha", "Int","Pow"     "Str", "Dex", "Con", "Wis", "Cha", "Int","Pow"
 };  };
   
Line 369
 
Line 368
   
 void check_stat_bounds(living *stats) {  void check_stat_bounds(living *stats) {
   int i,v;    int i,v;
   for(i=0;i<7;i++)    for(i=0;i<NUM_STATS;i++)
     if((v=get_attr_value(stats,i))>MAX_STAT)      if((v=get_attr_value(stats,i))>MAX_STAT)
       set_attr_value(stats,i,MAX_STAT);        set_attr_value(stats,i,MAX_STAT);
     else if(v<MIN_STAT)      else if(v<MIN_STAT)
Line 383
 
Line 382
  * the object.   * the object.
  * It is the calling functions responsibilty to check to see if the object   * It is the calling functions responsibilty to check to see if the object
  * can be applied or not.   * can be applied or not.
    * The main purpose of calling this function is the messages that are
    * displayed - fix_player should really always be called after this when
    * removing an object - that is because it is impossible to know if some object
    * is the only source of an attacktype or spell attunement, so this function
    * will clear the bits, but the player may still have some other object
    * that gives them that ability.
  */   */
 int change_abil(object *op, object *tmp) {  int change_abil(object *op, object *tmp) {
   int flag=QUERY_FLAG(tmp,FLAG_APPLIED)?1:-1,i,j,success=0;    int flag=QUERY_FLAG(tmp,FLAG_APPLIED)?1:-1,i,j,success=0;
Line 397
 
Line 402
   
   if(op->type==PLAYER) {    if(op->type==PLAYER) {
     if (tmp->type==POTION) {      if (tmp->type==POTION) {
       for(j=0;j<7;j++) {        for(j=0;j<NUM_STATS;j++) {
         i = get_attr_value(&(op->contr->orig_stats),j);          i = get_attr_value(&(op->contr->orig_stats),j);
   
  /* Check to see if stats are within limits such that this can be   /* Check to see if stats are within limits such that this can be
Line 420
 
Line 425
      * sure if this is strictly necessary, being that fix_player probably       * sure if this is strictly necessary, being that fix_player probably
      * recalculates this anyway.       * recalculates this anyway.
      */       */
     for(j=0;j<7;j++)      for(j=0;j<NUM_STATS;j++)
       change_attr_value(&(op->stats),j,flag*get_attr_value(&(tmp->stats),j));        change_attr_value(&(op->stats),j,flag*get_attr_value(&(tmp->stats),j));
     check_stat_bounds(&(op->stats));      check_stat_bounds(&(op->stats));
     } /* end of potion handling code */      } /* end of potion handling code */
Line 440
 
Line 445
    */     */
   fix_player(op);    fix_player(op);
   
   if(tmp->attacktype & AT_CONFUSION) {    /* Fix player won't add the bows ability to the player, so don't
      * print out message if this is a bow.
      */
     if(tmp->attacktype & AT_CONFUSION && tmp->type != BOW) {
     success=1;      success=1;
     if(flag>0)      if(flag>0)
       (*draw_info_func)(NDI_UNIQUE, 0, op,"Your hands begin to glow red.");        (*draw_info_func)(NDI_UNIQUE, 0, op,"Your hands begin to glow red.");
Line 642
 
Line 650
   }    }
   
      if(tmp->type!=EXPERIENCE && !potion_max) {       if(tmp->type!=EXPERIENCE && !potion_max) {
  for (j=0; j<7; j++) {   for (j=0; j<NUM_STATS; j++) {
      if ((i=get_attr_value(&(tmp->stats),j))!=0) {       if ((i=get_attr_value(&(tmp->stats),j))!=0) {
  success=1;   success=1;
  if (i * flag > 0)   if (i * flag > 0)
Line 661
 
Line 669
  */   */
   
 void drain_stat(object *op) {  void drain_stat(object *op) {
   drain_specific_stat(op, RANDOM()%7);    drain_specific_stat(op, RANDOM()%NUM_STATS);
 }  }
   
 void drain_specific_stat(object *op, int deplete_stats) {  void drain_specific_stat(object *op, int deplete_stats) {
Line 774
 
Line 782
  * Updates all abilities given by applied objects in the inventory   * Updates all abilities given by applied objects in the inventory
  * of the given object.  Note: This function works for both monsters   * of the given object.  Note: This function works for both monsters
  * and players; the "player" in the name is purely an archaic inheritance.   * and players; the "player" in the name is purely an archaic inheritance.
    * This functions starts from base values (archetype or player object)
    * and then adjusts them according to what the player has equipped.
  */   */
 /* July 95 - inserted stuff to handle new skills/exp system - b.t.  /* July 95 - inserted stuff to handle new skills/exp system - b.t.
    spell system split, grace points now added to system  --peterm     spell system split, grace points now added to system  --peterm
  */   */
   
 void fix_player(object *op) {  void fix_player(object *op) {
   int i,j, light=0;      int i,j;
   float f,max=9,added_speed=0,bonus_speed=0, sp_tmp,speed_reduce_from_disease=1;    float f,max=9,added_speed=0,bonus_speed=0, sp_tmp,speed_reduce_from_disease=1;
   float M,W,s,D,K,S,M2;  
   int weapon_weight=0,weapon_speed=0;    int weapon_weight=0,weapon_speed=0;
   int best_wc=0, best_ac=0, wc=0, ac=0;    int best_wc=0, best_ac=0, wc=0, ac=0;
   int prot[NROFATTACKS], vuln[NROFATTACKS], potion_resist[NROFATTACKS];    int prot[NROFATTACKS], vuln[NROFATTACKS], potion_resist[NROFATTACKS];
   object *grace_obj=NULL,*mana_obj=NULL,*hp_obj=NULL,*wc_obj=NULL,*tmp;    object *grace_obj=NULL,*mana_obj=NULL,*hp_obj=NULL,*wc_obj=NULL,*tmp;
      
       /* First task is to clear all the values back to their original values */
   if(op->type==PLAYER) {    if(op->type==PLAYER) {
     for(i=0;i<7;i++) {   for(i=0;i<NUM_STATS;i++) {
       set_attr_value(&(op->stats),i,get_attr_value(&(op->contr->orig_stats),i));        set_attr_value(&(op->stats),i,get_attr_value(&(op->contr->orig_stats),i));
     }      }
 #ifdef SPELL_ENCUMBRANCE  #ifdef SPELL_ENCUMBRANCE
Line 797
 
Line 807
 #endif  #endif
     if(op->chosen_skill&&op->chosen_skill->exp_obj)      if(op->chosen_skill&&op->chosen_skill->exp_obj)
        op->chosen_skill->level=op->chosen_skill->exp_obj->level;         op->chosen_skill->level=op->chosen_skill->exp_obj->level;
   
         op->attacktype=0;              op->attacktype=0;   
  op->contr->digestion = 0;   op->contr->digestion = 0;
  op->contr->gen_hp = 0;   op->contr->gen_hp = 0;
  op->contr->gen_sp = 0;   op->contr->gen_sp = 0;
  op->contr->gen_grace = 0;   op->contr->gen_grace = 0;
  op->contr->gen_sp_armour = 10;   op->contr->gen_sp_armour = 10;
    for (i=0; i < range_size; i++)
        op->contr->ranges[i] = NULL;
   }    }
       memcpy(op->body_used, op->body_info, sizeof(op->body_info));
   
   if(op->slaying!=NULL) {    if(op->slaying!=NULL) {
     free_string(op->slaying);      free_string(op->slaying);
     op->slaying=NULL;      op->slaying=NULL;
Line 814
 
Line 829
  CLEAR_FLAG(op, FLAG_XRAYS);   CLEAR_FLAG(op, FLAG_XRAYS);
  CLEAR_FLAG(op, FLAG_MAKE_INVIS);   CLEAR_FLAG(op, FLAG_MAKE_INVIS);
   }    }
   
   CLEAR_FLAG(op,FLAG_LIFESAVE);    CLEAR_FLAG(op,FLAG_LIFESAVE);
   CLEAR_FLAG(op,FLAG_STEALTH);    CLEAR_FLAG(op,FLAG_STEALTH);
   CLEAR_FLAG(op,FLAG_BLIND);    CLEAR_FLAG(op,FLAG_BLIND);
Line 831
 
Line 847
   op->path_denied=op->arch->clone.path_denied;    op->path_denied=op->arch->clone.path_denied;
   
   /* initializing resistances from the values in player/monster's    /* initializing resistances from the values in player/monster's
    * archetype clone:  */       * archetype clone
        */
   memcpy(&op->resist, &op->arch->clone.resist, sizeof(op->resist));    memcpy(&op->resist, &op->arch->clone.resist, sizeof(op->resist));
      
   for (i=0;i<NROFATTACKS;i++) {    for (i=0;i<NROFATTACKS;i++) {
Line 845
 
Line 862
   wc=op->arch->clone.stats.wc;    wc=op->arch->clone.stats.wc;
   op->stats.dam=op->arch->clone.stats.dam;    op->stats.dam=op->arch->clone.stats.dam;
   
   if(!QUERY_FLAG(op,FLAG_USE_ARMOUR) && op->type==PLAYER) {  
     /* for players which cannot use armour, they gain AC -1 per 3 levels,      /* for players which cannot use armour, they gain AC -1 per 3 levels,
      * plus a small amount of physical resist, those poor suckers. ;) */       * plus a small amount of physical resist, those poor suckers. ;)
        */
       if(!QUERY_FLAG(op,FLAG_USE_ARMOUR) && op->type==PLAYER) {
     ac=MAX(-10,op->arch->clone.stats.ac - op->level/3);      ac=MAX(-10,op->arch->clone.stats.ac - op->level/3);
     prot[ATNR_PHYSICAL] += ((100-prot[AT_PHYSICAL])*(80*op->level/MAXLEVEL))/100;      prot[ATNR_PHYSICAL] += ((100-prot[AT_PHYSICAL])*(80*op->level/MAXLEVEL))/100;
   }    }
Line 857
 
Line 875
   op->stats.luck=op->arch->clone.stats.luck;    op->stats.luck=op->arch->clone.stats.luck;
   op->speed = op->arch->clone.speed;    op->speed = op->arch->clone.speed;
   
       /* OK - we've reset most all the objects attributes to sane values.
        * now go through and make adjustments for what the player has equipped.
        */
   
   for(tmp=op->inv;tmp!=NULL;tmp=tmp->below) {    for(tmp=op->inv;tmp!=NULL;tmp=tmp->below) {
     /* See note in map.c:update_position about making this additive       /* See note in map.c:update_position about making this additive
      * since light sources are never applied, need to put check here.       * since light sources are never applied, need to put check here.
      */       */
     if (tmp->glow_radius > light) light=tmp->glow_radius;   if (tmp->glow_radius > op->glow_radius) op->glow_radius=tmp->glow_radius;
   
    /* This happens because apply_potion calls change_abil with the potion
    * applied so we can tell the player what chagned.  But change_abil
    * then calls this function.
    */
    if (QUERY_FLAG(tmp, FLAG_APPLIED) && tmp->type == POTION) {
        continue;
    }
          
    /* Container objects are not meant to adjust a players, but other applied
    * objects need to make adjustments.
    * This block should handle all player specific changes
    */
     if(QUERY_FLAG(tmp,FLAG_APPLIED) && tmp->type!=CONTAINER && tmp->type!=CLOSE_CON) {      if(QUERY_FLAG(tmp,FLAG_APPLIED) && tmp->type!=CONTAINER && tmp->type!=CLOSE_CON) {
      /* The meaning of stats in skill or experience objects is different -       if(op->type==PLAYER) {
       * we use them solely to link skills to experience, thus it is    /* EXPERIENCE objects. What we are doing here is looking for "relevant"
       * inappropriate to allow these applied objects to change stats.   * experience objects. Some of these will be used to calculate
              * An exception is exp_wis, containing info about god-properties! */    * level-based changes in player status. For expample, the
       if(op->type==PLAYER && (tmp->type!=EXPERIENCE || !strcmp(tmp->arch->name, "experience_wis"))) {   * experience object which has exp_obj->stats.Str set controls the
  if (tmp->type != POTION) {   * wc bonus of the player. -b.t.
    for(i=0;i<7;i++)   * This code is sort of odd, in that we only set the pointer if
      change_attr_value(&(op->stats),i,get_attr_value(&(tmp->stats),i));   * it hasn't already been set.  It seems to me that it is either a bug
    * that a player may have multiple of these, or we should
    * be choosing the best ones.
    */
    if (tmp->type == EXPERIENCE) {
        if (tmp->stats.Str && !wc_obj)
    wc_obj = tmp;
        if (tmp->stats.Con && !hp_obj)
    hp_obj = tmp;
        if (tmp->stats.Pow && !mana_obj)  /* for spellpoint determ */
    mana_obj = tmp;
        if (tmp->stats.Wis && !grace_obj)
    grace_obj = tmp;
  }   }
    if (tmp->type == BOW)
        op->contr->ranges[range_bow] = tmp;
   
    if (tmp->type == WAND || tmp->type == ROD || tmp->type==HORN)
        op->contr->ranges[range_misc] = tmp;
   
    /* Other expereience objects have bogus stat info as shown above, we
    * don't want to use those adjustments.
    */
    if (tmp->type != EXPERIENCE || !strcmp(tmp->arch->name, "experience_wis")) {
        for(i=0;i<NUM_STATS;i++)
    change_attr_value(&(op->stats),i,get_attr_value(&(tmp->stats),i));
   
  /* these are the items that currently can change digestion, regeneration,   /* these are the items that currently can change digestion, regeneration,
  * spell point recovery and mana point recovery.  Seems sort of an arbitary   * spell point recovery and mana point recovery.  Seems sort of an arbitary
  * list, but other items store other info into stats array. */        * list, but other items store other info into stats array.
  if ( (tmp->type == EXPERIENCE)  || (tmp->type == WEAPON)        */
       || (tmp->type == ARMOUR)   || (tmp->type == HELMET)       if ((tmp->type == EXPERIENCE)  || (tmp->type == WEAPON) ||
       || (tmp->type == SHIELD)   || (tmp->type == RING)   (tmp->type == ARMOUR)   || (tmp->type == HELMET) ||
       || (tmp->type == BOOTS)    || (tmp->type == GLOVES)   (tmp->type == SHIELD)   || (tmp->type == RING) ||
       || (tmp->type == AMULET )  || (tmp->type == GIRDLE)   (tmp->type == BOOTS)    || (tmp->type == GLOVES) ||
       || (tmp->type == BRACERS ) || (tmp->type == CLOAK)    (tmp->type == AMULET )  || (tmp->type == GIRDLE) ||
       || (tmp->type == DISEASE)  || (tmp->type == FORCE)) {   (tmp->type == BRACERS ) || (tmp->type == CLOAK) ||
    (tmp->type == DISEASE)  || (tmp->type == FORCE)) {
    op->contr->digestion     += tmp->stats.food;     op->contr->digestion     += tmp->stats.food;
    op->contr->gen_hp        += tmp->stats.hp;     op->contr->gen_hp        += tmp->stats.hp;
    op->contr->gen_sp        += tmp->stats.sp;     op->contr->gen_sp        += tmp->stats.sp;
    op->contr->gen_grace     += tmp->stats.grace;     op->contr->gen_grace     += tmp->stats.grace;
    /* Experience objects use last_heal for permanent exp, so   op->contr->gen_sp_armour+= tmp->gen_sp_armour;
     * don't add those in.   op->contr->item_power += tmp->item_power;
     */  
    if (tmp->type != EXPERIENCE)  
  op->contr->gen_sp_armour += tmp->last_heal;  
 #if 0  
    if (tmp->last_heal) LOG(llevDebug,"Object %s applied, gen_sp_armour + %d = %d\n", tmp->name, tmp->last_heal, op->contr->gen_sp_armour);  
 #endif  
  }  
       }        }
    } /* If this not an experience object */
        } /* if this is a player */
   
        /* Update slots used for items */
        for (i=0; i<NUM_BODY_LOCATIONS; i++)
    op->body_used[i] += tmp->body_info[i];
   
       if(tmp->type==SYMPTOM) {        if(tmp->type==SYMPTOM) {
  speed_reduce_from_disease = tmp->last_sp / 100.0;   speed_reduce_from_disease = tmp->last_sp / 100.0;
Line 906
 
Line 965
       /* Pos. and neg. protections are counted seperate (-> pro/vuln).        /* Pos. and neg. protections are counted seperate (-> pro/vuln).
        * (Negative protections are calculated extactly like positive.)         * (Negative protections are calculated extactly like positive.)
        * Resistance from potions are treated special as well. If there's         * Resistance from potions are treated special as well. If there's
        * more than one potion-effect, the bigger prot.-value is taken. */        * more than one potion-effect, the bigger prot.-value is taken.
         */
       if (tmp->type != POTION) {        if (tmp->type != POTION) {
  for (i=0; i<NROFATTACKS; i++) {   for (i=0; i<NROFATTACKS; i++) {
    if (!strcmp(tmp->arch->name, "force") &&       /* Potential for cursed potions, in which case we just can use
        tmp->resist[i] && tmp->type==POTION_EFFECT) {        * a straight MAX, as potion_resist is initialized to zero.
         */
        if (tmp->type==POTION_EFFECT) {
      if (potion_resist[i])       if (potion_resist[i])
        potion_resist[i] = MAX(potion_resist[i], tmp->resist[i]);         potion_resist[i] = MAX(potion_resist[i], tmp->resist[i]);
      else       else
Line 923
 
Line 985
  }   }
       }        }
   
       if (tmp->type!=BOW) {       /* There may be other things that should not adjust the attacktype */
    if(tmp->type != SYMPTOM)        if (tmp->type!=BOW && tmp->type != SYMPTOM)
  op->attacktype|=tmp->attacktype;   op->attacktype|=tmp->attacktype;
 /*        if (tmp->attacktype) LOG(llevDebug,"Object %s applied, attacktype=0x%x\n", tmp->name, tmp->attacktype);*/  
       }  
       op->path_attuned|=tmp->path_attuned;        op->path_attuned|=tmp->path_attuned;
       op->path_repelled|=tmp->path_repelled;        op->path_repelled|=tmp->path_repelled;
       op->path_denied|=tmp->path_denied;        op->path_denied|=tmp->path_denied;
       op->stats.luck+=tmp->stats.luck;        op->stats.luck+=tmp->stats.luck;
       if(QUERY_FLAG(tmp,FLAG_LIFESAVE))  
         SET_FLAG(op,FLAG_LIFESAVE);       if(QUERY_FLAG(tmp,FLAG_LIFESAVE))       SET_FLAG(op,FLAG_LIFESAVE);
       if(QUERY_FLAG(tmp,FLAG_REFL_SPELL))       if(QUERY_FLAG(tmp,FLAG_REFL_SPELL))     SET_FLAG(op,FLAG_REFL_SPELL);
         SET_FLAG(op,FLAG_REFL_SPELL);       if(QUERY_FLAG(tmp,FLAG_REFL_MISSILE))   SET_FLAG(op,FLAG_REFL_MISSILE);
       if(QUERY_FLAG(tmp,FLAG_REFL_MISSILE))       if(QUERY_FLAG(tmp,FLAG_STEALTH))        SET_FLAG(op,FLAG_STEALTH);
         SET_FLAG(op,FLAG_REFL_MISSILE);       if(QUERY_FLAG(tmp,FLAG_XRAYS))     SET_FLAG(op,FLAG_XRAYS);
       if(QUERY_FLAG(tmp,FLAG_STEALTH))       if(QUERY_FLAG(tmp,FLAG_BLIND))     SET_FLAG(op,FLAG_BLIND);
         SET_FLAG(op,FLAG_STEALTH);       if(QUERY_FLAG(tmp,FLAG_SEE_IN_DARK))    SET_FLAG(op,FLAG_SEE_IN_DARK);
   
       if(QUERY_FLAG(tmp,FLAG_UNDEAD)&&!QUERY_FLAG(&op->arch->clone,FLAG_UNDEAD))        if(QUERY_FLAG(tmp,FLAG_UNDEAD)&&!QUERY_FLAG(&op->arch->clone,FLAG_UNDEAD))
         SET_FLAG(op,FLAG_UNDEAD);          SET_FLAG(op,FLAG_UNDEAD);
   
       if(QUERY_FLAG(tmp,FLAG_MAKE_INVIS)) {        if(QUERY_FLAG(tmp,FLAG_MAKE_INVIS)) {
         SET_FLAG(op,FLAG_MAKE_INVIS); op->invisible=1; }   SET_FLAG(op,FLAG_MAKE_INVIS);
    op->invisible=1;
        }
   
       if(QUERY_FLAG(tmp,FLAG_FLYING)) {        if(QUERY_FLAG(tmp,FLAG_FLYING)) {
         SET_FLAG(op,FLAG_FLYING);          SET_FLAG(op,FLAG_FLYING);
         if(!QUERY_FLAG(op,FLAG_WIZ))          if(!QUERY_FLAG(op,FLAG_WIZ))
           max=1;            max=1;
       }        }
       if(QUERY_FLAG(tmp,FLAG_XRAYS))  
         SET_FLAG(op,FLAG_XRAYS);  
    
       if(QUERY_FLAG(tmp,FLAG_BLIND))        if(tmp->stats.exp && tmp->type!=EXPERIENCE) {
  SET_FLAG(op,FLAG_BLIND);  
   
       if(QUERY_FLAG(tmp,FLAG_SEE_IN_DARK))   
  SET_FLAG(op,FLAG_SEE_IN_DARK);  
   
       if(tmp->stats.exp && tmp->type!=EXPERIENCE  
       ) {  
         if(tmp->stats.exp > 0) {          if(tmp->stats.exp > 0) {
           added_speed+=(float)tmp->stats.exp/3.0;            added_speed+=(float)tmp->stats.exp/3.0;
           bonus_speed+=1.0+(float)tmp->stats.exp/3.0;            bonus_speed+=1.0+(float)tmp->stats.exp/3.0;
         } else          } else
           added_speed+=(float)tmp->stats.exp;            added_speed+=(float)tmp->stats.exp;
       }        }
       switch(tmp->type) {  
   
      /* EXPERIENCE objects. What we are doing here is looking for "relevant"   
       * experience objects. Some of these will be used to calculate   
       * level-based changes in player status. For expample, the   
       * experience object which has exp_obj->stats.Str set controls the   
       * wc bonus of the player. -b.t.  
       */  
       case EXPERIENCE:   
  if(op->type!=PLAYER)    /* Only players should have these. */   
    LOG(llevError,"Error: %s has exp_obj in invenory\n",op->name);   
  else {  
     if (tmp->stats.Str && !wc_obj)   
  wc_obj = tmp;  
     if (tmp->stats.Con && !hp_obj)   
  hp_obj = tmp;  
     if (tmp->stats.Pow && !mana_obj)  /* for spellpoint determ */   
  mana_obj = tmp;  
     if (tmp->stats.Wis && !grace_obj)  
  grace_obj = tmp;   
  }  
         break;  
    
       case SKILL: /* skills modifying the character -b.t. */        switch(tmp->type) {
    /* skills modifying the character -b.t. */
  /* for all skills and skill granting objects */    /* for all skills and skill granting objects */
    case SKILL:
  if(tmp==op->chosen_skill) {    if(tmp==op->chosen_skill) {
   
      wc-=tmp->stats.wc;   
   
      if(tmp->stats.dam>0) { /* skill is a 'weapon' */        if(tmp->stats.dam>0) { /* skill is a 'weapon' */
  if(!QUERY_FLAG(op,FLAG_READY_WEAPON))    if(!QUERY_FLAG(op,FLAG_READY_WEAPON))
      weapon_speed = (int) WEAPON_SPEED(tmp);       weapon_speed = (int) WEAPON_SPEED(tmp);
Line 1005
 
Line 1037
  op->stats.dam+=tmp->stats.dam*(1 + (op->chosen_skill->level/9));   op->stats.dam+=tmp->stats.dam*(1 + (op->chosen_skill->level/9));
  if(tmp->magic) op->stats.dam += tmp->magic;   if(tmp->magic) op->stats.dam += tmp->magic;
      }       }
   
      if(tmp->stats.wc)       if(tmp->stats.wc)
  wc-=(tmp->stats.wc+tmp->magic);   wc-=(tmp->stats.wc+tmp->magic);
   
   
      if(tmp->slaying!=NULL) {       if(tmp->slaying!=NULL) {
  if (op->slaying != NULL)   if (op->slaying != NULL)
      free_string (op->slaying);       free_string (op->slaying);
Line 1018
 
Line 1048
   
      if(tmp->stats.ac)       if(tmp->stats.ac)
  ac-=(tmp->stats.ac+tmp->magic);   ac-=(tmp->stats.ac+tmp->magic);
   
 #ifdef SPELL_ENCUMBRANCE  #ifdef SPELL_ENCUMBRANCE
      if(op->type==PLAYER) op->contr->encumbrance+=(int)3*tmp->weight/1000;       if(op->type==PLAYER) op->contr->encumbrance+=(int)3*tmp->weight/1000;
 #endif  #endif
Line 1035
 
Line 1064
       case BOOTS:        case BOOTS:
       case GLOVES:        case GLOVES:
       case CLOAK:        case CLOAK:
   
         if(tmp->stats.wc)          if(tmp->stats.wc)
           wc-=(tmp->stats.wc+tmp->magic);            wc-=(tmp->stats.wc+tmp->magic);
         if(tmp->stats.dam)          if(tmp->stats.dam)
Line 1057
 
Line 1085
             free_string (op->slaying);              free_string (op->slaying);
           add_refcount(op->slaying = tmp->slaying);            add_refcount(op->slaying = tmp->slaying);
         }          }
        /* If there is desire that two handed weapons should do
         * extra strength damage, this is where the code should
         * go.
         */
 #ifdef PLUGINS  #ifdef PLUGINS
  if (tmp->event_hook[EVENT_ATTACK] != NULL) {   if (tmp->event_hook[EVENT_ATTACK] != NULL) {
      if (op->current_weapon_script)       if (op->current_weapon_script)
Line 1070
 
Line 1102
  if(op->type==PLAYER) op->contr->encumbrance+=(int)3*tmp->weight/1000;   if(op->type==PLAYER) op->contr->encumbrance+=(int)3*tmp->weight/1000;
 #endif  #endif
         break;          break;
   
       case ARMOUR: /* Only the best of these three are used: */        case ARMOUR: /* Only the best of these three are used: */
 #ifdef SPELL_ENCUMBRANCE  #ifdef SPELL_ENCUMBRANCE
  if(op->type==PLAYER) op->contr->encumbrance+=(int)tmp->weight/1000;   if(op->type==PLAYER) op->contr->encumbrance+=(int)tmp->weight/1000;
Line 1096
 
Line 1129
         if(ARMOUR_SPEED(tmp)&&ARMOUR_SPEED(tmp)/10.0<max)          if(ARMOUR_SPEED(tmp)&&ARMOUR_SPEED(tmp)/10.0<max)
           max=ARMOUR_SPEED(tmp)/10.0;            max=ARMOUR_SPEED(tmp)/10.0;
         break;          break;
       }       } /* switch tmp->type */
     }   } /* item is equipped */
   } /* Item is equipped - end of for loop going through items. */      } /* for loop of items */
   
       /* We've gone through all the objects the player has equipped.  For many things, we
        * have generated intermediate values which we now need to assign.
        */
      
   /* 'total resistance = total protections - total vulnerabilities'.    /* 'total resistance = total protections - total vulnerabilities'.
    * If there is an uncursed potion in effect, granting more protection     * If there is an uncursed potion in effect, granting more protection
    * than that, we take: 'total resistance = resistance from potion'.     * than that, we take: 'total resistance = resistance from potion'.
    * If there is a cursed (and no uncursed) potion in effect, we take     * If there is a cursed (and no uncursed) potion in effect, we take
    * 'total resistance = vulnerability from cursed potion'. */       * 'total resistance = vulnerability from cursed potion'.
        */
   for (i=0; i<NROFATTACKS; i++) {    for (i=0; i<NROFATTACKS; i++) {
     op->resist[i] = prot[i] - vuln[i];      op->resist[i] = prot[i] - vuln[i];
     if (potion_resist[i] && ((potion_resist[i] > op->resist[i]) ||      if (potion_resist[i] && ((potion_resist[i] > op->resist[i]) ||
Line 1112
 
Line 1150
       op->resist[i] = potion_resist[i];        op->resist[i] = potion_resist[i];
     }      }
      
   /* awarding hp -- I changed this so that the mean between the 'fighter'      /* Figure out the players sp/mana/hp totals. */
    * level (hp_obj->level) and overall scores are used. The system of hp  
    * progression remains unchanged for no skills. b.t.  
    */  
   if(op->type==PLAYER) {    if(op->type==PLAYER) {
     int pl_level;      int pl_level;
   
     check_stat_bounds(&(op->stats));      check_stat_bounds(&(op->stats));
     if(!hp_obj) hp_obj = op; /* happens when skills are not used */       if(!hp_obj) hp_obj = op; /* happens when skills are not used */
 #if 0  
     pl_level = (op->level + hp_obj->level)/2;  
 #else  
     pl_level=op->level;      pl_level=op->level;
 #endif  
     if(pl_level<1) pl_level=1; /* safety, we should always get 1 levels worth of hp! */       if(pl_level<1) pl_level=1; /* safety, we should always get 1 levels worth of hp! */
   
    /* You basically get half a con bonus/level.  But we do take into account rounding,
    * so if your bonus is 7, you still get 7 worth of bonus every 2 levels.
    */
     for(i=1,op->stats.maxhp=0;i<=pl_level&&i<=10;i++) {      for(i=1,op->stats.maxhp=0;i<=pl_level&&i<=10;i++) {
       j=op->contr->levhp[i]+con_bonus[op->stats.Con]/2;        j=op->contr->levhp[i]+con_bonus[op->stats.Con]/2;
       if(i%2&&con_bonus[op->stats.Con]%2) {        if(i%2&&con_bonus[op->stats.Con]%2) {
Line 1134
 
Line 1171
  else   else
      j--;       j--;
       }        }
       op->stats.maxhp+=j>1?j:1;       op->stats.maxhp+=j>1?j:1; /* always get at least 1 hp/level */
     }      }
   
     for(i=11;i<=op->level;i++)      for(i=11;i<=op->level;i++)
       op->stats.maxhp+=2;        op->stats.maxhp+=2;
   
     if(op->stats.hp>op->stats.maxhp)      if(op->stats.hp>op->stats.maxhp)
       op->stats.hp=op->stats.maxhp;        op->stats.hp=op->stats.maxhp;
   
Line 1150
 
Line 1189
   
  /* set maxsp */   /* set maxsp */
     if(!mana_obj || !mana_obj->level || op->type!=PLAYER) mana_obj = op;      if(!mana_obj || !mana_obj->level || op->type!=PLAYER) mana_obj = op;
   
     for(i=1,op->stats.maxsp=0;i<=mana_obj->level&&i<=10;i++) {      for(i=1,op->stats.maxsp=0;i<=mana_obj->level&&i<=10;i++) {
       j=op->contr->levsp[i]+sp_bonus[op->stats.Pow]/2;        j=op->contr->levsp[i]+sp_bonus[op->stats.Pow]/2;
       if((i%2) && (sp_bonus[op->stats.Pow]%2)) {        if((i%2) && (sp_bonus[op->stats.Pow]%2)) {
Line 1162
 
Line 1202
     }      }
     for(i=11;i<=mana_obj->level;i++)      for(i=11;i<=mana_obj->level;i++)
       op->stats.maxsp+=2;        op->stats.maxsp+=2;
   
     /* Characters can get their sp supercharged via rune of transferrance */      /* Characters can get their sp supercharged via rune of transferrance */
     if(op->stats.sp>op->stats.maxsp*2)      if(op->stats.sp>op->stats.maxsp*2)
       op->stats.sp=op->stats.maxsp*2;        op->stats.sp=op->stats.maxsp*2;
Line 1178
 
Line 1219
     for(i=1,op->stats.maxgrace=0;i<=grace_obj->level&&i<=10;i++) {      for(i=1,op->stats.maxgrace=0;i<=grace_obj->level&&i<=10;i++) {
  float grace_tmp=0.0;   float grace_tmp=0.0;
   
        /* Got some extra bonus at first level */
        if(i<2) {
    grace_tmp += 1.0+(((float)grace_bonus[op->stats.Pow] +
       (float)grace_bonus[op->stats.Wis])/4.0);
        } else {
  grace_tmp=(float)op->contr->levgrace[i]   grace_tmp=(float)op->contr->levgrace[i]
  +((float)grace_bonus[op->stats.Pow] +    +((float)grace_bonus[op->stats.Pow] +
    (float)grace_bonus[op->stats.Wis])/8.0;     (float)grace_bonus[op->stats.Wis])/8.0;
  /* changed the starting grace for playability -b.t. */        }
  if(i<2)   
      grace_tmp += 1.0+(((float)grace_bonus[op->stats.Pow] +   
  (float)grace_bonus[op->stats.Wis])/4.0);   
  /*  I'll omit the odd even stuff from above for now  --PeterM */  
  if (grace_tmp<1.0) grace_tmp=1.0;   if (grace_tmp<1.0) grace_tmp=1.0;
  sp_tmp+=grace_tmp;   sp_tmp+=grace_tmp;
     }      }
     op->stats.maxgrace=(int)sp_tmp;      op->stats.maxgrace=(int)sp_tmp;
     /* one grace point per level after 11 */  
    /* two grace points per level after 11 */
     for(i=11;i<=grace_obj->level;i++)      for(i=11;i<=grace_obj->level;i++)
  op->stats.maxgrace+=2;   op->stats.maxgrace+=2;
   
Line 1198
 
Line 1241
       * to put limits on the whims of the gods?  I omit any fix for overlarge        * to put limits on the whims of the gods?  I omit any fix for overlarge
       * grace--PeterM */        * grace--PeterM */
   
     if(op->contr->braced)  
    if(op->contr->braced) {
       ac+=2;        ac+=2;
        wc+=4;
    }
     else      else
       ac-=dex_bonus[op->stats.Dex];        ac-=dex_bonus[op->stats.Dex];
   
    /* In new exp/skills system, wc bonuses are related to      /* In new exp/skills system, wc bonuses are related to
     * the players level in a relevant exp object (wc_obj)      * the players level in a relevant exp object (wc_obj)
     * not the general player level -b.t.  */   * not the general player level -b.t.
    /* I changed this slightly so that wc bonuses are better   * I changed this slightly so that wc bonuses are better
     * than before. This is to balance out the fact that       * than before. This is to balance out the fact that
     * the player no longer gets a personal weapon w/ 1      * the player no longer gets a personal weapon w/ 1
     * improvementevery level, now its fighterlevel/5. So      * improvementevery level, now its fighterlevel/5. So
Line 1216
 
Line 1262
     */      */
   
     if(op->type==PLAYER && wc_obj && wc_obj->level>1) {       if(op->type==PLAYER && wc_obj && wc_obj->level>1) {
       int i;  
       wc-=(wc_obj->level+thaco_bonus[op->stats.Str]);        wc-=(wc_obj->level+thaco_bonus[op->stats.Str]);
       for(i=1;i<wc_obj->level;i++) {         for(i=1;i<wc_obj->level;i++) {
  /* addtional wc every 6 levels */    /* addtional wc every 6 levels */
  if(!(i%6)) wc--;    if(!(i%6)) wc--;
  /* addtional dam every 4 levels. */    /* addtional dam every 4 levels. */
  if(!(i%4)&&!(dam_bonus[op->stats.Str]<0))    if(!(i%4) && (dam_bonus[op->stats.Str]>=0))
      op->stats.dam+=(1+(dam_bonus[op->stats.Str]/5));       op->stats.dam+=(1+(dam_bonus[op->stats.Str]/5));
       }        }
     } else       } else
     wc-=(op->level+thaco_bonus[op->stats.Str]);      wc-=(op->level+thaco_bonus[op->stats.Str]);
   
     op->stats.dam+=dam_bonus[op->stats.Str];      op->stats.dam+=dam_bonus[op->stats.Str];
     if(op->contr->braced)  
       wc+=4;  
     if(op->stats.dam<1)      if(op->stats.dam<1)
       op->stats.dam=1;        op->stats.dam=1;
   
     op->speed=1.0+speed_bonus[op->stats.Dex];      op->speed=1.0+speed_bonus[op->stats.Dex];
 #ifdef SEARCH_ITEMS  #ifdef SEARCH_ITEMS
     if (op->contr->search_str[0])      if (op->contr->search_str[0])
Line 1240
 
Line 1285
 #endif  #endif
     if (op->attacktype==0)      if (op->attacktype==0)
  op->attacktype=op->arch->clone.attacktype;   op->attacktype=op->arch->clone.attacktype;
   }  
       } /* End if player */
   
   if(added_speed>=0)    if(added_speed>=0)
     op->speed+=added_speed/10.0;      op->speed+=added_speed/10.0;
   else /* Something wrong here...: */    else /* Something wrong here...: */
     op->speed /= (float)(1.0-added_speed);      op->speed /= (float)(1.0-added_speed);
   
       /* Max is determined by armour */
   if(op->speed>max)    if(op->speed>max)
     op->speed=max;      op->speed=max;
   
Line 1259
 
Line 1308
   }    }
   
   op->speed+=bonus_speed/10.0; /* Not affected by limits */    op->speed+=bonus_speed/10.0; /* Not affected by limits */
   
   /* Put a lower limit on speed.  Note with this speed, you move once every    /* Put a lower limit on speed.  Note with this speed, you move once every
    * 100 ticks or so.  This amounts to once every 12 seconds of realtime.     * 100 ticks or so.  This amounts to once every 12 seconds of realtime.
    */     */
   op->speed = op->speed * speed_reduce_from_disease;    op->speed = op->speed * speed_reduce_from_disease;
   
   if (op->speed<0.01 && op->type==PLAYER) op->speed=0.01;    if (op->speed<0.01 && op->type==PLAYER) op->speed=0.01;
   
   if(op->type == PLAYER) {    if(op->type == PLAYER) {
 /* (This formula was made by vidarl@ifi.uio.no) */   float M,W,s,D,K,S,M2;
   
    /* (This formula was made by vidarl@ifi.uio.no)
    * Note that we never used these values again - basically
    * all of these could be subbed into one big equation, but
    * that would just be a real pain to read.
    */
     M=(max_carry[op->stats.Str]-121)/121.0;      M=(max_carry[op->stats.Str]-121)/121.0;
     M2=max_carry[op->stats.Str]/100.0;      M2=max_carry[op->stats.Str]/100.0;
     W=weapon_weight/20000.0;      W=weapon_weight/20000.0;
Line 1295
 
Line 1352
   else if (ac<-120) ac=-120;    else if (ac<-120) ac=-120;
   op->stats.ac=ac;    op->stats.ac=ac;
   
   op->glow_radius = light;  
   
   update_ob_speed(op);    update_ob_speed(op);
   
 }  }
   
 /*  /*


Legend:
line(s) removed in v.1.36 
line(s) changed
 line(s) added in v.1.37

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