spell_parser.c
1 /* ************************************************************************ 2 * File: spell_parser.c Part of CircleMUD * 3 * Usage: top-level magic routines; outside points of entry to magic sys. * 4 * * 5 * All rights reserved. See license.doc for complete information. * 6 * * 7 * Copyright (C) 1993, 94 by the Trustees of the Johns Hopkins University * 8 * CircleMUD is based on DikuMUD, Copyright (C) 1990, 1991. * 9 ************************************************************************ */ 10 11 12 #include "conf.h" 13 #include "sysdep.h" 14 15 16 #include "structs.h" 17 #include "utils.h" 18 #include "interpreter.h" 19 #include "spells.h" 20 #include "handler.h" 21 #include "comm.h" 22 #include "db.h" 23 24 25 #define SINFO spell_info[spellnum] 26 27 /* local globals */ 28 struct spell_info_type spell_info[TOP_SPELL_DEFINE + 1]; 29 30 /* local functions */ 31 void say_spell(struct char_data *ch, int spellnum, struct char_data *tch, struct obj_data *tobj); 32 void spello(int spl, const char *name, int max_mana, int min_mana, int mana_change, int minpos, int targets, int violent, int routines, const char *wearoff); 33 int mag_manacost(struct char_data *ch, int spellnum); 34 ACMD(do_cast); 35 void unused_spell(int spl); 36 void mag_assign_spells(void); 37 38 /* 39 * This arrangement is pretty stupid, but the number of skills is limited by 40 * the playerfile. We can arbitrarily increase the number of skills by 41 * increasing the space in the playerfile. Meanwhile, 200 should provide 42 * ample slots for skills. 43 */ 44 45 struct syllable { 46 const char *org; 47 const char *news; 48 }; 49 50 51 struct syllable syls[] = { 52 {" ", " "}, 53 {"ar", "abra"}, 54 {"ate", "i"}, 55 {"cau", "kada"}, 56 {"blind", "nose"}, 57 {"bur", "mosa"}, 58 {"cu", "judi"}, 59 {"de", "oculo"}, 60 {"dis", "mar"}, 61 {"ect", "kamina"}, 62 {"en", "uns"}, 63 {"gro", "cra"}, 64 {"light", "dies"}, 65 {"lo", "hi"}, 66 {"magi", "kari"}, 67 {"mon", "bar"}, 68 {"mor", "zak"}, 69 {"move", "sido"}, 70 {"ness", "lacri"}, 71 {"ning", "illa"}, 72 {"per", "duda"}, 73 {"ra", "gru"}, 74 {"re", "candus"}, 75 {"son", "sabru"}, 76 {"tect", "infra"}, 77 {"tri", "cula"}, 78 {"ven", "nofo"}, 79 {"word of", "inset"}, 80 {"a", "i"}, {"b", "v"}, {"c", "q"}, {"d", "m"}, {"e", "o"}, {"f", "y"}, {"g", "t"}, 81 {"h", "p"}, {"i", "u"}, {"j", "y"}, {"k", "t"}, {"l", "r"}, {"m", "w"}, {"n", "b"}, 82 {"o", "a"}, {"p", "s"}, {"q", "d"}, {"r", "f"}, {"s", "g"}, {"t", "h"}, {"u", "e"}, 83 {"v", "z"}, {"w", "x"}, {"x", "n"}, {"y", "l"}, {"z", "k"}, {"", ""} 84 }; 85 86 const char *unused_spellname = "!UNUSED!"; /* So we can get &unused_spellname */ 87 88 int mag_manacost(struct char_data *ch, int spellnum) 89 { 90 return MAX(SINFO.mana_max - (SINFO.mana_change * 91 (GET_LEVEL(ch) - SINFO.min_level[(int) GET_CLASS(ch)])), 92 SINFO.mana_min); 93 } 94 95 96 void say_spell(struct char_data *ch, int spellnum, struct char_data *tch, 97 struct obj_data *tobj) 98 { 99 char lbuf[256], buf[256], buf1[256], buf2[256]; /* FIXME */ 100 const char *format; 101 102 struct char_data *i; 103 int j, ofs = 0; 104 105 *buf = '\0'; 106 strlcpy(lbuf, skill_name(spellnum), sizeof(lbuf)); 107 108 while (lbuf[ofs]) { 109 for (j = 0; *(syls[j].org); j++) { 110 if (!strncmp(syls[j].org, lbuf + ofs, strlen(syls[j].org))) { 111 strcat(buf, syls[j].news); /* strcat: BAD */ 112 ofs += strlen(syls[j].org); 113 break; 114 } 115 } 116 /* i.e., we didn't find a match in syls[] */ 117 if (!*syls[j].org) { 118 log("No entry in syllable table for substring of '%s'", lbuf); 119 ofs++; 120 } 121 } 122 123 if (tch != NULL && IN_ROOM(tch) == IN_ROOM(ch)) { 124 if (tch == ch) 125 format = "$n closes $s eyes and utters the words, '%s'."; 126 else 127 format = "$n stares at $N and utters the words, '%s'."; 128 } else if (tobj != NULL && 129 ((IN_ROOM(tobj) == IN_ROOM(ch)) || (tobj->carried_by == ch))) 130 format = "$n stares at $p and utters the words, '%s'."; 131 else 132 format = "$n utters the words, '%s'."; 133 134 snprintf(buf1, sizeof(buf1), format, skill_name(spellnum)); 135 snprintf(buf2, sizeof(buf2), format, buf); 136 137 for (i = world[IN_ROOM(ch)].people; i; i = i->next_in_room) { 138 if (i == ch || i == tch || !i->desc || !AWAKE(i)) 139 continue; 140 if (GET_CLASS(ch) == GET_CLASS(i)) 141 perform_act(buf1, ch, tobj, tch, i); 142 else 143 perform_act(buf2, ch, tobj, tch, i); 144 } 145 146 if (tch != NULL && tch != ch && IN_ROOM(tch) == IN_ROOM(ch)) { 147 snprintf(buf1, sizeof(buf1), "$n stares at you and utters the words, '%s'.", 148 GET_CLASS(ch) == GET_CLASS(tch) ? skill_name(spellnum) : buf); 149 act(buf1, FALSE, ch, NULL, tch, TO_VICT); 150 } 151 } 152 153 /* 154 * This function should be used anytime you are not 100% sure that you have 155 * a valid spell/skill number. A typical for() loop would not need to use 156 * this because you can guarantee > 0 and <= TOP_SPELL_DEFINE. 157 */ 158 const char *skill_name(int num) 159 { 160 if (num > 0 && num <= TOP_SPELL_DEFINE) 161 return (spell_info[num].name); 162 else if (num == -1) 163 return ("UNUSED"); 164 else 165 return ("UNDEFINED"); 166 } 167 168 169 int find_skill_num(char *name) 170 { 171 int skindex, ok; 172 char *temp, *temp2; 173 char first[256], first2[256], tempbuf[256]; 174 175 for (skindex = 1; skindex <= TOP_SPELL_DEFINE; skindex++) { 176 if (is_abbrev(name, spell_info[skindex].name)) 177 return (skindex); 178 179 ok = TRUE; 180 strlcpy(tempbuf, spell_info[skindex].name, sizeof(tempbuf)); /* strlcpy: OK */ 181 temp = any_one_arg(tempbuf, first); 182 temp2 = any_one_arg(name, first2); 183 while (*first && *first2 && ok) { 184 if (!is_abbrev(first2, first)) 185 ok = FALSE; 186 temp = any_one_arg(temp, first); 187 temp2 = any_one_arg(temp2, first2); 188 } 189 190 if (ok && !*first2) 191 return (skindex); 192 } 193 194 return (-1); 195 } 196 197 198 199 /* 200 * This function is the very heart of the entire magic system. All 201 * invocations of all types of magic -- objects, spoken and unspoken PC 202 * and NPC spells, the works -- all come through this function eventually. 203 * This is also the entry point for non-spoken or unrestricted spells. 204 * Spellnum 0 is legal but silently ignored here, to make callers simpler. 205 */ 206 int call_magic(struct char_data *caster, struct char_data *cvict, 207 struct obj_data *ovict, int spellnum, int level, int casttype) 208 { 209 int savetype; 210 211 if (spellnum < 1 || spellnum > TOP_SPELL_DEFINE) 212 return (0); 213 214 if (ROOM_FLAGGED(IN_ROOM(caster), ROOM_NOMAGIC)) { 215 send_to_char(caster, "Your magic fizzles out and dies.\r\n"); 216 act("$n's magic fizzles out and dies.", FALSE, caster, 0, 0, TO_ROOM); 217 return (0); 218 } 219 if (ROOM_FLAGGED(IN_ROOM(caster), ROOM_PEACEFUL) && 220 (SINFO.violent || IS_SET(SINFO.routines, MAG_DAMAGE))) { 221 send_to_char(caster, "A flash of white light fills the room, dispelling your violent magic!\r\n"); 222 act("White light from no particular source suddenly fills the room, then vanishes.", FALSE, caster, 0, 0, TO_ROOM); 223 return (0); 224 } 225 /* determine the type of saving throw */ 226 switch (casttype) { 227 case CAST_STAFF: 228 case CAST_SCROLL: 229 case CAST_POTION: 230 case CAST_WAND: 231 savetype = SAVING_ROD; 232 break; 233 case CAST_SPELL: 234 savetype = SAVING_SPELL; 235 break; 236 default: 237 savetype = SAVING_BREATH; 238 break; 239 } 240 241 242 if (IS_SET(SINFO.routines, MAG_DAMAGE)) 243 if (mag_damage(level, caster, cvict, spellnum, savetype) == -1) 244 return (-1); /* Successful and target died, don't cast again. */ 245 246 if (IS_SET(SINFO.routines, MAG_AFFECTS)) 247 mag_affects(level, caster, cvict, spellnum, savetype); 248 249 if (IS_SET(SINFO.routines, MAG_UNAFFECTS)) 250 mag_unaffects(level, caster, cvict, spellnum, savetype); 251 252 if (IS_SET(SINFO.routines, MAG_POINTS)) 253 mag_points(level, caster, cvict, spellnum, savetype); 254 255 if (IS_SET(SINFO.routines, MAG_ALTER_OBJS)) 256 mag_alter_objs(level, caster, ovict, spellnum, savetype); 257 258 if (IS_SET(SINFO.routines, MAG_GROUPS)) 259 mag_groups(level, caster, spellnum, savetype); 260 261 if (IS_SET(SINFO.routines, MAG_MASSES)) 262 mag_masses(level, caster, spellnum, savetype); 263 264 if (IS_SET(SINFO.routines, MAG_AREAS)) 265 mag_areas(level, caster, spellnum, savetype); 266 267 if (IS_SET(SINFO.routines, MAG_SUMMONS)) 268 mag_summons(level, caster, ovict, spellnum, savetype); 269 270 if (IS_SET(SINFO.routines, MAG_CREATIONS)) 271 mag_creations(level, caster, spellnum); 272 273 if (IS_SET(SINFO.routines, MAG_MANUAL)) 274 switch (spellnum) { 275 case SPELL_CHARM: MANUAL_SPELL(spell_charm); break; 276 case SPELL_CREATE_WATER: MANUAL_SPELL(spell_create_water); break; 277 case SPELL_DETECT_POISON: MANUAL_SPELL(spell_detect_poison); break; 278 case SPELL_ENCHANT_WEAPON: MANUAL_SPELL(spell_enchant_weapon); break; 279 case SPELL_IDENTIFY: MANUAL_SPELL(spell_identify); break; 280 case SPELL_LOCATE_OBJECT: MANUAL_SPELL(spell_locate_object); break; 281 case SPELL_SUMMON: MANUAL_SPELL(spell_summon); break; 282 case SPELL_WORD_OF_RECALL: MANUAL_SPELL(spell_recall); break; 283 case SPELL_TELEPORT: MANUAL_SPELL(spell_teleport); break; 284 } 285 286 return (1); 287 } 288 289 /* 290 * mag_objectmagic: This is the entry-point for all magic items. This should 291 * only be called by the 'quaff', 'use', 'recite', etc. routines. 292 * 293 * For reference, object values 0-3: 294 * staff - [0] level [1] max charges [2] num charges [3] spell num 295 * wand - [0] level [1] max charges [2] num charges [3] spell num 296 * scroll - [0] level [1] spell num [2] spell num [3] spell num 297 * potion - [0] level [1] spell num [2] spell num [3] spell num 298 * 299 * Staves and wands will default to level 14 if the level is not specified; 300 * the DikuMUD format did not specify staff and wand levels in the world 301 * files (this is a CircleMUD enhancement). 302 */ 303 void mag_objectmagic(struct char_data *ch, struct obj_data *obj, 304 char *argument) 305 { 306 char arg[MAX_INPUT_LENGTH]; 307 int i, k; 308 struct char_data *tch = NULL, *next_tch; 309 struct obj_data *tobj = NULL; 310 311 one_argument(argument, arg); 312 313 k = generic_find(arg, FIND_CHAR_ROOM | FIND_OBJ_INV | FIND_OBJ_ROOM | 314 FIND_OBJ_EQUIP, ch, &tch, &tobj); 315 316 switch (GET_OBJ_TYPE(obj)) { 317 case ITEM_STAFF: 318 act("You tap $p three times on the ground.", FALSE, ch, obj, 0, TO_CHAR); 319 if (obj->action_description) 320 act(obj->action_description, FALSE, ch, obj, 0, TO_ROOM); 321 else 322 act("$n taps $p three times on the ground.", FALSE, ch, obj, 0, TO_ROOM); 323 324 if (GET_OBJ_VAL(obj, 2) <= 0) { 325 send_to_char(ch, "It seems powerless.\r\n"); 326 act("Nothing seems to happen.", FALSE, ch, obj, 0, TO_ROOM); 327 } else { 328 GET_OBJ_VAL(obj, 2)--; 329 WAIT_STATE(ch, PULSE_VIOLENCE); 330 /* Level to cast spell at. */ 331 k = GET_OBJ_VAL(obj, 0) ? GET_OBJ_VAL(obj, 0) : DEFAULT_STAFF_LVL; 332 333 /* 334 * Problem : Area/mass spells on staves can cause crashes. 335 * Solution: Remove the special nature of area/mass spells on staves. 336 * Problem : People like that behavior. 337 * Solution: We special case the area/mass spells here. 338 */ 339 if (HAS_SPELL_ROUTINE(GET_OBJ_VAL(obj, 3), MAG_MASSES | MAG_AREAS)) { 340 for (i = 0, tch = world[IN_ROOM(ch)].people; tch; tch = tch->next_in_room) 341 i++; 342 while (i-- > 0) 343 call_magic(ch, NULL, NULL, GET_OBJ_VAL(obj, 3), k, CAST_STAFF); 344 } else { 345 for (tch = world[IN_ROOM(ch)].people; tch; tch = next_tch) { 346 next_tch = tch->next_in_room; 347 if (ch != tch) 348 call_magic(ch, tch, NULL, GET_OBJ_VAL(obj, 3), k, CAST_STAFF); 349 } 350 } 351 } 352 break; 353 case ITEM_WAND: 354 if (k == FIND_CHAR_ROOM) { 355 if (tch == ch) { 356 act("You point $p at yourself.", FALSE, ch, obj, 0, TO_CHAR); 357 act("$n points $p at $mself.", FALSE, ch, obj, 0, TO_ROOM); 358 } else { 359 act("You point $p at $N.", FALSE, ch, obj, tch, TO_CHAR); 360 if (obj->action_description) 361 act(obj->action_description, FALSE, ch, obj, tch, TO_ROOM); 362 else 363 act("$n points $p at $N.", TRUE, ch, obj, tch, TO_ROOM); 364 } 365 } else if (tobj != NULL) { 366 act("You point $p at $P.", FALSE, ch, obj, tobj, TO_CHAR); 367 if (obj->action_description) 368 act(obj->action_description, FALSE, ch, obj, tobj, TO_ROOM); 369 else 370 act("$n points $p at $P.", TRUE, ch, obj, tobj, TO_ROOM); 371 } else if (IS_SET(spell_info[GET_OBJ_VAL(obj, 3)].routines, MAG_AREAS | MAG_MASSES)) { 372 /* Wands with area spells don't need to be pointed. */ 373 act("You point $p outward.", FALSE, ch, obj, NULL, TO_CHAR); 374 act("$n points $p outward.", TRUE, ch, obj, NULL, TO_ROOM); 375 } else { 376 act("At what should $p be pointed?", FALSE, ch, obj, NULL, TO_CHAR); 377 return; 378 } 379 380 if (GET_OBJ_VAL(obj, 2) <= 0) { 381 send_to_char(ch, "It seems powerless.\r\n"); 382 act("Nothing seems to happen.", FALSE, ch, obj, 0, TO_ROOM); 383 return; 384 } 385 GET_OBJ_VAL(obj, 2)--; 386 WAIT_STATE(ch, PULSE_VIOLENCE); 387 if (GET_OBJ_VAL(obj, 0)) 388 call_magic(ch, tch, tobj, GET_OBJ_VAL(obj, 3), 389 GET_OBJ_VAL(obj, 0), CAST_WAND); 390 else 391 call_magic(ch, tch, tobj, GET_OBJ_VAL(obj, 3), 392 DEFAULT_WAND_LVL, CAST_WAND); 393 break; 394 case ITEM_SCROLL: 395 if (*arg) { 396 if (!k) { 397 act("There is nothing to here to affect with $p.", FALSE, 398 ch, obj, NULL, TO_CHAR); 399 return; 400 } 401 } else 402 tch = ch; 403 404 act("You recite $p which dissolves.", TRUE, ch, obj, 0, TO_CHAR); 405 if (obj->action_description) 406 act(obj->action_description, FALSE, ch, obj, NULL, TO_ROOM); 407 else 408 act("$n recites $p.", FALSE, ch, obj, NULL, TO_ROOM); 409 410 WAIT_STATE(ch, PULSE_VIOLENCE); 411 for (i = 1; i <= 3; i++) 412 if (call_magic(ch, tch, tobj, GET_OBJ_VAL(obj, i), 413 GET_OBJ_VAL(obj, 0), CAST_SCROLL) <= 0) 414 break; 415 416 if (obj != NULL) 417 extract_obj(obj); 418 break; 419 case ITEM_POTION: 420 tch = ch; 421 act("You quaff $p.", FALSE, ch, obj, NULL, TO_CHAR); 422 if (obj->action_description) 423 act(obj->action_description, FALSE, ch, obj, NULL, TO_ROOM); 424 else 425 act("$n quaffs $p.", TRUE, ch, obj, NULL, TO_ROOM); 426 427 WAIT_STATE(ch, PULSE_VIOLENCE); 428 for (i = 1; i <= 3; i++) 429 if (call_magic(ch, ch, NULL, GET_OBJ_VAL(obj, i), 430 GET_OBJ_VAL(obj, 0), CAST_POTION) <= 0) 431 break; 432 433 if (obj != NULL) 434 extract_obj(obj); 435 break; 436 default: 437 log("SYSERR: Unknown object_type %d in mag_objectmagic.", 438 GET_OBJ_TYPE(obj)); 439 break; 440 } 441 } 442 443 444 /* 445 * cast_spell is used generically to cast any spoken spell, assuming we 446 * already have the target char/obj and spell number. It checks all 447 * restrictions, etc., prints the words, etc. 448 * 449 * Entry point for NPC casts. Recommended entry point for spells cast 450 * by NPCs via specprocs. 451 */ 452 int cast_spell(struct char_data *ch, struct char_data *tch, 453 struct obj_data *tobj, int spellnum) 454 { 455 if (spellnum < 0 || spellnum > TOP_SPELL_DEFINE) { 456 log("SYSERR: cast_spell trying to call spellnum %d/%d.", spellnum, 457 TOP_SPELL_DEFINE); 458 return (0); 459 } 460 461 if (GET_POS(ch) < SINFO.min_position) { 462 switch (GET_POS(ch)) { 463 case POS_SLEEPING: 464 send_to_char(ch, "You dream about great magical powers.\r\n"); 465 break; 466 case POS_RESTING: 467 send_to_char(ch, "You cannot concentrate while resting.\r\n"); 468 break; 469 case POS_SITTING: 470 send_to_char(ch, "You can't do this sitting!\r\n"); 471 break; 472 case POS_FIGHTING: 473 send_to_char(ch, "Impossible! You can't concentrate enough!\r\n"); 474 break; 475 default: 476 send_to_char(ch, "You can't do much of anything like this!\r\n"); 477 break; 478 } 479 return (0); 480 } 481 if (AFF_FLAGGED(ch, AFF_CHARM) && (ch->master == tch)) { 482 send_to_char(ch, "You are afraid you might hurt your master!\r\n"); 483 return (0); 484 } 485 if ((tch != ch) && IS_SET(SINFO.targets, TAR_SELF_ONLY)) { 486 send_to_char(ch, "You can only cast this spell upon yourself!\r\n"); 487 return (0); 488 } 489 if ((tch == ch) && IS_SET(SINFO.targets, TAR_NOT_SELF)) { 490 send_to_char(ch, "You cannot cast this spell upon yourself!\r\n"); 491 return (0); 492 } 493 if (IS_SET(SINFO.routines, MAG_GROUPS) && !AFF_FLAGGED(ch, AFF_GROUP)) { 494 send_to_char(ch, "You can't cast this spell if you're not in a group!\r\n"); 495 return (0); 496 } 497 send_to_char(ch, "%s", OK); 498 say_spell(ch, spellnum, tch, tobj); 499 500 return (call_magic(ch, tch, tobj, spellnum, GET_LEVEL(ch), CAST_SPELL)); 501 } 502 503 504 /* 505 * do_cast is the entry point for PC-casted spells. It parses the arguments, 506 * determines the spell number and finds a target, throws the die to see if 507 * the spell can be cast, checks for sufficient mana and subtracts it, and 508 * passes control to cast_spell(). 509 */ 510 ACMD(do_cast) 511 { 512 struct char_data *tch = NULL; 513 struct obj_data *tobj = NULL; 514 char *s, *t; 515 int mana, spellnum, i, target = 0; 516 517 if (IS_NPC(ch)) 518 return; 519 520 /* get: blank, spell name, target name */ 521 s = strtok(argument, "'"); 522 523 if (s == NULL) { 524 send_to_char(ch, "Cast what where?\r\n"); 525 return; 526 } 527 s = strtok(NULL, "'"); 528 if (s == NULL) { 529 send_to_char(ch, "Spell names must be enclosed in the Holy Magic Symbols: '\r\n"); 530 return; 531 } 532 t = strtok(NULL, "\0"); 533 534 /* spellnum = search_block(s, spells, 0); */ 535 spellnum = find_skill_num(s); 536 537 if ((spellnum < 1) || (spellnum > MAX_SPELLS)) { 538 send_to_char(ch, "Cast what?!?\r\n"); 539 return; 540 } 541 if (GET_LEVEL(ch) < SINFO.min_level[(int) GET_CLASS(ch)]) { 542 send_to_char(ch, "You do not know that spell!\r\n"); 543 return; 544 } 545 if (GET_SKILL(ch, spellnum) == 0) { 546 send_to_char(ch, "You are unfamiliar with that spell.\r\n"); 547 return; 548 } 549 /* Find the target */ 550 if (t != NULL) { 551 char arg[MAX_INPUT_LENGTH]; 552 553 strlcpy(arg, t, sizeof(arg)); 554 one_argument(arg, t); 555 skip_spaces(&t); 556 } 557 if (IS_SET(SINFO.targets, TAR_IGNORE)) { 558 target = TRUE; 559 } else if (t != NULL && *t) { 560 if (!target && (IS_SET(SINFO.targets, TAR_CHAR_ROOM))) { 561 if ((tch = get_char_vis(ch, t, NULL, FIND_CHAR_ROOM)) != NULL) 562 target = TRUE; 563 } 564 if (!target && IS_SET(SINFO.targets, TAR_CHAR_WORLD)) 565 if ((tch = get_char_vis(ch, t, NULL, FIND_CHAR_WORLD)) != NULL) 566 target = TRUE; 567 568 if (!target && IS_SET(SINFO.targets, TAR_OBJ_INV)) 569 if ((tobj = get_obj_in_list_vis(ch, t, NULL, ch->carrying)) != NULL) 570 target = TRUE; 571 572 if (!target && IS_SET(SINFO.targets, TAR_OBJ_EQUIP)) { 573 for (i = 0; !target && i < NUM_WEARS; i++) 574 if (GET_EQ(ch, i) && isname(t, GET_EQ(ch, i)->name)) { 575 tobj = GET_EQ(ch, i); 576 target = TRUE; 577 } 578 } 579 if (!target && IS_SET(SINFO.targets, TAR_OBJ_ROOM)) 580 if ((tobj = get_obj_in_list_vis(ch, t, NULL, world[IN_ROOM(ch)].contents)) != NULL) 581 target = TRUE; 582 583 if (!target && IS_SET(SINFO.targets, TAR_OBJ_WORLD)) 584 if ((tobj = get_obj_vis(ch, t, NULL)) != NULL) 585 target = TRUE; 586 587 } else { /* if target string is empty */ 588 if (!target && IS_SET(SINFO.targets, TAR_FIGHT_SELF)) 589 if (FIGHTING(ch) != NULL) { 590 tch = ch; 591 target = TRUE; 592 } 593 if (!target && IS_SET(SINFO.targets, TAR_FIGHT_VICT)) 594 if (FIGHTING(ch) != NULL) { 595 tch = FIGHTING(ch); 596 target = TRUE; 597 } 598 /* if no target specified, and the spell isn't violent, default to self */ 599 if (!target && IS_SET(SINFO.targets, TAR_CHAR_ROOM) && 600 !SINFO.violent) { 601 tch = ch; 602 target = TRUE; 603 } 604 if (!target) { 605 send_to_char(ch, "Upon %s should the spell be cast?\r\n", 606 IS_SET(SINFO.targets, TAR_OBJ_ROOM | TAR_OBJ_INV | TAR_OBJ_WORLD | TAR_OBJ_EQUIP) ? "what" : "who"); 607 return; 608 } 609 } 610 611 if (target && (tch == ch) && SINFO.violent) { 612 send_to_char(ch, "You shouldn't cast that on yourself -- could be bad for your health!\r\n"); 613 return; 614 } 615 if (!target) { 616 send_to_char(ch, "Cannot find the target of your spell!\r\n"); 617 return; 618 } 619 mana = mag_manacost(ch, spellnum); 620 if ((mana > 0) && (GET_MANA(ch) < mana) && (GET_LEVEL(ch) < LVL_IMMORT)) { 621 send_to_char(ch, "You haven't the energy to cast that spell!\r\n"); 622 return; 623 } 624 625 /* You throws the dice and you takes your chances.. 101% is total failure */ 626 if (rand_number(0, 101) > GET_SKILL(ch, spellnum)) { 627 WAIT_STATE(ch, PULSE_VIOLENCE); 628 if (!tch || !skill_message(0, ch, tch, spellnum)) 629 send_to_char(ch, "You lost your concentration!\r\n"); 630 if (mana > 0) 631 GET_MANA(ch) = MAX(0, MIN(GET_MAX_MANA(ch), GET_MANA(ch) - (mana / 2))); 632 if (SINFO.violent && tch && IS_NPC(tch)) 633 hit(tch, ch, TYPE_UNDEFINED); 634 } else { /* cast spell returns 1 on success; subtract mana & set waitstate */ 635 if (cast_spell(ch, tch, tobj, spellnum)) { 636 WAIT_STATE(ch, PULSE_VIOLENCE); 637 if (mana > 0) 638 GET_MANA(ch) = MAX(0, MIN(GET_MAX_MANA(ch), GET_MANA(ch) - mana)); 639 } 640 } 641 } 642 643 644 645 void spell_level(int spell, int chclass, int level) 646 { 647 int bad = 0; 648 649 if (spell < 0 || spell > TOP_SPELL_DEFINE) { 650 log("SYSERR: attempting assign to illegal spellnum %d/%d", spell, TOP_SPELL_DEFINE); 651 return; 652 } 653 654 if (chclass < 0 || chclass >= NUM_CLASSES) { 655 log("SYSERR: assigning '%s' to illegal class %d/%d.", skill_name(spell), 656 chclass, NUM_CLASSES - 1); 657 bad = 1; 658 } 659 660 if (level < 1 || level > LVL_IMPL) { 661 log("SYSERR: assigning '%s' to illegal level %d/%d.", skill_name(spell), 662 level, LVL_IMPL); 663 bad = 1; 664 } 665 666 if (!bad) 667 spell_info[spell].min_level[chclass] = level; 668 } 669 670 671 /* Assign the spells on boot up */ 672 void spello(int spl, const char *name, int max_mana, int min_mana, 673 int mana_change, int minpos, int targets, int violent, int routines, const char *wearoff) 674 { 675 int i; 676 677 for (i = 0; i < NUM_CLASSES; i++) 678 spell_info[spl].min_level[i] = LVL_IMMORT; 679 spell_info[spl].mana_max = max_mana; 680 spell_info[spl].mana_min = min_mana; 681 spell_info[spl].mana_change = mana_change; 682 spell_info[spl].min_position = minpos; 683 spell_info[spl].targets = targets; 684 spell_info[spl].violent = violent; 685 spell_info[spl].routines = routines; 686 spell_info[spl].name = name; 687 spell_info[spl].wear_off_msg = wearoff; 688 } 689 690 691 void unused_spell(int spl) 692 { 693 int i; 694 695 for (i = 0; i < NUM_CLASSES; i++) 696 spell_info[spl].min_level[i] = LVL_IMPL + 1; 697 spell_info[spl].mana_max = 0; 698 spell_info[spl].mana_min = 0; 699 spell_info[spl].mana_change = 0; 700 spell_info[spl].min_position = 0; 701 spell_info[spl].targets = 0; 702 spell_info[spl].violent = 0; 703 spell_info[spl].routines = 0; 704 spell_info[spl].name = unused_spellname; 705 } 706 707 #define skillo(skill, name) spello(skill, name, 0, 0, 0, 0, 0, 0, 0, NULL); 708 709 710 /* 711 * Arguments for spello calls: 712 * 713 * spellnum, maxmana, minmana, manachng, minpos, targets, violent?, routines. 714 * 715 * spellnum: Number of the spell. Usually the symbolic name as defined in 716 * spells.h (such as SPELL_HEAL). 717 * 718 * spellname: The name of the spell. 719 * 720 * maxmana : The maximum mana this spell will take (i.e., the mana it 721 * will take when the player first gets the spell). 722 * 723 * minmana : The minimum mana this spell will take, no matter how high 724 * level the caster is. 725 * 726 * manachng: The change in mana for the spell from level to level. This 727 * number should be positive, but represents the reduction in mana cost as 728 * the caster's level increases. 729 * 730 * minpos : Minimum position the caster must be in for the spell to work 731 * (usually fighting or standing). targets : A "list" of the valid targets 732 * for the spell, joined with bitwise OR ('|'). 733 * 734 * violent : TRUE or FALSE, depending on if this is considered a violent 735 * spell and should not be cast in PEACEFUL rooms or on yourself. Should be 736 * set on any spell that inflicts damage, is considered aggressive (i.e. 737 * charm, curse), or is otherwise nasty. 738 * 739 * routines: A list of magic routines which are associated with this spell 740 * if the spell uses spell templates. Also joined with bitwise OR ('|'). 741 * 742 * See the CircleMUD documentation for a more detailed description of these 743 * fields. 744 */ 745 746 /* 747 * NOTE: SPELL LEVELS ARE NO LONGER ASSIGNED HERE AS OF Circle 3.0 bpl9. 748 * In order to make this cleaner, as well as to make adding new classes 749 * much easier, spell levels are now assigned in class.c. You only need 750 * a spello() call to define a new spell; to decide who gets to use a spell 751 * or skill, look in class.c. -JE 5 Feb 1996 752 */ 753 754 void mag_assign_spells(void) 755 { 756 int i; 757 758 /* Do not change the loop below. */ 759 for (i = 0; i <= TOP_SPELL_DEFINE; i++) 760 unused_spell(i); 761 /* Do not change the loop above. */ 762 763 spello(SPELL_ANIMATE_DEAD, "animate dead", 35, 10, 3, POS_STANDING, 764 TAR_OBJ_ROOM, FALSE, MAG_SUMMONS, 765 NULL); 766 767 spello(SPELL_ARMOR, "armor", 30, 15, 3, POS_FIGHTING, 768 TAR_CHAR_ROOM, FALSE, MAG_AFFECTS, 769 "You feel less protected."); 770 771 spello(SPELL_BLESS, "bless", 35, 5, 3, POS_STANDING, 772 TAR_CHAR_ROOM | TAR_OBJ_INV, FALSE, MAG_AFFECTS | MAG_ALTER_OBJS, 773 "You feel less righteous."); 774 775 spello(SPELL_BLINDNESS, "blindness", 35, 25, 1, POS_STANDING, 776 TAR_CHAR_ROOM | TAR_NOT_SELF, FALSE, MAG_AFFECTS, 777 "You feel a cloak of blindness dissolve."); 778 779 spello(SPELL_BURNING_HANDS, "burning hands", 30, 10, 3, POS_FIGHTING, 780 TAR_CHAR_ROOM | TAR_FIGHT_VICT, TRUE, MAG_DAMAGE, 781 NULL); 782 783 spello(SPELL_CALL_LIGHTNING, "call lightning", 40, 25, 3, POS_FIGHTING, 784 TAR_CHAR_ROOM | TAR_FIGHT_VICT, TRUE, MAG_DAMAGE, 785 NULL); 786 787 spello(SPELL_CHARM, "charm person", 75, 50, 2, POS_FIGHTING, 788 TAR_CHAR_ROOM | TAR_NOT_SELF, TRUE, MAG_MANUAL, 789 "You feel more self-confident."); 790 791 spello(SPELL_CHILL_TOUCH, "chill touch", 30, 10, 3, POS_FIGHTING, 792 TAR_CHAR_ROOM | TAR_FIGHT_VICT, TRUE, MAG_DAMAGE | MAG_AFFECTS, 793 "You feel your strength return."); 794 795 spello(SPELL_CLONE, "clone", 80, 65, 5, POS_STANDING, 796 TAR_SELF_ONLY, FALSE, MAG_SUMMONS, 797 NULL); 798 799 spello(SPELL_COLOR_SPRAY, "color spray", 30, 15, 3, POS_FIGHTING, 800 TAR_CHAR_ROOM | TAR_FIGHT_VICT, TRUE, MAG_DAMAGE, 801 NULL); 802 803 spello(SPELL_CONTROL_WEATHER, "control weather", 75, 25, 5, POS_STANDING, 804 TAR_IGNORE, FALSE, MAG_MANUAL, 805 NULL); 806 807 spello(SPELL_CREATE_FOOD, "create food", 30, 5, 4, POS_STANDING, 808 TAR_IGNORE, FALSE, MAG_CREATIONS, 809 NULL); 810 811 spello(SPELL_CREATE_WATER, "create water", 30, 5, 4, POS_STANDING, 812 TAR_OBJ_INV | TAR_OBJ_EQUIP, FALSE, MAG_MANUAL, 813 NULL); 814 815 spello(SPELL_CURE_BLIND, "cure blind", 30, 5, 2, POS_STANDING, 816 TAR_CHAR_ROOM, FALSE, MAG_UNAFFECTS, 817 NULL); 818 819 spello(SPELL_CURE_CRITIC, "cure critic", 30, 10, 2, POS_FIGHTING, 820 TAR_CHAR_ROOM, FALSE, MAG_POINTS, 821 NULL); 822 823 spello(SPELL_CURE_LIGHT, "cure light", 30, 10, 2, POS_FIGHTING, 824 TAR_CHAR_ROOM, FALSE, MAG_POINTS, 825 NULL); 826 827 spello(SPELL_CURSE, "curse", 80, 50, 2, POS_STANDING, 828 TAR_CHAR_ROOM | TAR_OBJ_INV, TRUE, MAG_AFFECTS | MAG_ALTER_OBJS, 829 "You feel more optimistic."); 830 831 spello(SPELL_DETECT_ALIGN, "detect alignment", 20, 10, 2, POS_STANDING, 832 TAR_CHAR_ROOM | TAR_SELF_ONLY, FALSE, MAG_AFFECTS, 833 "You feel less aware."); 834 835 spello(SPELL_DETECT_INVIS, "detect invisibility", 20, 10, 2, POS_STANDING, 836 TAR_CHAR_ROOM | TAR_SELF_ONLY, FALSE, MAG_AFFECTS, 837 "Your eyes stop tingling."); 838 839 spello(SPELL_DETECT_MAGIC, "detect magic", 20, 10, 2, POS_STANDING, 840 TAR_CHAR_ROOM | TAR_SELF_ONLY, FALSE, MAG_AFFECTS, 841 "The detect magic wears off."); 842 843 spello(SPELL_DETECT_POISON, "detect poison", 15, 5, 1, POS_STANDING, 844 TAR_CHAR_ROOM | TAR_OBJ_INV | TAR_OBJ_ROOM, FALSE, MAG_MANUAL, 845 "The detect poison wears off."); 846 847 spello(SPELL_DISPEL_EVIL, "dispel evil", 40, 25, 3, POS_FIGHTING, 848 TAR_CHAR_ROOM | TAR_FIGHT_VICT, TRUE, MAG_DAMAGE, 849 NULL); 850 851 spello(SPELL_DISPEL_GOOD, "dispel good", 40, 25, 3, POS_FIGHTING, 852 TAR_CHAR_ROOM | TAR_FIGHT_VICT, TRUE, MAG_DAMAGE, 853 NULL); 854 855 spello(SPELL_EARTHQUAKE, "earthquake", 40, 25, 3, POS_FIGHTING, 856 TAR_IGNORE, TRUE, MAG_AREAS, 857 NULL); 858 859 spello(SPELL_ENCHANT_WEAPON, "enchant weapon", 150, 100, 10, POS_STANDING, 860 TAR_OBJ_INV, FALSE, MAG_MANUAL, 861 NULL); 862 863 spello(SPELL_ENERGY_DRAIN, "energy drain", 40, 25, 1, POS_FIGHTING, 864 TAR_CHAR_ROOM | TAR_FIGHT_VICT, TRUE, MAG_DAMAGE | MAG_MANUAL, 865 NULL); 866 867 spello(SPELL_GROUP_ARMOR, "group armor", 50, 30, 2, POS_STANDING, 868 TAR_IGNORE, FALSE, MAG_GROUPS, 869 NULL); 870 871 spello(SPELL_FIREBALL, "fireball", 40, 30, 2, POS_FIGHTING, 872 TAR_CHAR_ROOM | TAR_FIGHT_VICT, TRUE, MAG_DAMAGE, 873 NULL); 874 875 spello(SPELL_GROUP_HEAL, "group heal", 80, 60, 5, POS_STANDING, 876 TAR_IGNORE, FALSE, MAG_GROUPS, 877 NULL); 878 879 spello(SPELL_HARM, "harm", 75, 45, 3, POS_FIGHTING, 880 TAR_CHAR_ROOM | TAR_FIGHT_VICT, TRUE, MAG_DAMAGE, 881 NULL); 882 883 spello(SPELL_HEAL, "heal", 60, 40, 3, POS_FIGHTING, 884 TAR_CHAR_ROOM, FALSE, MAG_POINTS | MAG_UNAFFECTS, 885 NULL); 886 887 spello(SPELL_INFRAVISION, "infravision", 25, 10, 1, POS_STANDING, 888 TAR_CHAR_ROOM | TAR_SELF_ONLY, FALSE, MAG_AFFECTS, 889 "Your night vision seems to fade."); 890 891 spello(SPELL_INVISIBLE, "invisibility", 35, 25, 1, POS_STANDING, 892 TAR_CHAR_ROOM | TAR_OBJ_INV | TAR_OBJ_ROOM, FALSE, MAG_AFFECTS | MAG_ALTER_OBJS, 893 "You feel yourself exposed."); 894 895 spello(SPELL_LIGHTNING_BOLT, "lightning bolt", 30, 15, 1, POS_FIGHTING, 896 TAR_CHAR_ROOM | TAR_FIGHT_VICT, TRUE, MAG_DAMAGE, 897 NULL); 898 899 spello(SPELL_LOCATE_OBJECT, "locate object", 25, 20, 1, POS_STANDING, 900 TAR_OBJ_WORLD, FALSE, MAG_MANUAL, 901 NULL); 902 903 spello(SPELL_MAGIC_MISSILE, "magic missile", 25, 10, 3, POS_FIGHTING, 904 TAR_CHAR_ROOM | TAR_FIGHT_VICT, TRUE, MAG_DAMAGE, 905 NULL); 906 907 spello(SPELL_POISON, "poison", 50, 20, 3, POS_STANDING, 908 TAR_CHAR_ROOM | TAR_NOT_SELF | TAR_OBJ_INV, TRUE, 909 MAG_AFFECTS | MAG_ALTER_OBJS, 910 "You feel less sick."); 911 912 spello(SPELL_PROT_FROM_EVIL, "protection from evil", 40, 10, 3, POS_STANDING, 913 TAR_CHAR_ROOM | TAR_SELF_ONLY, FALSE, MAG_AFFECTS, 914 "You feel less protected."); 915 916 spello(SPELL_REMOVE_CURSE, "remove curse", 45, 25, 5, POS_STANDING, 917 TAR_CHAR_ROOM | TAR_OBJ_INV | TAR_OBJ_EQUIP, FALSE, 918 MAG_UNAFFECTS | MAG_ALTER_OBJS, 919 NULL); 920 921 spello(SPELL_REMOVE_POISON, "remove poison", 40, 8, 4, POS_STANDING, 922 TAR_CHAR_ROOM | TAR_OBJ_INV | TAR_OBJ_ROOM, FALSE, MAG_UNAFFECTS | MAG_ALTER_OBJS, 923 NULL); 924 925 spello(SPELL_SANCTUARY, "sanctuary", 110, 85, 5, POS_STANDING, 926 TAR_CHAR_ROOM, FALSE, MAG_AFFECTS, 927 "The white aura around your body fades."); 928 929 spello(SPELL_SENSE_LIFE, "sense life", 20, 10, 2, POS_STANDING, 930 TAR_CHAR_ROOM | TAR_SELF_ONLY, FALSE, MAG_AFFECTS, 931 "You feel less aware of your surroundings."); 932 933 spello(SPELL_SHOCKING_GRASP, "shocking grasp", 30, 15, 3, POS_FIGHTING, 934 TAR_CHAR_ROOM | TAR_FIGHT_VICT, TRUE, MAG_DAMAGE, 935 NULL); 936 937 spello(SPELL_SLEEP, "sleep", 40, 25, 5, POS_STANDING, 938 TAR_CHAR_ROOM, TRUE, MAG_AFFECTS, 939 "You feel less tired."); 940 941 spello(SPELL_STRENGTH, "strength", 35, 30, 1, POS_STANDING, 942 TAR_CHAR_ROOM, FALSE, MAG_AFFECTS, 943 "You feel weaker."); 944 945 spello(SPELL_SUMMON, "summon", 75, 50, 3, POS_STANDING, 946 TAR_CHAR_WORLD | TAR_NOT_SELF, FALSE, MAG_MANUAL, 947 NULL); 948 949 spello(SPELL_TELEPORT, "teleport", 75, 50, 3, POS_STANDING, 950 TAR_CHAR_ROOM, FALSE, MAG_MANUAL, 951 NULL); 952 953 spello(SPELL_WATERWALK, "waterwalk", 40, 20, 2, POS_STANDING, 954 TAR_CHAR_ROOM, FALSE, MAG_AFFECTS, 955 "Your feet seem less buoyant."); 956 957 spello(SPELL_WORD_OF_RECALL, "word of recall", 20, 10, 2, POS_FIGHTING, 958 TAR_CHAR_ROOM, FALSE, MAG_MANUAL, 959 NULL); 960 961 962 /* NON-castable spells should appear below here. */ 963 964 spello(SPELL_IDENTIFY, "identify", 0, 0, 0, 0, 965 TAR_CHAR_ROOM | TAR_OBJ_INV | TAR_OBJ_ROOM, FALSE, MAG_MANUAL, 966 NULL); 967 968 /* 969 * These spells are currently not used, not implemented, and not castable. 970 * Values for the 'breath' spells are filled in assuming a dragon's breath. 971 */ 972 973 spello(SPELL_FIRE_BREATH, "fire breath", 0, 0, 0, POS_SITTING, 974 TAR_IGNORE, TRUE, 0, 975 NULL); 976 977 spello(SPELL_GAS_BREATH, "gas breath", 0, 0, 0, POS_SITTING, 978 TAR_IGNORE, TRUE, 0, 979 NULL); 980 981 spello(SPELL_FROST_BREATH, "frost breath", 0, 0, 0, POS_SITTING, 982 TAR_IGNORE, TRUE, 0, 983 NULL); 984 985 spello(SPELL_ACID_BREATH, "acid breath", 0, 0, 0, POS_SITTING, 986 TAR_IGNORE, TRUE, 0, 987 NULL); 988 989 spello(SPELL_LIGHTNING_BREATH, "lightning breath", 0, 0, 0, POS_SITTING, 990 TAR_IGNORE, TRUE, 0, 991 NULL); 992 993 /* 994 * Declaration of skills - this actually doesn't do anything except 995 * set it up so that immortals can use these skills by default. The 996 * min level to use the skill for other classes is set up in class.c. 997 */ 998 999 skillo(SKILL_BACKSTAB, "backstab"); 1000 skillo(SKILL_BASH, "bash"); 1001 skillo(SKILL_HIDE, "hide"); 1002 skillo(SKILL_KICK, "kick"); 1003 skillo(SKILL_PICK_LOCK, "pick lock"); 1004 skillo(SKILL_RESCUE, "rescue"); 1005 skillo(SKILL_SNEAK, "sneak"); 1006 skillo(SKILL_STEAL, "steal"); 1007 skillo(SKILL_TRACK, "track"); 1008 } 1009