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

effects.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 #if defined(macintosh)
00028 #include <types.h>
00029 #else
00030 #include <sys/types.h>
00031 #endif
00032 #include <stdio.h>
00033 #include <stdlib.h>
00034 #include <string.h>
00035 #include <time.h>
00036 #include "merc.h"
00037 #include "recycle.h"
00038 
00039 void acid_effect (void *vo, int level, int dam, int target)
00040 {
00041     if (target == TARGET_ROOM)
00042     {                            /* nail objects on the floor */
00043         ROOM_INDEX_DATA *room = (ROOM_INDEX_DATA *) vo;
00044         OBJ_DATA *obj, *obj_next;
00045 
00046         for (obj = room->contents; obj != NULL; obj = obj_next)
00047         {
00048             obj_next = obj->next_content;
00049             acid_effect (obj, level, dam, TARGET_OBJ);
00050         }
00051         return;
00052     }
00053 
00054     if (target == TARGET_CHAR)
00055     {                            /* do the effect on a victim */
00056         CHAR_DATA *victim = (CHAR_DATA *) vo;
00057         OBJ_DATA *obj, *obj_next;
00058 
00059         /* let's toast some gear */
00060         for (obj = victim->carrying; obj != NULL; obj = obj_next)
00061         {
00062             obj_next = obj->next_content;
00063             acid_effect (obj, level, dam, TARGET_OBJ);
00064         }
00065         return;
00066     }
00067 
00068     if (target == TARGET_OBJ)
00069     {                            /* toast an object */
00070         OBJ_DATA *obj = (OBJ_DATA *) vo;
00071         OBJ_DATA *t_obj, *n_obj;
00072         int chance;
00073         char *msg;
00074 
00075         if (IS_OBJ_STAT (obj, ITEM_BURN_PROOF)
00076             || IS_OBJ_STAT (obj, ITEM_NOPURGE) || number_range (0, 4) == 0)
00077             return;
00078 
00079         chance = level / 4 + dam / 10;
00080 
00081         if (chance > 25)
00082             chance = (chance - 25) / 2 + 25;
00083         if (chance > 50)
00084             chance = (chance - 50) / 2 + 50;
00085 
00086         if (IS_OBJ_STAT (obj, ITEM_BLESS))
00087             chance -= 5;
00088 
00089         chance -= obj->level * 2;
00090 
00091         switch (obj->item_type)
00092         {
00093             default:
00094                 return;
00095             case ITEM_CONTAINER:
00096             case ITEM_CORPSE_PC:
00097             case ITEM_CORPSE_NPC:
00098                 msg = "$p fumes and dissolves.";
00099                 break;
00100             case ITEM_ARMOR:
00101                 msg = "$p is pitted and etched.";
00102                 break;
00103             case ITEM_CLOTHING:
00104                 msg = "$p is corroded into scrap.";
00105                 break;
00106             case ITEM_STAFF:
00107             case ITEM_WAND:
00108                 chance -= 10;
00109                 msg = "$p corrodes and breaks.";
00110                 break;
00111             case ITEM_SCROLL:
00112                 chance += 10;
00113                 msg = "$p is burned into waste.";
00114                 break;
00115         }
00116 
00117         chance = URANGE (5, chance, 95);
00118 
00119         if (number_percent () > chance)
00120             return;
00121 
00122         if (obj->carried_by != NULL)
00123             act (msg, obj->carried_by, obj, NULL, TO_ALL);
00124         else if (obj->in_room != NULL && obj->in_room->people != NULL)
00125             act (msg, obj->in_room->people, obj, NULL, TO_ALL);
00126 
00127         if (obj->item_type == ITEM_ARMOR)
00128         {                        /* etch it */
00129             AFFECT_DATA *paf;
00130             bool af_found = FALSE;
00131             int i;
00132 
00133             affect_enchant (obj);
00134 
00135             for (paf = obj->affected; paf != NULL; paf = paf->next)
00136             {
00137                 if (paf->location == APPLY_AC)
00138                 {
00139                     af_found = TRUE;
00140                     paf->type = -1;
00141                     paf->modifier += 1;
00142                     paf->level = UMAX (paf->level, level);
00143                     break;
00144                 }
00145             }
00146 
00147             if (!af_found)
00148                 /* needs a new affect */
00149             {
00150                 paf = new_affect ();
00151 
00152                 paf->type = -1;
00153                 paf->level = level;
00154                 paf->duration = -1;
00155                 paf->location = APPLY_AC;
00156                 paf->modifier = 1;
00157                 paf->bitvector = 0;
00158                 paf->next = obj->affected;
00159                 obj->affected = paf;
00160             }
00161 
00162             if (obj->carried_by != NULL && obj->wear_loc != WEAR_NONE)
00163                 for (i = 0; i < 4; i++)
00164                     obj->carried_by->armor[i] += 1;
00165             return;
00166         }
00167 
00168         /* get rid of the object */
00169         if (obj->contains)
00170         {                        /* dump contents */
00171             for (t_obj = obj->contains; t_obj != NULL; t_obj = n_obj)
00172             {
00173                 n_obj = t_obj->next_content;
00174                 obj_from_obj (t_obj);
00175                 if (obj->in_room != NULL)
00176                     obj_to_room (t_obj, obj->in_room);
00177                 else if (obj->carried_by != NULL)
00178                     obj_to_room (t_obj, obj->carried_by->in_room);
00179                 else
00180                 {
00181                     extract_obj (t_obj);
00182                     continue;
00183                 }
00184 
00185                 acid_effect (t_obj, level / 2, dam / 2, TARGET_OBJ);
00186             }
00187         }
00188 
00189         extract_obj (obj);
00190         return;
00191     }
00192 }
00193 
00194 
00195 void cold_effect (void *vo, int level, int dam, int target)
00196 {
00197     if (target == TARGET_ROOM)
00198     {                            /* nail objects on the floor */
00199         ROOM_INDEX_DATA *room = (ROOM_INDEX_DATA *) vo;
00200         OBJ_DATA *obj, *obj_next;
00201 
00202         for (obj = room->contents; obj != NULL; obj = obj_next)
00203         {
00204             obj_next = obj->next_content;
00205             cold_effect (obj, level, dam, TARGET_OBJ);
00206         }
00207         return;
00208     }
00209 
00210     if (target == TARGET_CHAR)
00211     {                            /* whack a character */
00212         CHAR_DATA *victim = (CHAR_DATA *) vo;
00213         OBJ_DATA *obj, *obj_next;
00214 
00215         /* chill touch effect */
00216         if (!saves_spell (level / 4 + dam / 20, victim, DAM_COLD))
00217         {
00218             AFFECT_DATA af;
00219 
00220             act ("$n turns blue and shivers.", victim, NULL, NULL, TO_ROOM);
00221             act ("A chill sinks deep into your bones.", victim, NULL, NULL,
00222                  TO_CHAR);
00223             af.where = TO_AFFECTS;
00224             af.type = skill_lookup ("chill touch");
00225             af.level = level;
00226             af.duration = 6;
00227             af.location = APPLY_STR;
00228             af.modifier = -1;
00229             af.bitvector = 0;
00230             affect_join (victim, &af);
00231         }
00232 
00233         /* hunger! (warmth sucked out */
00234         if (!IS_NPC (victim))
00235             gain_condition (victim, COND_HUNGER, dam / 20);
00236 
00237         /* let's toast some gear */
00238         for (obj = victim->carrying; obj != NULL; obj = obj_next)
00239         {
00240             obj_next = obj->next_content;
00241             cold_effect (obj, level, dam, TARGET_OBJ);
00242         }
00243         return;
00244     }
00245 
00246     if (target == TARGET_OBJ)
00247     {                            /* toast an object */
00248         OBJ_DATA *obj = (OBJ_DATA *) vo;
00249         int chance;
00250         char *msg;
00251 
00252         if (IS_OBJ_STAT (obj, ITEM_BURN_PROOF)
00253             || IS_OBJ_STAT (obj, ITEM_NOPURGE) || number_range (0, 4) == 0)
00254             return;
00255 
00256         chance = level / 4 + dam / 10;
00257 
00258         if (chance > 25)
00259             chance = (chance - 25) / 2 + 25;
00260         if (chance > 50)
00261             chance = (chance - 50) / 2 + 50;
00262 
00263         if (IS_OBJ_STAT (obj, ITEM_BLESS))
00264             chance -= 5;
00265 
00266         chance -= obj->level * 2;
00267 
00268         switch (obj->item_type)
00269         {
00270             default:
00271                 return;
00272             case ITEM_POTION:
00273                 msg = "$p freezes and shatters!";
00274                 chance += 25;
00275                 break;
00276             case ITEM_DRINK_CON:
00277                 msg = "$p freezes and shatters!";
00278                 chance += 5;
00279                 break;
00280         }
00281 
00282         chance = URANGE (5, chance, 95);
00283 
00284         if (number_percent () > chance)
00285             return;
00286 
00287         if (obj->carried_by != NULL)
00288             act (msg, obj->carried_by, obj, NULL, TO_ALL);
00289         else if (obj->in_room != NULL && obj->in_room->people != NULL)
00290             act (msg, obj->in_room->people, obj, NULL, TO_ALL);
00291 
00292         extract_obj (obj);
00293         return;
00294     }
00295 }
00296 
00297 
00298 
00299 void fire_effect (void *vo, int level, int dam, int target)
00300 {
00301     if (target == TARGET_ROOM)
00302     {                            /* nail objects on the floor */
00303         ROOM_INDEX_DATA *room = (ROOM_INDEX_DATA *) vo;
00304         OBJ_DATA *obj, *obj_next;
00305 
00306         for (obj = room->contents; obj != NULL; obj = obj_next)
00307         {
00308             obj_next = obj->next_content;
00309             fire_effect (obj, level, dam, TARGET_OBJ);
00310         }
00311         return;
00312     }
00313 
00314     if (target == TARGET_CHAR)
00315     {                            /* do the effect on a victim */
00316         CHAR_DATA *victim = (CHAR_DATA *) vo;
00317         OBJ_DATA *obj, *obj_next;
00318 
00319         /* chance of blindness */
00320         if (!IS_AFFECTED (victim, AFF_BLIND)
00321             && !saves_spell (level / 4 + dam / 20, victim, DAM_FIRE))
00322         {
00323             AFFECT_DATA af;
00324             act ("$n is blinded by smoke!", victim, NULL, NULL, TO_ROOM);
00325             act ("Your eyes tear up from smoke...you can't see a thing!",
00326                  victim, NULL, NULL, TO_CHAR);
00327 
00328             af.where = TO_AFFECTS;
00329             af.type = skill_lookup ("fire breath");
00330             af.level = level;
00331             af.duration = number_range (0, level / 10);
00332             af.location = APPLY_HITROLL;
00333             af.modifier = -4;
00334             af.bitvector = AFF_BLIND;
00335 
00336             affect_to_char (victim, &af);
00337         }
00338 
00339         /* getting thirsty */
00340         if (!IS_NPC (victim))
00341             gain_condition (victim, COND_THIRST, dam / 20);
00342 
00343         /* let's toast some gear! */
00344         for (obj = victim->carrying; obj != NULL; obj = obj_next)
00345         {
00346             obj_next = obj->next_content;
00347 
00348             fire_effect (obj, level, dam, TARGET_OBJ);
00349         }
00350         return;
00351     }
00352 
00353     if (target == TARGET_OBJ)
00354     {                            /* toast an object */
00355         OBJ_DATA *obj = (OBJ_DATA *) vo;
00356         OBJ_DATA *t_obj, *n_obj;
00357         int chance;
00358         char *msg;
00359 
00360         if (IS_OBJ_STAT (obj, ITEM_BURN_PROOF)
00361             || IS_OBJ_STAT (obj, ITEM_NOPURGE) || number_range (0, 4) == 0)
00362             return;
00363 
00364         chance = level / 4 + dam / 10;
00365 
00366         if (chance > 25)
00367             chance = (chance - 25) / 2 + 25;
00368         if (chance > 50)
00369             chance = (chance - 50) / 2 + 50;
00370 
00371         if (IS_OBJ_STAT (obj, ITEM_BLESS))
00372             chance -= 5;
00373         chance -= obj->level * 2;
00374 
00375         switch (obj->item_type)
00376         {
00377             default:
00378                 return;
00379             case ITEM_CONTAINER:
00380                 msg = "$p ignites and burns!";
00381                 break;
00382             case ITEM_POTION:
00383                 chance += 25;
00384                 msg = "$p bubbles and boils!";
00385                 break;
00386             case ITEM_SCROLL:
00387                 chance += 50;
00388                 msg = "$p crackles and burns!";
00389                 break;
00390             case ITEM_STAFF:
00391                 chance += 10;
00392                 msg = "$p smokes and chars!";
00393                 break;
00394             case ITEM_WAND:
00395                 msg = "$p sparks and sputters!";
00396                 break;
00397             case ITEM_FOOD:
00398                 msg = "$p blackens and crisps!";
00399                 break;
00400             case ITEM_PILL:
00401                 msg = "$p melts and drips!";
00402                 break;
00403         }
00404 
00405         chance = URANGE (5, chance, 95);
00406 
00407         if (number_percent () > chance)
00408             return;
00409 
00410         if (obj->carried_by != NULL)
00411             act (msg, obj->carried_by, obj, NULL, TO_ALL);
00412         else if (obj->in_room != NULL && obj->in_room->people != NULL)
00413             act (msg, obj->in_room->people, obj, NULL, TO_ALL);
00414 
00415         if (obj->contains)
00416         {
00417             /* dump the contents */
00418 
00419             for (t_obj = obj->contains; t_obj != NULL; t_obj = n_obj)
00420             {
00421                 n_obj = t_obj->next_content;
00422                 obj_from_obj (t_obj);
00423                 if (obj->in_room != NULL)
00424                     obj_to_room (t_obj, obj->in_room);
00425                 else if (obj->carried_by != NULL)
00426                     obj_to_room (t_obj, obj->carried_by->in_room);
00427                 else
00428                 {
00429                     extract_obj (t_obj);
00430                     continue;
00431                 }
00432                 fire_effect (t_obj, level / 2, dam / 2, TARGET_OBJ);
00433             }
00434         }
00435 
00436         extract_obj (obj);
00437         return;
00438     }
00439 }
00440 
00441 void poison_effect (void *vo, int level, int dam, int target)
00442 {
00443     if (target == TARGET_ROOM)
00444     {                            /* nail objects on the floor */
00445         ROOM_INDEX_DATA *room = (ROOM_INDEX_DATA *) vo;
00446         OBJ_DATA *obj, *obj_next;
00447 
00448         for (obj = room->contents; obj != NULL; obj = obj_next)
00449         {
00450             obj_next = obj->next_content;
00451             poison_effect (obj, level, dam, TARGET_OBJ);
00452         }
00453         return;
00454     }
00455 
00456     if (target == TARGET_CHAR)
00457     {                            /* do the effect on a victim */
00458         CHAR_DATA *victim = (CHAR_DATA *) vo;
00459         OBJ_DATA *obj, *obj_next;
00460 
00461         /* chance of poisoning */
00462         if (!saves_spell (level / 4 + dam / 20, victim, DAM_POISON))
00463         {
00464             AFFECT_DATA af;
00465 
00466             send_to_char ("You feel poison coursing through your veins.\n\r",
00467                           victim);
00468             act ("$n looks very ill.", victim, NULL, NULL, TO_ROOM);
00469 
00470             af.where = TO_AFFECTS;
00471             af.type = gsn_poison;
00472             af.level = level;
00473             af.duration = level / 2;
00474             af.location = APPLY_STR;
00475             af.modifier = -1;
00476             af.bitvector = AFF_POISON;
00477             affect_join (victim, &af);
00478         }
00479 
00480         /* equipment */
00481         for (obj = victim->carrying; obj != NULL; obj = obj_next)
00482         {
00483             obj_next = obj->next_content;
00484             poison_effect (obj, level, dam, TARGET_OBJ);
00485         }
00486         return;
00487     }
00488 
00489     if (target == TARGET_OBJ)
00490     {                            /* do some poisoning */
00491         OBJ_DATA *obj = (OBJ_DATA *) vo;
00492         int chance;
00493 
00494 
00495         if (IS_OBJ_STAT (obj, ITEM_BURN_PROOF)
00496             || IS_OBJ_STAT (obj, ITEM_BLESS) || number_range (0, 4) == 0)
00497             return;
00498 
00499         chance = level / 4 + dam / 10;
00500         if (chance > 25)
00501             chance = (chance - 25) / 2 + 25;
00502         if (chance > 50)
00503             chance = (chance - 50) / 2 + 50;
00504 
00505         chance -= obj->level * 2;
00506 
00507         switch (obj->item_type)
00508         {
00509             default:
00510                 return;
00511             case ITEM_FOOD:
00512                 break;
00513             case ITEM_DRINK_CON:
00514                 if (obj->value[0] == obj->value[1])
00515                     return;
00516                 break;
00517         }
00518 
00519         chance = URANGE (5, chance, 95);
00520 
00521         if (number_percent () > chance)
00522             return;
00523 
00524         obj->value[3] = 1;
00525         return;
00526     }
00527 }
00528 
00529 
00530 void shock_effect (void *vo, int level, int dam, int target)
00531 {
00532     if (target == TARGET_ROOM)
00533     {
00534         ROOM_INDEX_DATA *room = (ROOM_INDEX_DATA *) vo;
00535         OBJ_DATA *obj, *obj_next;
00536 
00537         for (obj = room->contents; obj != NULL; obj = obj_next)
00538         {
00539             obj_next = obj->next_content;
00540             shock_effect (obj, level, dam, TARGET_OBJ);
00541         }
00542         return;
00543     }
00544 
00545     if (target == TARGET_CHAR)
00546     {
00547         CHAR_DATA *victim = (CHAR_DATA *) vo;
00548         OBJ_DATA *obj, *obj_next;
00549 
00550         /* daze and confused? */
00551         if (!saves_spell (level / 4 + dam / 20, victim, DAM_LIGHTNING))
00552         {
00553             send_to_char ("Your muscles stop responding.\n\r", victim);
00554             DAZE_STATE (victim, UMAX (12, level / 4 + dam / 20));
00555         }
00556 
00557         /* toast some gear */
00558         for (obj = victim->carrying; obj != NULL; obj = obj_next)
00559         {
00560             obj_next = obj->next_content;
00561             shock_effect (obj, level, dam, TARGET_OBJ);
00562         }
00563         return;
00564     }
00565 
00566     if (target == TARGET_OBJ)
00567     {
00568         OBJ_DATA *obj = (OBJ_DATA *) vo;
00569         int chance;
00570         char *msg;
00571 
00572         if (IS_OBJ_STAT (obj, ITEM_BURN_PROOF)
00573             || IS_OBJ_STAT (obj, ITEM_NOPURGE) || number_range (0, 4) == 0)
00574             return;
00575 
00576         chance = level / 4 + dam / 10;
00577 
00578         if (chance > 25)
00579             chance = (chance - 25) / 2 + 25;
00580         if (chance > 50)
00581             chance = (chance - 50) / 2 + 50;
00582 
00583         if (IS_OBJ_STAT (obj, ITEM_BLESS))
00584             chance -= 5;
00585 
00586         chance -= obj->level * 2;
00587 
00588         switch (obj->item_type)
00589         {
00590             default:
00591                 return;
00592             case ITEM_WAND:
00593             case ITEM_STAFF:
00594                 chance += 10;
00595                 msg = "$p overloads and explodes!";
00596                 break;
00597             case ITEM_JEWELRY:
00598                 chance -= 10;
00599                 msg = "$p is fused into a worthless lump.";
00600         }
00601 
00602         chance = URANGE (5, chance, 95);
00603 
00604         if (number_percent () > chance)
00605             return;
00606 
00607         if (obj->carried_by != NULL)
00608             act (msg, obj->carried_by, obj, NULL, TO_ALL);
00609         else if (obj->in_room != NULL && obj->in_room->people != NULL)
00610             act (msg, obj->in_room->people, obj, NULL, TO_ALL);
00611 
00612         extract_obj (obj);
00613         return;
00614     }
00615 }

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