Main Page | Alphabetical List | Data Structures | File List | Data Fields | Globals

handler.c

Go to the documentation of this file.
00001 /***************************************************************************
00002  *  Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,        *
00003  *  Michael Seifert, Hans Henrik Strfeldt, Tom Madsen, and Katja Nyboe.    *
00004  *                                                                         *
00005  *  Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael          *
00006  *  Chastain, Michael Quan, and Mitchell Tse.                              *
00007  *                                                                         *
00008  *  In order to use any part of this Merc Diku Mud, you must comply with   *
00009  *  both the original Diku license in 'license.doc' as well the Merc       *
00010  *  license in 'license.txt'.  In particular, you may not remove either of *
00011  *  these copyright notices.                                               *
00012  *                                                                         *
00013  *  Much time and thought has gone into this software and you are          *
00014  *  benefitting.  We hope that you share your changes too.  What goes      *
00015  *  around, comes around.                                                  *
00016  **************************************************************************/
00017 
00018 /***************************************************************************
00019  *   ROM 2.4 is copyright 1993-1998 Russ Taylor                            *
00020  *   ROM has been brought to you by the ROM consortium                     *
00021  *       Russ Taylor (rtaylor@hypercube.org)                               *
00022  *       Gabrielle Taylor (gtaylor@hypercube.org)                          *
00023  *       Brian Moore (zump@rom.org)                                        *
00024  *   By using this code, you have agreed to follow the terms of the        *
00025  *   ROM license, in the file Rom24/doc/rom.license                        *
00026  **************************************************************************/
00027 
00028 #if defined(macintosh)
00029 #include <types.h>
00030 #else
00031 #include <sys/types.h>
00032 #endif
00033 #include <ctype.h>
00034 #include <stdio.h>
00035 #include <string.h>
00036 #include <time.h>
00037 #include "merc.h"
00038 #include "interp.h"
00039 #include "magic.h"
00040 #include "recycle.h"
00041 #include "tables.h"
00042 
00043 /*
00044  * Local functions.
00045  */
00046 void affect_modify args ((CHAR_DATA * ch, AFFECT_DATA * paf, bool fAdd));
00047 
00048 
00049 /* friend stuff -- for NPC's mostly */
00050 bool is_friend (CHAR_DATA * ch, CHAR_DATA * victim)
00051 {
00052     if (is_same_group (ch, victim))
00053         return TRUE;
00054 
00055 
00056     if (!IS_NPC (ch))
00057         return FALSE;
00058 
00059     if (!IS_NPC (victim))
00060     {
00061         if (IS_SET (ch->off_flags, ASSIST_PLAYERS))
00062             return TRUE;
00063         else
00064             return FALSE;
00065     }
00066 
00067     if (IS_AFFECTED (ch, AFF_CHARM))
00068         return FALSE;
00069 
00070     if (IS_SET (ch->off_flags, ASSIST_ALL))
00071         return TRUE;
00072 
00073     if (ch->group && ch->group == victim->group)
00074         return TRUE;
00075 
00076     if (IS_SET (ch->off_flags, ASSIST_VNUM)
00077         && ch->pIndexData == victim->pIndexData)
00078         return TRUE;
00079 
00080     if (IS_SET (ch->off_flags, ASSIST_RACE) && ch->race == victim->race)
00081         return TRUE;
00082 
00083     if (IS_SET (ch->off_flags, ASSIST_ALIGN)
00084         && !IS_SET (ch->act, ACT_NOALIGN)
00085         && !IS_SET (victim->act, ACT_NOALIGN)
00086         && ((IS_GOOD (ch) && IS_GOOD (victim))
00087             || (IS_EVIL (ch) && IS_EVIL (victim)) || (IS_NEUTRAL (ch)
00088                                                       &&
00089                                                       IS_NEUTRAL (victim))))
00090         return TRUE;
00091 
00092     return FALSE;
00093 }
00094 
00095 /* returns number of people on an object */
00096 int count_users (OBJ_DATA * obj)
00097 {
00098     CHAR_DATA *fch;
00099     int count = 0;
00100 
00101     if (obj->in_room == NULL)
00102         return 0;
00103 
00104     for (fch = obj->in_room->people; fch != NULL; fch = fch->next_in_room)
00105         if (fch->on == obj)
00106             count++;
00107 
00108     return count;
00109 }
00110 
00111 /* returns material number */
00112 int material_lookup (const char *name)
00113 {
00114     return 0;
00115 }
00116 
00117 int weapon_lookup (const char *name)
00118 {
00119     int type;
00120 
00121     for (type = 0; weapon_table[type].name != NULL; type++)
00122     {
00123         if (LOWER (name[0]) == LOWER (weapon_table[type].name[0])
00124             && !str_prefix (name, weapon_table[type].name))
00125             return type;
00126     }
00127 
00128     return -1;
00129 }
00130 
00131 int weapon_type (const char *name)
00132 {
00133     int type;
00134 
00135     for (type = 0; weapon_table[type].name != NULL; type++)
00136     {
00137         if (LOWER (name[0]) == LOWER (weapon_table[type].name[0])
00138             && !str_prefix (name, weapon_table[type].name))
00139             return weapon_table[type].type;
00140     }
00141 
00142     return WEAPON_EXOTIC;
00143 }
00144 
00145 char *item_name (int item_type)
00146 {
00147     int type;
00148 
00149     for (type = 0; item_table[type].name != NULL; type++)
00150         if (item_type == item_table[type].type)
00151             return item_table[type].name;
00152     return "none";
00153 }
00154 
00155 char *weapon_name (int weapon_type)
00156 {
00157     int type;
00158 
00159     for (type = 0; weapon_table[type].name != NULL; type++)
00160         if (weapon_type == weapon_table[type].type)
00161             return weapon_table[type].name;
00162     return "exotic";
00163 }
00164 
00165 int attack_lookup (const char *name)
00166 {
00167     int att;
00168 
00169     for (att = 0; attack_table[att].name != NULL; att++)
00170     {
00171         if (LOWER (name[0]) == LOWER (attack_table[att].name[0])
00172             && !str_prefix (name, attack_table[att].name))
00173             return att;
00174     }
00175 
00176     return 0;
00177 }
00178 
00179 /* returns a flag for wiznet */
00180 long wiznet_lookup (const char *name)
00181 {
00182     int flag;
00183 
00184     for (flag = 0; wiznet_table[flag].name != NULL; flag++)
00185     {
00186         if (LOWER (name[0]) == LOWER (wiznet_table[flag].name[0])
00187             && !str_prefix (name, wiznet_table[flag].name))
00188             return flag;
00189     }
00190 
00191     return -1;
00192 }
00193 
00194 /* returns class number */
00195 int class_lookup (const char *name)
00196 {
00197     int class;
00198 
00199     for (class = 0; class < MAX_CLASS; class++)
00200     {
00201         if (LOWER (name[0]) == LOWER (class_table[class].name[0])
00202             && !str_prefix (name, class_table[class].name))
00203             return class;
00204     }
00205 
00206     return -1;
00207 }
00208 
00209 /* for immunity, vulnerabiltiy, and resistant
00210    the 'globals' (magic and weapons) may be overriden
00211    three other cases -- wood, silver, and iron -- are checked in fight.c */
00212 
00213 int check_immune (CHAR_DATA * ch, int dam_type)
00214 {
00215     int immune, def;
00216     int bit;
00217 
00218     immune = -1;
00219     def = IS_NORMAL;
00220 
00221     if (dam_type == DAM_NONE)
00222         return immune;
00223 
00224     if (dam_type <= 3)
00225     {
00226         if (IS_SET (ch->imm_flags, IMM_WEAPON))
00227             def = IS_IMMUNE;
00228         else if (IS_SET (ch->res_flags, RES_WEAPON))
00229             def = IS_RESISTANT;
00230         else if (IS_SET (ch->vuln_flags, VULN_WEAPON))
00231             def = IS_VULNERABLE;
00232     }
00233     else
00234     {                            /* magical attack */
00235 
00236         if (IS_SET (ch->imm_flags, IMM_MAGIC))
00237             def = IS_IMMUNE;
00238         else if (IS_SET (ch->res_flags, RES_MAGIC))
00239             def = IS_RESISTANT;
00240         else if (IS_SET (ch->vuln_flags, VULN_MAGIC))
00241             def = IS_VULNERABLE;
00242     }
00243 
00244     /* set bits to check -- VULN etc. must ALL be the same or this will fail */
00245     switch (dam_type)
00246     {
00247         case (DAM_BASH):
00248             bit = IMM_BASH;
00249             break;
00250         case (DAM_PIERCE):
00251             bit = IMM_PIERCE;
00252             break;
00253         case (DAM_SLASH):
00254             bit = IMM_SLASH;
00255             break;
00256         case (DAM_FIRE):
00257             bit = IMM_FIRE;
00258             break;
00259         case (DAM_COLD):
00260             bit = IMM_COLD;
00261             break;
00262         case (DAM_LIGHTNING):
00263             bit = IMM_LIGHTNING;
00264             break;
00265         case (DAM_ACID):
00266             bit = IMM_ACID;
00267             break;
00268         case (DAM_POISON):
00269             bit = IMM_POISON;
00270             break;
00271         case (DAM_NEGATIVE):
00272             bit = IMM_NEGATIVE;
00273             break;
00274         case (DAM_HOLY):
00275             bit = IMM_HOLY;
00276             break;
00277         case (DAM_ENERGY):
00278             bit = IMM_ENERGY;
00279             break;
00280         case (DAM_MENTAL):
00281             bit = IMM_MENTAL;
00282             break;
00283         case (DAM_DISEASE):
00284             bit = IMM_DISEASE;
00285             break;
00286         case (DAM_DROWNING):
00287             bit = IMM_DROWNING;
00288             break;
00289         case (DAM_LIGHT):
00290             bit = IMM_LIGHT;
00291             break;
00292         case (DAM_CHARM):
00293             bit = IMM_CHARM;
00294             break;
00295         case (DAM_SOUND):
00296             bit = IMM_SOUND;
00297             break;
00298         default:
00299             return def;
00300     }
00301 
00302     if (IS_SET (ch->imm_flags, bit))
00303         immune = IS_IMMUNE;
00304     else if (IS_SET (ch->res_flags, bit) && immune != IS_IMMUNE)
00305         immune = IS_RESISTANT;
00306     else if (IS_SET (ch->vuln_flags, bit))
00307     {
00308         if (immune == IS_IMMUNE)
00309             immune = IS_RESISTANT;
00310         else if (immune == IS_RESISTANT)
00311             immune = IS_NORMAL;
00312         else
00313             immune = IS_VULNERABLE;
00314     }
00315 
00316     if (immune == -1)
00317         return def;
00318     else
00319         return immune;
00320 }
00321 
00322 bool is_clan (CHAR_DATA * ch)
00323 {
00324     return ch->clan;
00325 }
00326 bool is_kingdom (CHAR_DATA *ch)
00327 {
00328     return ch->king;
00329 }
00330 
00331 bool is_same_kingdom (CHAR_DATA *ch, CHAR_DATA *victim)
00332 {
00333     if (ch->king == 0)
00334         return FALSE;
00335     else
00336         return (ch->king == victim->king);
00337 }
00338 
00339 bool is_same_clan (CHAR_DATA * ch, CHAR_DATA * victim)
00340 {
00341     if (clan_table[ch->clan].independent)
00342         return FALSE;
00343     else
00344         return (ch->clan == victim->clan);
00345 }
00346 
00347 /* checks mob format */
00348 bool is_old_mob (CHAR_DATA * ch)
00349 {
00350     if (ch->pIndexData == NULL)
00351         return FALSE;
00352     else if (ch->pIndexData->new_format)
00353         return FALSE;
00354     return TRUE;
00355 }
00356 
00357 /* for returning skill information */
00358 int get_skill (CHAR_DATA * ch, int sn)
00359 {
00360     int skill;
00361 
00362     if (sn == -1)
00363     {                            /* shorthand for level based skills */
00364         skill = ch->level * 5 / 2;
00365     }
00366 
00367     else if (sn < -1 || sn > MAX_SKILL)
00368     {
00369         bug ("Bad sn %d in get_skill.", sn);
00370         skill = 0;
00371     }
00372 
00373     else if (!IS_NPC (ch))
00374     {
00375         if (ch->level < skill_table[sn].skill_level[ch->class])
00376             skill = 0;
00377         else
00378             skill = ch->pcdata->learned[sn];
00379     }
00380 
00381     else
00382     {                            /* mobiles */
00383 
00384 
00385 
00386         if (skill_table[sn].spell_fun != spell_null)
00387             skill = 40 + 2 * ch->level;
00388 
00389         else if (sn == gsn_sneak || sn == gsn_hide)
00390             skill = ch->level * 2 + 20;
00391 
00392         else if ((sn == gsn_dodge && IS_SET (ch->off_flags, OFF_DODGE))
00393                  || (sn == gsn_parry && IS_SET (ch->off_flags, OFF_PARRY)))
00394             skill = ch->level * 2;
00395 
00396         else if (sn == gsn_shield_block)
00397             skill = 10 + 2 * ch->level;
00398 
00399         else if (sn == gsn_second_attack && (IS_SET (ch->act, ACT_WARRIOR)
00400                                              || IS_SET (ch->act, ACT_THIEF)))
00401             skill = 10 + 3 * ch->level;
00402 
00403         else if (sn == gsn_third_attack && IS_SET (ch->act, ACT_WARRIOR))
00404             skill = 4 * ch->level - 40;
00405 
00406         else if (sn == gsn_hand_to_hand)
00407             skill = 40 + 2 * ch->level;
00408 
00409         else if (sn == gsn_trip && IS_SET (ch->off_flags, OFF_TRIP))
00410             skill = 10 + 3 * ch->level;
00411 
00412         else if (sn == gsn_bash && IS_SET (ch->off_flags, OFF_BASH))
00413             skill = 10 + 3 * ch->level;
00414 
00415         else if (sn == gsn_disarm && (IS_SET (ch->off_flags, OFF_DISARM)
00416                                       || IS_SET (ch->act, ACT_WARRIOR)
00417                                       || IS_SET (ch->act, ACT_THIEF)))
00418             skill = 20 + 3 * ch->level;
00419 
00420         else if (sn == gsn_berserk && IS_SET (ch->off_flags, OFF_BERSERK))
00421             skill = 3 * ch->level;
00422 
00423         else if (sn == gsn_kick)
00424             skill = 10 + 3 * ch->level;
00425 /*else if (sn == gsn_dragonbash)
00426         skill = 10 + 3 * ch->level;*/
00427 
00428         else if (sn == gsn_backstab && IS_SET (ch->act, ACT_THIEF))
00429             skill = 20 + 2 * ch->level;
00430 
00431         else if (sn == gsn_rescue)
00432             skill = 40 + ch->level;
00433 
00434         else if (sn == gsn_recall)
00435             skill = 40 + ch->level;
00436 
00437         else if (sn == gsn_sword
00438                  || sn == gsn_dagger
00439                  || sn == gsn_spear
00440                  || sn == gsn_mace
00441                  || sn == gsn_axe
00442                  || sn == gsn_flail || sn == gsn_whip || sn == gsn_polearm)
00443             skill = 40 + 5 * ch->level / 2;
00444 
00445         else
00446             skill = 0;
00447     }
00448 
00449     if (ch->daze > 0)
00450     {
00451         if (skill_table[sn].spell_fun != spell_null)
00452             skill /= 2;
00453         else
00454             skill = 2 * skill / 3;
00455     }
00456 
00457     if (!IS_NPC (ch) && ch->pcdata->condition[COND_DRUNK] > 10)
00458         skill = 9 * skill / 10;
00459 
00460     return URANGE (0, skill, 100);
00461 }
00462 
00463 /* for returning weapon information */
00464 int get_weapon_sn (CHAR_DATA * ch)
00465 {
00466     OBJ_DATA *wield;
00467     int sn;
00468 
00469     wield = get_eq_char (ch, WEAR_WIELD);
00470     if (wield == NULL || wield->item_type != ITEM_WEAPON)
00471         sn = gsn_hand_to_hand;
00472     else
00473         switch (wield->value[0])
00474         {
00475             default:
00476                 sn = -1;
00477                 break;
00478             case (WEAPON_SWORD):
00479                 sn = gsn_sword;
00480                 break;
00481             case (WEAPON_DAGGER):
00482                 sn = gsn_dagger;
00483                 break;
00484             case (WEAPON_SPEAR):
00485                 sn = gsn_spear;
00486                 break;
00487             case (WEAPON_MACE):
00488                 sn = gsn_mace;
00489                 break;
00490             case (WEAPON_AXE):
00491                 sn = gsn_axe;
00492                 break;
00493             case (WEAPON_FLAIL):
00494                 sn = gsn_flail;
00495                 break;
00496             case (WEAPON_WHIP):
00497                 sn = gsn_whip;
00498                 break;
00499             case (WEAPON_POLEARM):
00500                 sn = gsn_polearm;
00501                 break;
00502         }
00503     return sn;
00504 }
00505 
00506 int get_weapon_skill (CHAR_DATA * ch, int sn)
00507 {
00508     int skill;
00509 
00510     /* -1 is exotic */
00511     if (IS_NPC (ch))
00512     {
00513         if (sn == -1)
00514             skill = 3 * ch->level;
00515         else if (sn == gsn_hand_to_hand)
00516             skill = 40 + 2 * ch->level;
00517         else
00518             skill = 40 + 5 * ch->level / 2;
00519     }
00520 
00521     else
00522     {
00523         if (sn == -1)
00524             skill = 3 * ch->level;
00525         else
00526             skill = ch->pcdata->learned[sn];
00527     }
00528 
00529     return URANGE (0, skill, 100);
00530 }
00531 
00532 
00533 /* used to de-screw characters */
00534 void reset_char (CHAR_DATA * ch)
00535 {
00536     int loc, mod, stat;
00537     OBJ_DATA *obj;
00538     AFFECT_DATA *af;
00539     int i;
00540 
00541     if (IS_NPC (ch))
00542         return;
00543 
00544     if (ch->pcdata->perm_hit == 0
00545         || ch->pcdata->perm_mana == 0
00546         || ch->pcdata->perm_move == 0 || ch->pcdata->last_level == 0)
00547     {
00548         /* do a FULL reset */
00549         for (loc = 0; loc < MAX_WEAR; loc++)
00550         {
00551             obj = get_eq_char (ch, loc);
00552             if (obj == NULL)
00553                 continue;
00554             if (!obj->enchanted)
00555                 for (af = obj->pIndexData->affected; af != NULL;
00556                      af = af->next)
00557                 {
00558                     mod = af->modifier;
00559                     switch (af->location)
00560                     {
00561                         case APPLY_SEX:
00562                             ch->sex -= mod;
00563                             if (ch->sex < 0 || ch->sex > 2)
00564                                 ch->sex =
00565                                     IS_NPC (ch) ? 0 : ch->pcdata->true_sex;
00566                             break;
00567                         case APPLY_MANA:
00568                             ch->max_mana -= mod;
00569                             break;
00570                         case APPLY_HIT:
00571                             ch->max_hit -= mod;
00572                             break;
00573                         case APPLY_MOVE:
00574                             ch->max_move -= mod;
00575                             break;
00576                     }
00577                 }
00578 
00579             for (af = obj->affected; af != NULL; af = af->next)
00580             {
00581                 mod = af->modifier;
00582                 switch (af->location)
00583                 {
00584                     case APPLY_SEX:
00585                         ch->sex -= mod;
00586                         break;
00587                     case APPLY_MANA:
00588                         ch->max_mana -= mod;
00589                         break;
00590                     case APPLY_HIT:
00591                         ch->max_hit -= mod;
00592                         break;
00593                     case APPLY_MOVE:
00594                         ch->max_move -= mod;
00595                         break;
00596                 }
00597             }
00598         }
00599         /* now reset the permanent stats */
00600         ch->pcdata->perm_hit = ch->max_hit;
00601         ch->pcdata->perm_mana = ch->max_mana;
00602         ch->pcdata->perm_move = ch->max_move;
00603         ch->pcdata->last_level = ch->played / 3600;
00604         if (ch->pcdata->true_sex < 0 || ch->pcdata->true_sex > 2)
00605         {
00606             if (ch->sex > 0 && ch->sex < 3)
00607                 ch->pcdata->true_sex = ch->sex;
00608             else
00609                 ch->pcdata->true_sex = 0;
00610         }
00611 
00612     }
00613 
00614     /* now restore the character to his/her true condition */
00615     for (stat = 0; stat < MAX_STATS; stat++)
00616         ch->mod_stat[stat] = 0;
00617 
00618     if (ch->pcdata->true_sex < 0 || ch->pcdata->true_sex > 2)
00619         ch->pcdata->true_sex = 0;
00620     ch->sex = ch->pcdata->true_sex;
00621     ch->max_hit = ch->pcdata->perm_hit;
00622     ch->max_mana = ch->pcdata->perm_mana;
00623     ch->max_move = ch->pcdata->perm_move;
00624 
00625     for (i = 0; i < 4; i++)
00626         ch->armor[i] = 100;
00627 
00628     ch->hitroll = 0;
00629     ch->damroll = 0;
00630     ch->saving_throw = 0;
00631 
00632     /* now start adding back the effects */
00633     for (loc = 0; loc < MAX_WEAR; loc++)
00634     {
00635         obj = get_eq_char (ch, loc);
00636         if (obj == NULL)
00637             continue;
00638         for (i = 0; i < 4; i++)
00639             ch->armor[i] -= apply_ac (obj, loc, i);
00640 
00641         if (!obj->enchanted)
00642             for (af = obj->pIndexData->affected; af != NULL; af = af->next)
00643             {
00644                 mod = af->modifier;
00645                 switch (af->location)
00646                 {
00647                     case APPLY_STR:
00648                         ch->mod_stat[STAT_STR] += mod;
00649                         break;
00650                     case APPLY_DEX:
00651                         ch->mod_stat[STAT_DEX] += mod;
00652                         break;
00653                     case APPLY_INT:
00654                         ch->mod_stat[STAT_INT] += mod;
00655                         break;
00656                     case APPLY_WIS:
00657                         ch->mod_stat[STAT_WIS] += mod;
00658                         break;
00659                     case APPLY_CON:
00660                         ch->mod_stat[STAT_CON] += mod;
00661                         break;
00662 
00663                     case APPLY_SEX:
00664                         ch->sex += mod;
00665                         break;
00666                     case APPLY_MANA:
00667                         ch->max_mana += mod;
00668                         break;
00669                     case APPLY_HIT:
00670                         ch->max_hit += mod;
00671                         break;
00672                     case APPLY_MOVE:
00673                         ch->max_move += mod;
00674                         break;
00675 
00676                     case APPLY_AC:
00677                         for (i = 0; i < 4; i++)
00678                             ch->armor[i] += mod;
00679                         break;
00680                     case APPLY_HITROLL:
00681                         ch->hitroll += mod;
00682                         break;
00683                     case APPLY_DAMROLL:
00684                         ch->damroll += mod;
00685                         break;
00686 
00687                     case APPLY_SAVES:
00688                         ch->saving_throw += mod;
00689                         break;
00690                     case APPLY_SAVING_ROD:
00691                         ch->saving_throw += mod;
00692                         break;
00693                     case APPLY_SAVING_PETRI:
00694                         ch->saving_throw += mod;
00695                         break;
00696                     case APPLY_SAVING_BREATH:
00697                         ch->saving_throw += mod;
00698                         break;
00699                     case APPLY_SAVING_SPELL:
00700                         ch->saving_throw += mod;
00701                         break;
00702                 }
00703             }
00704 
00705         for (af = obj->affected; af != NULL; af = af->next)
00706         {
00707             mod = af->modifier;
00708             switch (af->location)
00709             {
00710                 case APPLY_STR:
00711                     ch->mod_stat[STAT_STR] += mod;
00712                     break;
00713                 case APPLY_DEX:
00714                     ch->mod_stat[STAT_DEX] += mod;
00715                     break;
00716                 case APPLY_INT:
00717                     ch->mod_stat[STAT_INT] += mod;
00718                     break;
00719                 case APPLY_WIS:
00720                     ch->mod_stat[STAT_WIS] += mod;
00721                     break;
00722                 case APPLY_CON:
00723                     ch->mod_stat[STAT_CON] += mod;
00724                     break;
00725 
00726                 case APPLY_SEX:
00727                     ch->sex += mod;
00728                     break;
00729                 case APPLY_MANA:
00730                     ch->max_mana += mod;
00731                     break;
00732                 case APPLY_HIT:
00733                     ch->max_hit += mod;
00734                     break;
00735                 case APPLY_MOVE:
00736                     ch->max_move += mod;
00737                     break;
00738 
00739                 case APPLY_AC:
00740                     for (i = 0; i < 4; i++)
00741                         ch->armor[i] += mod;
00742                     break;
00743                 case APPLY_HITROLL:
00744                     ch->hitroll += mod;
00745                     break;
00746                 case APPLY_DAMROLL:
00747                     ch->damroll += mod;
00748                     break;
00749 
00750                 case APPLY_SAVES:
00751                     ch->saving_throw += mod;
00752                     break;
00753                 case APPLY_SAVING_ROD:
00754                     ch->saving_throw += mod;
00755                     break;
00756                 case APPLY_SAVING_PETRI:
00757                     ch->saving_throw += mod;
00758                     break;
00759                 case APPLY_SAVING_BREATH:
00760                     ch->saving_throw += mod;
00761                     break;
00762                 case APPLY_SAVING_SPELL:
00763                     ch->saving_throw += mod;
00764                     break;
00765             }
00766         }
00767     }
00768 
00769     /* now add back spell effects */
00770     for (af = ch->affected; af != NULL; af = af->next)
00771     {
00772         mod = af->modifier;
00773         switch (af->location)
00774         {
00775             case APPLY_STR:
00776                 ch->mod_stat[STAT_STR] += mod;
00777                 break;
00778             case APPLY_DEX:
00779                 ch->mod_stat[STAT_DEX] += mod;
00780                 break;
00781             case APPLY_INT:
00782                 ch->mod_stat[STAT_INT] += mod;
00783                 break;
00784             case APPLY_WIS:
00785                 ch->mod_stat[STAT_WIS] += mod;
00786                 break;
00787             case APPLY_CON:
00788                 ch->mod_stat[STAT_CON] += mod;
00789                 break;
00790 
00791             case APPLY_SEX:
00792                 ch->sex += mod;
00793                 break;
00794             case APPLY_MANA:
00795                 ch->max_mana += mod;
00796                 break;
00797             case APPLY_HIT:
00798                 ch->max_hit += mod;
00799                 break;
00800             case APPLY_MOVE:
00801                 ch->max_move += mod;
00802                 break;
00803 
00804             case APPLY_AC:
00805                 for (i = 0; i < 4; i++)
00806                     ch->armor[i] += mod;
00807                 break;
00808             case APPLY_HITROLL:
00809                 ch->hitroll += mod;
00810                 break;
00811             case APPLY_DAMROLL:
00812                 ch->damroll += mod;
00813                 break;
00814 
00815             case APPLY_SAVES:
00816                 ch->saving_throw += mod;
00817                 break;
00818             case APPLY_SAVING_ROD:
00819                 ch->saving_throw += mod;
00820                 break;
00821             case APPLY_SAVING_PETRI:
00822                 ch->saving_throw += mod;
00823                 break;
00824             case APPLY_SAVING_BREATH:
00825                 ch->saving_throw += mod;
00826                 break;
00827             case APPLY_SAVING_SPELL:
00828                 ch->saving_throw += mod;
00829                 break;
00830         }
00831     }
00832 
00833     /* make sure sex is RIGHT!!!! */
00834     if (ch->sex < 0 || ch->sex > 2)
00835         ch->sex = ch->pcdata->true_sex;
00836 }
00837 
00838 
00839 /*
00840  * Retrieve a character's trusted level for permission checking.
00841  */
00842 int get_trust (CHAR_DATA * ch)
00843 {
00844     if (ch->desc != NULL && ch->desc->original != NULL)
00845         ch = ch->desc->original;
00846 
00847     if (ch->trust)
00848         return ch->trust;
00849 
00850     if (IS_NPC (ch) && ch->level >= LEVEL_HERO)
00851         return LEVEL_HERO - 1;
00852     else
00853         return ch->level;
00854 }
00855 
00856 
00857 /*
00858  * Retrieve a character's age.
00859  */
00860 int get_age (CHAR_DATA * ch)
00861 {
00862     if (!IS_NPC(ch) && ch->pcdata->plr_age < 10)
00863     {
00864         ch->pcdata->plr_age = 17;
00865         send_to_char("{RAge incorrect, age updated!{x\n\r",ch);
00866         return ch->pcdata->plr_age;
00867     }
00868     
00869     if (IS_NPC(ch))
00870         return 17 + (ch->played + (int) (current_time - ch->logon)) / 72000;
00871     return ch->pcdata->plr_age;
00872 }
00873 
00874 /* command for retrieving stats */
00875 int get_curr_stat (CHAR_DATA * ch, int stat)
00876 {
00877     int max;
00878 
00879     if (IS_NPC (ch) || ch->level > LEVEL_IMMORTAL)
00880         max = 100;
00881 
00882     else
00883     {
00884         max = pc_race_table[ch->race].max_stats[stat] + 4;
00885 
00886         if (class_table[ch->class].attr_prime == stat)
00887             max += 2;
00888 
00889         if (ch->race == race_lookup ("human"))
00890             max += 1;
00891 
00892         max = UMIN (max, 100);
00893     }
00894 
00895     return URANGE (3, ch->perm_stat[stat] + ch->mod_stat[stat], max);
00896 }
00897 
00898 /* command for returning max training score */
00899 int get_max_train (CHAR_DATA * ch, int stat)
00900 {
00901     int max;
00902 
00903     if (IS_NPC (ch) || ch->level > LEVEL_IMMORTAL)
00904         return 100;
00905 
00906     max = pc_race_table[ch->race].max_stats[stat];
00907     if (class_table[ch->class].attr_prime == stat)
00908     {
00909         if (ch->race == race_lookup ("human"))
00910             max += 3;
00911         else
00912             max += 2;
00913     }
00914 
00915     return UMIN (max, 100);
00916 }
00917 
00918 
00919 /*
00920  * Retrieve a character's carry capacity.
00921  */
00922 int can_carry_n (CHAR_DATA * ch)
00923 {
00924     if (!IS_NPC (ch) && ch->level >= LEVEL_IMMORTAL)
00925         return 1000;
00926 
00927     if (IS_NPC (ch) && IS_SET (ch->act, ACT_PET))
00928         return 0;
00929 
00930     return MAX_WEAR + 2 * get_curr_stat (ch, STAT_DEX) + ch->level;
00931 }
00932 
00933 
00934 
00935 /*
00936  * Retrieve a character's carry capacity.
00937  */
00938 int can_carry_w (CHAR_DATA * ch)
00939 {
00940     if (!IS_NPC (ch) && ch->level >= LEVEL_IMMORTAL)
00941         return 10000000;
00942 
00943     if (IS_NPC (ch) && IS_SET (ch->act, ACT_PET))
00944         return 0;
00945 
00946     return str_app[get_curr_stat (ch, STAT_STR)].carry * 10 + ch->level * 25;
00947 }
00948 
00949 
00950 
00951 /*
00952  * See if a string is one of the names of an object.
00953  */
00954 
00955 bool is_name (char *str, char *namelist)
00956 {
00957     char name[MAX_INPUT_LENGTH], part[MAX_INPUT_LENGTH];
00958     char *list, *string;
00959 
00960     /* fix crash on NULL namelist */
00961     if (namelist == NULL || namelist[0] == '\0')
00962         return FALSE;
00963 
00964     /* fixed to prevent is_name on "" returning TRUE */
00965     if (str[0] == '\0')
00966         return FALSE;
00967 
00968     string = str;
00969     /* we need ALL parts of string to match part of namelist */
00970     for (;;)
00971     {                            /* start parsing string */
00972         str = one_argument (str, part);
00973 
00974         if (part[0] == '\0')
00975             return TRUE;
00976 
00977         /* check to see if this is part of namelist */
00978         list = namelist;
00979         for (;;)
00980         {                        /* start parsing namelist */
00981             list = one_argument (list, name);
00982             if (name[0] == '\0')    /* this name was not found */
00983                 return FALSE;
00984 
00985             if (!str_prefix (string, name))
00986                 return TRUE;    /* full pattern match */
00987 
00988             if (!str_prefix (part, name))
00989                 break;
00990         }
00991     }
00992 }
00993 
00994 bool is_exact_name (char *str, char *namelist)
00995 {
00996     char name[MAX_INPUT_LENGTH];
00997 
00998     if (namelist == NULL)
00999         return FALSE;
01000 
01001     for (;;)
01002     {
01003         namelist = one_argument (namelist, name);
01004         if (name[0] == '\0')
01005             return FALSE;
01006         if (!str_cmp (str, name))
01007             return TRUE;
01008     }
01009 }
01010 
01011 /* enchanted stuff for eq */
01012 void affect_enchant (OBJ_DATA * obj)
01013 {
01014     /* okay, move all the old flags into new vectors if we have to */
01015     if (!obj->enchanted)
01016     {
01017         AFFECT_DATA *paf, *af_new;
01018         obj->enchanted = TRUE;
01019 
01020         for (paf = obj->pIndexData->affected; paf != NULL; paf = paf->next)
01021         {
01022             af_new = new_affect ();
01023 
01024             af_new->next = obj->affected;
01025             obj->affected = af_new;
01026 
01027             af_new->where = paf->where;
01028             af_new->type = UMAX (0, paf->type);
01029             af_new->level = paf->level;
01030             af_new->duration = paf->duration;
01031             af_new->location = paf->location;
01032             af_new->modifier = paf->modifier;
01033             af_new->bitvector = paf->bitvector;
01034         }
01035     }
01036 }
01037 
01038 
01039 /*
01040  * Apply or remove an affect to a character.
01041  */
01042 void affect_modify (CHAR_DATA * ch, AFFECT_DATA * paf, bool fAdd)
01043 {
01044     OBJ_DATA *wield;
01045     int mod, i;
01046 
01047     mod = paf->modifier;
01048 
01049     if (fAdd)
01050     {
01051         switch (paf->where)
01052         {
01053             case TO_AFFECTS:
01054                 SET_BIT (ch->affected_by, paf->bitvector);
01055                 break;
01056             case TO_IMMUNE:
01057                 SET_BIT (ch->imm_flags, paf->bitvector);
01058                 break;
01059             case TO_RESIST:
01060                 SET_BIT (ch->res_flags, paf->bitvector);
01061                 break;
01062             case TO_VULN:
01063                 SET_BIT (ch->vuln_flags, paf->bitvector);
01064                 break;
01065         }
01066     }
01067     else
01068     {
01069         switch (paf->where)
01070         {
01071             case TO_AFFECTS:
01072                 REMOVE_BIT (ch->affected_by, paf->bitvector);
01073                 break;
01074             case TO_IMMUNE:
01075                 REMOVE_BIT (ch->imm_flags, paf->bitvector);
01076                 break;
01077             case TO_RESIST:
01078                 REMOVE_BIT (ch->res_flags, paf->bitvector);
01079                 break;
01080             case TO_VULN:
01081                 REMOVE_BIT (ch->vuln_flags, paf->bitvector);
01082                 break;
01083         }
01084         mod = 0 - mod;
01085     }
01086 
01087     switch (paf->location)
01088     {
01089         default:
01090             bug ("Affect_modify: unknown location %d.", paf->location);
01091             return;
01092 
01093         case APPLY_NONE:
01094             break;
01095         case APPLY_STR:
01096             ch->mod_stat[STAT_STR] += mod;
01097             break;
01098         case APPLY_DEX:
01099             ch->mod_stat[STAT_DEX] += mod;
01100             break;
01101         case APPLY_INT:
01102             ch->mod_stat[STAT_INT] += mod;
01103             break;
01104         case APPLY_WIS:
01105             ch->mod_stat[STAT_WIS] += mod;
01106             break;
01107         case APPLY_CON:
01108             ch->mod_stat[STAT_CON] += mod;
01109             break;
01110         case APPLY_SEX:
01111             ch->sex += mod;
01112             break;
01113         case APPLY_CLASS:
01114             break;
01115         case APPLY_LEVEL:
01116             break;
01117         case APPLY_AGE:
01118             break;
01119         case APPLY_HEIGHT:
01120             break;
01121         case APPLY_WEIGHT:
01122             break;
01123         case APPLY_MANA:
01124             ch->max_mana += mod;
01125             break;
01126         case APPLY_HIT:
01127             ch->max_hit += mod;
01128             break;
01129         case APPLY_MOVE:
01130             ch->max_move += mod;
01131             break;
01132         case APPLY_GOLD:
01133             break;
01134         case APPLY_EXP:
01135             break;
01136         case APPLY_AC:
01137             for (i = 0; i < 4; i++)
01138                 ch->armor[i] += mod;
01139             break;
01140         case APPLY_HITROLL:
01141             ch->hitroll += mod;
01142             break;
01143         case APPLY_DAMROLL:
01144             ch->damroll += mod;
01145             break;
01146         case APPLY_SAVES:
01147             ch->saving_throw += mod;
01148             break;
01149         case APPLY_SAVING_ROD:
01150             ch->saving_throw += mod;
01151             break;
01152         case APPLY_SAVING_PETRI:
01153             ch->saving_throw += mod;
01154             break;
01155         case APPLY_SAVING_BREATH:
01156             ch->saving_throw += mod;
01157             break;
01158         case APPLY_SAVING_SPELL:
01159             ch->saving_throw += mod;
01160             break;
01161         case APPLY_SPELL_AFFECT:
01162             break;
01163     }
01164 
01165     /*
01166      * Check for weapon wielding.
01167      * Guard against recursion (for weapons with affects).
01168      */
01169     if (!IS_NPC (ch) && (wield = get_eq_char (ch, WEAR_WIELD)) != NULL
01170         && get_obj_weight (wield) >
01171         (str_app[get_curr_stat (ch, STAT_STR)].wield * 10))
01172     {
01173         static int depth;
01174 
01175         if (depth == 0)
01176         {
01177             depth++;
01178             act ("You drop $p.", ch, wield, NULL, TO_CHAR);
01179             act ("$n drops $p.", ch, wield, NULL, TO_ROOM);
01180             obj_from_char (wield);
01181             obj_to_room (wield, ch->in_room);
01182             depth--;
01183         }
01184     }
01185 
01186     return;
01187 }
01188 
01189 
01190 /* find an effect in an affect list */
01191 AFFECT_DATA *affect_find (AFFECT_DATA * paf, int sn)
01192 {
01193     AFFECT_DATA *paf_find;
01194 
01195     for (paf_find = paf; paf_find != NULL; paf_find = paf_find->next)
01196     {
01197         if (paf_find->type == sn)
01198             return paf_find;
01199     }
01200 
01201     return NULL;
01202 }
01203 
01204 /* fix object affects when removing one */
01205 void affect_check (CHAR_DATA * ch, int where, int vector)
01206 {
01207     AFFECT_DATA *paf;
01208     OBJ_DATA *obj;
01209 
01210     if (where == TO_OBJECT || where == TO_WEAPON || vector == 0)
01211         return;
01212 
01213     for (paf = ch->affected; paf != NULL; paf = paf->next)
01214         if (paf->where == where && paf->bitvector == vector)
01215         {
01216             switch (where)
01217             {
01218                 case TO_AFFECTS:
01219                     SET_BIT (ch->affected_by, vector);
01220                     break;
01221                 case TO_IMMUNE:
01222                     SET_BIT (ch->imm_flags, vector);
01223                     break;
01224                 case TO_RESIST:
01225                     SET_BIT (ch->res_flags, vector);
01226                     break;
01227                 case TO_VULN:
01228                     SET_BIT (ch->vuln_flags, vector);
01229                     break;
01230             }
01231             return;
01232         }
01233 
01234     for (obj = ch->carrying; obj != NULL; obj = obj->next_content)
01235     {
01236         if (obj->wear_loc == -1)
01237             continue;
01238 
01239         for (paf = obj->affected; paf != NULL; paf = paf->next)
01240             if (paf->where == where && paf->bitvector == vector)
01241             {
01242                 switch (where)
01243                 {
01244                     case TO_AFFECTS:
01245                         SET_BIT (ch->affected_by, vector);
01246                         break;
01247                     case TO_IMMUNE:
01248                         SET_BIT (ch->imm_flags, vector);
01249                         break;
01250                     case TO_RESIST:
01251                         SET_BIT (ch->res_flags, vector);
01252                         break;
01253                     case TO_VULN:
01254                         SET_BIT (ch->vuln_flags, vector);
01255 
01256                 }
01257                 return;
01258             }
01259 
01260         if (obj->enchanted)
01261             continue;
01262 
01263         for (paf = obj->pIndexData->affected; paf != NULL; paf = paf->next)
01264             if (paf->where == where && paf->bitvector == vector)
01265             {
01266                 switch (where)
01267                 {
01268                     case TO_AFFECTS:
01269                         SET_BIT (ch->affected_by, vector);
01270                         break;
01271                     case TO_IMMUNE:
01272                         SET_BIT (ch->imm_flags, vector);
01273                         break;
01274                     case TO_RESIST:
01275                         SET_BIT (ch->res_flags, vector);
01276                         break;
01277                     case TO_VULN:
01278                         SET_BIT (ch->vuln_flags, vector);
01279                         break;
01280                 }
01281                 return;
01282             }
01283     }
01284 }
01285 
01286 /*
01287  * Give an affect to a char.
01288  */
01289 void affect_to_char (CHAR_DATA * ch, AFFECT_DATA * paf)
01290 {
01291     AFFECT_DATA *paf_new;
01292 
01293     paf_new = new_affect ();
01294 
01295     *paf_new = *paf;
01296 
01297     VALIDATE (paf);                /* in case we missed it when we set up paf */
01298     paf_new->next = ch->affected;
01299     ch->affected = paf_new;
01300 
01301     affect_modify (ch, paf_new, TRUE);
01302     return;
01303 }
01304 
01305 /* give an affect to an object */
01306 void affect_to_obj (OBJ_DATA * obj, AFFECT_DATA * paf)
01307 {
01308     AFFECT_DATA *paf_new;
01309 
01310     paf_new = new_affect ();
01311 
01312     *paf_new = *paf;
01313 
01314     VALIDATE (paf);                /* in case we missed it when we set up paf */
01315     paf_new->next = obj->affected;
01316     obj->affected = paf_new;
01317 
01318     /* apply any affect vectors to the object's extra_flags */
01319     if (paf->bitvector)
01320         switch (paf->where)
01321         {
01322             case TO_OBJECT:
01323                 SET_BIT (obj->extra_flags, paf->bitvector);
01324                 break;
01325             case TO_WEAPON:
01326                 if (obj->item_type == ITEM_WEAPON)
01327                     SET_BIT (obj->value[4], paf->bitvector);
01328                 break;
01329         }
01330 
01331 
01332     return;
01333 }
01334 
01335 
01336 
01337 /*
01338  * Remove an affect from a char.
01339  */
01340 void affect_remove (CHAR_DATA * ch, AFFECT_DATA * paf)
01341 {
01342     int where;
01343     int vector;
01344 
01345     if (ch->affected == NULL)
01346     {
01347         bug ("Affect_remove: no affect.", 0);
01348         return;
01349     }
01350 
01351     affect_modify (ch, paf, FALSE);
01352     where = paf->where;
01353     vector = paf->bitvector;
01354 
01355     if (paf == ch->affected)
01356     {
01357         ch->affected = paf->next;
01358     }
01359     else
01360     {
01361         AFFECT_DATA *prev;
01362 
01363         for (prev = ch->affected; prev != NULL; prev = prev->next)
01364         {
01365             if (prev->next == paf)
01366             {
01367                 prev->next = paf->next;
01368                 break;
01369             }
01370         }
01371 
01372         if (prev == NULL)
01373         {
01374             bug ("Affect_remove: cannot find paf.", 0);
01375             return;
01376         }
01377     }
01378 
01379     free_affect (paf);
01380 
01381     affect_check (ch, where, vector);
01382     return;
01383 }
01384 
01385 void affect_remove_obj (OBJ_DATA * obj, AFFECT_DATA * paf)
01386 {
01387     int where, vector;
01388     if (obj->affected == NULL)
01389     {
01390         bug ("Affect_remove_object: no affect.", 0);
01391         return;
01392     }
01393 
01394     if (obj->carried_by != NULL && obj->wear_loc != -1)
01395         affect_modify (obj->carried_by, paf, FALSE);
01396 
01397     where = paf->where;
01398     vector = paf->bitvector;
01399 
01400     /* remove flags from the object if needed */
01401     if (paf->bitvector)
01402         switch (paf->where)
01403         {
01404             case TO_OBJECT:
01405                 REMOVE_BIT (obj->extra_flags, paf->bitvector);
01406                 break;
01407             case TO_WEAPON:
01408                 if (obj->item_type == ITEM_WEAPON)
01409                     REMOVE_BIT (obj->value[4], paf->bitvector);
01410                 break;
01411         }
01412 
01413     if (paf == obj->affected)
01414     {
01415         obj->affected = paf->next;
01416     }
01417     else
01418     {
01419         AFFECT_DATA *prev;
01420 
01421         for (prev = obj->affected; prev != NULL; prev = prev->next)
01422         {
01423             if (prev->next == paf)
01424             {
01425                 prev->next = paf->next;
01426                 break;
01427             }
01428         }
01429 
01430         if (prev == NULL)
01431         {
01432             bug ("Affect_remove_object: cannot find paf.", 0);
01433             return;
01434         }
01435     }
01436 
01437     free_affect (paf);
01438 
01439     if (obj->carried_by != NULL && obj->wear_loc != -1)
01440         affect_check (obj->carried_by, where, vector);
01441     return;
01442 }
01443 
01444 
01445 
01446 /*
01447  * Strip all affects of a given sn.
01448  */
01449 void affect_strip (CHAR_DATA * ch, int sn)
01450 {
01451     AFFECT_DATA *paf;
01452     AFFECT_DATA *paf_next;
01453 
01454     for (paf = ch->affected; paf != NULL; paf = paf_next)
01455     {
01456         paf_next = paf->next;
01457         if (paf->type == sn)
01458             affect_remove (ch, paf);
01459     }
01460 
01461     return;
01462 }
01463 
01464 
01465 
01466 /*
01467  * Return true if a char is affected by a spell.
01468  */
01469 bool is_affected (CHAR_DATA * ch, int sn)
01470 {
01471     AFFECT_DATA *paf;
01472 
01473     for (paf = ch->affected; paf != NULL; paf = paf->next)
01474     {
01475         if (paf->type == sn)
01476             return TRUE;
01477     }
01478 
01479     return FALSE;
01480 }
01481 
01482 
01483 
01484 /*
01485  * Add or enhance an affect.
01486  */
01487 void affect_join (CHAR_DATA * ch, AFFECT_DATA * paf)
01488 {
01489     AFFECT_DATA *paf_old;
01490     bool found;
01491 
01492     found = FALSE;
01493     for (paf_old = ch->affected; paf_old != NULL; paf_old = paf_old->next)
01494     {
01495         if (paf_old->type == paf->type)
01496         {
01497             paf->level = (paf->level += paf_old->level) / 2;
01498             paf->duration += paf_old->duration;
01499             paf->modifier += paf_old->modifier;
01500             affect_remove (ch, paf_old);
01501             break;
01502         }
01503     }
01504 
01505     affect_to_char (ch, paf);
01506     return;
01507 }
01508 
01509 
01510 
01511 /*
01512  * Move a char out of a room.
01513  */
01514 void char_from_room (CHAR_DATA * ch)
01515 {
01516     OBJ_DATA *obj;
01517 
01518     if (ch->in_room == NULL)
01519     {
01520         bug ("Char_from_room: NULL.", 0);
01521         return;
01522     }
01523 
01524     if (!IS_NPC (ch))
01525         --ch->in_room->area->nplayer;
01526 
01527     if ((obj = get_eq_char (ch, WEAR_LIGHT)) != NULL
01528         && obj->item_type == ITEM_LIGHT
01529         && obj->value[2] != 0 && ch->in_room->light > 0)
01530         --ch->in_room->light;
01531 
01532     if (ch == ch->in_room->people)
01533     {
01534         ch->in_room->people = ch->next_in_room;
01535     }
01536     else
01537     {
01538         CHAR_DATA *prev;
01539 
01540         for (prev = ch->in_room->people; prev; prev = prev->next_in_room)
01541         {
01542             if (prev->next_in_room == ch)
01543             {
01544                 prev->next_in_room = ch->next_in_room;
01545                 break;
01546             }
01547         }
01548 
01549         if (prev == NULL)
01550             bug ("Char_from_room: ch not found.", 0);
01551     }
01552 
01553     ch->in_room = NULL;
01554     ch->next_in_room = NULL;
01555     ch->on = NULL;                /* sanity check! */
01556     return;
01557 }
01558 
01559 
01560 
01561 /*
01562  * Move a char into a room.
01563  */
01564 void char_to_room (CHAR_DATA * ch, ROOM_INDEX_DATA * pRoomIndex)
01565 {
01566     OBJ_DATA *obj;
01567 
01568     if (pRoomIndex == NULL)
01569     {
01570         ROOM_INDEX_DATA *room;
01571 
01572         bug ("Char_to_room: NULL.", 0);
01573 
01574         if ((room = get_room_index (1)) != NULL)
01575     {
01576                 send_to_char("Unable to find room requested. You have been droped into limbo - please pray up about this.\n\r",ch);
01577         char_to_room (ch, room);
01578     }
01579 
01580         return;
01581     }
01582 
01583     ch->in_room = pRoomIndex;
01584     ch->next_in_room = pRoomIndex->people;
01585     pRoomIndex->people = ch;
01586 
01587     if (!IS_NPC (ch))
01588     {
01589         if (ch->in_room->area->empty)
01590         {
01591             ch->in_room->area->empty = FALSE;
01592             ch->in_room->area->age = 0;
01593         }
01594         ++ch->in_room->area->nplayer;
01595     }
01596 
01597     if ((obj = get_eq_char (ch, WEAR_LIGHT)) != NULL
01598         && obj->item_type == ITEM_LIGHT && obj->value[2] != 0)
01599         ++ch->in_room->light;
01600 
01601     if (IS_AFFECTED (ch, AFF_PLAGUE))
01602     {
01603         AFFECT_DATA *af, plague;
01604         CHAR_DATA *vch;
01605 
01606         for (af = ch->affected; af != NULL; af = af->next)
01607         {
01608             if (af->type == gsn_plague)
01609                 break;
01610         }
01611 
01612         if (af == NULL)
01613         {
01614             REMOVE_BIT (ch->affected_by, AFF_PLAGUE);
01615             return;
01616         }
01617 
01618         if (af->level == 1)
01619             return;
01620 
01621         plague.where = TO_AFFECTS;
01622         plague.type = gsn_plague;
01623         plague.level = af->level - 1;
01624         plague.duration = number_range (1, 2 * plague.level);
01625         plague.location = APPLY_STR;
01626         plague.modifier = -5;
01627         plague.bitvector = AFF_PLAGUE;
01628 
01629         for (vch = ch->in_room->people; vch != NULL; vch = vch->next_in_room)
01630         {
01631             if (!saves_spell (plague.level - 2, vch, DAM_DISEASE)
01632                 && !IS_IMMORTAL (vch) &&
01633                 !IS_AFFECTED (vch, AFF_PLAGUE) && number_bits (6) == 0)
01634             {
01635                 send_to_char ("You feel hot and feverish.\n\r", vch);
01636                 act ("$n shivers and looks very ill.", vch, NULL, NULL,
01637                      TO_ROOM);
01638                 affect_join (vch, &plague);
01639             }
01640         }
01641     }
01642 
01643 
01644     return;
01645 }
01646 
01647 
01648 
01649 /*
01650  * Give an obj to a char.
01651  */
01652 void obj_to_char (OBJ_DATA * obj, CHAR_DATA * ch)
01653 {
01654     obj->next_content = ch->carrying;
01655     ch->carrying = obj;
01656     obj->carried_by = ch;
01657     obj->in_room = NULL;
01658     obj->in_obj = NULL;
01659     ch->carry_number += get_obj_number (obj);
01660     ch->carry_weight += get_obj_weight (obj);
01661 }
01662 
01663 
01664 
01665 /*
01666  * Take an obj from its character.
01667  */
01668 void obj_from_char (OBJ_DATA * obj)
01669 {
01670     CHAR_DATA *ch;
01671 
01672     if ((ch = obj->carried_by) == NULL)
01673     {
01674         bug ("Obj_from_char: null ch.", 0);
01675         return;
01676     }
01677 
01678     if (obj->wear_loc != WEAR_NONE)
01679         unequip_char (ch, obj);
01680 
01681     if (ch->carrying == obj)
01682     {
01683         ch->carrying = obj->next_content;
01684     }
01685     else
01686     {
01687         OBJ_DATA *prev;
01688 
01689         for (prev = ch->carrying; prev != NULL; prev = prev->next_content)
01690         {
01691             if (prev->next_content == obj)
01692             {
01693                 prev->next_content = obj->next_content;
01694                 break;
01695             }
01696         }
01697 
01698         if (prev == NULL)
01699             bug ("Obj_from_char: obj not in list.", 0);
01700     }
01701 
01702     obj->carried_by = NULL;
01703     obj->next_content = NULL;
01704     ch->carry_number -= get_obj_number (obj);
01705     ch->carry_weight -= get_obj_weight (obj);
01706     return;
01707 }
01708 
01709 
01710 
01711 /*
01712  * Find the ac value of an obj, including position effect.
01713  */
01714 int apply_ac (OBJ_DATA * obj, int iWear, int type)
01715 {
01716     if (obj->item_type != ITEM_ARMOR)
01717         return 0;
01718 
01719     switch (iWear)
01720     {
01721         case WEAR_BODY:
01722             return 3 * obj->value[type];
01723         case WEAR_HEAD:
01724             return 2 * obj->value[type];
01725         case WEAR_LEGS:
01726             return 2 * obj->value[type];
01727         case WEAR_FEET:
01728             return obj->value[type];
01729         case WEAR_HANDS:
01730             return obj->value[type];
01731         case WEAR_ARMS:
01732             return obj->value[type];
01733         case