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

special.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 #include <time.h>
00031 #else
00032 #include <sys/types.h>
00033 #endif
00034 #include <stdio.h>
00035 #include <stdlib.h>
00036 #include <string.h>
00037 #include <time.h>
00038 #include "merc.h"
00039 #include "interp.h"
00040 #include "magic.h"
00041 
00042 /*
00043  * The following special functions are available for mobiles.
00044  */
00045 DECLARE_SPEC_FUN (spec_breath_any);
00046 DECLARE_SPEC_FUN (spec_breath_acid);
00047 DECLARE_SPEC_FUN (spec_breath_fire);
00048 DECLARE_SPEC_FUN (spec_breath_frost);
00049 DECLARE_SPEC_FUN (spec_breath_gas);
00050 DECLARE_SPEC_FUN (spec_breath_lightning);
00051 DECLARE_SPEC_FUN (spec_cast_adept);
00052 DECLARE_SPEC_FUN (spec_cast_cleric);
00053 DECLARE_SPEC_FUN (spec_cast_judge);
00054 DECLARE_SPEC_FUN (spec_cast_mage);
00055 DECLARE_SPEC_FUN (spec_cast_undead);
00056 DECLARE_SPEC_FUN (spec_executioner);
00057 DECLARE_SPEC_FUN (spec_fido);
00058 DECLARE_SPEC_FUN (spec_guard);
00059 DECLARE_SPEC_FUN (spec_janitor);
00060 DECLARE_SPEC_FUN (spec_mayor);
00061 DECLARE_SPEC_FUN (spec_poison);
00062 DECLARE_SPEC_FUN (spec_thief);
00063 DECLARE_SPEC_FUN (spec_nasty);
00064 DECLARE_SPEC_FUN (spec_troll_member);
00065 DECLARE_SPEC_FUN (spec_ogre_member);
00066 DECLARE_SPEC_FUN (spec_patrolman);
00067 DECLARE_SPEC_FUN (spec_wolf_forest);
00068 DECLARE_SPEC_FUN (spec_panther_forest);
00069 /* the function table */
00070 const struct spec_type spec_table[] = {
00071     {"spec_breath_any", spec_breath_any},
00072     {"spec_breath_acid", spec_breath_acid},
00073     {"spec_breath_fire", spec_breath_fire},
00074     {"spec_breath_frost", spec_breath_frost},
00075     {"spec_breath_gas", spec_breath_gas},
00076     {"spec_breath_lightning", spec_breath_lightning},
00077     {"spec_cast_adept", spec_cast_adept},
00078     {"spec_cast_cleric", spec_cast_cleric},
00079     {"spec_cast_judge", spec_cast_judge},
00080     {"spec_cast_mage", spec_cast_mage},
00081     {"spec_cast_undead", spec_cast_undead},
00082     {"spec_executioner", spec_executioner},
00083     {"spec_fido", spec_fido},
00084     {"spec_guard", spec_guard},
00085     {"spec_janitor", spec_janitor},
00086     {"spec_mayor", spec_mayor},
00087     {"spec_poison", spec_poison},
00088     {"spec_thief", spec_thief},
00089     {"spec_nasty", spec_nasty},
00090     {"spec_troll_member", spec_troll_member},
00091     {"spec_ogre_member", spec_ogre_member},
00092     {"spec_patrolman", spec_patrolman},
00093     {"spec_wolf_forest", spec_wolf_forest},
00094     {"spec_panther_forest", spec_panther_forest},
00095     {NULL, NULL}
00096 };
00097 
00098 /*
00099  * Given a name, return the appropriate spec fun.
00100  */
00101 SPEC_FUN *spec_lookup (const char *name)
00102 {
00103     int i;
00104 
00105     for (i = 0; spec_table[i].name != NULL; i++)
00106     {
00107         if (LOWER (name[0]) == LOWER (spec_table[i].name[0])
00108             && !str_prefix (name, spec_table[i].name))
00109             return spec_table[i].function;
00110     }
00111 
00112     return 0;
00113 }
00114 
00115 char *spec_name (SPEC_FUN * function)
00116 {
00117     int i;
00118 
00119     for (i = 0; spec_table[i].function != NULL; i++)
00120     {
00121         if (function == spec_table[i].function)
00122             return spec_table[i].name;
00123     }
00124 
00125     return NULL;
00126 }
00127 
00128 bool spec_panther_forest (CHAR_DATA *ch)
00129 {
00130     CHAR_DATA *vch, *victim = NULL;
00131     int count=0;
00132 
00133     if (!IS_AWAKE(ch) || IS_AFFECTED(ch, AFF_CALM) || ch->in_room == NULL
00134             ||  IS_AFFECTED(ch, AFF_CHARM) || ch->fighting != NULL)
00135         return FALSE;
00136 
00137     for (vch = ch->in_room->people;vch != NULL; vch = vch->next_in_room)
00138     {
00139         if (!IS_NPC(vch) || ch == vch)
00140             continue;
00141         if (vch->pIndexData->group == 301 && !is_safe(ch, vch))
00142         {
00143             if (number_range(0, count)==0)
00144                 victim = vch;
00145             count ++;
00146         }
00147     }
00148     if (victim == NULL)
00149         return FALSE;
00150 
00151     act ("$n peers around and jumps into the air, puncing onto $N!", ch, NULL, victim, TO_ALL);
00152     do_bash(ch, victim->name);
00153     return TRUE;
00154 }
00155     
00156 bool spec_wolf_forest (CHAR_DATA *ch)
00157 {
00158     CHAR_DATA *vch, *victim = NULL;
00159     int count=0;
00160     char *message;
00161 
00162     if (!IS_AWAKE(ch) || IS_AFFECTED(ch, AFF_CALM) || ch->in_room == NULL
00163             || IS_AFFECTED (ch, AFF_CHARM) || ch->fighting != NULL)
00164         return FALSE;
00165 
00166     for (vch = ch->in_room->people;vch != NULL; vch = vch->next_in_room)
00167     {
00168         if (!IS_NPC(vch) || ch == vch)
00169             continue;
00170         if (vch->pIndexData->group == 302 &&!is_safe(ch, vch))
00171         {
00172             if (number_range(0,count)==0)
00173                 victim=vch;
00174             count ++;
00175         }
00176     }
00177     if (victim == NULL)
00178         return FALSE;
00179         act ("$n licks $s lips and growls at $N, attacking", ch, NULL, victim, TO_ALL);    
00180         multi_hit (ch, victim, TYPE_UNDEFINED);
00181         return TRUE;
00182 }
00183     
00184 
00185 bool spec_troll_member (CHAR_DATA * ch)
00186 {
00187     CHAR_DATA *vch, *victim = NULL;
00188     int count = 0;
00189     char *message;
00190 
00191     if (!IS_AWAKE (ch) || IS_AFFECTED (ch, AFF_CALM) || ch->in_room == NULL
00192         || IS_AFFECTED (ch, AFF_CHARM) || ch->fighting != NULL)
00193         return FALSE;
00194 
00195     /* find an ogre to beat up */
00196     for (vch = ch->in_room->people; vch != NULL; vch = vch->next_in_room)
00197     {
00198         if (!IS_NPC (vch) || ch == vch)
00199             continue;
00200 
00201         if (vch->pIndexData->vnum == MOB_VNUM_PATROLMAN)
00202             return FALSE;
00203 
00204         if (vch->pIndexData->group == GROUP_VNUM_OGRES
00205             && ch->level > vch->level - 2 && !is_safe (ch, vch))
00206         {
00207             if (number_range (0, count) == 0)
00208                 victim = vch;
00209 
00210             count++;
00211         }
00212     }
00213 
00214     if (victim == NULL)
00215         return FALSE;
00216 
00217     /* say something, then raise hell */
00218     switch (number_range (0, 6))
00219     {
00220         default:
00221             message = NULL;
00222             break;
00223         case 0:
00224             message = "$n yells 'I've been looking for you, punk!'";
00225             break;
00226         case 1:
00227             message = "With a scream of rage, $n attacks $N.";
00228             break;
00229         case 2:
00230             message =
00231                 "$n says 'What's slimy Ogre trash like you doing around here?'";
00232             break;
00233         case 3:
00234             message = "$n cracks his knuckles and says 'Do ya feel lucky?'";
00235             break;
00236         case 4:
00237             message = "$n says 'There's no cops to save you this time!'";
00238             break;
00239         case 5:
00240             message = "$n says 'Time to join your brother, spud.'";
00241             break;
00242         case 6:
00243             message = "$n says 'Let's rock.'";
00244             break;
00245     }
00246 
00247     if (message != NULL)
00248         act (message, ch, NULL, victim, TO_ALL);
00249     multi_hit (ch, victim, TYPE_UNDEFINED);
00250     return TRUE;
00251 }
00252 
00253 bool spec_ogre_member (CHAR_DATA * ch)
00254 {
00255     CHAR_DATA *vch, *victim = NULL;
00256     int count = 0;
00257     char *message;
00258 
00259     if (!IS_AWAKE (ch) || IS_AFFECTED (ch, AFF_CALM) || ch->in_room == NULL
00260         || IS_AFFECTED (ch, AFF_CHARM) || ch->fighting != NULL)
00261         return FALSE;
00262 
00263     /* find an troll to beat up */
00264     for (vch = ch->in_room->people; vch != NULL; vch = vch->next_in_room)
00265     {
00266         if (!IS_NPC (vch) || ch == vch)
00267             continue;
00268 
00269         if (vch->pIndexData->vnum == MOB_VNUM_PATROLMAN)
00270             return FALSE;
00271 
00272         if (vch->pIndexData->group == GROUP_VNUM_TROLLS
00273             && ch->level > vch->level - 2 && !is_safe (ch, vch))
00274         {
00275             if (number_range (0, count) == 0)
00276                 victim = vch;
00277 
00278             count++;
00279         }
00280     }
00281 
00282     if (victim == NULL)
00283         return FALSE;
00284 
00285     /* say something, then raise hell */
00286     switch (number_range (0, 6))
00287     {
00288         default:
00289             message = NULL;
00290             break;
00291         case 0:
00292             message = "$n yells 'I've been looking for you, punk!'";
00293             break;
00294         case 1:
00295             message = "With a scream of rage, $n attacks $N.'";
00296             break;
00297         case 2:
00298             message =
00299                 "$n says 'What's Troll filth like you doing around here?'";
00300             break;
00301         case 3:
00302             message = "$n cracks his knuckles and says 'Do ya feel lucky?'";
00303             break;
00304         case 4:
00305             message = "$n says 'There's no cops to save you this time!'";
00306             break;
00307         case 5:
00308             message = "$n says 'Time to join your brother, spud.'";
00309             break;
00310         case 6:
00311             message = "$n says 'Let's rock.'";
00312             break;
00313     }
00314 
00315     if (message != NULL)
00316         act (message, ch, NULL, victim, TO_ALL);
00317     multi_hit (ch, victim, TYPE_UNDEFINED);
00318     return TRUE;
00319 }
00320 
00321 bool spec_patrolman (CHAR_DATA * ch)
00322 {
00323     CHAR_DATA *vch, *victim = NULL;
00324     OBJ_DATA *obj;
00325     char *message;
00326     int count = 0;
00327 
00328     if (!IS_AWAKE (ch) || IS_AFFECTED (ch, AFF_CALM) || ch->in_room == NULL
00329         || IS_AFFECTED (ch, AFF_CHARM) || ch->fighting != NULL)
00330         return FALSE;
00331 
00332     /* look for a fight in the room */
00333     for (vch = ch->in_room->people; vch != NULL; vch = vch->next_in_room)
00334     {
00335         if (vch == ch)
00336             continue;
00337 
00338         if (vch->fighting != NULL)
00339         {                        /* break it up! */
00340             if (number_range (0, count) == 0)
00341                 victim = (vch->level > vch->fighting->level)
00342                     ? vch : vch->fighting;
00343             count++;
00344         }
00345     }
00346 
00347     if (victim == NULL
00348         || (IS_NPC (victim)
00349             && victim->spec_fun == ch->spec_fun)) return FALSE;
00350 
00351     if (((obj = get_eq_char (ch, WEAR_NECK_1)) != NULL
00352          && obj->pIndexData->vnum == OBJ_VNUM_WHISTLE)
00353         || ((obj = get_eq_char (ch, WEAR_NECK_2)) != NULL
00354             && obj->pIndexData->vnum == OBJ_VNUM_WHISTLE))
00355     {
00356         act ("You blow down hard on $p.", ch, obj, NULL, TO_CHAR);
00357         act ("$n blows on $p, ***WHEEEEEEEEEEEET***", ch, obj, NULL, TO_ROOM);
00358 
00359         for (vch = char_list; vch != NULL; vch = vch->next)
00360         {
00361             if (vch->in_room == NULL)
00362                 continue;
00363 
00364             if (vch->in_room != ch->in_room
00365                 && vch->in_room->area == ch->in_room->area)
00366                 send_to_char ("You hear a shrill whistling sound.\n\r", vch);
00367         }
00368     }
00369 
00370     switch (number_range (0, 6))
00371     {
00372         default:
00373             message = NULL;
00374             break;
00375         case 0:
00376             message = "$n yells 'All roit! All roit! break it up!'";
00377             break;
00378         case 1:
00379             message =
00380                 "$n says 'Society's to blame, but what's a bloke to do?'";
00381             break;
00382         case 2:
00383             message = "$n mumbles 'bloody kids will be the death of us all.'";
00384             break;
00385         case 3:
00386             message = "$n shouts 'Stop that! Stop that!' and attacks.";
00387             break;
00388         case 4:
00389             message = "$n pulls out his billy and goes to work.";
00390             break;
00391         case 5:
00392             message =
00393                 "$n sighs in resignation and proceeds to break up the fight.";
00394             break;
00395         case 6:
00396             message = "$n says 'Settle down, you hooligans!'";
00397             break;
00398     }
00399 
00400     if (message != NULL)
00401         act (message, ch, NULL, NULL, TO_ALL);
00402 
00403     multi_hit (ch, victim, TYPE_UNDEFINED);
00404 
00405     return TRUE;
00406 }
00407 
00408 
00409 bool spec_nasty (CHAR_DATA * ch)
00410 {
00411     CHAR_DATA *victim, *v_next;
00412     long gold;
00413 
00414     if (!IS_AWAKE (ch))
00415     {
00416         return FALSE;
00417     }
00418 
00419     if (ch->position != POS_FIGHTING)
00420     {
00421         for (victim = ch->in_room->people; victim != NULL; victim = v_next)
00422         {
00423             v_next = victim->next_in_room;
00424             if (!IS_NPC (victim)
00425                 && (victim->level > ch->level)
00426                 && (victim->level < ch->level + 10))
00427             {
00428                 do_function (ch, &do_backstab, victim->name);
00429                 if (ch->position != POS_FIGHTING)
00430                 {
00431                     do_function (ch, &do_murder, victim->name);
00432                 }
00433 
00434                 /* should steal some coins right away? :) */
00435                 return TRUE;
00436             }
00437         }
00438         return FALSE;            /*  No one to attack */
00439     }
00440 
00441     /* okay, we must be fighting.... steal some coins and flee */
00442     if ((victim = ch->fighting) == NULL)
00443         return FALSE;            /* let's be paranoid.... */
00444 
00445     switch (number_bits (2))
00446     {
00447         case 0:
00448             act ("$n rips apart your coin purse, spilling your gold!",
00449                  ch, NULL, victim, TO_VICT);
00450             act ("You slash apart $N's coin purse and gather his gold.",
00451                  ch, NULL, victim, TO_CHAR);
00452             act ("$N's coin purse is ripped apart!",
00453                  ch, NULL, victim, TO_NOTVICT);
00454             gold = victim->gold / 10;    /* steal 10% of his gold */
00455             victim->gold -= gold;
00456             ch->gold += gold;
00457             return TRUE;
00458 
00459         case 1:
00460             do_function (ch, &do_flee, "");
00461             return TRUE;
00462 
00463         default:
00464             return FALSE;
00465     }
00466 }
00467 
00468 /*
00469  * Core procedure for dragons.
00470  */
00471 bool dragon (CHAR_DATA * ch, char *spell_name)
00472 {
00473     CHAR_DATA *victim;
00474     CHAR_DATA *v_next;
00475     int sn;
00476 
00477     if (ch->position != POS_FIGHTING)
00478         return FALSE;
00479 
00480     for (victim = ch->in_room->people; victim != NULL; victim = v_next)
00481     {
00482         v_next = victim->next_in_room;
00483         if (victim->fighting == ch && number_bits (3) == 0)
00484             break;
00485     }
00486 
00487     if (victim == NULL)
00488         return FALSE;
00489 
00490     if ((sn = skill_lookup (spell_name)) < 0)
00491         return FALSE;
00492     (*skill_table[sn].spell_fun) (sn, ch->level, ch, victim, TARGET_CHAR);
00493     return TRUE;
00494 }
00495 
00496 
00497 
00498 /*
00499  * Special procedures for mobiles.
00500  */
00501 bool spec_breath_any (CHAR_DATA * ch)
00502 {
00503     if (ch->position != POS_FIGHTING)
00504         return FALSE;
00505 
00506     switch (number_bits (3))
00507     {
00508         case 0:
00509             return spec_breath_fire (ch);
00510         case 1:
00511         case 2:
00512             return spec_breath_lightning (ch);
00513         case 3:
00514             return spec_breath_gas (ch);
00515         case 4:
00516             return spec_breath_acid (ch);
00517         case 5:
00518         case 6:
00519         case 7:
00520             return spec_breath_frost (ch);
00521     }
00522 
00523     return FALSE;
00524 }
00525 
00526 
00527 
00528 bool spec_breath_acid (CHAR_DATA * ch)
00529 {
00530     return dragon (ch, "acid breath");
00531 }
00532 
00533 
00534 
00535 bool spec_breath_fire (CHAR_DATA * ch)
00536 {
00537     return dragon (ch, "fire breath");
00538 }
00539 
00540 
00541 
00542 bool spec_breath_frost (CHAR_DATA * ch)
00543 {
00544     return dragon (ch, "frost breath");
00545 }
00546 
00547 
00548 
00549 bool spec_breath_gas (CHAR_DATA * ch)
00550 {
00551     int sn;
00552 
00553     if (ch->position != POS_FIGHTING)
00554         return FALSE;
00555 
00556     if ((sn = skill_lookup ("gas breath")) < 0)
00557         return FALSE;
00558     (*skill_table[sn].spell_fun) (sn, ch->level, ch, NULL, TARGET_CHAR);
00559     return TRUE;
00560 }
00561 
00562 
00563 
00564 bool spec_breath_lightning (CHAR_DATA * ch)
00565 {
00566     return dragon (ch, "lightning breath");
00567 }
00568 
00569 
00570 
00571 bool spec_cast_adept (CHAR_DATA * ch)
00572 {
00573     CHAR_DATA *victim;
00574     CHAR_DATA *v_next;
00575 
00576     if (!IS_AWAKE (ch))
00577         return FALSE;
00578 
00579     for (victim = ch->in_room->people; victim != NULL; victim = v_next)
00580     {
00581         v_next = victim->next_in_room;
00582         if (victim != ch && can_see (ch, victim) && number_bits (1) == 0
00583             && !IS_NPC (victim) && victim->level < 11)
00584             break;
00585     }
00586 
00587     if (victim == NULL)
00588         return FALSE;
00589 
00590     switch (number_bits (4))
00591     {
00592         case 0:
00593             act ("$n utters the word 'abrazak'.", ch, NULL, NULL, TO_ROOM);
00594             spell_armor (skill_lookup ("armor"), ch->level, ch, victim,
00595                          TARGET_CHAR);
00596             return TRUE;
00597 
00598         case 1:
00599             act ("$n utters the word 'fido'.", ch, NULL, NULL, TO_ROOM);
00600             spell_bless (skill_lookup ("bless"), ch->level, ch, victim,
00601                          TARGET_CHAR);
00602             return TRUE;
00603 
00604         case 2:
00605             act ("$n utters the words 'judicandus noselacri'.", ch, NULL,
00606                  NULL, TO_ROOM);
00607             spell_cure_blindness (skill_lookup ("cure blindness"), ch->level,
00608                                   ch, victim, TARGET_CHAR);
00609             return TRUE;
00610 
00611         case 3:
00612             act ("$n utters the words 'judicandus dies'.", ch, NULL, NULL,
00613                  TO_ROOM);
00614             spell_cure_light (skill_lookup ("cure light"), ch->level, ch,
00615                               victim, TARGET_CHAR);
00616             return TRUE;
00617 
00618         case 4:
00619             act ("$n utters the words 'judicandus sausabru'.", ch, NULL, NULL,
00620                  TO_ROOM);
00621             spell_cure_poison (skill_lookup ("cure poison"), ch->level, ch,
00622                                victim, TARGET_CHAR);
00623             return TRUE;
00624 
00625         case 5:
00626             act ("$n utters the word 'candusima'.", ch, NULL, NULL, TO_ROOM);
00627             spell_refresh (skill_lookup ("refresh"), ch->level, ch, victim,
00628                            TARGET_CHAR);
00629             return TRUE;
00630 
00631         case 6:
00632             act ("$n utters the words 'judicandus eugzagz'.", ch, NULL, NULL,
00633                  TO_ROOM);
00634             spell_cure_disease (skill_lookup ("cure disease"), ch->level, ch,
00635                                 victim, TARGET_CHAR);
00636     }
00637 
00638     return FALSE;
00639 }
00640 
00641 
00642 
00643 bool spec_cast_cleric (CHAR_DATA * ch)
00644 {
00645     CHAR_DATA *victim;
00646     CHAR_DATA *v_next;
00647     char *spell;
00648     int sn;
00649 
00650     if (ch->position != POS_FIGHTING)
00651         return FALSE;
00652 
00653     for (victim = ch->in_room->people; victim != NULL; victim = v_next)
00654     {
00655         v_next = victim->next_in_room;
00656         if (victim->fighting == ch && number_bits (2) == 0)
00657             break;
00658     }
00659 
00660     if (victim == NULL)
00661         return FALSE;
00662 
00663     for (;;)
00664     {
00665         int min_level;
00666 
00667         switch (number_bits (4))
00668         {
00669             case 0:
00670                 min_level = 0;
00671                 spell = "blindness";
00672                 break;
00673             case 1:
00674                 min_level = 3;
00675                 spell = "cause serious";
00676                 break;
00677             case 2:
00678                 min_level = 7;
00679                 spell = "earthquake";
00680                 break;
00681             case 3:
00682                 min_level = 9;
00683                 spell = "cause critical";
00684                 break;
00685             case 4:
00686                 min_level = 10;
00687                 spell = "dispel evil";
00688                 break;
00689             case 5:
00690                 min_level = 12;
00691                 spell = "curse";
00692                 break;
00693             case 6:
00694                 min_level = 12;
00695                 spell = "change sex";
00696                 break;
00697             case 7:
00698                 min_level = 13;
00699                 spell = "flamestrike";
00700                 break;
00701             case 8:
00702             case 9:
00703             case 10:
00704                 min_level = 15;
00705                 spell = "harm";
00706                 break;
00707             case 11:
00708                 min_level = 15;
00709                 spell = "plague";
00710                 break;
00711             default:
00712                 min_level = 16;
00713                 spell = "dispel magic";
00714                 break;
00715         }
00716 
00717         if (ch->level >= min_level)
00718             break;
00719     }
00720 
00721     if ((sn = skill_lookup (spell)) < 0)
00722         return FALSE;
00723     (*skill_table[sn].spell_fun) (sn, ch->level, ch, victim, TARGET_CHAR);
00724     return TRUE;
00725 }
00726 
00727 bool spec_cast_judge (CHAR_DATA * ch)
00728 {
00729     CHAR_DATA *victim;
00730     CHAR_DATA *v_next;
00731     char *spell;
00732     int sn;
00733 
00734     if (ch->position != POS_FIGHTING)
00735         return FALSE;
00736 
00737     for (victim = ch->in_room->people; victim != NULL; victim = v_next)
00738     {
00739         v_next = victim->next_in_room;
00740         if (victim->fighting == ch && number_bits (2) == 0)
00741             break;
00742     }
00743 
00744     if (victim == NULL)
00745         return FALSE;
00746 
00747     spell = "high explosive";
00748     if ((sn = skill_lookup (spell)) < 0)
00749         return FALSE;
00750     (*skill_table[sn].spell_fun) (sn, ch->level, ch, victim, TARGET_CHAR);
00751     return TRUE;
00752 }
00753 
00754 
00755 
00756 bool spec_cast_mage (CHAR_DATA * ch)
00757 {
00758     CHAR_DATA *victim;
00759     CHAR_DATA *v_next;
00760     char *spell;
00761     int sn;
00762 
00763     if (ch->position != POS_FIGHTING)
00764         return FALSE;
00765 
00766     for (victim = ch->in_room->people; victim != NULL; victim = v_next)
00767     {
00768         v_next = victim->next_in_room;
00769         if (victim->fighting == ch && number_bits (2) == 0)
00770             break;
00771     }
00772 
00773     if (victim == NULL)
00774         return FALSE;
00775 
00776     for (;;)
00777     {
00778         int min_level;
00779 
00780         switch (number_bits (4))
00781         {
00782             case 0:
00783                 min_level = 0;
00784                 spell = "blindness";
00785                 break;
00786             case 1:
00787                 min_level = 3;
00788                 spell = "chill touch";
00789                 break;
00790             case 2:
00791                 min_level = 7;
00792                 spell = "weaken";
00793                 break;
00794             case 3:
00795                 min_level = 8;
00796                 spell = "teleport";
00797                 break;
00798             case 4:
00799                 min_level = 11;
00800                 spell = "colour spray";
00801                 break;
00802             case 5:
00803                 min_level = 12;
00804                 spell = "change sex";
00805                 break;
00806             case 6:
00807                 min_level = 13;
00808                 spell = "energy drain";
00809                 break;
00810             case 7:
00811             case 8:
00812             case 9:
00813                 min_level = 15;
00814                 spell = "fireball";
00815                 break;
00816             case 10:
00817                 min_level = 20;
00818                 spell = "plague";
00819                 break;
00820             default:
00821                 min_level = 20;
00822                 spell = "acid blast";
00823                 break;
00824         }
00825 
00826         if (ch->level >= min_level)
00827             break;
00828     }
00829 
00830     if ((sn = skill_lookup (spell)) < 0)
00831         return FALSE;
00832     (*skill_table[sn].spell_fun) (sn, ch->level, ch, victim, TARGET_CHAR);
00833     return TRUE;
00834 }
00835 
00836 
00837 
00838 bool spec_cast_undead (CHAR_DATA * ch)
00839 {
00840     CHAR_DATA *victim;
00841     CHAR_DATA *v_next;
00842     char *spell;
00843     int sn;
00844 
00845     if (ch->position != POS_FIGHTING)
00846         return FALSE;
00847 
00848     for (victim = ch->in_room->people; victim != NULL; victim = v_next)
00849     {
00850         v_next = victim->next_in_room;
00851         if (victim->fighting == ch && number_bits (2) == 0)
00852             break;
00853     }
00854 
00855     if (victim == NULL)
00856         return FALSE;
00857 
00858     for (;;)
00859     {
00860         int min_level;
00861 
00862         switch (number_bits (4))
00863         {
00864             case 0:
00865                 min_level = 0;
00866                 spell = "curse";
00867                 break;
00868             case 1:
00869                 min_level = 3;
00870                 spell = "weaken";
00871                 break;
00872             case 2:
00873                 min_level = 6;
00874                 spell = "chill touch";
00875                 break;
00876             case 3:
00877                 min_level = 9;
00878                 spell = "blindness";
00879                 break;
00880             case 4:
00881                 min_level = 12;
00882                 spell = "poison";
00883                 break;
00884             case 5:
00885                 min_level = 15;
00886                 spell = "energy drain";
00887                 break;
00888             case 6:
00889                 min_level = 18;
00890                 spell = "harm";
00891                 break;
00892             case 7:
00893                 min_level = 21;
00894                 spell = "teleport";
00895                 break;
00896             case 8:
00897                 min_level = 20;
00898                 spell = "plague";
00899                 break;
00900             default:
00901                 min_level = 18;
00902                 spell = "harm";
00903                 break;
00904         }
00905 
00906         if (ch->level >= min_level)
00907             break;
00908     }
00909 
00910     if ((sn = skill_lookup (spell)) < 0)
00911         return FALSE;
00912     (*skill_table[sn].spell_fun) (sn, ch->level, ch, victim, TARGET_CHAR);
00913     return TRUE;
00914 }
00915 
00916 
00917 bool spec_executioner (CHAR_DATA * ch)
00918 {
00919     char buf[MAX_STRING_LENGTH];
00920     CHAR_DATA *victim;
00921     CHAR_DATA *v_next;
00922     char *crime;
00923 
00924     if (!IS_AWAKE (ch) || ch->fighting != NULL)
00925         return FALSE;
00926 
00927     crime = "";
00928     for (victim = ch->in_room->people; victim != NULL; victim = v_next)
00929     {
00930         v_next = victim->next_in_room;
00931 
00932         if (!IS_NPC (victim) && IS_SET (victim->act, PLR_KILLER)
00933             && can_see (ch, victim))
00934         {
00935             crime = "KILLER";
00936             break;
00937         }
00938 
00939         if (!IS_NPC (victim) && IS_SET (victim->act, PLR_THIEF)
00940             && can_see (ch, victim))
00941         {
00942             crime = "THIEF";
00943             break;
00944         }
00945     }
00946 
00947     if (victim == NULL)
00948         return FALSE;
00949 
00950     sprintf (buf, "%s is a %s!  PROTECT THE INNOCENT!  MORE BLOOOOD!!!",
00951              victim->name, crime);
00952     REMOVE_BIT (ch->comm, COMM_NOSHOUT);
00953     do_function (ch, &do_yell, buf);
00954     multi_hit (ch, victim, TYPE_UNDEFINED);
00955     return TRUE;
00956 }
00957 
00958 
00959 
00960 bool spec_fido (CHAR_DATA * ch)
00961 {
00962     OBJ_DATA *corpse;
00963     OBJ_DATA *c_next;
00964     OBJ_DATA *obj;
00965     OBJ_DATA *obj_next;
00966 
00967     if (!IS_AWAKE (ch))
00968         return FALSE;
00969 
00970     for (corpse = ch->in_room->contents; corpse != NULL; corpse = c_next)
00971     {
00972         c_next = corpse->next_content;
00973         if (corpse->item_type != ITEM_CORPSE_NPC)
00974             continue;
00975 
00976         act ("$n savagely devours a corpse.", ch, NULL, NULL, TO_ROOM);
00977         for (obj = corpse->contains; obj; obj = obj_next)
00978         {
00979             obj_next = obj->next_content;
00980             obj_from_obj (obj);
00981             obj_to_room (obj, ch->in_room);
00982         }
00983         extract_obj (corpse);
00984         return TRUE;
00985     }
00986 
00987     return FALSE;
00988 }
00989 
00990 
00991 
00992 bool spec_guard (CHAR_DATA * ch)
00993 {
00994     char buf[MAX_STRING_LENGTH];
00995     CHAR_DATA *victim;
00996     CHAR_DATA *v_next;
00997     CHAR_DATA *ech;
00998     char *crime;
00999     int max_evil;
01000 
01001     if (!IS_AWAKE (ch) || ch->fighting != NULL)
01002         return FALSE;
01003 
01004     max_evil = 300;
01005     ech = NULL;
01006     crime = "";
01007 
01008     for (victim = ch->in_room->people; victim != NULL; victim = v_next)
01009     {
01010         v_next = victim->next_in_room;
01011 
01012         if (!IS_NPC (victim) && IS_SET (victim->act, PLR_KILLER)
01013             && can_see (ch, victim))
01014         {
01015             crime = "KILLER";
01016             break;
01017         }
01018 
01019         if (!IS_NPC (victim) && IS_SET (victim->act, PLR_THIEF)
01020             && can_see (ch, victim))
01021         {
01022             crime = "THIEF";
01023             break;
01024         }
01025 
01026         if (victim->fighting != NULL
01027             && victim->fighting != ch && victim->alignment < max_evil)
01028         {
01029             max_evil = victim->alignment;
01030             ech = victim;
01031         }
01032     }
01033 
01034     if (victim != NULL)
01035     {
01036         sprintf (buf, "%s is a %s!  PROTECT THE INNOCENT!!  BANZAI!!",
01037                  victim->name, crime);
01038         REMOVE_BIT (ch->comm, COMM_NOSHOUT);
01039         do_function (ch, &do_yell, buf);
01040         multi_hit (ch, victim, TYPE_UNDEFINED);
01041         return TRUE;
01042     }
01043 
01044     if (ech != NULL)
01045     {
01046         act ("$n screams 'PROTECT THE INNOCENT!!  BANZAI!!",
01047              ch, NULL, NULL, TO_ROOM);
01048         multi_hit (ch, ech, TYPE_UNDEFINED);
01049         return TRUE;
01050     }
01051 
01052     return FALSE;
01053 }
01054 
01055 
01056 
01057 bool spec_janitor (CHAR_DATA * ch)
01058 {
01059     OBJ_DATA *trash;
01060     OBJ_DATA *trash_next;
01061 
01062     if (!IS_AWAKE (ch))
01063         return FALSE;
01064 
01065     for (trash = ch->in_room->contents; trash != NULL; trash = trash_next)
01066     {
01067         trash_next = trash->next_content;
01068         if (!IS_SET (trash->wear_flags, ITEM_TAKE) || !can_loot (ch, trash))
01069             continue;
01070         if (trash->item_type == ITEM_DRINK_CON
01071             || trash->item_type == ITEM_TRASH || trash->cost < 10)
01072         {
01073             act ("$n picks up some trash.", ch, NULL, NULL, TO_ROOM);
01074             obj_from_room (trash);
01075             obj_to_char (trash, ch);
01076             return TRUE;
01077         }
01078     }
01079 
01080     return FALSE;
01081 }
01082 
01083 
01084 
01085 bool spec_mayor (CHAR_DATA * ch)
01086 {
01087     static const char open_path[] =
01088         "W3a3003b33000c111d0d111Oe333333Oe22c222112212111a1S.";
01089 
01090     static const char close_path[] =
01091         "W3a3003b33000c111d0d111CE333333CE22c222112212111a1S.";
01092 
01093     static const char *path;
01094     static int pos;
01095     static bool move;
01096 
01097     if (!move)
01098     {
01099         if (time_info.hour == 6)
01100         {
01101             path = open_path;
01102             move = TRUE;
01103             pos = 0;
01104         }
01105 
01106         if (time_info.hour == 20)
01107         {
01108             path = close_path;
01109             move = TRUE;
01110             pos = 0;
01111         }
01112     }
01113 
01114     if (ch->fighting != NULL)
01115         return spec_cast_mage (ch);
01116     if (!move || ch->position < POS_SLEEPING)
01117         return FALSE;
01118 
01119     switch (path[pos])
01120     {
01121         case '0':
01122         case '1':
01123         case '2':
01124         case '3':
01125             move_char (ch, path[pos] - '0', FALSE);
01126             break;
01127 
01128         case 'W':
01129             ch->position = POS_STANDING;
01130             act ("$n awakens and groans loudly.", ch, NULL, NULL, TO_ROOM);
01131             break;
01132 
01133         case 'S':
01134             ch->position = POS_SLEEPING;
01135             act ("$n lies down and falls asleep.", ch, NULL, NULL, TO_ROOM);
01136             break;
01137 
01138         case 'a':
01139             act ("$n says 'Hello Honey!'", ch, NULL, NULL, TO_ROOM);
01140             break;
01141 
01142         case 'b':
01143             act
01144                 ("$n says 'What a view!  I must do something about that dump!'",
01145                  ch, NULL, NULL, TO_ROOM);
01146             break;
01147 
01148         case 'c':
01149             act
01150                 ("$n says 'Vandals!  Youngsters have no respect for anything!'",
01151                  ch, NULL, NULL, TO_ROOM);
01152             break;
01153 
01154         case 'd':
01155             act ("$n says 'Good day, citizens!'", ch, NULL, NULL, TO_ROOM);
01156             break;
01157 
01158         case 'e':
01159             act ("$n says 'I hereby declare the city of Midgaard open!'",
01160                  ch, NULL, NULL, TO_ROOM);
01161             break;
01162 
01163         case 'E':
01164             act ("$n says 'I hereby declare the city of Midgaard closed!'",
01165                  ch, NULL, NULL, TO_ROOM);
01166             break;
01167 
01168         case 'O':
01169 /*    do_function(ch, &do_unlock, "gate" ); */
01170             do_function (ch, &do_open, "gate");
01171             break;
01172 
01173         case 'C':
01174             do_function (ch, &do_close, "gate");
01175 /*    do_function(ch, &do_lock, "gate" ); */
01176             break;
01177 
01178         case '.':
01179             move = FALSE;
01180             break;
01181     }
01182 
01183     pos++;
01184     return FALSE;
01185 }
01186 
01187 
01188 
01189 bool spec_poison (CHAR_DATA * ch)
01190 {
01191     CHAR_DATA *victim;
01192 
01193     if (ch->position != POS_FIGHTING
01194         || (victim = ch->fighting) == NULL
01195         || number_percent () > 2 * ch->level) return FALSE;
01196 
01197     act ("You bite $N!", ch, NULL, victim, TO_CHAR);
01198     act ("$n bites $N!", ch, NULL, victim, TO_NOTVICT);
01199     act ("$n bites you!", ch, NULL, victim, TO_VICT);
01200     spell_poison (gsn_poison, ch->level, ch, victim, TARGET_CHAR);
01201     return TRUE;
01202 }
01203 
01204 
01205 
01206 bool spec_thief (CHAR_DATA * ch)
01207 {
01208     CHAR_DATA *victim;
01209     CHAR_DATA *v_next;
01210     long gold, silver;
01211 
01212     if (ch->position != POS_STANDING)
01213         return FALSE;
01214 
01215     for (victim = ch->in_room->people; victim != NULL; victim = v_next)
01216     {
01217         v_next = victim->next_in_room;
01218 
01219         if (IS_NPC (victim)
01220             || victim->level >= LEVEL_IMMORTAL
01221             || number_bits (5) != 0 || !can_see (ch, victim))
01222             continue;
01223 
01224         if (IS_AWAKE (victim) && number_range (0, ch->level) == 0)
01225         {
01226             act ("You discover $n's hands in your wallet!",
01227                  ch, NULL, victim, TO_VICT);
01228             act ("$N discovers $n's hands in $S wallet!",
01229                  ch, NULL, victim, TO_NOTVICT);
01230             return TRUE;
01231         }
01232         else
01233         {
01234             gold =
01235                 victim->gold * UMIN (number_range (1, 20),
01236                                      ch->level / 2) / 100;
01237             gold = UMIN (gold, ch->level * ch->level * 10);
01238             ch->gold += gold;
01239             victim->gold -= gold;
01240             silver =
01241                 victim->silver * UMIN (number_range (1, 20),
01242                                        ch->level / 2) / 100;
01243             silver = UMIN (silver, ch->level * ch->level * 25);
01244             ch->silver += silver;
01245             victim->silver -= silver;
01246             return TRUE;
01247         }
01248     }
01249 
01250     return FALSE;
01251 }

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