Difference for server/apply.c from version 1.86 to 1.87


version 1.86 version 1.87
Line 1
 
Line 1
 /*  /*
  * static char *rcsid_apply_c =   * static char *rcsid_apply_c =
  *   "$Id: apply.c,v 1.86 2003/09/04 06:25:32 temitchell Exp $";   *   "$Id: apply.c,v 1.87 2003/09/13 05:02:07 mwedel Exp $";
  */   */
 /*  /*
     CrossFire, A Multiplayer game for X-windows      CrossFire, A Multiplayer game for X-windows
Line 113
 
Line 113
         identify(tmp);          identify(tmp);
     }      }
   
     /* only players get this */      /* Potion of restoration - only for players */
     if (op->type==PLAYER&&(tmp->attacktype & AT_DEPLETE)) { /* Potion of restoration */      if (op->type==PLAYER&&(tmp->attacktype & AT_DEPLETE)) {
       object *depl;        object *depl;
       archetype *at;        archetype *at;
   
Line 139
 
Line 139
         fix_player(op);          fix_player(op);
       }        }
       else        else
         new_draw_info(NDI_UNIQUE,0,op, "You feel a great loss...");       new_draw_info(NDI_UNIQUE,0,op, "You potion had no effect.");
   
       decrease_ob(tmp);        decrease_ob(tmp);
       return 1;        return 1;
     }      }
     /* only players get this */  
     if(op->type==PLAYER&&tmp->attacktype&AT_GODPOWER) {    /* improvement potion */      /* improvement potion - only for players */
       if(op->type==PLAYER&&tmp->attacktype&AT_GODPOWER) {
   
  for(i=1;i<MIN(11,op->level);i++) {   for(i=1;i<MIN(11,op->level);i++) {
      if (QUERY_FLAG(tmp,FLAG_CURSED) || QUERY_FLAG(tmp,FLAG_DAMNED)) {       if (QUERY_FLAG(tmp,FLAG_CURSED) || QUERY_FLAG(tmp,FLAG_DAMNED)) {
Line 203
 
Line 204
   
   
     /* A potion that casts a spell.  Healing, restore spellpoint (power potion)      /* A potion that casts a spell.  Healing, restore spellpoint (power potion)
      * and heroism all fit into this category.       * and heroism all fit into this category.  Given the spell object code,
        * there is no limit to the number of spells that potions can be cast,
        * but direction is problematic to try and imbue fireball potions for example.
      */       */
     if (tmp->stats.sp) {      if (tmp->inv) {
       if(QUERY_FLAG(tmp, FLAG_CURSED) || QUERY_FLAG(tmp, FLAG_DAMNED)) {        if(QUERY_FLAG(tmp, FLAG_CURSED) || QUERY_FLAG(tmp, FLAG_DAMNED)) {
        object *fball;
   
         new_draw_info(NDI_UNIQUE,0,op, "Yech!  Your lungs are on fire!");          new_draw_info(NDI_UNIQUE,0,op, "Yech!  Your lungs are on fire!");
         cast_spell(op,tmp, 0, 3, 1, spellPotion,NULL);              /* Explodes a fireball centered at player */
               fball = get_archetype(EXPLODING_FIREBALL);
               fball->dam_modifier=random_roll(1, op->level, op, PREFER_LOW)/5+1;
               fball->stats.maxhp=random_roll(1, op->level, op, PREFER_LOW)/10+2;
               fball->x = op->x;
               fball->y = op->y;
               insert_ob_in_map(fball, op->map, NULL, 0);
       } else        } else
         cast_spell(op,tmp, op->facing, tmp->stats.sp, 1, spellPotion,NULL);       cast_spell(op,tmp, op->facing, tmp->inv, NULL);
   
       decrease_ob(tmp);        decrease_ob(tmp);
       /* if youre dead, no point in doing this... */        /* if youre dead, no point in doing this... */
       if(!QUERY_FLAG(op,FLAG_REMOVED)) fix_player(op);        if(!QUERY_FLAG(op,FLAG_REMOVED)) fix_player(op);
Line 247
 
Line 259
   
     /* Only thing left are the stat potions */      /* Only thing left are the stat potions */
     if(op->type==PLAYER) { /* only for players */      if(op->type==PLAYER) { /* only for players */
       if((QUERY_FLAG(tmp, FLAG_CURSED) || QUERY_FLAG(tmp, FLAG_DAMNED))    if((QUERY_FLAG(tmp, FLAG_CURSED) || QUERY_FLAG(tmp, FLAG_DAMNED)) && tmp->value!=0)
    && tmp->value!=0)  
  CLEAR_FLAG(tmp, FLAG_APPLIED);   CLEAR_FLAG(tmp, FLAG_APPLIED);
       else        else
  SET_FLAG(tmp, FLAG_APPLIED);   SET_FLAG(tmp, FLAG_APPLIED);
Line 986
 
Line 997
 static int apply_altar (object *altar, object *sacrifice, object *originator)  static int apply_altar (object *altar, object *sacrifice, object *originator)
 {  {
   /* Only players can make sacrifices on spell casting altars. */    /* Only players can make sacrifices on spell casting altars. */
   if (altar->stats.sp && ( ! originator || originator->type != PLAYER))      if (altar->inv && ( ! originator || originator->type != PLAYER))
     return 0;      return 0;
   if (operate_altar (altar, &sacrifice))  
   {      if (operate_altar (altar, &sacrifice)) {
     /* Simple check.  Unfortunately, it means you can't cast magic bullet      /* Simple check.  Unfortunately, it means you can't cast magic bullet
      * with an altar.  We call it a Potion - altars are stationary - it       * with an altar.  We call it a Potion - altars are stationary - it
      * is up to map designers to use them properly.       * is up to map designers to use them properly.
      */       */
     if (altar->stats.sp)   if (altar->inv && altar->inv->type==SPELL) {
     {  
       new_draw_info_format (NDI_BLACK, 0, originator, "The altar casts %s.",        new_draw_info_format (NDI_BLACK, 0, originator, "The altar casts %s.",
                             spells[altar->stats.sp].name);     altar->inv->name);
       cast_spell (originator, altar, 0, altar->stats.sp, 0, spellPotion, NULL);       cast_spell (originator, altar, 0, altar->inv, NULL);
       /* If it is connected, push the button.  Fixes some problems with        /* If it is connected, push the button.  Fixes some problems with
        * old maps.         * old maps.
        */         */
       push_button (altar);  /*     push_button (altar);*/
     } else {      } else {
       altar->value = 1;  /* works only once */        altar->value = 1;  /* works only once */
       push_button (altar);        push_button (altar);
Line 1216
 
Line 1226
     apply_altar (trap, victim, originator);      apply_altar (trap, victim, originator);
     goto leave;      goto leave;
   
   case MMISSILE:  
     if (QUERY_FLAG (victim, FLAG_ALIVE)) {  
       tag_t trap_tag = trap->count;  
       hit_player (victim, trap->stats.dam, trap, AT_MAGIC);  
       if ( ! was_destroyed (trap, trap_tag)) {  
           remove_ob (trap);  
           free_object (trap);  
       }  
     }  
     goto leave;  
   
   case THROWN_OBJ:    case THROWN_OBJ:
     if (trap->inv == NULL)      if (trap->inv == NULL)
       goto leave;        goto leave;
Line 1242
 
Line 1241
       hit_with_arrow (trap, victim);        hit_with_arrow (trap, victim);
     goto leave;      goto leave;
   
   case CANCELLATION:  
   case BALL_LIGHTNING:  
     if (QUERY_FLAG (victim, FLAG_ALIVE))  
       hit_player (victim, trap->stats.dam, trap, trap->attacktype);  
     else if (victim->material || victim->materialname)  
       save_throw_object (victim, trap->attacktype, trap);  
     goto leave;  
   
   case CONE:  
     if(QUERY_FLAG(victim, FLAG_ALIVE)&&trap->speed) {  
       uint32 attacktype = trap->attacktype & ~AT_COUNTERSPELL;  
       if (attacktype)  
         hit_player(victim,trap->stats.dam,trap,attacktype);  
     }  
     goto leave;  
   
   case FBULLET:      case SPELL_EFFECT:
   case BULLET:   apply_spell_effect(trap, victim);
     if (QUERY_FLAG (victim, FLAG_NO_PASS)  
         || QUERY_FLAG (victim, FLAG_ALIVE))  
       check_fired_arch (trap);  
     goto leave;      goto leave;
   
   case TRAPDOOR:    case TRAPDOOR:
Line 1384
 
Line 1365
 static void apply_book (object *op, object *tmp)  static void apply_book (object *op, object *tmp)
 {  {
     int lev_diff;      int lev_diff;
       object *skill_ob;
     event *evt;      event *evt;
   
     if(QUERY_FLAG(op, FLAG_BLIND)&&!QUERY_FLAG(op,FLAG_WIZ)) {      if(QUERY_FLAG(op, FLAG_BLIND)&&!QUERY_FLAG(op,FLAG_WIZ)) {
Line 1397
 
Line 1379
     }      }
   
     /* need a literacy skill to read stuff! */      /* need a literacy skill to read stuff! */
     if ( ! change_skill(op,SK_LITERACY)) {      skill_ob = find_skill_by_name(op, tmp->skill);
       if ( ! skill_ob) {
       new_draw_info(NDI_UNIQUE, 0,op,        new_draw_info(NDI_UNIQUE, 0,op,
  "You are unable to decipher the strange symbols.");   "You are unable to decipher the strange symbols.");
       return;        return;
     }      }
     lev_diff = tmp->level - (SK_level(op) + 5);      lev_diff = tmp->level - (skill_ob->level + 5);
     if ( ! QUERY_FLAG (op, FLAG_WIZ) && lev_diff > 0)      if ( ! QUERY_FLAG (op, FLAG_WIZ) && lev_diff > 0) {
     {  
       if (lev_diff < 2)        if (lev_diff < 2)
  new_draw_info(NDI_UNIQUE, 0,op,"This book is just barely beyond your comprehension.");   new_draw_info(NDI_UNIQUE, 0,op,"This book is just barely beyond your comprehension.");
       else if (lev_diff < 3)        else if (lev_diff < 3)
Line 1422
 
Line 1404
   
     new_draw_info_format (NDI_UNIQUE, 0, op,      new_draw_info_format (NDI_UNIQUE, 0, op,
                           "You open the %s and start reading.", tmp->name);                            "You open the %s and start reading.", tmp->name);
   
     /* GROS: Handle for plugin trigger event */      /* GROS: Handle for plugin trigger event */
     if ((evt = find_event(tmp, EVENT_APPLY)) != NULL)      if ((evt = find_event(tmp, EVENT_APPLY)) != NULL)
     {      {
Line 1449
 
Line 1432
   
     /* gain xp from reading */      /* gain xp from reading */
     if(!QUERY_FLAG(tmp,FLAG_NO_SKILL_IDENT)) { /* only if not read before */      if(!QUERY_FLAG(tmp,FLAG_NO_SKILL_IDENT)) { /* only if not read before */
       int exp_gain=calc_skill_exp(op,tmp);   int exp_gain=calc_skill_exp(op,tmp, skill_ob);
       if(!QUERY_FLAG(tmp,FLAG_IDENTIFIED)) {        if(!QUERY_FLAG(tmp,FLAG_IDENTIFIED)) {
         /*exp_gain *= 2; because they just identified it too */          /*exp_gain *= 2; because they just identified it too */
         SET_FLAG(tmp,FLAG_IDENTIFIED);          SET_FLAG(tmp,FLAG_IDENTIFIED);
Line 1457
 
Line 1440
         if(tmp->env) esrv_update_item(UPD_FLAGS|UPD_NAME, op,tmp);          if(tmp->env) esrv_update_item(UPD_FLAGS|UPD_NAME, op,tmp);
         else op->contr->socket.update_look=1;          else op->contr->socket.update_look=1;
       }        }
       add_exp(op,exp_gain);        change_exp(op,exp_gain, skill_ob->skill, 0);
       SET_FLAG(tmp,FLAG_NO_SKILL_IDENT); /* so no more xp gained from this book */        SET_FLAG(tmp,FLAG_NO_SKILL_IDENT); /* so no more xp gained from this book */
     }      }
 }  }
   
   /* op is the person learning the skill, tmp is the skill scroll object */
   
   
 static void apply_skillscroll (object *op, object *tmp)  static void apply_skillscroll (object *op, object *tmp)
 {  {
   switch ((int) learn_skill (op, tmp))      switch ((int) learn_skill (op, tmp)) {
   {  
     case 0:      case 0:
       new_draw_info(NDI_UNIQUE, 0,op,"You already possess the knowledge ");        new_draw_info(NDI_UNIQUE, 0,op,"You already possess the knowledge ");
       new_draw_info_format(NDI_UNIQUE, 0,op,"held within the %s.\n",query_name(tmp));        new_draw_info_format(NDI_UNIQUE, 0,op,"held within the %s.\n",query_name(tmp));
Line 1474
 
Line 1458
   
     case 1:      case 1:
       new_draw_info_format(NDI_UNIQUE, 0,op,"You succeed in learning %s",        new_draw_info_format(NDI_UNIQUE, 0,op,"You succeed in learning %s",
       skills[tmp->stats.sp].name);   tmp->name);
       new_draw_info_format(NDI_UNIQUE, 0, op,        new_draw_info_format(NDI_UNIQUE, 0, op,
           "Type 'bind ready_skill %s",skills[tmp->stats.sp].name);   "Type 'bind ready_skill %s",tmp->name);
       new_draw_info(NDI_UNIQUE, 0,op,"to store the skill in a key.");        new_draw_info(NDI_UNIQUE, 0,op,"to store the skill in a key.");
       fix_player(op); /* to immediately link new skill to exp object */  
       decrease_ob(tmp);        decrease_ob(tmp);
       return;        return;
   
Line 1496
 
Line 1479
  * prayers are special.   * prayers are special.
  */   */
   
 static object *find_special_prayer_mark (object *op, int spell)  static object *find_special_prayer_mark (object *op, char *spell)
 {  {
     object *tmp;      object *tmp;
   
     for (tmp = op->inv; tmp; tmp = tmp->below)      for (tmp = op->inv; tmp; tmp = tmp->below)
         if (tmp->type == FORCE && tmp->slaying          if (tmp->type == FORCE && tmp->slaying
             && strcmp (tmp->slaying, "special prayer") == 0              && !strcmp (tmp->slaying, "special prayer")
             && tmp->stats.sp == spell)              && !strcmp(tmp->name, spell))
             return tmp;              return tmp;
     return 0;      return 0;
 }  }
   
 static void insert_special_prayer_mark (object *op, int spell)  static void insert_special_prayer_mark (object *op, char *spell)
 {  {
     object *force = get_archetype ("force");      object *force = get_archetype ("force");
     force->speed = 0;      force->speed = 0;
     update_ob_speed (force);      update_ob_speed (force);
     force->slaying = add_string ("special prayer");      force->slaying = add_string ("special prayer");
     force->stats.sp = spell;      if (force->name) free_string(force->name);
       force->name = add_string(spell);
     insert_ob_in_ob (force, op);      insert_ob_in_ob (force, op);
 }  }
   
 extern void do_learn_spell (object *op, int spell, int special_prayer)  void do_learn_spell (object *op, object *spell, int special_prayer)
 {  {
     object *tmp = find_special_prayer_mark (op, spell);      object *tmp = find_special_prayer_mark (op, spell->name);
   
     if (op->type != PLAYER) {      if (op->type != PLAYER) {
         LOG (llevError, "BUG: do_forget_spell(): not a player\n");          LOG (llevError, "BUG: do_learn_spell(): not a player\n");
         return;          return;
     }      }
   
     /* Upgrade special prayers to normal prayers */      /* Upgrade special prayers to normal prayers */
     if (check_spell_known (op, spell)) {      if (check_spell_known (op, spell->name)) {
         if (special_prayer || ! tmp) {          if (special_prayer || ! tmp) {
             LOG (llevError, "BUG: do_learn_spell(): spell already known, but "              LOG (llevError, "BUG: do_learn_spell(): spell already known, but can't upgrade it\n");
              "can't upgrade it\n");  
             return;              return;
         }          }
         remove_ob (tmp);          remove_ob (tmp);
Line 1541
 
Line 1524
   
     /* Learn new spell/prayer */      /* Learn new spell/prayer */
     if (tmp) {      if (tmp) {
         LOG (llevError, "BUG: do_learn_spell(): spell unknown, but special "          LOG (llevError, "BUG: do_learn_spell(): spell unknown, but special prayer mark present\n");
              "prayer mark present\n");  
         remove_ob (tmp);          remove_ob (tmp);
         free_object (tmp);          free_object (tmp);
     }      }
     play_sound_player_only (op->contr, SOUND_LEARN_SPELL, 0, 0);      play_sound_player_only (op->contr, SOUND_LEARN_SPELL, 0, 0);
     op->contr->known_spells[op->contr->nrofknownspells++] = spell;      tmp = get_object();
     if (op->contr->nrofknownspells == 1)      copy_object(spell, tmp);
         op->contr->chosen_spell = spell;      insert_ob_in_ob(tmp, op);
          
     /* For godgiven spells the player gets a reminder-mark inserted,      /* For godgiven spells the player gets a reminder-mark inserted,
        that this spell must be removed on changing cults! */       * that this spell must be removed on changing cults!
     if (special_prayer)       */
       insert_special_prayer_mark (op, spell);      if (special_prayer) {
    insert_special_prayer_mark (op, spell->name);
    SET_FLAG(tmp, FLAG_STARTEQUIP);
       }
   
     new_draw_info_format (NDI_UNIQUE, 0, op,       new_draw_info_format (NDI_UNIQUE, 0, op,
             "Type 'bind cast %s", spells[spell].name);              "Type 'bind cast %s", spell->name);
     new_draw_info (NDI_UNIQUE, 0, op, "to store the spell in a key.");      new_draw_info (NDI_UNIQUE, 0, op, "to store the spell in a key.");
 }  }
   
 extern void do_forget_spell (object *op, int spell)  void do_forget_spell (object *op, char *spell)
 {  {
     object *tmp;      object *tmp, *spob;
     int i;  
   
     if (op->type != PLAYER) {      if (op->type != PLAYER) {
         LOG (llevError, "BUG: do_forget_spell(): not a player\n");          LOG (llevError, "BUG: do_forget_spell(): not a player\n");
         return;          return;
     }      }
     if ( ! check_spell_known (op, spell)) {      if ( (spob=check_spell_known (op, spell)) == NULL) {
         LOG (llevError, "BUG: do_forget_spell(): spell not known\n");          LOG (llevError, "BUG: do_forget_spell(): spell not known\n");
         return;          return;
     }      }
          
     new_draw_info_format (NDI_UNIQUE|NDI_NAVY, 0, op,      new_draw_info_format (NDI_UNIQUE|NDI_NAVY, 0, op,
    "You lose knowledge of %s.", spells[spell].name);     "You lose knowledge of %s.", spell);
   
     tmp = find_special_prayer_mark (op, spell);      tmp = find_special_prayer_mark (op, spell);
     if (tmp) {      if (tmp) {
         remove_ob (tmp);          remove_ob (tmp);
         free_object (tmp);          free_object (tmp);
     }      }
       remove_ob(spob);
     for (i = 0; i < op->contr->nrofknownspells; i++)      free_object(spob);
     {  
         if (op->contr->known_spells[i] == spell) {  
             op->contr->known_spells[i] =  
                     op->contr->known_spells[--op->contr->nrofknownspells];  
             return;  
         }  
     }  
     LOG (llevError, "BUG: do_forget_spell(): couldn't find spell\n");  
 }  }
   
 static void apply_spellbook (object *op, object *tmp)  static void apply_spellbook (object *op, object *tmp)
 {  {
       object *skop, *spell, *spell_skill;
   
     if(QUERY_FLAG(op, FLAG_BLIND)&&!QUERY_FLAG(op,FLAG_WIZ)) {      if(QUERY_FLAG(op, FLAG_BLIND)&&!QUERY_FLAG(op,FLAG_WIZ)) {
       new_draw_info(NDI_UNIQUE, 0,op,"You are unable to read while blind.");        new_draw_info(NDI_UNIQUE, 0,op,"You are unable to read while blind.");
       return;        return;
     }      }
   
     /* artifact_spellbooks have 'slaying' field point to a spell name,      /* artifact_spellbooks have 'slaying' field point to a spell name,
     ** instead of having their spell stored in stats.sp.  We should update       * instead of having their spell stored in stats.sp.  These are
     ** stats->sp to point to that spell */       * legacy spellbooks
        */
    
     if(tmp->slaying != NULL) {      if(tmp->slaying != NULL) {
        if((tmp->stats.sp = look_up_spell_name(tmp->slaying)) <0 ){   spell=arch_to_object(find_archetype_by_object_name(tmp->slaying));
    tmp->stats.sp = -1;    if (!spell) {
    new_draw_info_format(NDI_UNIQUE, 0, op,     new_draw_info_format(NDI_UNIQUE, 0, op,
  "The book's formula for %s is incomplete", tmp->slaying);   "The book's formula for %s is incomplete", tmp->slaying);
    return;     return;
        }         }
        /* now clear tmp->slaying since we no longer need it */   else
        insert_ob_in_ob(spell, tmp);
        free_string(tmp->slaying);         free_string(tmp->slaying);
        tmp->slaying=NULL;         tmp->slaying=NULL;
     }      }
   
       skop = find_skill_by_name(op, tmp->skill);
   
     /* need a literacy skill to learn spells. Also, having a literacy level      /* need a literacy skill to learn spells. Also, having a literacy level
      * lower than the spell will make learning the spell more difficult */       * lower than the spell will make learning the spell more difficult */
     if ( ! change_skill(op,SK_LITERACY)) {      if ( !skop) {
       new_draw_info(NDI_UNIQUE, 0,op,"You can't read! Your attempt fails.");        new_draw_info(NDI_UNIQUE, 0,op,"You can't read! Your attempt fails.");
       return;        return;
     }      }
     if(tmp->stats.sp < 0 || tmp->stats.sp > NROFREALSPELLS  
         || spells[tmp->stats.sp].level>(SK_level(op)+10)) {      spell = tmp->inv;
       if (!spell) {
    LOG(llevError,"apply_spellbook: Book %s has no spell in it!\n", tmp->name);
    new_draw_info(NDI_UNIQUE, 0,op,"The spellbook symbols make no sense.");
       }
       if (spell->level > (skop->level+10)) {
       new_draw_info(NDI_UNIQUE, 0,op,"You are unable to decipher the strange symbols.");        new_draw_info(NDI_UNIQUE, 0,op,"You are unable to decipher the strange symbols.");
       return;        return;
     }       }
   
     new_draw_info_format(NDI_UNIQUE, 0, op,       new_draw_info_format(NDI_UNIQUE, 0, op,
  "The spellbook contains the %s level spell %s.",   "The spellbook contains the %s level spell %s.",
             get_levelnumber(spells[tmp->stats.sp].level),              get_levelnumber(spell->level), spell->name);
             spells[tmp->stats.sp].name);  
   
     if (!QUERY_FLAG(tmp, FLAG_IDENTIFIED)) {      if (!QUERY_FLAG(tmp, FLAG_IDENTIFIED)) {
  identify(tmp);   identify(tmp);
Line 1643
 
Line 1629
      op->contr->socket.update_look=1;       op->contr->socket.update_look=1;
     }      }
   
     if (check_spell_known (op, tmp->stats.sp) && (tmp->stats.Wis ||      /* I removed the check for special_prayer_mark here - it didn't make
         find_special_prayer_mark (op, tmp->stats.sp) == NULL))       * a lot of sense - special prayers are not found in spellbooks, and
     {       * if the player doesn't know the spell, doesn't make a lot of sense that
        * they would have a special prayer mark.
        */
       if (check_spell_known (op, spell->name)) {
  new_draw_info(NDI_UNIQUE, 0,op,"You already know that spell.\n");   new_draw_info(NDI_UNIQUE, 0,op,"You already know that spell.\n");
  return;   return;
     }      }
   
     /* I changed spell learning in 3 ways:      if (spell->skill) {
    spell_skill = find_skill_by_name(op, spell->skill);
    if (!spell_skill) {
        new_draw_info_format(NDI_UNIQUE, 0, op,
    "You lack the skill %s to use this spell",
    spell->skill);
        return;
    }
    if (spell_skill->level < spell->level) {
        new_draw_info_format(NDI_UNIQUE, 0, op,
    "You need to be level %d in %s to learn this spell.",
    spell->level, spell->skill);
        return;
    }
       }
   
       /* Logic as follows
      *       *
      *  1- MU spells use Int to learn, Cleric spells use Wisdom       *  1- MU spells use Int to learn, Cleric spells use Wisdom
      *       *
      *  2- The learner's level (in skills sytem level==literacy level; if no        *  2- The learner's skill level in literacy adjusts the chance to learn
      *     skills level == overall level) impacts the chances of spell learning.        *     a spell.
      *       *
      *  3 -Automatically fail to learn if you read while confused       *  3 -Automatically fail to learn if you read while confused
      *        *
Line 1664
 
Line 1669
      */        */
     if(QUERY_FLAG(op,FLAG_CONFUSED)) {       if(QUERY_FLAG(op,FLAG_CONFUSED)) {
       new_draw_info(NDI_UNIQUE,0,op,"In your confused state you flub the wording of the text!");        new_draw_info(NDI_UNIQUE,0,op,"In your confused state you flub the wording of the text!");
       /* this needs to be a - number [garbled] */   scroll_failure(op, 0 - random_roll(0, spell->level, op, PREFER_LOW), MAX(spell->stats.sp, spell->stats.grace));
       scroll_failure(op, 0 - random_roll(0, spells[tmp->stats.sp].level, op, PREFER_LOW), spells[tmp->stats.sp].sp);      } else if(QUERY_FLAG(tmp,FLAG_STARTEQUIP) ||
     } else if(QUERY_FLAG(tmp,FLAG_STARTEQUIP) || random_roll(0, 149, op, PREFER_LOW)-(2*SK_level(op)) <   (random_roll(0, 100, op, PREFER_LOW)-(5*skop->level)) <
  learn_spell[spells[tmp->stats.sp].cleric ? op->stats.Wis : op->stats.Int]) {         learn_spell[spell->stats.grace ? op->stats.Wis : op->stats.Int]) {
   
       new_draw_info(NDI_UNIQUE, 0,op,"You succeed in learning the spell!");        new_draw_info(NDI_UNIQUE, 0,op,"You succeed in learning the spell!");
       do_learn_spell (op, tmp->stats.sp, 0);   do_learn_spell (op, spell, 0);
   
       /* xp gain to literacy for spell learning */        /* xp gain to literacy for spell learning */
       if ( ! QUERY_FLAG (tmp, FLAG_STARTEQUIP))        if ( ! QUERY_FLAG (tmp, FLAG_STARTEQUIP))
         add_exp(op,calc_skill_exp(op,tmp));       change_exp(op,calc_skill_exp(op,tmp,skop), skop->skill, 0);
     } else {      } else {
       play_sound_player_only(op->contr, SOUND_FUMBLE_SPELL,0,0);        play_sound_player_only(op->contr, SOUND_FUMBLE_SPELL,0,0);
       new_draw_info(NDI_UNIQUE, 0,op,"You fail to learn the spell.\n");        new_draw_info(NDI_UNIQUE, 0,op,"You fail to learn the spell.\n");
Line 1684
 
Line 1690
   
 void apply_scroll (object *op, object *tmp, int dir)  void apply_scroll (object *op, object *tmp, int dir)
 {  {
     int scroll_spell=tmp->stats.sp, old_spell=0;      object *skop;
     rangetype old_shoot=range_none;  
     char buf[MAX_BUF];  
   
     if(QUERY_FLAG(op, FLAG_BLIND)&&!QUERY_FLAG(op,FLAG_WIZ)) {      if(QUERY_FLAG(op, FLAG_BLIND)&&!QUERY_FLAG(op,FLAG_WIZ)) {
       new_draw_info(NDI_UNIQUE, 0,op, "You are unable to read while blind.");        new_draw_info(NDI_UNIQUE, 0,op, "You are unable to read while blind.");
Line 1696
 
Line 1700
     if (!QUERY_FLAG(tmp, FLAG_IDENTIFIED))       if (!QUERY_FLAG(tmp, FLAG_IDENTIFIED))
  identify(tmp);   identify(tmp);
   
     if( scroll_spell < 0 || scroll_spell >= NROFREALSPELLS) {      if (!tmp->inv || tmp->inv->type != SPELL) {
         new_draw_info (NDI_UNIQUE, 0, op,          new_draw_info (NDI_UNIQUE, 0, op,
                        "The scroll just doesn't make sense!");                         "The scroll just doesn't make sense!");
         return;          return;
Line 1706
 
Line 1710
  /* players need a literacy skill to read stuff! */   /* players need a literacy skill to read stuff! */
  int exp_gain=0;   int exp_gain=0;
   
         if ( ! change_skill(op,SK_LITERACY)) {   /* hard code literacy - tmp->skill points to where the exp
    * should go for anything killed by the spell.
    */
    skop = find_skill_by_name(op, skill_names[SK_LITERACY]);
   
           if ( ! skop) {
           new_draw_info(NDI_UNIQUE, 0,op,            new_draw_info(NDI_UNIQUE, 0,op,
             "You are unable to decipher the strange symbols.");              "You are unable to decipher the strange symbols.");
           return;            return;
         }           }
   
  /* We give exp for reading the scroll.  I reduced this (0.95.3) to   if((exp_gain = calc_skill_exp(op,tmp, skop)))
  * give half as much since there is no longer any risk.  Even this       change_exp(op,exp_gain, skop->skill, 0);
  * could be excessive.  
  */  
  if((exp_gain = calc_skill_exp(op,tmp)))  
      add_exp(op,exp_gain/2);  
   
   
         /* Now, call here so the right skill is readied -- literacy   
  * isnt necesarily connected to the exp obj to which the xp   
  * will go (for kills made by the magic of the scroll)   
  */   
         SET_FLAG(tmp,FLAG_APPLIED);  
         (void) check_skill_to_apply(op,tmp);  
         CLEAR_FLAG(tmp,FLAG_APPLIED);  
         old_shoot= op->contr->shoottype;  
         old_spell = op->contr->chosen_spell;  
         op->contr->shoottype=range_golem;  
         op->contr->chosen_spell = scroll_spell;  
     }      }
   
     new_draw_info_format(NDI_BLACK, 0, op,      new_draw_info_format(NDI_BLACK, 0, op,
         "The scroll of %s turns to dust.", spells[tmp->stats.sp].name);        "The scroll of %s turns to dust.", tmp->inv->name);
   
     /* Not sure if there is a reason to inform everyone on the map of this, but whatever */  
     sprintf(buf, "%s reads a scroll of %s.",op->name,spells[tmp->stats.sp].name);  
     new_info_map(NDI_ORANGE, op->map, buf);  
   
     cast_spell(op,tmp,dir,scroll_spell,0,spellScroll,NULL);      cast_spell(op,tmp,dir,tmp->inv, NULL);
     decrease_ob(tmp);      decrease_ob(tmp);
   
     if(op->type==PLAYER && op->contr->golem==NULL) {  
         op->contr->shoottype=old_shoot;  
  op->contr->chosen_spell = old_spell;  
     }  
 }  }
   
 /* Applies a treasure object - by default, chest.  op  /* Applies a treasure object - by default, chest.  op
Line 2269
 
Line 2253
     return 1;      return 1;
   
   case POTION:    case POTION:
     SET_FLAG(tmp,FLAG_APPLIED);  
     (void) check_skill_to_apply(op,tmp);  
     CLEAR_FLAG(tmp,FLAG_APPLIED);  
     (void) apply_potion(op, tmp);      (void) apply_potion(op, tmp);
     return 1;      return 1;
   
Line 2490
 
Line 2471
      new_draw_info_format(NDI_UNIQUE, 0, who, "You unwield %s.",query_name(op));       new_draw_info_format(NDI_UNIQUE, 0, who, "You unwield %s.",query_name(op));
   
      (void) change_abil (who,op);       (void) change_abil (who,op);
      /* 'unready' melee weapons skill if it is current skill */  
      (void) check_skill_to_apply(who,op);  
      if(QUERY_FLAG(who,FLAG_READY_WEAPON))       if(QUERY_FLAG(who,FLAG_READY_WEAPON))
  CLEAR_FLAG(who,FLAG_READY_WEAPON);   CLEAR_FLAG(who,FLAG_READY_WEAPON);
      /* GROS: update the current_weapon_script field (used with script_attack for weapons) */       /* GROS: update the current_weapon_script field (used with script_attack for weapons) */
      who->current_weapon_script = NULL;       who->current_weapon_script = NULL;
      who->current_weapon = NULL;       who->current_weapon = NULL;
        clear_skill(who);
      break;       break;
   
  case SKILL:         /* allows objects to impart skills */   case SKILL:         /* allows objects to impart skills */
    case SKILL_TOOL:
      if (op != who->chosen_skill) {       if (op != who->chosen_skill) {
  LOG (llevError, "BUG: apply_special(): applied skill is not a chosen skill\n");   LOG (llevError, "BUG: apply_special(): applied skill is not a chosen skill\n");
      }       }
      if (who->type==PLAYER) {       if (who->type==PLAYER) {
    if (who->contr->shoottype == range_skill)
  who->contr->shoottype = range_none;   who->contr->shoottype = range_none;
  if ( ! op->invisible) {   if ( ! op->invisible) {
      /* its a tool, need to unlink it */  
      unlink_skill (op);  
      new_draw_info_format (NDI_UNIQUE, 0, who,       new_draw_info_format (NDI_UNIQUE, 0, who,
                                     "You stop using the %s.", query_name(op));                                      "You stop using the %s.", query_name(op));
    } else {
      new_draw_info_format (NDI_UNIQUE, 0, who,       new_draw_info_format (NDI_UNIQUE, 0, who,
                                     "You can no longer use the skill: %s.",                                      "You can no longer use the skill: %s.",
                                     skills[op->stats.sp].name);                                      op->skill);
  }   }
      }       }
      (void) change_abil (who, op);       (void) change_abil (who, op);
Line 2564
 
Line 2545
  case WAND:   case WAND:
  case ROD:   case ROD:
  case HORN:   case HORN:
      (void) check_skill_to_apply(who,op);       clear_skill(who);
      new_draw_info_format(NDI_UNIQUE, 0, who, "You unready %s.",query_name(op));       new_draw_info_format(NDI_UNIQUE, 0, who, "You unready %s.",query_name(op));
      if(who->type==PLAYER) {       if(who->type==PLAYER) {
  who->contr->shoottype = range_none;   who->contr->shoottype = range_none;
Line 2868
 
Line 2849
 int apply_special (object *who, object *op, int aflags)  int apply_special (object *who, object *op, int aflags)
 {  {
     int basic_flag = aflags & AP_BASIC_FLAGS;      int basic_flag = aflags & AP_BASIC_FLAGS;
     object *tmp, *tmp2;      object *tmp, *tmp2, *skop=NULL;
     event *evt;      event *evt;
     int i;      int i;
   
Line 2899
 
Line 2880
   
     i = can_apply_object(who, op);      i = can_apply_object(who, op);
   
     /* Somewhere around here the item_power check should be done */  
   
     /* Can't just apply this object.  Lets see what not and what to do */      /* Can't just apply this object.  Lets see what not and what to do */
     if (i) {      if (i) {
  if (i & CAN_APPLY_NEVER) {   if (i & CAN_APPLY_NEVER) {
Line 2926
 
Line 2905
      }       }
  }   }
     }      }
       if (op->skill && op->type != SKILL && op->type != SKILL_TOOL) {
    skop=find_skill_by_name(who, op->skill);
    if (!skop) {
        new_draw_info_format(NDI_UNIQUE, 0, who, "You need the %s skill to use this item!", op->skill);
        return 1;
    } else {
        /* While experience will be credited properly, we want to change the
         * skill so that the dam and wc get updated
         */
        change_skill(who, skop, 0);
    }
       }
   
       if (who->type == PLAYER && op->item_power &&
    (op->item_power + who->item_power) > (settings.item_power_factor * who->level)) {
    new_draw_info(NDI_UNIQUE, 0, who, "Equipping that combined with other items would consume your soul!");
    return 1;
       }
   
   
     /* Ok.  We are now at the state where we can apply the new object.      /* Ok.  We are now at the state where we can apply the new object.
      * Note that we don't have the checks for can_use_...       * Note that we don't have the checks for can_use_...
      * below - that is already taken care of by can_apply_object.        * below - that is already taken care of by can_apply_object.
Line 2957
 
Line 2956
      }       }
      SET_FLAG(op, FLAG_APPLIED);       SET_FLAG(op, FLAG_APPLIED);
   
      /* check for melee weapons skill, alter player status.       if (skop) change_skill(who, skop, 1);
      * Note that we need to call this *before* change_abil */  
      if(!check_skill_to_apply(who,op)) return 1;  
      if(!QUERY_FLAG(who,FLAG_READY_WEAPON))       if(!QUERY_FLAG(who,FLAG_READY_WEAPON))
  SET_FLAG(who, FLAG_READY_WEAPON);   SET_FLAG(who, FLAG_READY_WEAPON);
   
Line 2998
 
Line 2995
      new_draw_info_format(NDI_UNIQUE, 0, who, "You turn on your %s.",       new_draw_info_format(NDI_UNIQUE, 0, who, "You turn on your %s.",
  op->name);   op->name);
      tmp2 = arch_to_object(op->other_arch);       tmp2 = arch_to_object(op->other_arch);
      tmp2->x = op->x;  
      tmp2->y = op->y;  
      tmp2->map = op->map;  
      tmp2->below = op->below;  
      tmp2->above = op->above;  
      tmp2->stats.food = op->stats.food;       tmp2->stats.food = op->stats.food;
      SET_FLAG(tmp2, FLAG_APPLIED);       SET_FLAG(tmp2, FLAG_APPLIED);
      if (tmp == NULL) {       if (tmp == NULL) {
Line 3028
 
Line 3020
  esrv_send_item(who, tmp2);   esrv_send_item(who, tmp2);
      return 0;       return 0;
      break;       break;
   
  /* this part is needed for skill-tools */    /* this part is needed for skill-tools */
  case SKILL:   case SKILL:
    case SKILL_TOOL:
      if (who->chosen_skill) {       if (who->chosen_skill) {
  LOG (llevError, "BUG: apply_special(): can't apply two skills\n");   LOG (llevError, "BUG: apply_special(): can't apply two skills\n");
  return 1;   return 1;
      }       }
      if (who->type == PLAYER) {       if (who->type == PLAYER) {
  who->contr->shoottype = range_skill;   who->contr->shoottype = range_skill;
    who->contr->ranges[range_skill] = op;
      if ( ! op->invisible) {       if ( ! op->invisible) {
  /* for tools */  
  if (op->exp_obj)  
      LOG (llevError, "BUG: apply_special(SKILL): found unapplied tool with experience object (%s)\n", op->name);  
  else  
      (void) link_player_skill (who, op);  
  new_draw_info_format (NDI_UNIQUE, 0, who, "You ready %s.",   new_draw_info_format (NDI_UNIQUE, 0, who, "You ready %s.",
                                   query_name (op));                                    query_name (op));
  new_draw_info_format (NDI_UNIQUE, 0, who,   new_draw_info_format (NDI_UNIQUE, 0, who,
                                   "You can now use the skill: %s.",                                    "You can now use the skill: %s.",
                                   skills[op->stats.sp].name);   op->skill);
      } else {       } else {
  new_draw_info_format (NDI_UNIQUE, 0, who, "Readied skill: %s.",   new_draw_info_format (NDI_UNIQUE, 0, who, "Readied skill: %s.",
                                   skills[op->stats.sp].name);         op->skill? op->skill:op->name);
      }       }
      }       }
      SET_FLAG (op, FLAG_APPLIED);       SET_FLAG (op, FLAG_APPLIED);
Line 3080
 
Line 3070
  case HORN:   case HORN:
      /* check for skill, alter player status */        /* check for skill, alter player status */
      SET_FLAG(op, FLAG_APPLIED);       SET_FLAG(op, FLAG_APPLIED);
      if(!check_skill_to_apply(who,op)) return 1;       if (skop) change_skill(who, skop, 0);
      new_draw_info_format (NDI_UNIQUE, 0, who, "You ready %s.", query_name(op));       new_draw_info_format (NDI_UNIQUE, 0, who, "You ready %s.", query_name(op));
   
      if(who->type==PLAYER) {       if(who->type==PLAYER) {
Line 3159
 
Line 3149
  op->stats.exp?op->stats.exp:MAX(op->map->difficulty, 5)))==NULL&&--i);   op->stats.exp?op->stats.exp:MAX(op->map->difficulty, 5)))==NULL&&--i);
       if(tmp==NULL)        if(tmp==NULL)
    return 0;     return 0;
       if(QUERY_FLAG(tmp, FLAG_CURSED) || QUERY_FLAG(tmp, FLAG_DAMNED))   if(QUERY_FLAG(tmp, FLAG_CURSED) || QUERY_FLAG(tmp, FLAG_DAMNED)) {
       {  
         free_object(tmp);          free_object(tmp);
         tmp = NULL;          tmp = NULL;
       }        }
     } while(!tmp);      } while(!tmp);
        tmp->x=op->x;
     tmp->x=op->x,tmp->y=op->y;       tmp->y=op->y;
     SET_FLAG(tmp,FLAG_UNPAID);      SET_FLAG(tmp,FLAG_UNPAID);
     insert_ob_in_map(tmp,op->map,NULL,0);      insert_ob_in_map(tmp,op->map,NULL,0);
     CLEAR_FLAG(op,FLAG_AUTO_APPLY);      CLEAR_FLAG(op,FLAG_AUTO_APPLY);
Line 3196
 
Line 3185
     free_object(op);      free_object(op);
     break;      break;
   }    }
   
   return tmp ? 1 : 0;    return tmp ? 1 : 0;
 }  }
   
Line 3219
 
Line 3207
   
         if (tmp->inv) {          if (tmp->inv) {
           object *invtmp, *invnext;            object *invtmp, *invnext;
   
           for (invtmp=tmp->inv; invtmp != NULL; invtmp = invnext) {            for (invtmp=tmp->inv; invtmp != NULL; invtmp = invnext) {
             invnext = invtmp->below;              invnext = invtmp->below;
             if(QUERY_FLAG(invtmp,FLAG_AUTO_APPLY))              if(QUERY_FLAG(invtmp,FLAG_AUTO_APPLY))
Line 3242
 
Line 3231
           tmp->speed = 0;            tmp->speed = 0;
           update_ob_speed(tmp);            update_ob_speed(tmp);
         }          }
         else if(tmp && tmp->arch && tmp->type!=PLAYER && tmp->type!=TREASURE && HAS_RANDOM_ITEMS(tmp))   else if(tmp && tmp->arch && tmp->type!=PLAYER && tmp->type!=TREASURE &&
       tmp->type != SPELL && HAS_RANDOM_ITEMS(tmp))
           create_treasure(tmp->randomitems, tmp, GT_APPLY,            create_treasure(tmp->randomitems, tmp, GT_APPLY,
                           m->difficulty,0);                            m->difficulty,0);
       }        }
   /*end of cycle through map square*/  
   for(x=0;x<MAP_WIDTH(m);x++)    for(x=0;x<MAP_WIDTH(m);x++)
     for(y=0;y<MAP_HEIGHT(m);y++)      for(y=0;y<MAP_HEIGHT(m);y++)
       for(tmp=get_map_ob(m,x,y);tmp!=NULL;tmp=tmp->above)        for(tmp=get_map_ob(m,x,y);tmp!=NULL;tmp=tmp->above)
Line 3256
 
Line 3246
 }  }
   
 /* eat_special_food() - some food may (temporarily) alter  /* eat_special_food() - some food may (temporarily) alter
  * player status. We do it w/ this routine and cast_change_attr().   * player status.  This used to call cast_change_attr(), but
  * Note the dircection is set to "99"  so that cast_change_attr()   * that doesn't work with the new spell code.  Since we know what
  * will only modify the user's status. We shouldnt be able to   * the food changes, just grab a force and use that instead.
  * effect others by eating food!  
  * -b.t.  
  */   */
   
 void eat_special_food(object *who, object *food) {  void eat_special_food(object *who, object *food) {
     /* Corresponding spell to cast to get protection to      object *force;
      * the attactkype.  This matches the order of ATNR values      int i, did_one=0, k;
      * in attack.h  
      */  
     static int sp_type[NROFATTACKS] = { SP_ARMOUR, SP_PROT_MAGIC, SP_PROT_FIRE,  
  SP_PROT_ELEC, SP_PROT_COLD, SP_PROT_CONFUSE, -1 /*acid */,  
  SP_PROT_DRAIN, -1 /*weaponmagic*/, -1 /*ghosthit*/, SP_PROT_POISON,  
  SP_PROT_SLOW, SP_PROT_PARALYZE, -1 /* turn undead */,  
  -1 /* fear */, SP_PROT_CANCEL, SP_PROT_DEPLETE, -1 /* death*/,  
  -1 /* chaos */, -1 /*counterspell */, -1 /* godpower */,  
  -1 /*holyword */, -1 /*blind*/, -1 /*internal */ };  
   
     /* matrix for stats we can increase by eating */      force = get_archetype(FORCE_NAME);
     int i;  
     /* Declare these static so they only get initialzed once.  IT doesn't appear  
      * that we are modifying these, so this works out ok.  
      */  
     static int stat[] = { STR, DEX, CON, CHA },  
     mod_stat[] = {SP_STRENGTH, SP_DEXTERITY, SP_CONSTITUTION, SP_CHARISMA };  
   
     /* check if food modifies stats of the eater */      for (i=0; i < NUM_STATS; i++) {
     for(i=0; i<(sizeof(stat)/sizeof(int)); i++)   k = get_attr_value(&food->stats, i);
  if(get_attr_value(&food->stats, stat[i]))   if (k) {
           cast_change_attr(who,who,99,mod_stat[i]);       set_attr_value(&force->stats, i, k);
        did_one = 1;
    }
       }
   
     /* check if we can protect the eater */      /* check if we can protect the eater */
     for (i=0; i<NROFATTACKS; i++) {      for (i=0; i<NROFATTACKS; i++) {
  if (food->resist[i]>0 && sp_type[i]!=-1)   if (food->resist[i]>0) {
      cast_change_attr(who,who,99,sp_type[i]);       force->resist[i] = food->resist[i] / 2;
        did_one = 1;
    }
       }
       if (did_one) {
    force->speed = 0.1;
    update_ob_speed(force);
    /* bigger morsel of food = longer effect time */
    force->stats.food = food->stats.food / 5;
    SET_FLAG(force, FLAG_IS_USED_UP);   
    SET_FLAG(force, FLAG_APPLIED);
    change_abil(who, force);
    insert_ob_in_ob(force, who);
       } else {
    free_object(force);
     }      }
   
   /* check for hp, sp change */    /* check for hp, sp change */
Line 3320
 
Line 3310
  /* place limit on max sp from food? */   /* place limit on max sp from food? */
      }       }
   }    }
       fix_player(who);
 }  }
   
   
Line 3399
 
Line 3390
   
     if(failure<= -1&&failure > -15) {/* wonder */      if(failure<= -1&&failure > -15) {/* wonder */
  new_draw_info(NDI_UNIQUE, 0,op,"Your spell warps!.");   new_draw_info(NDI_UNIQUE, 0,op,"Your spell warps!.");
  cast_cone(op,op,0,10,SP_WOW,spellarch[SP_WOW],0);   object *tmp;
    tmp=get_archetype(SPELL_WONDER);
    cast_wonder(op, op, 0, tmp);
    free_object(tmp);
     } else if (failure <= -15&&failure > -35) {/* drain mana */      } else if (failure <= -15&&failure > -35) {/* drain mana */
  new_draw_info(NDI_UNIQUE, 0,op,"Your mana is drained!.");   new_draw_info(NDI_UNIQUE, 0,op,"Your mana is drained!.");
  op->stats.sp -= random_roll(0, power-1, op, PREFER_LOW);   op->stats.sp -= random_roll(0, power-1, op, PREFER_LOW);
Line 3416
 
Line 3410
      new_draw_info(NDI_UNIQUE, 0,op,"The magic recoils on you!");       new_draw_info(NDI_UNIQUE, 0,op,"The magic recoils on you!");
      blind_player(op,op,power);       blind_player(op,op,power);
  } else if (failure <= -80) {/* blast the immediate area */   } else if (failure <= -80) {/* blast the immediate area */
        object *tmp;
        tmp=get_archetype(LOOSE_MANA);
        cast_magic_storm(op,tmp, power);
      new_draw_info(NDI_UNIQUE, 0,op,"You unlease uncontrolled mana!");       new_draw_info(NDI_UNIQUE, 0,op,"You unlease uncontrolled mana!");
      cast_mana_storm(op,power);       free_object(tmp);
  }   }
     }      }
 }  }


Legend:
line(s) removed in v.1.86 
line(s) changed
 line(s) added in v.1.87

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