SPECIAL.C
上传用户:kesirui
上传日期:2007-01-07
资源大小:263k
文件大小:48k
源码类别:

Internet/网络编程

开发平台:

WINDOWS

  1. /***************************************************************************
  2.  *  Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,        *
  3.  *  Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe.   *
  4.  *                                                                         *
  5.  *  Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael          *
  6.  *  Chastain, Michael Quan, and Mitchell Tse.                              *
  7.  *                                                                         *
  8.  *  In order to use any part of this Merc Diku Mud, you must comply with   *
  9.  *  both the original Diku license in 'license.doc' as well the Merc       *
  10.  *  license in 'license.txt'.  In particular, you may not remove either of *
  11.  *  these copyright notices.                                               *
  12.  *                                                                         *
  13.  *  Much time and thought has gone into this software and you are          *
  14.  *  benefitting.  We hope that you share your changes too.  What goes      *
  15.  *  around, comes around.                                                  *
  16.  ***************************************************************************/
  17. #if defined(macintosh)
  18. #include <types.h>
  19. #else
  20. #include <sys/types.h>
  21. #endif
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. #include <string.h>
  25. #include <time.h>
  26. #include "merc.h"
  27. #include <ctype.h> // @@@ Needed for spec_cast_from_list
  28. /*
  29.  * The following special functions are available for mobiles.
  30.  */
  31. DECLARE_SPEC_FUN( spec_breath_any );
  32. DECLARE_SPEC_FUN( spec_breath_acid );
  33. DECLARE_SPEC_FUN( spec_breath_fire );
  34. DECLARE_SPEC_FUN( spec_breath_frost );
  35. DECLARE_SPEC_FUN( spec_breath_gas );
  36. DECLARE_SPEC_FUN( spec_breath_lightning );
  37. DECLARE_SPEC_FUN( spec_cast_adept );
  38. DECLARE_SPEC_FUN( spec_cast_cleric );
  39. DECLARE_SPEC_FUN( spec_cast_judge );
  40. DECLARE_SPEC_FUN( spec_cast_mage );
  41. DECLARE_SPEC_FUN( spec_cast_undead );
  42. DECLARE_SPEC_FUN( spec_executioner );
  43. DECLARE_SPEC_FUN( spec_fido );
  44. DECLARE_SPEC_FUN( spec_guard );
  45. DECLARE_SPEC_FUN( spec_janitor );
  46. DECLARE_SPEC_FUN( spec_mayor );
  47. DECLARE_SPEC_FUN( spec_poison );
  48. DECLARE_SPEC_FUN( spec_thief );
  49. DECLARE_SPEC_FUN(       spec_cast_psionicist    );
  50. DECLARE_SPEC_FUN( spec_animated_dead    ); // @@@
  51. DECLARE_SPEC_FUN( spec_taxidermist    ); // @@@
  52. DECLARE_SPEC_FUN( spec_capn_swing    ); // @@@
  53. DECLARE_SPEC_FUN( spec_snake_charm ); // @@@
  54. DECLARE_SPEC_FUN( spec_hunger );
  55. DECLARE_SPEC_FUN( spec_cast_from_list ); // @@@ ###
  56. DECLARE_SPEC_FUN( spec_shopkeeper ); // @@@
  57. DECLARE_SPEC_FUN( spec_obj_bribe ); // @@@
  58. DECLARE_SPEC_FUN( spec_agg_no_object ); // @@@
  59. DECLARE_SPEC_FUN( spec_follow_mob ); // @@@
  60. DECLARE_SPEC_FUN( spec_generator ); // @@@
  61. DECLARE_SPEC_FUN( spec_defend_vs_agg ); // @@@
  62. DECLARE_SPEC_FUN( spec_agg_if_object ); // @@@
  63. DECLARE_SPEC_FUN( spec_circuit ); // @@@
  64. DECLARE_SPEC_FUN( spec_hatred ); // @@@
  65. /*
  66.  * Given a name, return the appropriate spec fun.
  67.  */
  68. SPEC_FUN *spec_lookup( const char *name )
  69. {
  70.     if ( !str_cmp( name, "spec_breath_any"   ) ) return spec_breath_any;
  71.     if ( !str_cmp( name, "spec_breath_acid"   ) ) return spec_breath_acid;
  72.     if ( !str_cmp( name, "spec_breath_fire"   ) ) return spec_breath_fire;
  73.     if ( !str_cmp( name, "spec_breath_frost"   ) ) return spec_breath_frost;
  74.     if ( !str_cmp( name, "spec_breath_gas"   ) ) return spec_breath_gas;
  75.     if ( !str_cmp( name, "spec_breath_lightning"  ) ) return
  76. spec_breath_lightning;
  77.     if ( !str_cmp( name, "spec_cast_adept"   ) ) return spec_cast_adept;
  78.     if ( !str_cmp( name, "spec_cast_cleric"   ) ) return spec_cast_cleric;
  79.     if ( !str_cmp( name, "spec_cast_judge"   ) ) return spec_cast_judge;
  80.     if ( !str_cmp( name, "spec_cast_mage"   ) ) return spec_cast_mage;
  81.     if ( !str_cmp( name, "spec_cast_undead"   ) ) return spec_cast_undead;
  82.     if ( !str_cmp( name, "spec_executioner"   ) ) return spec_executioner;
  83.     if ( !str_cmp( name, "spec_fido"   ) ) return spec_fido;
  84.     if ( !str_cmp( name, "spec_guard"   ) ) return spec_guard;
  85.     if ( !str_cmp( name, "spec_janitor"   ) ) return spec_janitor;
  86.     if ( !str_cmp( name, "spec_mayor"   ) ) return spec_mayor;
  87.     if ( !str_cmp( name, "spec_poison"   ) ) return spec_poison;
  88.     if ( !str_cmp( name, "spec_cast_psionicist"   ) ) return
  89.                                                         spec_cast_psionicist;
  90.                                                         
  91.     if ( !str_cmp( name, "spec_thief"   ) ) return spec_thief;
  92.     if ( !str_cmp( name, "spec_taxidermist"   ) ) return spec_taxidermist; // @@@
  93.     if ( !str_cmp( name, "spec_animated_dead"   ) ) return spec_animated_dead;
  94.     if ( !str_cmp( name, "spec_capn_swing"   ) ) return spec_capn_swing; // @@@
  95.     if ( !str_cmp( name, "spec_snake_charm"   ) ) return spec_snake_charm; // @@@
  96.     if ( !str_cmp( name, "spec_hunger"   ) ) return spec_hunger; // @@
  97.     if ( !str_cmp( name, "spec_cast_from_list" )) return spec_cast_from_list; // @@@ ###
  98.     if ( !str_cmp( name, "spec_shopkeeper" )) return spec_shopkeeper; // @@@ ###
  99.     if ( !str_cmp( name, "spec_obj_bribe" )) return spec_obj_bribe; // @@@ ###
  100.     if ( !str_cmp( name, "spec_agg_no_object" )) return spec_agg_no_object; // @@@ ###
  101.     if ( !str_cmp( name, "spec_follow_mob" )) return spec_follow_mob; // @@@
  102.     if ( !str_cmp( name, "spec_generator" )) return spec_generator; // @@@
  103.     if ( !str_cmp( name, "spec_defend_vs_agg" )) return spec_defend_vs_agg; // @@@
  104.     if ( !str_cmp( name, "spec_agg_if_object" )) return spec_agg_if_object; // @@@
  105.     if ( !str_cmp( name, "spec_circuit" )) return spec_circuit; // @@@
  106.     if ( !str_cmp( name, "spec_hatred" )) return spec_hatred; // @@@
  107.     return 0;
  108. }
  109. /*
  110.  * Core procedure for dragons.
  111.  */
  112. bool dragon( CHAR_DATA *ch, char *spell_name )
  113. {
  114.     CHAR_DATA *victim;
  115.     CHAR_DATA *v_next;
  116.     int sn;
  117.     if ( ch->position != POS_FIGHTING )
  118. return FALSE;
  119.     for ( victim = ch->in_room->people; victim != NULL; victim = v_next )
  120.     {
  121. v_next = victim->next_in_room;
  122. if ( victim->fighting == ch && number_bits( 2 ) == 0 )
  123.     break;
  124.     }
  125.     if ( victim == NULL )
  126. return FALSE;
  127.     if ( ( sn = skill_lookup( spell_name ) ) < 0 )
  128. return FALSE;
  129.     (*skill_table[sn].spell_fun) ( sn, ch->level, ch, victim );
  130.     return TRUE;
  131. }
  132. /*
  133.  * Special procedures for mobiles.
  134.  */
  135. bool spec_breath_any( CHAR_DATA *ch )
  136. {
  137.     if ( ch->position != POS_FIGHTING )
  138. return FALSE;
  139.     switch ( number_bits( 3 ) )
  140.     {
  141.     case 0: return spec_breath_fire ( ch );
  142.     case 1:
  143.     case 2: return spec_breath_lightning ( ch );
  144.     case 3: return spec_breath_gas ( ch );
  145.     case 4: return spec_breath_acid ( ch );
  146.     case 5:
  147.     case 6:
  148.     case 7: return spec_breath_frost ( ch );
  149.     }
  150.     return FALSE;
  151. }
  152. bool spec_breath_acid( CHAR_DATA *ch )
  153. {
  154.     return dragon( ch, "acid breath" );
  155. }
  156. bool spec_breath_fire( CHAR_DATA *ch )
  157. {
  158.     return dragon( ch, "fire breath" );
  159. }
  160. bool spec_breath_frost( CHAR_DATA *ch )
  161. {
  162.     return dragon( ch, "frost breath" );
  163. }
  164. bool spec_breath_gas( CHAR_DATA *ch )
  165. {
  166.     int sn;
  167.     if ( ch->position != POS_FIGHTING )
  168. return FALSE;
  169.     if ( ( sn = skill_lookup( "gas breath" ) ) < 0 )
  170. return FALSE;
  171.     (*skill_table[sn].spell_fun) ( sn, ch->level, ch, NULL );
  172.     return TRUE;
  173. }
  174. bool spec_breath_lightning( CHAR_DATA *ch )
  175. {
  176.     return dragon( ch, "lightning breath" );
  177. }
  178. bool spec_cast_adept( CHAR_DATA *ch )
  179. {
  180.     CHAR_DATA *victim;
  181.     CHAR_DATA *v_next;
  182.     if ( !IS_AWAKE(ch) )
  183. return FALSE;
  184.     for ( victim = ch->in_room->people; victim != NULL; victim = v_next )
  185.     {
  186. v_next = victim->next_in_room;
  187. if ( victim != ch && can_see( ch, victim ) && number_bits( 1 ) == 0 )
  188.     break;
  189.     }
  190.     if ( victim == NULL )
  191. return FALSE;
  192.     switch ( number_bits( 3 ) )
  193.     {
  194.     case 0:
  195. act( "$n utters the word 'tehctah'.", ch, NULL, NULL, TO_ROOM );
  196. spell_armor( skill_lookup( "armor" ), ch->level, ch, victim );
  197. return TRUE;
  198.     case 1:
  199. act( "$n utters the word 'nhak'.", ch, NULL, NULL, TO_ROOM );
  200. spell_bless( skill_lookup( "bless" ), ch->level, ch, victim );
  201. return TRUE;
  202.     case 2:
  203. act( "$n utters the word 'yeruf'.", ch, NULL, NULL, TO_ROOM );
  204. spell_cure_blindness( skill_lookup( "cure blindness" ),
  205.     ch->level, ch, victim );
  206. return TRUE;
  207.     case 3:
  208. act( "$n utters the word 'garf'.", ch, NULL, NULL, TO_ROOM );
  209. spell_cure_light( skill_lookup( "cure light" ),
  210.     ch->level, ch, victim );
  211. return TRUE;
  212.     case 4:
  213. act( "$n utters the words 'rozar'.", ch, NULL, NULL, TO_ROOM );
  214. spell_cure_poison( skill_lookup( "cure poison" ),
  215.     ch->level, ch, victim );
  216. return TRUE;
  217.     case 5:
  218. act( "$n utters the words 'nadroj'.", ch, NULL, NULL, TO_ROOM );
  219. spell_refresh( skill_lookup( "refresh" ), ch->level, ch, victim );
  220. return TRUE;
  221.     }
  222.     return FALSE;
  223. }
  224. bool spec_cast_cleric( CHAR_DATA *ch )
  225. {
  226.     CHAR_DATA *victim;
  227.     CHAR_DATA *v_next;
  228.     char *spell;
  229.     int sn;
  230.     if ( ch->position != POS_FIGHTING )
  231. return FALSE;
  232.     for ( victim = ch->in_room->people; victim != NULL; victim = v_next )
  233.     {
  234. v_next = victim->next_in_room;
  235. if ( victim->fighting == ch && number_bits( 2 ) == 0 )
  236.     break;
  237.     }
  238.     if ( victim == NULL )
  239. return FALSE;
  240.     for ( ;; )
  241.     {
  242. int min_level;
  243. switch ( number_bits( 4 ) )
  244. {
  245. case  0: min_level =  0; spell = "blindness";      break;
  246. case  1: min_level =  3; spell = "cause serious";  break;
  247. case  2: min_level =  7; spell = "earthquake";     break;
  248. case  3: min_level =  9; spell = "cause critical"; break;
  249. case  4: min_level = 10; spell = "dispel evil";    break;
  250. case  5: min_level = 12; spell = "curse";          break;
  251. case  6: min_level = 12; spell = "change sex";     break;
  252. case  7: min_level = 13; spell = "flamestrike";    break;
  253. case  8:
  254. case  9:
  255. case 10: min_level = 15; spell = "harm";           break;
  256. default: min_level = 16; spell = "dispel magic";   break;
  257. }
  258. if ( ch->level >= min_level )
  259.     break;
  260.     }
  261.     if ( ( sn = skill_lookup( spell ) ) < 0 )
  262. return FALSE;
  263.     (*skill_table[sn].spell_fun) ( sn, ch->level, ch, victim );
  264.     return TRUE;
  265. }
  266. bool spec_cast_judge( CHAR_DATA *ch )
  267. {
  268.     CHAR_DATA *victim;
  269.     CHAR_DATA *v_next;
  270.     char *spell;
  271.     int sn;
  272.     if ( ch->position != POS_FIGHTING )
  273. return FALSE;
  274.     for ( victim = ch->in_room->people; victim != NULL; victim = v_next )
  275.     {
  276. v_next = victim->next_in_room;
  277. if ( victim->fighting == ch && number_bits( 2 ) == 0 )
  278.     break;
  279.     }
  280.     if ( victim == NULL )
  281. return FALSE;
  282.     spell = "high explosive";
  283.     if ( ( sn = skill_lookup( spell ) ) < 0 )
  284. return FALSE;
  285.     (*skill_table[sn].spell_fun) ( sn, ch->level, ch, victim );
  286.     return TRUE;
  287. }
  288. bool spec_cast_mage( CHAR_DATA *ch )
  289. {
  290.     CHAR_DATA *victim;
  291.     CHAR_DATA *v_next;
  292.     char *spell;
  293.     int sn;
  294.     if ( ch->position != POS_FIGHTING )
  295. return FALSE;
  296.     for ( victim = ch->in_room->people; victim != NULL; victim = v_next )
  297.     {
  298. v_next = victim->next_in_room;
  299. if ( victim->fighting == ch && number_bits( 2 ) == 0 )
  300.     break;
  301.     }
  302.     if ( victim == NULL )
  303. return FALSE;
  304.     for ( ;; )
  305.     {
  306. int min_level;
  307. switch ( number_bits( 4 ) )
  308. {
  309. case  0: min_level =  0; spell = "blindness";      break;
  310. case  1: min_level =  3; spell = "chill touch";    break;
  311. case  2: min_level =  7; spell = "weaken";         break;
  312. case  3: min_level =  8; spell = "teleport";       break;
  313. case  4: min_level = 11; spell = "colour spray";   break;
  314. case  5: min_level = 12; spell = "change sex";     break;
  315. case  6: min_level = 13; spell = "energy drain";   break;
  316. case  7:
  317. case  8:
  318. case  9: min_level = 15; spell = "fireball";       break;
  319. default: min_level = 20; spell = "acid blast";     break;
  320. }
  321. if ( ch->level >= min_level )
  322.     break;
  323.     }
  324.     if ( ( sn = skill_lookup( spell ) ) < 0 )
  325. return FALSE;
  326.     (*skill_table[sn].spell_fun) ( sn, ch->level, ch, victim );
  327.     return TRUE;
  328. }
  329. bool spec_cast_undead( CHAR_DATA *ch )
  330. {
  331.     CHAR_DATA *victim;
  332.     CHAR_DATA *v_next;
  333.     char *spell;
  334.     int sn;
  335.     if ( ch->position != POS_FIGHTING )
  336. return FALSE;
  337.     for ( victim = ch->in_room->people; victim != NULL; victim = v_next )
  338.     {
  339. v_next = victim->next_in_room;
  340. if ( victim->fighting == ch && number_bits( 2 ) == 0 )
  341.     break;
  342.     }
  343.     if ( victim == NULL )
  344. return FALSE;
  345.     for ( ;; )
  346.     {
  347. int min_level;
  348. switch ( number_bits( 4 ) )
  349. {
  350. case  0: min_level =  0; spell = "curse";          break;
  351. case  1: min_level =  3; spell = "weaken";         break;
  352. case  2: min_level =  6; spell = "chill touch";    break;
  353. case  3: min_level =  9; spell = "blindness";      break;
  354. case  4: min_level = 12; spell = "poison";         break;
  355. case  5: min_level = 15; spell = "energy drain";   break;
  356. case  6: min_level = 18; spell = "harm";           break;
  357. case  7: min_level = 21; spell = "teleport";       break;
  358. default: min_level = 24; spell = "gate";           break;
  359. }
  360. if ( ch->level >= min_level )
  361.     break;
  362.     }
  363.     if ( ( sn = skill_lookup( spell ) ) < 0 )
  364. return FALSE;
  365.     (*skill_table[sn].spell_fun) ( sn, ch->level, ch, victim );
  366.     return TRUE;
  367. }
  368. bool spec_executioner( CHAR_DATA *ch )
  369. {
  370.     char buf[MAX_STRING_LENGTH];
  371.     CHAR_DATA *victim;
  372.     CHAR_DATA *v_next;
  373.     char *crime;
  374.     if ( !IS_AWAKE(ch) || ch->fighting != NULL )
  375. return FALSE;
  376.     crime = "";
  377.     for ( victim = ch->in_room->people; victim != NULL; victim = v_next )
  378.     {
  379. v_next = victim->next_in_room;
  380. if ( !IS_NPC(victim) && IS_SET(victim->act, PLR_KILLER) )
  381.     { crime = "KILLER"; break; }
  382. if ( !IS_NPC(victim) && IS_SET(victim->act, PLR_THIEF) )
  383.     { crime = "THIEF"; break; }
  384.     }
  385.     if ( victim == NULL )
  386. return FALSE;
  387.     sprintf( buf, "%s is a %s!  PROTECT THE INNOCENT!  MORE BLOOOOD!!!",
  388. victim->name, crime );
  389.     do_shout( ch, buf );
  390.     multi_hit( ch, victim, TYPE_UNDEFINED );
  391.     char_to_room( create_mobile( get_mob_index(MOB_VNUM_CITYGUARD) ),
  392. ch->in_room );
  393.     char_to_room( create_mobile( get_mob_index(MOB_VNUM_CITYGUARD) ),
  394. ch->in_room );
  395.     return TRUE;
  396. }
  397. bool spec_fido( CHAR_DATA *ch )
  398. {
  399.     OBJ_DATA *corpse;
  400.     OBJ_DATA *c_next;
  401.     OBJ_DATA *obj;
  402.     OBJ_DATA *obj_next;
  403.     if ( !IS_AWAKE(ch) )
  404. return FALSE;
  405.     for ( corpse = ch->in_room->contents; corpse != NULL; corpse = c_next )
  406.     {
  407. c_next = corpse->next_content;
  408. if ( corpse->item_type != ITEM_CORPSE_NPC )
  409.     continue;
  410. act( "$n savagely devours a corpse.", ch, NULL, NULL, TO_ROOM );
  411. for ( obj = corpse->contains; obj; obj = obj_next )
  412. {
  413.     obj_next = obj->next_content;
  414.     obj_from_obj( obj );
  415.     obj_to_room( obj, ch->in_room );
  416. }
  417. extract_obj( corpse );
  418. return TRUE;
  419.     }
  420.     return FALSE;
  421. }
  422. bool spec_guard( CHAR_DATA *ch )
  423. {
  424.     char buf[MAX_STRING_LENGTH];
  425.     CHAR_DATA *victim;
  426.     CHAR_DATA *v_next;
  427.     CHAR_DATA *ech;
  428.     char *crime;
  429.     int max_evil;
  430.     if ( !IS_AWAKE(ch) || ch->fighting != NULL )
  431. return FALSE;
  432.     max_evil = 300;
  433.     ech      = NULL;
  434.     crime    = "";
  435.     for ( victim = ch->in_room->people; victim != NULL; victim = v_next )
  436.     {
  437. v_next = victim->next_in_room;
  438. if ( !IS_NPC(victim) && IS_SET(victim->act, PLR_KILLER) )
  439.     { crime = "KILLER"; break; }
  440. if ( !IS_NPC(victim) && IS_SET(victim->act, PLR_THIEF) )
  441.     { crime = "THIEF"; break; }
  442. if ( victim->fighting != NULL
  443. &&   victim->fighting != ch
  444. &&   victim->alignment < max_evil )
  445. {
  446.     max_evil = victim->alignment;
  447.     ech      = victim;
  448. }
  449.     }
  450.     if ( victim != NULL )
  451.     {
  452. sprintf( buf, "%s is a %s!  PROTECT THE INNOCENT!!  BANZAI!!",
  453.     victim->name, crime );
  454. do_shout( ch, buf );
  455. multi_hit( ch, victim, TYPE_UNDEFINED );
  456. return TRUE;
  457.     }
  458.     if ( ech != NULL )
  459.     {
  460. act( "$n screams 'PROTECT THE INNOCENT!!  BANZAI!!",
  461.     ch, NULL, NULL, TO_ROOM );
  462. multi_hit( ch, ech, TYPE_UNDEFINED );
  463. return TRUE;
  464.     }
  465.     return FALSE;
  466. }
  467. bool spec_janitor( CHAR_DATA *ch )
  468. {
  469.     OBJ_DATA *trash;
  470.     OBJ_DATA *trash_next;
  471.     if ( !IS_AWAKE(ch) )
  472. return FALSE;
  473.     for ( trash = ch->in_room->contents; trash != NULL; trash = trash_next )
  474.     {
  475. trash_next = trash->next_content;
  476. if ( !IS_SET( trash->wear_flags, ITEM_TAKE ) )
  477.     continue;
  478. if ( trash->item_type == ITEM_DRINK_CON
  479. ||   trash->item_type == ITEM_TRASH
  480. ||   trash->cost < 10 )
  481. {
  482.     act( "$n picks up some trash.", ch, NULL, NULL, TO_ROOM );
  483.     obj_from_room( trash );
  484.     obj_to_char( trash, ch );
  485.     return TRUE;
  486. }
  487.     }
  488.     return FALSE;
  489. }
  490. bool spec_mayor( CHAR_DATA *ch )
  491. {
  492.     static const char open_path[] =
  493. "W3a3003b33000c111d0d111Oe333333Oe22c222112212111a1S.";
  494.     static const char close_path[] =
  495. "W3a3003b33000c111d0d111CE333333CE22c222112212111a1S.";
  496.     static const char *path;
  497.     static int pos;
  498.     static bool move;
  499.     if ( !move )
  500.     {
  501. if ( time_info.hour ==  6 )
  502. {
  503.     path = open_path;
  504.     move = TRUE;
  505.     pos  = 0;
  506. }
  507. if ( time_info.hour == 20 )
  508. {
  509.     path = close_path;
  510.     move = TRUE;
  511.     pos  = 0;
  512. }
  513.     }
  514.     if ( ch->fighting != NULL )
  515. return spec_cast_cleric( ch );
  516.     if ( !move || ch->position < POS_SLEEPING )
  517. return FALSE;
  518.     switch ( path[pos] )
  519.     {
  520.     case '0':
  521.     case '1':
  522.     case '2':
  523.     case '3':
  524. move_char( ch, path[pos] - '0' );
  525. break;
  526.     case 'W':
  527. ch->position = POS_STANDING;
  528. act( "$n awakens and groans loudly.", ch, NULL, NULL, TO_ROOM );
  529. break;
  530.     case 'S':
  531. ch->position = POS_SLEEPING;
  532. act( "$n lies down and falls asleep.", ch, NULL, NULL, TO_ROOM );
  533. break;
  534.     case 'a':
  535. act( "$n says 'Hello Honey!'", ch, NULL, NULL, TO_ROOM );
  536. break;
  537.     case 'b':
  538. act( "$n says 'What a view!  I must do something about that dump!'",
  539.     ch, NULL, NULL, TO_ROOM );
  540. break;
  541.     case 'c':
  542. act( "$n says 'Vandals!  Youngsters have no respect for anything!'",
  543.     ch, NULL, NULL, TO_ROOM );
  544. break;
  545.     case 'd':
  546. act( "$n says 'Good day, citizens!'", ch, NULL, NULL, TO_ROOM );
  547. break;
  548.     case 'e':
  549. act( "$n says 'I hereby declare the city of Midgaard open!'",
  550.     ch, NULL, NULL, TO_ROOM );
  551. break;
  552.     case 'E':
  553. act( "$n says 'I hereby declare the city of Midgaard closed!'",
  554.     ch, NULL, NULL, TO_ROOM );
  555. break;
  556.     case 'O':
  557. do_unlock( ch, "gate" );
  558. do_open( ch, "gate" );
  559. break;
  560.     case 'C':
  561. do_close( ch, "gate" );
  562. do_lock( ch, "gate" );
  563. break;
  564.     case '.' :
  565. move = FALSE;
  566. break;
  567.     }
  568.     pos++;
  569.     return FALSE;
  570. }
  571. bool spec_poison( CHAR_DATA *ch )
  572. {
  573.     CHAR_DATA *victim;
  574.     if ( ch->position != POS_FIGHTING
  575.     || ( victim = ch->fighting ) == NULL
  576.     ||   number_percent( ) > 2 * ch->level )
  577. return FALSE;
  578.     act( "You bite $N!",  ch, NULL, victim, TO_CHAR    );
  579.     act( "$n bites $N!",  ch, NULL, victim, TO_NOTVICT );
  580.     act( "$n bites you!", ch, NULL, victim, TO_VICT    );
  581.     spell_poison( gsn_poison, ch->level, ch, victim );
  582.     return TRUE;
  583. }
  584. bool spec_thief( CHAR_DATA *ch )
  585. {
  586.     CHAR_DATA *victim;
  587.     CHAR_DATA *v_next;
  588.     int gold;
  589.     if ( ch->position != POS_STANDING )
  590. return FALSE;
  591.     for ( victim = ch->in_room->people; victim != NULL; victim = v_next )
  592.     {
  593. v_next = victim->next_in_room;
  594. if ( IS_NPC(victim)
  595. ||   victim->level >= LEVEL_IMMORTAL
  596. ||   number_bits( 2 ) != 0
  597. ||   !can_see( ch, victim ) ) /* Thx Glop */
  598.     continue;
  599. if ( IS_AWAKE(victim) && number_range( 0, ch->level ) == 0 )
  600. {
  601.     act( "You discover $n's hands in your wallet!",
  602. ch, NULL, victim, TO_VICT );
  603.     act( "$N discovers $n's hands in $S wallet!",
  604. ch, NULL, victim, TO_NOTVICT );
  605.     return TRUE;
  606. }
  607. else
  608. {
  609.     gold = victim->gold * number_range( 1, 20 ) / 100;
  610.     ch->gold     += 7 * gold / 8;
  611.     victim->gold -= gold;
  612.     return TRUE;
  613. }
  614.     }
  615.     return FALSE;
  616. }
  617. // @@@
  618. bool spec_taxidermist( CHAR_DATA *ch )
  619. {
  620.     OBJ_DATA *inv;
  621.     int sn;
  622.     if ( ch->position != POS_STANDING )
  623. return FALSE;
  624.     if ( ch->pIndexData->pShop == 0 ||
  625.          time_info.hour < ch->pIndexData->pShop->open_hour ||
  626.          time_info.hour > ch->pIndexData->pShop->close_hour )
  627.        return FALSE;
  628.     for ( inv = ch->carrying; inv != NULL; inv = inv->next_content )
  629.     {
  630.     if (inv->item_type == ITEM_CORPSE_NPC)
  631.        {
  632.        if ( ( sn = skill_lookup( "make purse" ) ) >= 0 )
  633.           (*skill_table[sn].spell_fun) ( sn, ch->level, ch, inv );
  634.        return TRUE;
  635.        }
  636.     else if (inv->wear_loc == WEAR_NONE && number_percent() < 5)
  637.        {
  638.        act( "$n suggests you buy $p.", ch, inv, NULL, TO_ROOM );
  639.        return TRUE;
  640.        }
  641.     }
  642.     return FALSE;
  643. }
  644. // @@@
  645. /* The start and end piers are hard-coded into Captain Swing.  If we need more
  646.    ferries we will have to give him something that encodes the vnums and the
  647.    current ferry state information */
  648. #define ROOM_VNUM_START 5950
  649. #define ROOM_VNUM_FINISH 5953
  650. #define OBJ_VNUM_TICKET 5953
  651. bool spec_capn_swing( CHAR_DATA *ch )
  652. {
  653.     static int state;                   /* Boat's current state, 0-11 */
  654.     static EXIT_DATA *exit_to_boat;     /* A 'doorless' door onto the boat,
  655.                                            disconnected when the ferry leaves
  656.                                            and reconnected when it returns. */
  657.     int has_ticket;                     /* Does the PC/Mob have a ticket? */
  658.     CHAR_DATA *passenger;               /* A passenger */
  659.     ROOM_INDEX_DATA *boat = ch->in_room->exit[1]->to_room; /* The boat room */
  660.     OBJ_DATA *obj;                      /* An inv object */
  661.     CHAR_DATA *sea_hag;                 /* A mob which boards the ship at sea */
  662.     CHAR_DATA *person;                  /* A person standing on the dock */
  663.     int i;
  664.     /* @@@ */
  665.     for (i = 0; i < 10; i++)
  666.        obj_to_room( create_money( 50 ),  boat);
  667.     switch(state) {
  668.     case 0: /* Check to see if anyone is on the boat */
  669.        for ( passenger = boat->people;
  670.              passenger;
  671.              passenger = passenger->next_in_room )
  672.           {
  673.           state = 1;
  674.           send_to_char("Captain Swing says 'All aboard?'.nr", passenger);
  675.           }
  676.        break;
  677.     case 1: /* Warn chars on boat they are going to Mahn-Tor */
  678.        state = 0;
  679.        for ( passenger = boat->people;
  680.              passenger;
  681.              passenger = passenger->next_in_room )
  682.           {
  683.           state = 2;
  684.           send_to_char("Captain Swing says 'Last call for Mahn-Tor!'.nr",
  685.              passenger);
  686.           }
  687.        break;
  688.     case 2: /* Check for tickets and leave the dock */
  689.        state = 0;
  690.        for ( passenger = boat->people;
  691.              passenger;
  692.              passenger = passenger->next_in_room )
  693.           {
  694.           /* We can't require immortals to have a ticket, as they might not
  695.              be able to afford one, and also might be able to kill Swing,
  696.              leaving the boat adrift until he repops. */
  697.           if ( IS_IMMORTAL(passenger) )
  698.              {
  699.              has_ticket = 1;
  700.              state = 3;
  701.              send_to_char( "Captain Swing has comped you.nr",
  702.                 passenger );
  703.              }
  704.           else
  705.              {
  706.              /* Check for a valid ferry ticket. */
  707.              has_ticket = 0;
  708.              for ( obj = passenger->carrying; obj; obj = obj->next_content )
  709.                 {
  710.                 if ( obj->pIndexData->vnum == OBJ_VNUM_TICKET )
  711.                 {
  712.                    has_ticket = 1;
  713.                    state = 3;
  714.                    extract_obj( obj );
  715.                    send_to_char( "Captain Swing collects your ticket.nr",
  716.                       passenger );
  717.                    }
  718.                 }
  719.              }
  720.           if (!has_ticket)
  721.              {
  722.              send_to_char( "Captain Swing notices you have no ticket and hurls"
  723.                            " you into the air.nr", passenger );
  724.              act( "$n is hurtled off by an angry Captain Swing.",
  725.                 passenger, NULL, NULL, TO_ROOM );
  726.              char_from_room( passenger );
  727.              char_to_room( passenger, boat->exit[3]->to_room );
  728.              act( "$n crashes to the ground.", passenger, NULL, NULL, TO_ROOM );
  729.              send_to_char( "You hit the ground, hard!nr", passenger);
  730.              do_look( passenger, "auto" );
  731.              }
  732.           }
  733.        /* Close and lock the pick-proof door, to prevent players from trying to
  734.           kill Captain Swing.  They shouldn't even be able to see him unless
  735.           they teleport into his room... */
  736.        SET_BIT(boat->exit[3]->exit_info, EX_CLOSED|EX_LOCKED);
  737.        for ( passenger = boat->people;
  738.              passenger;
  739.              passenger = passenger->next_in_room )
  740.           send_to_char("Captain Swing has secured the door.nr"
  741.              "You feel the boat begin to rock as it leaves the dock.nr",
  742.              passenger);
  743.        /* Remove the boat from the dock's list of exits */
  744.        exit_to_boat = get_room_index( ROOM_VNUM_START )->exit[1];
  745.        get_room_index( ROOM_VNUM_START )->exit[1] = 0;
  746.        /* Let people on the dock know the boat has left without them */
  747.        for ( person = get_room_index( ROOM_VNUM_START )->people;
  748.              person;
  749.              person = person->next_in_room )
  750.           send_to_char("A ship pulls away from the dock.nr", person);
  751.        state = 3;
  752.        break;
  753.     case 3: /* Boring.  Makes the boat ride take a long time */
  754.     case 4:
  755.     case 5:
  756.     case 6:
  757.     case 8:
  758.     case 9:
  759.        for ( passenger = boat->people;
  760.              passenger;
  761.              passenger = passenger->next_in_room )
  762.           send_to_char("You begin to feel seasick as"
  763.              " the ferry rocks up and down.nr", passenger);
  764.        state++;
  765.        break;
  766.     case 7: /* A sea monster invades the ship! */
  767.        if ( number_percent() < 33 )
  768.           {
  769.           sea_hag = create_mobile( get_mob_index(7041) );
  770.           char_to_room( sea_hag, boat );
  771.           act( "The porthole opens and $n climbs through!", sea_hag, NULL, NULL,
  772.              TO_ROOM );
  773.           }
  774.        state++;
  775.        break;
  776.     case 10: /* The boat lands at the far pier.  (There is no way to board) */
  777.        REMOVE_BIT(boat->exit[3]->exit_info, EX_CLOSED|EX_LOCKED);
  778.        boat->exit[3]->to_room = get_room_index( ROOM_VNUM_FINISH );
  779.        for ( passenger = boat->people;
  780.              passenger;
  781.              passenger = passenger->next_in_room )
  782.           send_to_char("You feel a gentle thud as the ferry docks.nr"
  783.              "Captain Swing opens the door and motions you to leave.nr",
  784.              passenger);
  785.        for ( person = get_room_index( ROOM_VNUM_FINISH )->people;
  786.              person;
  787.              person = person->next_in_room )
  788.           send_to_char("A ship pulls into the dock.nr", person);
  789.        state = 11;
  790.        break;
  791.     case 11: /* Get passengers off the boat so it can return to Midgaard */
  792.        state = 0;
  793.        for ( passenger = boat->people; passenger;
  794.                                          passenger = passenger->next_in_room )
  795.           {
  796.           /* The boat will not return until all passengers debark */
  797.           state = 11;
  798.           send_to_char("Captain Swing reminds you to debark promptly.nr",
  799.              passenger);
  800.           }
  801.        /* Did the boat return? */
  802.        if (state == 0)
  803.           {
  804.           /* The boat is now back at the start pier */
  805.           boat->exit[3]->to_room = get_room_index( ROOM_VNUM_START );
  806.           /* Add the boat to the dock's list of exits */
  807.           get_room_index( ROOM_VNUM_START )->exit[1] = exit_to_boat;
  808.           for ( person = get_room_index( ROOM_VNUM_START )->people;
  809.                 person;
  810.                 person = person->next_in_room )
  811.              send_to_char("A ship pulls into the dock.nr", person);
  812.           }
  813.        break;
  814.     }
  815.     return FALSE;
  816. }
  817. bool spec_snake_charm( CHAR_DATA *ch )
  818. {
  819.     CHAR_DATA *victim;
  820.     CHAR_DATA *v_next;
  821.     char *spell;
  822.     int sn;
  823.     if ( ch->position != POS_FIGHTING )
  824.        {
  825.        switch ( number_bits( 3 ) ) {
  826.        case 0:
  827.           do_order( ch, "all sing charmer" ); /* a chance to get free here */
  828.           break;
  829.        case 1:
  830.           do_order( ch,
  831.              "all chat 'The snake charmer area is pretty cool.  "
  832.              "I'm getting a lot of experience really fast!" );
  833.           break;
  834.        case 2:
  835.           do_order( ch,
  836.              "all chat 'YES!  I just got 327xp for killing the snake charmer!");
  837.           break;
  838.        case 3:
  839.           do_order( ch, "all remove dagger" );
  840.           do_order( ch, "all give dagger charmer" );
  841.           break;
  842.        case 4:
  843.           do_order( ch, "all remove sword" );
  844.           do_order( ch, "all give sword charmer" );
  845.           break;
  846.        case 5:
  847.           do_order( ch, "all remove mace" );
  848.           do_order( ch, "all give mace charmer" );
  849.           break;
  850.        case 6:
  851.           do_order( ch, "all drop all" );
  852.           break;
  853.        case 7:
  854.           do_order( ch, "all cast 'cure light' charmer" );
  855.           break;
  856.        };
  857.        return TRUE;
  858.        }
  859.     for ( victim = ch->in_room->people; victim != NULL; victim = v_next )
  860.     {
  861. v_next = victim->next_in_room;
  862. if ( victim->fighting == ch && number_bits( 2 ) == 0 )
  863.     break;
  864.     }
  865.     if ( victim == NULL )
  866. return FALSE;
  867. act( "$n begins playing a new, beautiful song.", ch, NULL, NULL, TO_ROOM );
  868.     spell_charm_person(gsn_charm_person, ch->level, ch, victim );
  869.     if (IS_AFFECTED(victim, AFF_CHARM))
  870.        stop_fighting( victim, TRUE );
  871. //       do_flee( victim, "" );
  872. //       do_rest( victim, "" );
  873. //       do_order( ch, "all rest" );
  874.     return TRUE;
  875. }
  876. bool spec_hunger( CHAR_DATA *ch )
  877. {
  878.     CHAR_DATA *victim;
  879.     OBJ_DATA *obj;
  880.     OBJ_DATA *obj_next;
  881.     if ( !IS_AWAKE(ch) )
  882. return FALSE;
  883.     for ( victim = ch->in_room->people; victim; victim = victim->next_in_room )
  884. if ( number_bits( 2 ) == 0 )
  885.     break;
  886.     if ( victim == NULL )
  887. return FALSE;
  888.     if ( !IS_NPC(victim) )
  889.        victim->pcdata->condition[COND_FULL] = 0;
  890.     for ( obj = victim->carrying; obj; obj = obj_next )
  891.        {
  892.        obj_next = obj->next_content;
  893.        if ( obj->item_type == ITEM_FOOD )
  894.           {
  895.           extract_obj( obj );
  896.           act( "Chomp!", ch, NULL, NULL, TO_ROOM );
  897.           }
  898.        }
  899.     act( "$n looks a little healthier.", ch, NULL, NULL, TO_ROOM );
  900.     return TRUE;
  901. }
  902. // @@@ ###
  903. /*
  904.    spec_cast_from_list-
  905.       I copied the basic structure from spec_cast_undead.  The first time any
  906.       mobile with this vnum gets pulsed, the cargo for this mobile vnum is
  907.       initialized.  From then on, the mobile will cast spells in it's cargo.
  908. */
  909. struct string_cargo_struct {
  910.    int ncount;
  911.    char *string_list[16];      /* Allow up to 16 spells / mobile vnum */
  912. };
  913. void check_init_cargo( CHAR_DATA *ch )
  914. {
  915.     struct string_cargo_struct *cls;
  916.     if (ch->pIndexData->cargo == 0)
  917.        {
  918.        /* remove the @ from the mobile's description */
  919.        char *q = strchr(ch->pIndexData->description, '@');
  920.        int ncount = 0;
  921.        // Allocate the cargo
  922.        ch->pIndexData->cargo = cls = alloc_perm( sizeof (*cls) );
  923.        /* Is there a spell cargo? */
  924.        if (q)
  925.           {
  926.           /* count the spells */
  927.           while (*q)
  928.              {
  929.              *q++ = '';  /* Break descr after @ into spell text */
  930.              while (isspace(*q))
  931.                 q++;
  932.              if (*q)
  933.                 {
  934.                 if (ncount < 16)
  935.                    cls->string_list[ncount++] = q;
  936.                 while (*q && *q != 'n')
  937. //                   {
  938. //                   if (*q == '_') /* fix _ in spell names to a space */
  939. //                      *q = ' ';
  940.                    q++;
  941. //                   }
  942.                 }
  943.              }
  944.           }
  945.        cls->ncount = ncount;
  946.        }
  947. }
  948. bool spec_cast_from_list( CHAR_DATA *ch )
  949. {
  950.     CHAR_DATA *victim;
  951.     CHAR_DATA *v_next;
  952.     char *spell;
  953.     int sn;
  954.     struct string_cargo_struct *cls;
  955.     int nwhich;
  956.     /* Do we need to initialize cargo? */
  957.     check_init_cargo(ch);
  958.     cls = ch->pIndexData->cargo;
  959.     if ( ch->position != POS_FIGHTING || cls->ncount == 0)
  960. return FALSE;
  961.     for ( victim = ch->in_room->people; victim != NULL; victim = v_next )
  962.     {
  963. v_next = victim->next_in_room;
  964. if ( victim->fighting == ch && number_bits( 2 ) == 0 )
  965.     break;
  966.     }
  967.     if ( victim == NULL )
  968. return FALSE;
  969.     // Calculate the spell randomly from mobile's table
  970.     nwhich = number_range(0, cls->ncount-1);
  971.     sn = skill_lookup( cls->string_list[nwhich] );
  972.     if (sn < 0)
  973.        return FALSE;
  974.     /* If the spell is defensive, the mobile casts on itself.  This allows it
  975.        to heal itself, bless itself, etc.  All other spells are cast on the
  976.        character the mob is fighting.  For offensive spells that is cool.  For
  977.        SELF spells it's not cool, if the mob casts 'STONE SKIN' say it will be
  978.        on the victim, not itself.  This is to allow TELEPORT to teleport the
  979.        victim away, like mages do.  Good idea?  I don't know...
  980.        If the spell has no target, like 'EARTHQUAKE', it is probably a bad idea
  981.        to have the mobile cast it...  The spell is probably coded to hit all
  982.        NPCs... */
  983.     if (skill_table[sn].target == TAR_CHAR_DEFENSIVE)
  984.        (*skill_table[sn].spell_fun) ( sn, ch->level, ch, ch );
  985.     else
  986.        (*skill_table[sn].spell_fun) ( sn, ch->level, ch, victim );
  987.     return TRUE;
  988. }
  989. bool spec_shopkeeper( CHAR_DATA *ch )
  990. {
  991.     OBJ_DATA *inv;
  992.     struct string_cargo_struct *cls;
  993.     /* Make sure the cargo was safely initialized */
  994.     check_init_cargo(ch);
  995.     if ( !IS_AWAKE(ch) || ch->position != POS_STANDING )
  996. return FALSE;
  997.     cls = ch->pIndexData->cargo;
  998.     for ( inv = ch->carrying; inv != NULL; inv = inv->next_content )
  999.     {
  1000.     int npercent = (cls->ncount >= 2) ? atoi(cls->string_list[1]) : 5;
  1001.     if (inv->wear_loc == WEAR_NONE && number_percent() < npercent)
  1002.        {
  1003.        if (cls->ncount)
  1004.           act( cls->string_list[0], ch, inv, NULL, TO_ROOM );
  1005.        else
  1006.           act( "$n suggests you buy a $p.", ch, inv, NULL, TO_ROOM );
  1007.        return TRUE;
  1008.        }
  1009.     }
  1010.     return FALSE;
  1011. }
  1012. // @@@ Modify to take a list of objects
  1013. bool spec_obj_bribe( CHAR_DATA *ch )
  1014. {
  1015.     OBJ_DATA *inv;
  1016.     int nobjvnum;
  1017.     struct string_cargo_struct *cls;
  1018.     char *p;
  1019.     char buf[MAX_STRING_LENGTH];
  1020.     sh_int old_trust;
  1021.     /* Make sure the cargo was safely initialized */
  1022.     check_init_cargo(ch);
  1023.     if ( ch->position != POS_STANDING )
  1024. return FALSE;
  1025.     cls = ch->pIndexData->cargo;
  1026.     if (!IS_AWAKE(ch) || cls->ncount < 2)
  1027.        return FALSE;
  1028.     for (p = cls->string_list[0]; *p; )
  1029.     {
  1030.        nobjvnum = atoi(p);
  1031.        for ( inv = ch->carrying; inv != NULL; inv = inv->next_content )
  1032.        {
  1033.        if (inv->pIndexData->vnum == nobjvnum)
  1034.           {
  1035.           int nwhich = number_range(1, cls->ncount-1);
  1036.           char *q;
  1037.           extract_obj( inv );
  1038.           q = p = cls->string_list[nwhich];
  1039.           if (*p)
  1040.              for ( ;; )
  1041.                 {
  1042.                 if (*p == ';' || *p == '')
  1043.                    {
  1044.                    memcpy(buf, q, p-q);
  1045.                    buf[p-q] = '';
  1046.                    old_trust = ch->trust;
  1047.                    ch->trust = 55;        /* Safe on TFC? */
  1048.                    interpret(ch, buf);
  1049.                    ch->trust = old_trust;
  1050.                    if (*p == '')
  1051.                       return TRUE;
  1052.                    q = p+1;
  1053.                    }
  1054.                 p++;
  1055.                 }
  1056.           }
  1057.        }
  1058.        while (*p && *p != ' ')
  1059.           p++;
  1060.        if (*p)
  1061.          p++;
  1062.     }
  1063.     return FALSE;
  1064. }
  1065. OBJ_DATA *is_wielding(CHAR_DATA *victim, char *vnum_list)
  1066. {
  1067.     OBJ_DATA *obj;
  1068.     int nobjvnum;
  1069.     while (*vnum_list)
  1070.     {
  1071.        nobjvnum = atoi(vnum_list);
  1072.        for ( obj = victim->carrying; obj != NULL; obj = obj->next_content )
  1073.        {
  1074.           if ( obj->pIndexData->vnum == nobjvnum && obj->wear_loc != -1)
  1075.              return obj;
  1076.        }
  1077.        while (*vnum_list && *vnum_list != ' ')
  1078.           vnum_list++;
  1079.        if (*vnum_list == ' ')
  1080.           vnum_list++;
  1081.    }
  1082.    return 0;
  1083. }
  1084. bool spec_agg_no_object( CHAR_DATA *ch )
  1085. {
  1086.     char buf[MAX_STRING_LENGTH];
  1087.     CHAR_DATA *victim;
  1088.     CHAR_DATA *v_next;
  1089.     struct string_cargo_struct *cls;
  1090. //    OBJ_DATA *obj;
  1091. //    int nobjvnum;
  1092.     /* Make sure the cargo was safely initialized */
  1093.     check_init_cargo(ch);
  1094.     cls = ch->pIndexData->cargo;
  1095.     if (!IS_AWAKE(ch) || cls->ncount < 2 || ch->fighting != NULL)
  1096.        return FALSE;
  1097. //    nobjvnum = atoi(cls->string_list[0]);
  1098.     for ( victim = ch->in_room->people; victim != NULL; victim = v_next )
  1099.     {
  1100.     v_next = victim->next_in_room;
  1101.     if (!IS_NPC(victim))
  1102.        if (!is_wielding(victim, cls->string_list[0]))
  1103.        {
  1104. // act( "$n screams 'PROTECT THE INNOCENT!!  BANZAI!!",
  1105.        act( cls->string_list[1], ch, NULL, NULL, TO_ROOM );
  1106.     multi_hit( ch, victim, TYPE_UNDEFINED );
  1107.        return TRUE;
  1108.        }
  1109.     }
  1110.     return FALSE;
  1111. }
  1112. bool spec_follow_mob( CHAR_DATA *ch )
  1113. {
  1114.     char buf[MAX_STRING_LENGTH];
  1115.     CHAR_DATA *victim;
  1116.     CHAR_DATA *v_next;
  1117.     struct string_cargo_struct *cls;
  1118.     OBJ_DATA *obj;
  1119.     int nmobvnum;
  1120.     /* Make sure the cargo was safely initialized */
  1121.     check_init_cargo(ch);
  1122.     cls = ch->pIndexData->cargo;
  1123.     if (!IS_AWAKE(ch) || cls->ncount < 1 || ch->fighting != NULL || ch->master)
  1124.        return FALSE;
  1125.     nmobvnum = atoi(cls->string_list[0]);
  1126.     for ( victim = ch->in_room->people; victim != NULL; victim = v_next )
  1127.     {
  1128.     v_next = victim->next_in_room;
  1129.     if (IS_NPC(victim) && victim->pIndexData->vnum == nmobvnum)
  1130.        {
  1131.        add_follower( ch, victim );
  1132.        break;
  1133.        }
  1134.     }
  1135.     return FALSE;
  1136. }
  1137. struct char_cargo_struct {
  1138.    int timer;
  1139.    int state;
  1140. };
  1141. /*
  1142.    Blight-generator:  Makes mobs aggressive.  (Ages...  starts out as some kind
  1143.       of low-level and when it gets to high level it changes its descr and
  1144.       starts up.--maybe)
  1145. */
  1146. // @@@ Modify this to take a list...
  1147. bool spec_generator( CHAR_DATA *ch )
  1148. {
  1149.     char buf[MAX_STRING_LENGTH];
  1150.     CHAR_DATA *victim;
  1151.     CHAR_DATA *v_next;
  1152.     struct string_cargo_struct *cls;
  1153.     OBJ_DATA *obj;
  1154.     struct char_cargo_struct *mobcargo = ch->cargo;
  1155.     /* Make sure the cargo was safely initialized */
  1156.     check_init_cargo(ch);
  1157.     /* If this mob is freshly popped, initialize the character cargo */
  1158.     if (mobcargo == 0)
  1159.        {
  1160.        mobcargo = ch->cargo = calloc(1, sizeof (struct char_cargo_struct));
  1161.        mobcargo->timer = 0;
  1162.        mobcargo->state = 0;
  1163.        }
  1164.     cls = ch->pIndexData->cargo;
  1165.     if (!IS_AWAKE(ch) || cls->ncount < 1 || ch->fighting != NULL)
  1166.        return FALSE;
  1167.     if (mobcargo->state < cls->ncount-1)
  1168.        {
  1169.        if (mobcargo->timer++ >= 10)
  1170.           {
  1171.           char buf[128];
  1172.           sprintf(buf, "New state is %d", ++mobcargo->state); // @@@
  1173.           free_string( ch->description );
  1174.         ch->description = str_dup( buf );
  1175.           act( "You here the sound of stretching and tearing.",
  1176.              ch, NULL, NULL, TO_ROOM );
  1177.           ch->level += 30 / cls->ncount + 1;
  1178.           ch->max_hit = ch->level * 8 + number_range(
  1179.    ch->level * ch->level / 4,
  1180.    ch->level * ch->level );
  1181.           mobcargo->timer = 0;
  1182.           }
  1183.        }
  1184.     else
  1185.        for ( victim = ch->in_room->people; victim != NULL; victim = v_next )
  1186.        {
  1187.           v_next = victim->next_in_room;
  1188.           if (IS_NPC(victim) && !saves_spell(ch->level, victim))
  1189.           {
  1190.              victim->act |= ACT_AGGRESSIVE;
  1191.              victim->act &= ~ACT_WIMPY; /* Add Super-Wimp if desired */
  1192.              victim->alignment = -1000;
  1193.           }
  1194.        }
  1195.     return FALSE;
  1196. }
  1197. /*
  1198.    Blight-fighter:  A cityguard that attacks aggressive mobs.
  1199. */
  1200. // @@@ Modify this to take a list...
  1201. bool spec_defend_vs_agg( CHAR_DATA *ch )
  1202. {
  1203.     char buf[MAX_STRING_LENGTH];
  1204.     CHAR_DATA *victim;
  1205.     CHAR_DATA *v_next;
  1206.     struct string_cargo_struct *cls;
  1207.     OBJ_DATA *obj;
  1208.     int nobjvnum;
  1209.     /* Make sure the cargo was safely initialized */
  1210.     check_init_cargo(ch);
  1211.     cls = ch->pIndexData->cargo;
  1212.     if (!IS_AWAKE(ch) || ch->fighting != NULL)
  1213.        return FALSE;
  1214.     for ( victim = ch->in_room->people; victim != NULL; victim = v_next )
  1215.     {
  1216.     v_next = victim->next_in_room;
  1217.     if (victim != ch && IS_NPC(victim) &&
  1218.         (victim->act & ACT_AGGRESSIVE) == ACT_AGGRESSIVE)
  1219.        {
  1220.        if (cls->ncount < 1)
  1221.           act( "$n screams 'PROTECT THE INNOCENT!!  BANZAI!!", ch, NULL, NULL,
  1222.              TO_ROOM);
  1223.        else
  1224.           act( cls->string_list[0], ch, NULL, NULL, TO_ROOM );
  1225.     multi_hit( ch, victim, TYPE_UNDEFINED );
  1226.        return TRUE;
  1227.        }
  1228.     }
  1229.     return FALSE;
  1230. }
  1231. /*
  1232.    Agg-if-object:  Attacks players who have an item in their inventory, say
  1233.    alcohol or they have stolen some holy relic.
  1234. */
  1235. // @@@ Modify this to take a list...
  1236. bool spec_agg_if_object( CHAR_DATA *ch )
  1237. {
  1238.     char buf[MAX_STRING_LENGTH];
  1239.     CHAR_DATA *victim;
  1240.     CHAR_DATA *v_next;
  1241.     struct string_cargo_struct *cls;
  1242.     OBJ_DATA *obj;
  1243.     int nobjvnum;
  1244.     /* Make sure the cargo was safely initialized */
  1245.     check_init_cargo(ch);
  1246.     cls = ch->pIndexData->cargo;
  1247.     if (!IS_AWAKE(ch) || cls->ncount < 2 || ch->fighting != NULL)
  1248.        return FALSE;
  1249.     nobjvnum = atoi(cls->string_list[0]);
  1250.     for ( victim = ch->in_room->people; victim != NULL; victim = v_next )
  1251.     {
  1252.        v_next = victim->next_in_room;
  1253.     /* @@@ This needs to be replaced with a no-hassle check */
  1254.     if (!IS_IMMORTAL(victim))
  1255.     {
  1256.        for ( obj = victim->carrying; obj != NULL; obj = obj->next_content )
  1257.        {
  1258.        if ( obj->pIndexData->vnum == nobjvnum )
  1259.           break;
  1260.        }
  1261.        if (obj)
  1262.        {
  1263.        act( cls->string_list[1], ch, NULL, NULL, TO_ROOM );
  1264.     multi_hit( ch, victim, TYPE_UNDEFINED );
  1265.        return TRUE;
  1266.        }
  1267.     }
  1268.     }
  1269.     return FALSE;
  1270. }
  1271. bool spec_circuit( CHAR_DATA *ch )
  1272. {
  1273.     OBJ_DATA *inv;
  1274.     int nobjvnum;
  1275.     struct string_cargo_struct *cls;
  1276.     struct char_cargo_struct *mobcargo = ch->cargo;
  1277.     /* Make sure the cargo was safely initialized */
  1278.     check_init_cargo(ch);
  1279.     /* If this mob is freshly popped, initialize the character cargo */
  1280.     if (mobcargo == 0)
  1281.        {
  1282.        mobcargo = ch->cargo = calloc(1, sizeof (struct char_cargo_struct));
  1283.        mobcargo->timer = 0;
  1284.        mobcargo->state = 0;
  1285.        }
  1286.     // Is the mob able to perform it's next action?
  1287.     cls = ch->pIndexData->cargo;
  1288.     if (!IS_AWAKE(ch) || cls->ncount < 1 || ch->fighting != NULL)
  1289.        return FALSE;
  1290.     // Is it time for a state change?
  1291.     // @@@ 10 is hardcoded...
  1292.     if (mobcargo->timer++ >= 10)
  1293.        {
  1294.        interpret(ch, cls->string_list[mobcargo->state]);
  1295.        mobcargo->timer = 0;
  1296.        if (mobcargo->state < cls->ncount-1)
  1297.           mobcargo->state++;
  1298.        else
  1299.           mobcargo->state = 0;
  1300.        return TRUE;
  1301.        }
  1302.     return FALSE;
  1303. }
  1304. /* This spec-fun lets mobs act the way they do on some muds--Remebering who
  1305.    they last fought against and going aggressive against that player.
  1306. */
  1307. bool spec_hatred( CHAR_DATA *ch )
  1308. {
  1309.     char *char_enemy = ch->cargo;   /* Store current hated char in cargo */
  1310.     CHAR_DATA *victim, *v_next;
  1311.     if (!IS_AWAKE(ch))              /* Mob can't hate while asleep */
  1312.        return FALSE;
  1313.     if (ch->fighting)               /* Is the mobile fighting? */
  1314.        {
  1315.        /* If the mobile is fighting a player, check and see if it is a player
  1316.           the mobile doesn't currently hate. */
  1317.        if (!IS_NPC(ch->fighting) &&
  1318.           (!char_enemy ||
  1319.            str_cmp(ch->fighting->name, char_enemy) == TRUE))
  1320.           {
  1321.           free_string( char_enemy );
  1322.           ch->cargo = str_dup( ch->fighting->name );
  1323.           }
  1324.        }
  1325.     /* The mobile is not fighting.  Does the mobile hate anyone? */
  1326.     else if (char_enemy)
  1327.        {
  1328.        /* Check the room for the player the mobile hates: */
  1329.        for ( victim = ch->in_room->people; victim != NULL; victim = v_next )
  1330.          {
  1331.          v_next = victim->next_in_room;
  1332.          /* @@@ A no-hassle check is needed here. */
  1333.          if (!IS_NPC(victim) && str_cmp(victim->name, char_enemy) == FALSE)
  1334.             {
  1335.             act( "$n screams with rage!", ch, NULL, NULL, TO_ROOM );
  1336.           multi_hit( ch, victim, TYPE_UNDEFINED );
  1337.             return TRUE;
  1338.             }
  1339.          }
  1340.        }
  1341.     return FALSE;
  1342. }
  1343. /*
  1344.  * Psionicist spec_fun by Thelonius for EnvyMud.
  1345.  */
  1346. bool spec_cast_psionicist( CHAR_DATA *ch )
  1347. {
  1348.     CHAR_DATA *victim;
  1349.     char      *spell;
  1350.     int        sn;
  1351.     if ( ch->position != POS_FIGHTING )
  1352.         return FALSE;
  1353.     for ( victim = ch->in_room->people; victim; victim = victim->next_in_room )
  1354.     {
  1355.         if ( victim->fighting == ch && can_see( ch, victim )
  1356.     && number_bits( 2 ) == 0 )
  1357.             break;
  1358.     }
  1359.     if ( !victim )
  1360.         return FALSE;
  1361.     for ( ; ; )
  1362.     {
  1363.         int min_level;
  1364.         switch ( number_bits( 4 ) )
  1365.         {
  1366.         case  0: min_level =  0; spell = "mind thrust";          break;
  1367.         case  1: min_level =  4; spell = "psychic drain";        break;
  1368.         case  2: min_level =  6; spell = "agitation";            break;
  1369.         case  3: min_level =  8; spell = "psychic crush";        break;
  1370.         case  4: min_level =  9; spell = "project force";        break;
  1371.         case  5: min_level = 13; spell = "ego whip";             break;
  1372.         case  6: min_level = 14; spell = "energy drain";         break;
  1373.         case  7:
  1374.         case  8: min_level = 17; spell = "psionic blast";        break;
  1375.         case  9: min_level = 20; spell = "detonate";             break;
  1376. case 10: min_level = 27; spell = "disintegrate";         break;
  1377.         default: min_level = 25; spell = "ultrablast";           break;
  1378.         }
  1379.         if ( ch->level >= min_level )
  1380.             break;
  1381.     }
  1382.     if ( ( sn = skill_lookup( spell ) ) < 0 )
  1383.         return FALSE;
  1384.     (*skill_table[sn].spell_fun) ( sn, ch->level, ch, victim );
  1385.     return TRUE;
  1386. }
  1387. #if 0
  1388. /* This current version of spec_animated_dead just emotes.  It could be
  1389.    enhanced in all kinds of ways...  Tying in HPs with the charm-master,
  1390.    turning on the charm master, etc.  When the charm wears off, the mobile
  1391.    turns to dust.
  1392. */
  1393. bool spec_animated_dead( CHAR_DATA *ch )
  1394. {
  1395.    if ( !IS_AFFECTED(ch, AFF_CHARM) )
  1396.       {
  1397.     act( "$n crumbles into dust.", ch, NULL, NULL, TO_ROOM );
  1398.       stop_fighting( ch, TRUE );
  1399.       /* Uncomment the following line if you have mobprogs */
  1400.       /* mprog_death_trigger( ch ); */
  1401.       extract_char( ch, TRUE );
  1402.       return TRUE;
  1403.       }
  1404.    switch ( number_bits(5) )
  1405.    {
  1406.    case 0:
  1407.     act( "Another gobbet of lose flesh falls off $n.", ch, NULL, NULL, TO_ROOM );
  1408.       return TRUE;
  1409.    case 1:
  1410.     act( "$n lets loose with a blood-curdling wail.", ch, NULL, NULL, TO_ROOM );
  1411.       return TRUE;
  1412.    case 2:
  1413.     act( "$n's odor is getting very bad.  You gag.", ch, NULL, NULL, TO_ROOM );
  1414.       return TRUE;
  1415.    default:
  1416.       break;
  1417.    }
  1418.    return FALSE;
  1419. }
  1420. #else
  1421. bool spec_animated_dead( CHAR_DATA *ch )
  1422. {
  1423.    act( "$n crumbles into dust.", ch, NULL, NULL, TO_ROOM );
  1424.    stop_fighting( ch, TRUE );
  1425.    /* Uncomment the following line if you have mobprogs */
  1426.    /* mprog_death_trigger( ch ); */
  1427.    extract_char( ch, TRUE );
  1428.    return TRUE;
  1429. }
  1430. #endif