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

update.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 <stdio.h>
00034 #include <string.h>
00035 #include <time.h>
00036 #include "merc.h"
00037 #include "interp.h"
00038 #include "music.h"
00039 #include "vehicles.h"
00040 /*
00041  * Local functions.
00042  */
00043 int hit_gain args ((CHAR_DATA * ch));
00044 int mana_gain args ((CHAR_DATA * ch));
00045 int move_gain args ((CHAR_DATA * ch));
00046 void mobile_update args ((void));
00047 void weather_update args ((void));
00048 void char_update args ((void));
00049 void obj_update args ((void));
00050 void aggr_update args ((void));
00051 
00052 /* used for saving */
00053 
00054 int save_number = 0;
00055 
00056 
00057 
00058 /*
00059  * Advancement stuff.
00060  */
00061 void advance_level (CHAR_DATA * ch, bool hide)
00062 {
00063     char buf[MAX_STRING_LENGTH];
00064     int add_hp;
00065     int add_mana;
00066     int add_move;
00067     int add_prac;
00068 
00069     ch->pcdata->last_level =
00070         (ch->played + (int) (current_time - ch->logon)) / 3600;
00071 
00072 //   sprintf (buf, "the %s",
00073   //           title_table[ch->class][ch->level][ch->sex ==
00074     //                                           SEX_FEMALE ? 1 : 0]);
00075   //  set_title (ch, buf);
00076 
00077     add_hp =
00078         con_app[get_curr_stat (ch, STAT_CON)].hitp +
00079         number_range (class_table[ch->class].hp_min,
00080                       class_table[ch->class].hp_max);
00081     add_mana = number_range (2, (2 * get_curr_stat (ch, STAT_INT)
00082                                  + get_curr_stat (ch, STAT_WIS)) / 5);
00083     if (!class_table[ch->class].fMana)
00084         add_mana /= 2;
00085     add_move = number_range (1, (get_curr_stat (ch, STAT_CON)
00086                                  + get_curr_stat (ch, STAT_DEX)) / 6);
00087     add_prac = wis_app[get_curr_stat (ch, STAT_WIS)].practice;
00088 
00089     add_hp = add_hp * 9 / 10;
00090     add_mana = add_mana * 9 / 10;
00091     add_move = add_move * 9 / 10;
00092 
00093     add_hp = UMAX (2, add_hp);
00094     add_mana = UMAX (2, add_mana);
00095     add_move = UMAX (6, add_move);
00096 
00097     ch->max_hit += add_hp;
00098     ch->max_mana += add_mana;
00099     ch->max_move += add_move;
00100     ch->practice += add_prac;
00101     ch->train += 2;
00102 
00103     ch->pcdata->perm_hit += add_hp;
00104     ch->pcdata->perm_mana += add_mana;
00105     ch->pcdata->perm_move += add_move;
00106 
00107     if (!hide)
00108     {
00109         sprintf (buf,
00110                  "You gain %d hit point%s, %d mana, %d move, and %d practice%s.\n\r",
00111                  add_hp, add_hp == 1 ? "" : "s", add_mana, add_move,
00112                  add_prac, add_prac == 1 ? "" : "s");
00113         send_to_char (buf, ch);
00114     }
00115     return;
00116 }
00117 
00118 
00119 
00120 void gain_exp (CHAR_DATA * ch, int gain)
00121 {
00122     char buf[MAX_STRING_LENGTH];
00123 
00124     if (IS_NPC (ch) || ch->level >= LEVEL_HERO)
00125         return;
00126 
00127     if (ch->level >= 51)
00128     {
00129     }
00130     else
00131     {
00132     ch->exp = UMAX (exp_per_level (ch, ch->pcdata->points), ch->exp + gain);
00133     }
00134     while (ch->level < LEVEL_HERO && ch->exp >=
00135            exp_per_level (ch, ch->pcdata->points) * (ch->level + 1))
00136     {
00137         send_to_char ("{GYou raise a level!!  {x", ch);
00138         ch->level += 1;
00139         sprintf (buf, "%s gained level %d", ch->name, ch->level);
00140         log_string (buf);
00141         sprintf (buf, "$N has attained level %d!", ch->level);
00142         wiznet (buf, ch, NULL, WIZ_LEVELS, 0, 0);
00143         advance_level (ch, FALSE);
00144         save_char_obj (ch);
00145     }
00146 
00147     return;
00148 }
00149 
00150 
00151 
00152 /*
00153  * Regeneration stuff.
00154  */
00155 int hit_gain (CHAR_DATA * ch)
00156 {
00157     int gain;
00158     int number;
00159 
00160     if (ch->in_room == NULL)
00161         return 0;
00162 
00163     if (IS_NPC (ch))
00164     {
00165         gain = 5 + ch->level;
00166         if (IS_AFFECTED (ch, AFF_REGENERATION))
00167             gain *= 2;
00168 
00169         switch (ch->position)
00170         {
00171             default:
00172                 gain /= 2;
00173                 break;
00174             case POS_SLEEPING:
00175                 gain = 3 * gain / 2;
00176                 break;
00177             case POS_RESTING:
00178                 break;
00179             case POS_FIGHTING:
00180                 gain /= 3;
00181                 break;
00182         }
00183 
00184 
00185     }
00186     else
00187     {
00188         gain = UMAX (3, get_curr_stat (ch, STAT_CON) - 3 + ch->level / 2);
00189         gain += class_table[ch->class].hp_max - 10;
00190         number = number_percent ();
00191         if (number < get_skill (ch, gsn_fast_healing))
00192         {
00193             gain += number * gain / 100;
00194             if (ch->hit < ch->max_hit)
00195                 check_improve (ch, gsn_fast_healing, TRUE, 8);
00196         }
00197 
00198         switch (ch->position)
00199         {
00200             default:
00201                 gain /= 4;
00202                 break;
00203             case POS_SLEEPING:
00204                 break;
00205             case POS_RESTING:
00206                 gain /= 2;
00207                 break;
00208             case POS_FIGHTING:
00209                 gain /= 6;
00210                 break;
00211         }
00212 
00213         if (ch->pcdata->condition[COND_HUNGER] == 0)
00214             gain /= 2;
00215 
00216         if (ch->pcdata->condition[COND_THIRST] == 0)
00217             gain /= 2;
00218 
00219     }
00220 
00221     gain = gain * ch->in_room->heal_rate / 100;
00222 
00223     if (ch->on != NULL && ch->on->item_type == ITEM_FURNITURE)
00224         gain = gain * ch->on->value[3] / 100;
00225 
00226     if (IS_AFFECTED (ch, AFF_POISON))
00227         gain /= 4;
00228 
00229     if (IS_AFFECTED (ch, AFF_PLAGUE))
00230         gain /= 8;
00231 
00232     if (IS_AFFECTED (ch, AFF_HASTE) || IS_AFFECTED (ch, AFF_SLOW))
00233         gain /= 2;
00234     
00235 
00236     return UMIN (gain, ch->max_hit - ch->hit);
00237 }
00238 
00239 
00240 
00241 int mana_gain (CHAR_DATA * ch)
00242 {
00243     int gain;
00244     int number;
00245 
00246     if (ch->in_room == NULL)
00247         return 0;
00248 
00249     if (IS_NPC (ch))
00250     {
00251         gain = 5 + ch->level;
00252         switch (ch->position)
00253         {
00254             default:
00255                 gain /= 2;
00256                 break;
00257             case POS_SLEEPING:
00258                 gain = 3 * gain / 2;
00259                 break;
00260             case POS_RESTING:
00261                 break;
00262             case POS_FIGHTING:
00263                 gain /= 3;
00264                 break;
00265         }
00266     }
00267     else
00268     {
00269         gain = (get_curr_stat (ch, STAT_WIS)
00270                 + get_curr_stat (ch, STAT_INT) + ch->level) / 2;
00271         number = number_percent ();
00272         if (number < get_skill (ch, gsn_meditation))
00273         {
00274             gain += number * gain / 100;
00275             if (ch->mana < ch->max_mana)
00276                 check_improve (ch, gsn_meditation, TRUE, 8);
00277         }
00278         if (!class_table[ch->class].fMana)
00279             gain /= 2;
00280 
00281         switch (ch->position)
00282         {
00283             default:
00284                 gain /= 4;
00285                 break;
00286             case POS_SLEEPING:
00287                 break;
00288             case POS_RESTING:
00289                 gain /= 2;
00290                 break;
00291             case POS_FIGHTING:
00292                 gain /= 6;
00293                 break;
00294         }
00295 
00296         if (ch->pcdata->condition[COND_HUNGER] == 0)
00297             gain /= 2;
00298 
00299         if (ch->pcdata->condition[COND_THIRST] == 0)
00300             gain /= 2;
00301 
00302     }
00303 
00304     gain = gain * ch->in_room->mana_rate / 100;
00305 
00306     if (ch->on != NULL && ch->on->item_type == ITEM_FURNITURE)
00307         gain = gain * ch->on->value[4] / 100;
00308 
00309     if (IS_AFFECTED (ch, AFF_POISON))
00310         gain /= 4;
00311 
00312     if (IS_AFFECTED (ch, AFF_PLAGUE))
00313         gain /= 8;
00314 
00315     if (IS_AFFECTED (ch, AFF_HASTE) || IS_AFFECTED (ch, AFF_SLOW))
00316         gain /= 2;
00317 
00318     return UMIN (gain, ch->max_mana - ch->mana);
00319 }
00320 
00321 
00322 
00323 int move_gain (CHAR_DATA * ch)
00324 {
00325     int gain;
00326 
00327     if (ch->in_room == NULL)
00328         return 0;
00329 
00330     if (IS_NPC (ch))
00331     {
00332         gain = ch->level;
00333     }
00334     else
00335     {
00336         gain = UMAX (15, ch->level);
00337 
00338         switch (ch->position)
00339         {
00340             case POS_SLEEPING:
00341                 gain += get_curr_stat (ch, STAT_DEX);
00342                 break;
00343             case POS_RESTING:
00344                 gain += get_curr_stat (ch, STAT_DEX) / 2;
00345                 break;
00346         }
00347 
00348         if (ch->pcdata->condition[COND_HUNGER] == 0)
00349             gain /= 2;
00350 
00351         if (ch->pcdata->condition[COND_THIRST] == 0)
00352             gain /= 2;
00353     }
00354 
00355     gain = gain * ch->in_room->heal_rate / 100;
00356 
00357     if (ch->on != NULL && ch->on->item_type == ITEM_FURNITURE)
00358         gain = gain * ch->on->value[3] / 100;
00359 
00360     if (IS_AFFECTED (ch, AFF_POISON))
00361         gain /= 4;
00362 
00363     if (IS_AFFECTED (ch, AFF_PLAGUE))
00364         gain /= 8;
00365 
00366     if (IS_AFFECTED (ch, AFF_HASTE) || IS_AFFECTED (ch, AFF_SLOW))
00367         gain /= 2;
00368 
00369     return UMIN (gain, ch->max_move - ch->move);
00370 }
00371 
00372 
00373 void gain_condition (CHAR_DATA * ch, int iCond, int value)
00374 {
00375     int condition;
00376 
00377     return;
00378     if (value == 0 || IS_NPC (ch) || (ch->level >= LEVEL_IMMORTAL && !IS_NPC(ch)))
00379         return;
00380     if (IS_SWITCHED(ch))
00381         return;
00382 
00383     condition = ch->pcdata->condition[iCond];
00384     if (condition == -1)
00385         return;
00386     ch->pcdata->condition[iCond] = URANGE (0, condition + value, 48);
00387 
00388     if (ch->pcdata->condition[iCond] == 0)
00389     {
00390         switch (iCond)
00391         {
00392             case COND_HUNGER:
00393                 send_to_char ("You are hungry.\n\r", ch);
00394                 break;
00395 
00396             case COND_THIRST:
00397                 send_to_char ("You are thirsty.\n\r", ch);
00398                 break;
00399 
00400             case COND_DRUNK:
00401                 if (condition != 0)
00402                     send_to_char ("You are sober.\n\r", ch);
00403                 break;
00404         }
00405     }
00406 
00407     return;
00408 }
00409 
00410 
00411 
00412 /*
00413  * Mob autonomous action.
00414  * This function takes 25% to 35% of ALL Merc cpu time.
00415  * -- Furey
00416  */
00417 void mobile_update (void)
00418 {
00419     CHAR_DATA *ch;
00420     CHAR_DATA *ch_next;
00421     EXIT_DATA *pexit;
00422     int door;
00423 
00424     /* Examine all mobs. */
00425     for (ch = char_list; ch != NULL; ch = ch_next)
00426     {
00427         ch_next = ch->next;
00428 
00429         if (!IS_NPC (ch) || ch->in_room == NULL
00430             || IS_AFFECTED (ch, AFF_CHARM)) continue;
00431 
00432         if (ch->in_room->area->empty && !IS_SET (ch->act, ACT_UPDATE_ALWAYS))
00433             continue;
00434 
00435         /* Examine call for special procedure */
00436         if (ch->spec_fun != 0)
00437         {
00438             if ((*ch->spec_fun) (ch))
00439                 continue;
00440         }
00441 
00442         if (ch->pIndexData->pShop != NULL)    /* give him some gold */
00443             if ((ch->gold * 100 + ch->silver) < ch->pIndexData->wealth)
00444             {
00445                 ch->gold +=
00446                     ch->pIndexData->wealth * number_range (1, 20) / 5000000;
00447                 ch->silver +=
00448                     ch->pIndexData->wealth * number_range (1, 20) / 50000;
00449             }
00450 
00451         /*
00452          * Check triggers only if mobile still in default position
00453          */
00454         if (ch->position == ch->pIndexData->default_pos)
00455         {
00456             /* Delay */
00457             if (HAS_TRIGGER (ch, TRIG_DELAY) && ch->mprog_delay > 0)
00458             {
00459                 if (--ch->mprog_delay <= 0)
00460                 {
00461                     mp_percent_trigger (ch, NULL, NULL, NULL, TRIG_DELAY);
00462                     continue;
00463                 }
00464             }
00465             if (HAS_TRIGGER (ch, TRIG_RANDOM))
00466             {
00467                 if (mp_percent_trigger (ch, NULL, NULL, NULL, TRIG_RANDOM))
00468                     continue;
00469             }
00470         }
00471 
00472         /* That's all for sleeping / busy monster, and empty zones */
00473         if (ch->position != POS_STANDING)
00474             continue;
00475 
00476         /* Scavenge */
00477         if (IS_SET (ch->act, ACT_SCAVENGER)
00478             && ch->in_room->contents != NULL && number_bits (6) == 0)
00479         {
00480             OBJ_DATA *obj;
00481             OBJ_DATA *obj_best;
00482             int max;
00483 
00484             max = 1;
00485             obj_best = 0;
00486             for (obj = ch->in_room->contents; obj; obj = obj->next_content)
00487             {
00488                 if (CAN_WEAR (obj, ITEM_TAKE) && can_loot (ch, obj)
00489                     && obj->cost > max && obj->cost > 0)
00490                 {
00491                     obj_best = obj;
00492                     max = obj->cost;
00493                 }
00494             }
00495 
00496             if (obj_best)
00497             {
00498                 obj_from_room (obj_best);
00499                 obj_to_char (obj_best, ch);
00500                 act ("$n gets $p.", ch, obj_best, NULL, TO_ROOM);
00501             }
00502         }
00503 
00504         /* Wander */
00505         if (!IS_SET (ch->act, ACT_SENTINEL)
00506             && number_bits (3) == 0
00507             && (door = number_bits (9)) <= 9
00508             && (pexit = ch->in_room->exit[door]) != NULL
00509             && pexit->u1.to_room != NULL
00510             && !IS_SET (pexit->exit_info, EX_CLOSED)
00511             && !IS_SET (pexit->u1.to_room->room_flags, ROOM_NO_MOB)
00512             && (!IS_SET (ch->act, ACT_STAY_AREA)
00513                 || pexit->u1.to_room->area == ch->in_room->area)
00514             && (!IS_SET (ch->act, ACT_OUTDOORS)
00515                 || !IS_SET (pexit->u1.to_room->room_flags, ROOM_INDOORS))
00516             && (!IS_SET (ch->act, ACT_INDOORS)
00517                 || IS_SET (pexit->u1.to_room->room_flags, ROOM_INDOORS)))
00518         {
00519             move_char (ch, door, FALSE);
00520         }
00521     }
00522 
00523     return;
00524 }
00525 
00526 
00527 
00528 /*
00529  * Update the weather.
00530  */
00531 void weather_update (void)
00532 {
00533     char buf[MAX_STRING_LENGTH];
00534     DESCRIPTOR_DATA *d;
00535     int diff;
00536 
00537     buf[0] = '\0';
00538 
00539     switch (++time_info.hour)
00540     {
00541         case 5:
00542             weather_info.sunlight = SUN_LIGHT;
00543             strcat (buf, "The moons lower beyond the horizen, as sky turns a dark {Mpink{x.\n\r");
00544             break;
00545 
00546         case 6:
00547             weather_info.sunlight = SUN_RISE;
00548             strcat (buf, "The sky turn orange as the {Ysun{x rises upon the eastern horizon.\n\r");
00549             break;
00550 
00551         case 19:
00552             weather_info.sunlight = SUN_SET;
00553             strcat (buf, "The skys turn {Ddark{x, as the {Ysun{x disapears into the western horizon.\n\r");
00554             break;
00555 
00556         case 20:
00557             weather_info.sunlight = SUN_DARK;
00558             strcat (buf, "The moons rise into the {Ddarkened{x sky, as the {Ddarkness{x begins.\n\r");
00559             break;
00560 
00561         case 24:
00562             time_info.hour = 0;
00563             time_info.day++;
00564             break;
00565     }
00566 
00567     if (time_info.day >= 35)
00568     {
00569         time_info.day = 0;
00570         time_info.month++;
00571     }
00572 
00573     if (time_info.month >= 17)
00574     {
00575         time_info.month = 0;
00576         time_info.year++;
00577     }
00578 
00579     /*
00580      * Weather change.
00581      */
00582     if (time_info.month >= 9 && time_info.month <= 16)
00583         diff = weather_info.mmhg > 985 ? -2 : 2;
00584     else
00585         diff = weather_info.mmhg > 1015 ? -2 : 2;
00586 
00587     weather_info.change += diff * dice (1, 4) + dice (2, 6) - dice (2, 6);
00588     weather_info.change = UMAX (weather_info.change, -12);
00589     weather_info.change = UMIN (weather_info.change, 12);
00590 
00591     weather_info.mmhg += weather_info.change;
00592     weather_info.mmhg = UMAX (weather_info.mmhg, 960);
00593     weather_info.mmhg = UMIN (weather_info.mmhg, 1040);
00594 
00595     switch (weather_info.sky)
00596     {
00597         default:
00598             bug ("Weather_update: bad sky %d.", weather_info.sky);
00599             weather_info.sky = SKY_CLOUDLESS;
00600             break;
00601 
00602         case SKY_CLOUDLESS:
00603             if (weather_info.mmhg < 990
00604                 || (weather_info.mmhg < 1010 && number_bits (2) == 0))
00605             {
00606                 strcat (buf, "Billowing clouds ripple across the sky.\n\r");
00607                 weather_info.sky = SKY_CLOUDY;
00608             }
00609             break;
00610 
00611         case SKY_CLOUDY:
00612             if (weather_info.mmhg < 970
00613                 || (weather_info.mmhg < 990 && number_bits (2) == 0))
00614             {
00615                 strcat (buf, "Your armour quickly becomes drenched, as rain falls from the sky.\n\r");
00616                 weather_info.sky = SKY_RAINING;
00617             }
00618 
00619             if (weather_info.mmhg > 1030 && number_bits (2) == 0)
00620             {
00621                 strcat (buf, "The billowing clouds above your head disappear.\n\r");
00622                 weather_info.sky = SKY_CLOUDLESS;
00623             }
00624             break;
00625 
00626         case SKY_RAINING:
00627             if (weather_info.mmhg < 970 && number_bits (2) == 0)
00628             {
00629                 strcat (buf, "{YLightning {wflashes{x in the sky and a loud bellowing roar is heard in the distance.\n\r");
00630                 weather_info.sky = SKY_LIGHTNING;
00631             }
00632 
00633             if (weather_info.mmhg > 1030
00634                 || (weather_info.mmhg > 1010 && number_bits (2) == 0))
00635             {
00636               //  extern bool just_rained;
00637           //    just_rained = TRUE;
00638         strcat (buf, "The rain stopped.\n\r");
00639                 weather_info.sky = SKY_CLOUDY;
00640             }
00641             break;
00642 
00643         case SKY_LIGHTNING:
00644             if (weather_info.mmhg > 1010
00645                 || (weather_info.mmhg > 990 && number_bits (2) == 0))
00646             {
00647                 strcat (buf, "The lightning has stopped.\n\r");
00648                 weather_info.sky = SKY_RAINING;
00649                 break;
00650             }
00651             break;
00652     }
00653 
00654     if (buf[0] != '\0')
00655     {
00656         for (d = descriptor_list; d != NULL; d = d->next)
00657         {
00658             if (d->connected == CON_PLAYING && IS_OUTSIDE (d->character)
00659                 && IS_AWAKE (d->character))
00660                 send_to_char (buf, d->character);
00661         }
00662     }
00663 
00664     return;
00665 }
00666 
00667 
00668 
00669 /*
00670  * Update all chars, including mobs.
00671 */
00672 void char_update (void)
00673 {
00674     CHAR_DATA *ch;
00675     CHAR_DATA *ch_next;
00676     CHAR_DATA *ch_quit;
00677   // char buf[MAX_STRING_LENGTH];
00678     ch_quit = NULL;
00679     extern bool isCopyover;
00680     extern int Copyovercount;
00681     extern CHAR_DATA *CopyoverPerson;
00682     extern char* CopyoverReason;
00683     char m_buf[500];
00684    //struct CCO *copyover_time;
00685     /* update save counter */
00686     save_number++;
00687 
00688     if (save_number > 29)
00689         save_number = 0;
00690 
00691     for (ch = char_list; ch != NULL; ch = ch_next)
00692     {
00693         AFFECT_DATA *paf;
00694         AFFECT_DATA *paf_next;
00695 
00696   ch_next = ch->next;
00697   
00698   if (isCopyover) /*(ch->c_over > 0)*/
00699   {
00700       switch (Copyovercount)
00701       {
00702           case 3:
00703             //ch->c_over--;
00704             Copyovercount--;
00705             send_to_all("", "{DBeyond {wThe {WShadows {R{!Copyover{x in {B2{x ticks!\n\r");
00706             if (CopyoverReason != NULL)
00707             {
00708                 sprintf(m_buf, "Reason for copyover: %s\n\r", CopyoverReason);
00709                 send_to_all("",m_buf);
00710             }
00711             break;
00712           case 2:
00713             //ch->c_over--;
00714             Copyovercount--;
00715             send_to_all("", "{DBeyond {wThe {WShadows {R{!Copyover{x in {B1{x tick.\n\r");
00716             if (CopyoverReason != NULL)
00717             {
00718                 sprintf(m_buf, "Reason for copyover: %s\n\r", CopyoverReason);
00719                 send_to_all("",m_buf);
00720             }
00721             break;
00722           case 1:
00723             send_to_all("", "Copyover is now started, your link may be frozen for a few moments.\n\r");
00724             //ch->c_over = 0;
00725             Copyovercount = 3;
00726             do_copyover(CopyoverPerson, "");
00727 
00728             break;
00729       }
00730       break;
00731   }
00732             
00733               
00734 
00735     
00736       if(!IS_SET(ch->chann, COMM_NOTICK))
00737        {
00738             send_to_char("\n",ch);
00739        }
00740       
00741     if (!IS_IMMORTAL(ch) && ch->timer > 30)
00742             ch_quit = ch;
00743 
00744         if (ch->position >= POS_STUNNED)
00745         {
00746             /* check to see if we need to go home */
00747             if (IS_NPC (ch) && ch->zone != NULL
00748                 && ch->zone != ch->in_room->area && ch->desc == NULL
00749                 && ch->fighting == NULL && !IS_AFFECTED (ch, AFF_CHARM)
00750                 && number_percent () < 5)
00751             {
00752                 act ("$n wanders on home.", ch, NULL, NULL, TO_ROOM);
00753                 extract_char (ch, TRUE);
00754                 continue;
00755             }
00756 
00757             if (ch->hit < ch->max_hit)
00758                 ch->hit += hit_gain (ch);
00759             else
00760                 ch->hit = ch->max_hit;
00761 
00762             if (ch->mana < ch->max_mana)
00763                 ch->mana += mana_gain (ch);
00764             else
00765                 ch->mana = ch->max_mana;
00766 
00767             if (ch->move < ch->max_move)
00768                 ch->move += move_gain (ch);
00769             else
00770                 ch->move = ch->max_move;
00771         }
00772 
00773         if (ch->position == POS_STUNNED)
00774             update_pos (ch);
00775 
00776         if (!IS_NPC (ch) && ch->level < LEVEL_IMMORTAL)
00777         {
00778             OBJ_DATA *obj;
00779 
00780             if ((obj = get_eq_char (ch, WEAR_LIGHT)) != NULL
00781                 && obj->item_type == ITEM_LIGHT && obj->value[2] > 0)
00782             {
00783                 if (--obj->value[2] == 0 && ch->in_room != NULL)
00784                 {
00785                     --ch->in_room->light;
00786                     act ("$p goes out.", ch, obj, NULL, TO_ROOM);
00787                     act ("$p flickers and goes out.", ch, obj, NULL, TO_CHAR);
00788                     extract_obj (obj);
00789                 }
00790                 else if (obj->value[2] <= 5 && ch->in_room != NULL)
00791                     act ("$p flickers.", ch, obj, NULL, TO_CHAR);
00792             }
00793 
00794             if (IS_IMMORTAL (ch))
00795                 ch->timer += 1;
00796 
00797             if (++ch->timer >= 12 && !IS_IMMORTAL(ch))
00798             {
00799                 if (ch->was_in_room == NULL && ch->in_room != NULL)
00800                 {
00801                     ch->was_in_room = ch->in_room;
00802                     if (ch->fighting != NULL)
00803                         stop_fighting (ch, TRUE);
00804                     act ("$n disappears into the void.",
00805                          ch, NULL, NULL, TO_ROOM);
00806                     send_to_char ("You disappear into the void.\n\r", ch);
00807                     if (ch->level > 1)
00808                         save_char_obj (ch);
00809                     char_from_room (ch);
00810                     char_to_room (ch, get_room_index (ROOM_VNUM_LIMBO));
00811                 }
00812             }
00813 
00814             gain_condition (ch, COND_DRUNK, -1);
00815             gain_condition (ch, COND_FULL, ch->size > SIZE_MEDIUM ? -4 : -2);
00816             gain_condition (ch, COND_THIRST, -1);
00817             gain_condition (ch, COND_HUNGER,
00818                             ch->size > SIZE_MEDIUM ? -2 : -1);
00819         }
00820 
00821         for (paf = ch->affected; paf != NULL; paf = paf_next)
00822         {
00823             paf_next = paf->next;
00824             if (paf->duration > 0)
00825             {
00826                 paf->duration--;
00827                 if (number_range (0, 4) == 0 && paf->level > 0)
00828                     paf->level--;    /* spell strength fades with time */
00829             }
00830             else if (paf->duration < 0);
00831             else
00832             {
00833                 if (paf_next == NULL
00834                     || paf_next->type != paf->type || paf_next->duration > 0)
00835                 {
00836                     if (paf->type > 0 && skill_table[paf->type].msg_off)
00837                     {
00838                         send_to_char (skill_table[paf->type].msg_off, ch);
00839                         send_to_char ("\n\r", ch);
00840                     }
00841                 }
00842 
00843                 affect_remove (ch, paf);
00844             }
00845         }
00846 
00847     if (!IS_NPC(ch) && ch->pcdata->plr_age < 10)
00848     {
00849         send_to_char("Age updated.\n\r",ch);
00850         ch->pcdata->plr_age = 17;
00851     }
00852     
00853 
00854         /*
00855          * Careful with the damages here,
00856          *   MUST NOT refer to ch after damage taken,
00857          *   as it may be lethal damage (on NPC).
00858          */
00859 
00860         if (is_affected (ch, gsn_plague) && ch != NULL)
00861         {
00862             AFFECT_DATA *af, plague;
00863             CHAR_DATA *vch;
00864             int dam;
00865 
00866             if (ch->in_room == NULL)
00867                 continue;
00868 
00869             act ("$n writhes in agony as plague sores erupt from $s skin.",
00870                  ch, NULL, NULL, TO_ROOM);
00871             send_to_char ("You writhe in agony from the plague.\n\r", ch);
00872             for (af = ch->affected; af != NULL; af = af->next)
00873             {
00874                 if (af->type == gsn_plague)
00875                     break;
00876             }
00877 
00878             if (af == NULL)
00879             {
00880                 REMOVE_BIT (ch->affected_by, AFF_PLAGUE);
00881                 continue;
00882             }
00883 
00884             if (af->level == 1)
00885                 continue;
00886 
00887             plague.where = TO_AFFECTS;
00888             plague.type = gsn_plague;
00889             plague.level = af->level - 1;
00890             plague.duration = number_range (1, 2 * plague.level);
00891             plague.location = APPLY_STR;
00892             plague.modifier = -5;
00893             plague.bitvector = AFF_PLAGUE;
00894 
00895             for (vch = ch->in_room->people; vch != NULL;
00896                  vch = vch->next_in_room)
00897             {
00898                 if (!saves_spell (plague.level - 2, vch, DAM_DISEASE)
00899                     && !IS_IMMORTAL (vch)
00900                     && !IS_AFFECTED (vch, AFF_PLAGUE) && number_bits (4) == 0)
00901                 {
00902                     send_to_char ("You feel hot and feverish.\n\r", vch);
00903                     act ("$n shivers and looks very ill.", vch, NULL, NULL,
00904                          TO_ROOM);
00905                     affect_join (vch, &plague);
00906                 }
00907             }
00908 
00909             dam = UMIN (ch->level, af->level / 5 + 1);
00910             ch->mana -= dam;
00911             ch->move -= dam;
00912             damage (ch, ch, dam, gsn_plague, DAM_DISEASE, FALSE);
00913         }
00914         else if (IS_AFFECTED (ch, AFF_POISON) && ch != NULL
00915                  && !IS_AFFECTED (ch, AFF_SLOW))
00916         {
00917             AFFECT_DATA *poison;
00918 
00919             poison = affect_find (ch->affected, gsn_poison);
00920 
00921             if (poison != NULL)
00922             {
00923                 act ("$n shivers and suffers.", ch, NULL, NULL, TO_ROOM);
00924                 send_to_char ("You shiver and suffer.\n\r", ch);
00925                 damage (ch, ch, poison->level / 10 + 1, gsn_poison,
00926                         DAM_POISON, FALSE);
00927             }
00928         }
00929 
00930         else if (ch->position == POS_INCAP && number_range (0, 1) == 0)
00931         {
00932             damage (ch, ch, 1, TYPE_UNDEFINED, DAM_NONE, FALSE);
00933         }
00934         else if (ch->position == POS_MORTAL)
00935         {
00936             damage (ch, ch, 1, TYPE_UNDEFINED, DAM_NONE, FALSE);
00937         }
00938     }
00939 
00940     /*
00941      * Autosave and autoquit.
00942      * Check that these chars still exist.
00943      */
00944     for (ch = char_list; ch != NULL; ch = ch_next)
00945     {
00946         /*
00947          * Edwin's fix for possible pet-induced problem
00948          * JR -- 10/15/00
00949          */
00950         if (!IS_VALID(ch))
00951         {
00952             bug("Update_char: Trying to work with an invalidated character.\n",0); 
00953         break;
00954         }
00955 
00956         ch_next = ch->next;
00957 
00958         if (ch->desc != NULL && ch->desc->descriptor % 30 == save_number)
00959         {
00960             save_char_obj (ch);
00961         }
00962 
00963         if (ch == ch_quit)
00964         {
00965             do_function (ch, &do_quit, "");
00966         }
00967     }
00968 /* NOTE TO SELF XXX: do NOT do this after the whole function
00969  * stuff...Lovely on copyovers! :P */
00970 //   if (IS_IMMORTAL(ch))
00971 //      ++ch->timer;
00972     
00973 
00974     
00975     return;
00976 
00977 }
00978 
00979 
00980 
00981 
00982 /*
00983  * Update all objs.
00984  * This function is performance sensitive.
00985  */
00986 void obj_update (void)
00987 {
00988     OBJ_DATA *obj;
00989     OBJ_DATA *obj_next;
00990     AFFECT_DATA *paf, *paf_next;
00991 
00992     for (obj = object_list; obj != NULL; obj = obj_next)
00993     {
00994         CHAR_DATA *rch;
00995         char *message;
00996 
00997         obj_next = obj->next;
00998 
00999         /* go through affects and decrement */
01000         for (paf = obj->affected; paf != NULL; paf = paf_next)
01001         {
01002             paf_next = paf->next;
01003             if (paf->duration > 0)
01004             {
01005                 paf->duration--;
01006                 if (number_range (0, 4) == 0 && paf->level > 0)
01007                     paf->level--;    /* spell strength fades with time */
01008             }
01009             else if (paf->duration < 0);
01010             else
01011             {
01012                 if (paf_next == NULL
01013                     || paf_next->type != paf->type || paf_next->duration > 0)
01014                 {
01015                     if (paf->type > 0 && skill_table[paf->type].msg_obj)
01016                     {
01017                         if (obj->carried_by != NULL)
01018                         {
01019                             rch = obj->carried_by;
01020                             act (skill_table[paf->type].msg_obj,
01021                                  rch, obj, NULL, TO_CHAR);
01022                         }
01023                         if (obj->in_room != NULL
01024                             && obj->in_room->people != NULL)
01025                         {
01026                             rch = obj->in_room->people;
01027                             act (skill_table[paf->type].msg_obj,
01028                                  rch, obj, NULL, TO_ALL);
01029                         }
01030                     }
01031                 }
01032 
01033                 affect_remove_obj (obj, paf);
01034             }
01035         }
01036 
01037 
01038         if (obj->timer <= 0 || --obj->timer > 0)
01039             continue;
01040 
01041         switch (obj->item_type)
01042         {
01043             default:
01044                 message = "$p crumbles into dust.";
01045                 break;
01046             case ITEM_FOUNTAIN:
01047                 message = "$p dries up.";
01048                 break;
01049             case ITEM_CORPSE_NPC:
01050                 message = "$p decays into dust.";
01051                 break;
01052             case ITEM_CORPSE_PC:
01053                 message = "$p decays into dust.";
01054                 break;
01055             case ITEM_FOOD:
01056                 message = "$p decomposes.";
01057                 break;
01058             case ITEM_POTION:
01059                 message = "$p has evaporated from disuse.";
01060                 break;
01061             case ITEM_PORTAL:
01062                 message = "$p fades out of existence.";
01063                 break;
01064             case ITEM_CONTAINER:
01065                 if (CAN_WEAR (obj, ITEM_WEAR_FLOAT))
01066                     if (obj->contains)
01067                         message =
01068                             "$p flickers and vanishes, spilling its contents on the floor.";
01069                     else
01070                         message = "$p flickers and vanishes.";
01071                 else
01072                     message = "$p crumbles into dust.";
01073                 break;
01074         }
01075 
01076         if (obj->carried_by != NULL)
01077         {
01078             if (IS_NPC (obj->carried_by)
01079                 && obj->carried_by->pIndexData->pShop != NULL)
01080                 obj->carried_by->silver += obj->cost / 5;
01081             else
01082             {
01083                 act (message, obj->carried_by, obj, NULL, TO_CHAR);
01084                 if (obj->wear_loc == WEAR_FLOAT)
01085                     act (message, obj->carried_by, obj, NULL, TO_ROOM);
01086             }
01087         }
01088         else if (obj->in_room != NULL && (rch = obj->in_room->people) != NULL)
01089         {
01090             if (!(obj->in_obj && obj->in_obj->pIndexData->vnum == OBJ_VNUM_PIT
01091                   && !CAN_WEAR (obj->in_obj, ITEM_TAKE)))
01092             {
01093                 act (message, rch, obj, NULL, TO_ROOM);
01094                 act (message, rch, obj, NULL, TO_CHAR);
01095             }
01096         }
01097 
01098         if ((obj->item_type == ITEM_CORPSE_PC || obj->wear_loc == WEAR_FLOAT)
01099             && obj->contains)
01100         {                        /* save the contents */
01101             OBJ_DATA *t_obj, *next_obj;
01102 
01103             for (t_obj = obj->contains; t_obj != NULL; t_obj = next_obj)
01104             {
01105                 next_obj = t_obj->next_content;
01106                 obj_from_obj (t_obj);
01107 
01108                 if (obj->in_obj)    /* in another object */
01109                     obj_to_obj (t_obj, obj->in_obj);
01110 
01111                 else if (obj->carried_by)    /* carried */
01112                     if (obj->wear_loc == WEAR_FLOAT)
01113                         if (obj->carried_by->in_room == NULL)
01114                             extract_obj (t_obj);
01115                         else
01116                             obj_to_room (t_obj, obj->carried_by->in_room);
01117                     else
01118                         obj_to_char (t_obj, obj->carried_by);
01119 
01120                 else if (obj->in_room == NULL)    /* destroy it */
01121                     extract_obj (t_obj);
01122 
01123                 else            /* to a room */
01124                     obj_to_room (t_obj, obj->in_room);
01125             }
01126         }
01127 
01128         extract_obj (obj);
01129     }
01130 
01131     return;
01132 }
01133 
01134 
01135 
01136 /*
01137  * Aggress.
01138  *
01139  * for each mortal PC
01140  *     for each mob in room
01141  *         aggress on some random PC
01142  *
01143  * This function takes 25% to 35% of ALL Merc cpu time.
01144  * Unfortunately, checking on each PC move is too tricky,
01145  *   because we don't the mob to just attack the first PC
01146  *   who leads the party into the room.
01147  *
01148  * -- Furey
01149  */
01150 void aggr_update (void)
01151 {
01152     CHAR_DATA *wch;
01153     CHAR_DATA *wch_next;
01154     CHAR_DATA *ch;
01155     CHAR_DATA *ch_next;
01156     CHAR_DATA *vch;
01157     CHAR_DATA *vch_next;
01158     CHAR_DATA *victim;
01159 
01160     for (wch = char_list; wch != NULL; wch = wch_next)
01161     {
01162         wch_next = wch->next;
01163         if (IS_NPC (wch)
01164             || wch->level >= LEVEL_IMMORTAL
01165             || wch->in_room == NULL || wch->in_room->area->empty) continue;
01166 
01167         for (ch = wch->in_room->people; ch != NULL; ch = ch_next)
01168         {
01169             int count;
01170 
01171             ch_next = ch->next_in_room;
01172 
01173             if (!IS_NPC (ch)
01174                 || !IS_SET (ch->act, ACT_AGGRESSIVE)
01175                 || IS_SET (ch->in_room->room_flags, ROOM_SAFE)
01176                 || IS_AFFECTED (ch, AFF_CALM)
01177                 || ch->fighting != NULL || IS_AFFECTED (ch, AFF_CHARM)
01178                 || !IS_AWAKE (ch)
01179                 || (IS_SET (ch->act, ACT_WIMPY) && IS_AWAKE (wch))
01180                 || !can_see (ch, wch) || number_bits (1) == 0)
01181                 continue;
01182 
01183             /*
01184              * Ok we have a 'wch' player character and a 'ch' npc aggressor.
01185              * Now make the aggressor fight a RANDOM pc victim in the room,
01186              *   giving each 'vch' an equal chance of selection.
01187              */
01188             count = 0;
01189             victim = NULL;
01190             for (vch = wch->in_room->people; vch != NULL; vch = vch_next)
01191             {
01192                 vch_next = vch->next_in_room;
01193 
01194                 if (!IS_NPC (vch)
01195                     && vch->level < LEVEL_IMMORTAL
01196                     && ch->level >= vch->level - 5
01197                     && (!IS_SET (ch->act, ACT_WIMPY) || !IS_AWAKE (vch))
01198                     && can_see (ch, vch))
01199                 {
01200                     if (number_range (0, count) == 0)
01201                         victim = vch;
01202                     count++;
01203                 }
01204             }
01205 
01206             if (victim == NULL)
01207                 continue;
01208 
01209             multi_hit (ch, victim, TYPE_UNDEFINED);
01210         }
01211     }
01212 
01213     return;
01214 }
01215 
01216 
01217 
01218 /*
01219  * Handle all kinds of updates.
01220  * Called once per pulse from game loop.
01221  * Random times to defeat tick-timing clients and players.
01222  */
01223 
01224 void update_handler (void)
01225 {
01226     static int pulse_area;
01227     static int pulse_mobile;
01228     static int pulse_violence;
01229     static int pulse_point;
01230     static int pulse_music;
01231     static int pulse_vehicle;
01232     VDATA *vehicle;
01233     char temp[1000];
01234 
01235     if (--pulse_area <= 0)
01236     {
01237         pulse_area = PULSE_AREA;
01238         /* number_range( PULSE_AREA / 2, 3 * PULSE_AREA / 2 ); */
01239         area_update ();
01240 //  save_clan_data();
01241 //  save_kingdom_data();
01242     
01243     }
01244 
01245     if (--pulse_music <= 0)
01246     {
01247         pulse_music = PULSE_MUSIC;
01248         song_update ();
01249     }
01250 
01251     if (--pulse_mobile <= 0)
01252     {
01253         pulse_mobile = PULSE_MOBILE;
01254         mobile_update ();
01255     }
01256 
01257     if (--pulse_vehicle <= 0)
01258     {
01259         for (vehicle=v_list;vehicle;vehicle=vehicle->next)
01260         {
01261             if (vehicle->path != NULL)
01262                 move_vehicle_npc(vehicle);
01263         }
01264         pulse_vehicle = PULSE_VEHICLE;
01265     }
01266         
01267 
01268     if (--pulse_violence <= 0)
01269     {
01270         
01271      
01272     pulse_violence = PULSE_VIOLENCE;
01273         violence_update ();
01274     }
01275 
01276     if (--pulse_point <= 0)
01277     {
01278         wiznet ("TICK!", NULL, NULL, WIZ_TICKS, 0, 0);
01279         pulse_point = PULSE_TICK;
01280 /* number_range( PULSE_TICK / 2, 3 * PULSE_TICK / 2 ); */
01281 //       extern bool just_rained;
01282 //  just_rained = FALSE;
01283     weather_update ();
01284         char_update ();
01285         obj_update ();
01286     save_clan_data();
01287     save_kingdom_data();
01288     do_web_who();
01289     }
01290     
01291     aggr_update ();
01292     tail_chain ();
01293     return;
01294 }

Generated on Thu Jan 13 21:48:14 2005 for Beyond the Shadows by  doxygen 1.4.0