tbamud/src/spells.c

453 lines
14 KiB
C
Raw Normal View History

/**************************************************************************
* File: spells.c Part of tbaMUD *
* Usage: Implementation of "manual spells." *
2006-12-19 22:56:18 +00:00
* *
* All rights reserved. See license for complete information. *
2006-12-19 22:56:18 +00:00
* *
* Copyright (C) 1993, 94 by the Trustees of the Johns Hopkins University *
* CircleMUD is based on DikuMUD, Copyright (C) 1990, 1991. *
**************************************************************************/
2006-12-19 22:56:18 +00:00
#include "conf.h"
#include "sysdep.h"
#include "structs.h"
#include "utils.h"
#include "comm.h"
#include "spells.h"
#include "handler.h"
#include "db.h"
#include "constants.h"
#include "interpreter.h"
#include "dg_scripts.h"
jeremyosborne | 2008-04-04 02:36:38 +0200 (Fri, 04 Apr 2008) | 1 line Minor Bugfix: All game configuration settings now reference the world config structure, not the individual config variables found in config.c. ------------------------------------------------------------------------ rumble | 2008-03-22 13:27:00 +0100 (Sat, 22 Mar 2008) | 1 line Added lib/world/qst/ directory, index, index.mini, and 0.qst. ------------------------------------------------------------------------ jeremyosborne | 2008-03-08 03:27:51 +0100 (Sat, 08 Mar 2008) | 3 lines Bugfix: the include directory (for .h files) is now referenced correctly in the depend statement. Deletion: listrent.c removed as a separate utility. ------------------------------------------------------------------------ jeremyosborne | 2008-03-08 03:08:51 +0100 (Sat, 08 Mar 2008) | 1 line Enhancement: utils/ Makefile will now use a depends file, and looks for dependen cies in the ../ directory (shrinks the necessary information to make each utilit y). ------------------------------------------------------------------------ Rumble | 2008-03-06 23:39:35 +0100 (Thu, 06 Mar 2008) | 1 line Made TBA specific changes. do_cheat, removed help level checking, and advance to level 32. ------------------------------------------------------------------------ jeremyosborne | 2008-03-06 18:37:12 +0100 (Thu, 06 Mar 2008) | 1 line Minor Update: Changed header of Makefile.in to read 'tbaMUD' and also added in a ttribution for the changes. (Thanks seqwith.) ------------------------------------------------------------------------ jeremyosborne | 2008-03-06 18:31:07 +0100 (Thu, 06 Mar 2008) | 4 lines Changed Makefile.in to use glob expressions when building the objects. This translates into no longer a need to update Makefile.in whenever a new .c file is added to the mud code. Other Makefile.* have not yet been changed (and need review, anyway). All CXREF cruft left in Makefile.in has been removed. tbaMUD is now using Doxygen. Technically, CXREF provides a bit more auto-documentation than Doxygen does, however the tbaMUD (and legacy circle code) has never been marked-up with the special CXREF codes required to effectively use the program. Since Doxygen is easier to use, and provides almost as much functionality as CXREF, CXREF support has been dropped. ------------------------------------------------------------------------ jeremyosborne | 2008-03-06 08:31:02 +0100 (Thu, 06 Mar 2008) | 1 line Bug Fix: asciiflag_conv* functions now can handle a negative numeric value. ------------------------------------------------------------------------ jeremyosborne | 2008-03-06 08:16:06 +0100 (Thu, 06 Mar 2008) | 1 line Bug fix/enhancement: Charmed mobs (specifically charmed mobs with a ->master) will no longer attempt to wander off. ------------------------------------------------------------------------ jeremyosborne | 2008-03-06 08:13:38 +0100 (Thu, 06 Mar 2008) | 6 lines Based on the compiler warning about mag_materials being an unused function, and the clone spell being unused. Bug fix: Clone can now be cast. It is an 'ignore' target spell. Fix and Modification: Clone, being an effectively unused spell that is only used by mortal Magic Users at level 30, is now implemented as very simple example of how to use mag_materials(). The item required by mag_materials is vnum 161, which in stock tbaMUD is some sacrificial entrails. ------------------------------------------------------------------------ jeremyosborne | 2008-03-05 01:43:09 +0100 (Wed, 05 Mar 2008) | 3 lines Bug Fix for "Did you mean:" including DG commands. ------------------------------------------------------------------------ jeremyosborne | 2008-03-05 01:29:18 +0100 (Wed, 05 Mar 2008) | 3 lines Bug Fix: do_simple_move slightly rewritten to handle Leave triggers that purge a door. Documentation: do_simple_move documented. ------------------------------------------------------------------------ Laoris | 2008-03-01 08:22:12 +0100 (Sat, 01 Mar 2008) | 1 line Trial run of columnizer function on commands list to see how people like it. ------------------------------------------------------------------------ jeremyosborne | 2008-02-26 22:36:17 +0100 (Tue, 26 Feb 2008) | 1 line asciimap, an in game automap, along with a couple of minor bug fixes to do with the automap, patched in (Thanks Jamdog). ------------------------------------------------------------------------ jeremyosborne | 2008-02-22 04:08:05 +0100 (Fri, 22 Feb 2008) | 1 line Minor update: Relocate local variable declaration to the top of ACMD(do_help) ------------------------------------------------------------------------ jeremyosborne | 2008-02-22 04:04:37 +0100 (Fri, 22 Feb 2008) | 6 lines Checked in the following placeholders for do_gen_tog: #define SCMD_AUTOLOOT 24 #define SCMD_AUTOGOLD 25 #define SCMD_AUTOSPLIT 26 #define SCMD_AUTOSAC 27 #define SCMD_AUTOASSIST 28 ------------------------------------------------------------------------ jeremyosborne | 2008-02-22 03:57:06 +0100 (Fri, 22 Feb 2008) | 1 line The Autoquest patch, along with a couple of minor bug fixes, has been integrated into tbaMUD. (Thanks Jamdog, Kenneth Ray and Morgaelin.) ------------------------------------------------------------------------ jeremyosborne | 2008-02-18 21:46:45 +0100 (Mon, 18 Feb 2008) | 2 lines Minor Fix: Casted NOWHERE, NOTHING, NOBODY and NOFLAG as IDXTYPE for the signed short int index types. ------------------------------------------------------------------------ jeremyosborne | 2008-02-18 03:36:16 +0100 (Mon, 18 Feb 2008) | 7 lines Added a new atoidx() conversion function for dealing with string to IDXTYPE conversions (in utils.c, prototype exported through utils.h). Added IDXTYPE_MIN and IDXTYPE_MAX defines (in structs.h). Replaced atoi references with atoidx in do_oasis_zedit (in zedit.c). ------------------------------------------------------------------------ Rumble | 2008-02-18 01:44:13 +0100 (Mon, 18 Feb 2008) | 1 line Fixed direction mapping to give readable directions instead of sub commands. ------------------------------------------------------------------------ jeremyosborne | 2008-02-18 00:26:15 +0100 (Mon, 18 Feb 2008) | 5 lines Since general olc editing are automatically saved to disk, 'shutdown reboot' has been changed to not-autosave by default. (Small change made to do_shutdown in act.wizard.c). ------------------------------------------------------------------------ jeremyosborne | 2008-02-18 00:12:12 +0100 (Mon, 18 Feb 2008) | 3 lines Changed: struct attack_hit_type moved to fight.h attack_hit_text exported through fight.h ------------------------------------------------------------------------ jeremyosborne | 2008-02-17 22:32:51 +0100 (Sun, 17 Feb 2008) | 7 lines - do_file heads or tails files correctly and has also been enhanced to return file info (act.wizard.c) - defines made for common log files created by autorun, and those used by do_file (db.h) - utility functions added: file_head(), file_tail(), file_sizeof(), and file_numlines() (defined utils.c and exported through utils.h) ------------------------------------------------------------------------ Rumble | 2008-02-16 23:24:05 +0100 (Sat, 16 Feb 2008) | 1 line Fixed export command. (thanks Kyle) ------------------------------------------------------------------------ jeremyosborne | 2008-02-16 22:42:46 +0100 (Sat, 16 Feb 2008) | 1 line Files are now tagged as executable. Should be able to be checked out from subver sion and executed without running chmod. ------------------------------------------------------------------------ Rumble | 2008-02-15 17:03:06 +0100 (Fri, 15 Feb 2008) | 1 line Fixed strcat() writing out of bounds in cedit.c since strdup() only malloc() strlen(str)+1 bytes. (thanks Buggo) and moved attack_hit_text back. ------------------------------------------------------------------------ jeremyosborne | 2008-02-13 20:41:02 +0100 (Wed, 13 Feb 2008) | 1 line Event queue function definitions, global variables and defines doxygenated. ------------------------------------------------------------------------ Rumble | 2008-02-12 00:23:38 +0100 (Tue, 12 Feb 2008) | 1 line Updated levels command to use an arg/range and added color parsing to greetings. (thanks Jamdog) ------------------------------------------------------------------------ jeremyosborne | 2008-02-11 21:06:10 +0100 (Mon, 11 Feb 2008) | 1 line Doxygen comments completed for weather.c ------------------------------------------------------------------------ Rumble | 2008-02-11 03:52:50 +0100 (Mon, 11 Feb 2008) | 1 line Corrected several 64-bit warnings. (thanks Buggo) ------------------------------------------------------------------------ Rumble | 2008-02-10 22:56:56 +0100 (Sun, 10 Feb 2008) | 1 line Added get_flag_by_name allowing for new trigedit variable checks like %actor.pref(FLAG)% checks. (thanks Jamdog) ------------------------------------------------------------------------ jeremyosborne | 2008-02-08 21:22:26 +0100 (Fri, 08 Feb 2008) | 3 lines COMPLETE: tbaMUD code re-org of global and local scope function and variable declarations. There may be a few things that I did not catch (some non extern keyword declarations of function prototypes within other functions, for example). BUG FIX: Unused functions encrypt_hex() and decrypt_hex() removed from mail.c. ------------------------------------------------------------------------ jeremyosborne | 2008-02-05 23:31:09 +0100 (Tue, 05 Feb 2008) | 2 lines Continued clean-up of 'extern' references to functions and variables. BUG UNCOVERED: set_title() in class.c incorrectly handles the const nature of the char * returned from title_female and title_male. ------------------------------------------------------------------------ jeremyosborne | 2008-02-05 19:38:17 +0100 (Tue, 05 Feb 2008) | 3 lines More work on mud clean-up. New file: spec_procs.h Created this file to house the legacy special procedures (spec_procs.c and castle.c) and special feature assignment in general. ------------------------------------------------------------------------ jeremyosborne | 2008-02-05 00:59:44 +0100 (Tue, 05 Feb 2008) | 3 lines - Minor Bugfix: Fixed parse error in mobact.c - Minor Bugfix: act.h is now included in all of the act functions. Forgot to do that the first time :( - Additions: ban.h has been added as the external entry point into the ban.c globals and functions. Files needing ban.h have been updated. ------------------------------------------------------------------------ jeremyosborne | 2008-02-04 20:02:11 +0100 (Mon, 04 Feb 2008) | 1 line All act*.c functions, defines and globals have been prototyped/declared in act.h. The file act.h does not contain every ACMD, only those ACMDs and utility functions available within the act*.c files. ------------------------------------------------------------------------ Rumble | 2008-02-04 17:59:47 +0100 (Mon, 04 Feb 2008) | 1 line Fixed the last few flags missed for the 128 bit conversion. ------------------------------------------------------------------------ Laoris | 2008-02-04 07:27:56 +0100 (Mon, 04 Feb 2008) | 3 lines Adding a column formatter for lists. Accepts printf-like arguments. Only used by medit right now. ------------------------------------------------------------------------ jeremyosborne | 2008-02-04 07:09:19 +0100 (Mon, 04 Feb 2008) | 2 lines - Changed the 'struct queue' to 'struct dg_queue' to avoid namespace conflicts. - Ongoing cleanup to mud project. ------------------------------------------------------------------------ Rumble | 2008-02-04 00:07:09 +0100 (Mon, 04 Feb 2008) | 1 line Fixed run_autowiz which ran twice on advancement. ------------------------------------------------------------------------ jeremyosborne | 2008-02-03 03:46:22 +0100 (Sun, 03 Feb 2008) | 1 line act.h created and added. This header will be the external entry point for the functions, function subcommands and variables within the act*.c files. It is not designed to be the entry point for all ACMD functions. ------------------------------------------------------------------------ jeremyosborne | 2008-02-03 02:44:29 +0100 (Sun, 03 Feb 2008) | 1 line Merge of another part of the code cleanup, the dg script stuff. ------------------------------------------------------------------------ jeremyosborne | 2008-02-02 08:56:03 +0100 (Sat, 02 Feb 2008) | 1 line Modularizing and organizing files continues. Committing comm.c and comm.h because they are hairy, and I don't want to do them over if my hard drive crashes. ------------------------------------------------------------------------ jeremyosborne | 2008-02-02 07:05:08 +0100 (Sat, 02 Feb 2008) | 4 lines - Marking all file scope functions as 'static' - Reorganization of the global variables and functions. ------------------------------------------------------------------------ jeremyosborne | 2008-01-31 10:20:47 +0100 (Thu, 31 Jan 2008) | 1 line * Protected the conf.h.* system config files from multiple calls. ------------------------------------------------------------------------ jeremyosborne | 2008-01-31 09:56:18 +0100 (Thu, 31 Jan 2008) | 1 line * Removed extraneous references to TRUE / FALSE and YES / NO defines. ------------------------------------------------------------------------ jeremyosborne | 2008-01-31 09:46:20 +0100 (Thu, 31 Jan 2008) | 2 lines * BUGFIX: NUM_POSITIONS set to 8 (was incorrectly set to 15 before) * Migrated NUM_* settings from oasis.h to more appropriate locations near where they are defined. (For Example: NUM_POSITIONS moved to structs.h next to the POSITION_* defines.) ------------------------------------------------------------------------ jeremyosborne | 2008-01-31 03:58:28 +0100 (Thu, 31 Jan 2008) | 1 line Added Appendix A - Coder Support. Right now, it simply speaks to the fact that we have included doxygen config files, are working to document the source code, and provides a rudimentary "do this" guide to create the doxygen cross references. ------------------------------------------------------------------------ jeremyosborne | 2008-01-30 07:12:07 +0100 (Wed, 30 Jan 2008) | 2 lines - All .h files now have doxygen recognized headers, and the format is slightly altered to ease editing of headers. - Protected all .h files from multiple calls. (Standard format is #ifndef _HEADE R_H_ #define _HEADER_H_ .... #endif) ------------------------------------------------------------------------ jeremyosborne | 2008-01-29 11:18:14 +0100 (Tue, 29 Jan 2008) | 1 line constants.h, structs.h and utils.h now protected from multiple includes. This is sometimes overkill, but good practice overall. ------------------------------------------------------------------------ jeremyosborne | 2008-01-29 10:38:18 +0100 (Tue, 29 Jan 2008) | 1 line Updated documentation for constants.c and constants.h. ------------------------------------------------------------------------ jeremyosborne | 2008-01-29 10:15:25 +0100 (Tue, 29 Jan 2008) | 3 lines The standard Doxygen configuration doxyfiles (config files) for tbaMUD. One is to be used with the Graphviz DOT (dox_withGraphs), one is designed to be used if Graphviz is not available. Now just need a short document describing the usage of doxygen. ------------------------------------------------------------------------ jeremyosborne | 2008-01-29 10:11:36 +0100 (Tue, 29 Jan 2008) | 1 line Minor document correction in struct dex_app_tpe. ------------------------------------------------------------------------ jeremyosborne | 2008-01-28 20:53:51 +0100 (Mon, 28 Jan 2008) | 1 line *bugfix* do_drink command: When a container is empty, the correct, "It is empty." message is now displayed. ------------------------------------------------------------------------ jeremyosborne | 2008-01-28 07:58:15 +0100 (Mon, 28 Jan 2008) | 3 lines Merging changes to trunk for: * utils.h, utils.c and structs.h doxygen comments * adding file dox_withGraphs.doxyfile
2008-04-12 01:31:58 +00:00
#include "act.h"
#include "fight.h"
2006-12-19 22:56:18 +00:00
/* Special spells appear below. */
2006-12-19 22:56:18 +00:00
ASPELL(spell_create_water)
{
int water;
if (ch == NULL || obj == NULL)
return;
/* level = MAX(MIN(level, LVL_IMPL), 1); - not used */
if (GET_OBJ_TYPE(obj) == ITEM_DRINKCON) {
if ((GET_OBJ_VAL(obj, 2) != LIQ_WATER) && (GET_OBJ_VAL(obj, 1) != 0)) {
name_from_drinkcon(obj);
GET_OBJ_VAL(obj, 2) = LIQ_SLIME;
name_to_drinkcon(obj, LIQ_SLIME);
} else {
water = MAX(GET_OBJ_VAL(obj, 0) - GET_OBJ_VAL(obj, 1), 0);
if (water > 0) {
if (GET_OBJ_VAL(obj, 1) >= 0)
name_from_drinkcon(obj);
GET_OBJ_VAL(obj, 2) = LIQ_WATER;
GET_OBJ_VAL(obj, 1) += water;
name_to_drinkcon(obj, LIQ_WATER);
weight_change_object(obj, water);
act("$p is filled.", FALSE, ch, obj, 0, TO_CHAR);
}
}
}
}
ASPELL(spell_recall)
{
if (victim == NULL || IS_NPC(victim))
return;
if (ZONE_FLAGGED(GET_ROOM_ZONE(IN_ROOM(victim)), ZONE_NOASTRAL)) {
send_to_char(ch, "A bright flash prevents your spell from working!");
return;
}
2006-12-19 22:56:18 +00:00
act("$n disappears.", TRUE, victim, 0, 0, TO_ROOM);
char_from_room(victim);
char_to_room(victim, r_mortal_start_room);
act("$n appears in the middle of the room.", TRUE, victim, 0, 0, TO_ROOM);
look_at_room(victim, 0);
entry_memory_mtrigger(victim);
greet_mtrigger(victim, -1);
greet_memory_mtrigger(victim);
}
ASPELL(spell_teleport)
{
room_rnum to_room;
if (victim == NULL || IS_NPC(victim))
return;
if (ZONE_FLAGGED(GET_ROOM_ZONE(IN_ROOM(victim)), ZONE_NOASTRAL)) {
send_to_char(ch, "A bright flash prevents your spell from working!");
return;
}
2006-12-19 22:56:18 +00:00
do {
to_room = rand_number(0, top_of_world);
} while (ROOM_FLAGGED(to_room, ROOM_PRIVATE) || ROOM_FLAGGED(to_room, ROOM_DEATH) ||
ROOM_FLAGGED(to_room, ROOM_GODROOM) || ZONE_FLAGGED(GET_ROOM_ZONE(to_room), ZONE_CLOSED) ||
ZONE_FLAGGED(GET_ROOM_ZONE(to_room), ZONE_NOASTRAL));
2006-12-19 22:56:18 +00:00
act("$n slowly fades out of existence and is gone.",
FALSE, victim, 0, 0, TO_ROOM);
char_from_room(victim);
char_to_room(victim, to_room);
act("$n slowly fades into existence.", FALSE, victim, 0, 0, TO_ROOM);
look_at_room(victim, 0);
entry_memory_mtrigger(victim);
greet_mtrigger(victim, -1);
greet_memory_mtrigger(victim);
}
#define SUMMON_FAIL "You failed.\r\n"
ASPELL(spell_summon)
{
if (ch == NULL || victim == NULL)
return;
if (GET_LEVEL(victim) > MIN(LVL_IMMORT - 1, level + 3)) {
send_to_char(ch, "%s", SUMMON_FAIL);
return;
}
if (ZONE_FLAGGED(GET_ROOM_ZONE(IN_ROOM(victim)), ZONE_NOASTRAL) ||
ZONE_FLAGGED(GET_ROOM_ZONE(IN_ROOM(ch)), ZONE_NOASTRAL)) {
send_to_char(ch, "A bright flash prevents your spell from working!");
return;
}
2006-12-19 22:56:18 +00:00
if (!CONFIG_PK_ALLOWED) {
if (MOB_FLAGGED(victim, MOB_AGGRESSIVE)) {
act("As the words escape your lips and $N travels\r\n"
"through time and space towards you, you realize that $E is\r\n"
"aggressive and might harm you, so you wisely send $M back.",
FALSE, ch, 0, victim, TO_CHAR);
return;
}
if (!IS_NPC(victim) && !PRF_FLAGGED(victim, PRF_SUMMONABLE) &&
!PLR_FLAGGED(victim, PLR_KILLER)) {
send_to_char(victim, "%s just tried to summon you to: %s.\r\n"
"%s failed because you have summon protection on.\r\n"
"Type NOSUMMON to allow other players to summon you.\r\n",
GET_NAME(ch), world[IN_ROOM(ch)].name,
(ch->player.sex == SEX_MALE) ? "He" : "She");
send_to_char(ch, "You failed because %s has summon protection on.\r\n", GET_NAME(victim));
mudlog(BRF, LVL_IMMORT, TRUE, "%s failed summoning %s to %s.", GET_NAME(ch), GET_NAME(victim), world[IN_ROOM(ch)].name);
return;
}
}
if (MOB_FLAGGED(victim, MOB_NOSUMMON) ||
(IS_NPC(victim) && mag_savingthrow(victim, SAVING_SPELL, 0))) {
send_to_char(ch, "%s", SUMMON_FAIL);
return;
}
act("$n disappears suddenly.", TRUE, victim, 0, 0, TO_ROOM);
char_from_room(victim);
char_to_room(victim, IN_ROOM(ch));
act("$n arrives suddenly.", TRUE, victim, 0, 0, TO_ROOM);
act("$n has summoned you!", FALSE, ch, 0, victim, TO_VICT);
look_at_room(victim, 0);
entry_memory_mtrigger(victim);
greet_mtrigger(victim, -1);
greet_memory_mtrigger(victim);
}
/* Used by the locate object spell to check the alias list on objects */
int isname_obj(char *search, char *list)
{
char *found_in_list; /* But could be something like 'ring' in 'shimmering.' */
char searchname[128];
char namelist[MAX_STRING_LENGTH];
int found_pos = -1;
int found_name=0; /* found the name we're looking for */
int match = 1;
int i;
/* Force to lowercase for string comparisons */
sprintf(searchname, "%s", search);
for (i = 0; searchname[i]; i++)
searchname[i] = LOWER(searchname[i]);
sprintf(namelist, "%s", list);
for (i = 0; namelist[i]; i++)
namelist[i] = LOWER(namelist[i]);
/* see if searchname exists any place within namelist */
found_in_list = strstr(namelist, searchname);
if (!found_in_list) {
return 0;
}
2006-12-19 22:56:18 +00:00
/* Found the name in the list, now see if it's a valid hit. The following
* avoids substrings (like ring in shimmering) is it at beginning of
* namelist? */
for (i = 0; searchname[i]; i++)
if (searchname[i] != namelist[i])
match = 0;
if (match) /* It was found at the start of the namelist string. */
found_name = 1;
else { /* It is embedded inside namelist. Is it preceded by a space? */
found_pos = found_in_list - namelist;
if (namelist[found_pos-1] == ' ')
found_name = 1;
}
if (found_name)
return 1;
else
return 0;
}
2006-12-19 22:56:18 +00:00
ASPELL(spell_locate_object)
{
struct obj_data *i;
char name[MAX_INPUT_LENGTH];
int j;
if (!obj) {
send_to_char(ch, "You sense nothing.\r\n");
return;
}
/* added a global var to catch 2nd arg. */
sprintf(name, "%s", cast_arg2);
j = GET_LEVEL(ch) / 2; /* # items to show = twice char's level */
2006-12-19 22:56:18 +00:00
for (i = object_list; i && (j > 0); i = i->next) {
if (!isname_obj(name, i->name))
2006-12-19 22:56:18 +00:00
continue;
send_to_char(ch, "%c%s", UPPER(*i->short_description), i->short_description + 1);
2006-12-19 22:56:18 +00:00
if (i->carried_by)
send_to_char(ch, " is being carried by %s.\r\n", PERS(i->carried_by, ch));
else if (IN_ROOM(i) != NOWHERE)
send_to_char(ch, " is in %s.\r\n", world[IN_ROOM(i)].name);
else if (i->in_obj)
send_to_char(ch, " is in %s.\r\n", i->in_obj->short_description);
else if (i->worn_by)
send_to_char(ch, " is being worn by %s.\r\n", PERS(i->worn_by, ch));
else
send_to_char(ch, "'s location is uncertain.\r\n");
j--;
}
}
ASPELL(spell_charm)
{
struct affected_type af;
if (victim == NULL || ch == NULL)
return;
if (victim == ch)
send_to_char(ch, "You like yourself even better!\r\n");
else if (!IS_NPC(victim) && !PRF_FLAGGED(victim, PRF_SUMMONABLE))
send_to_char(ch, "You fail because SUMMON protection is on!\r\n");
else if (AFF_FLAGGED(victim, AFF_SANCTUARY))
send_to_char(ch, "Your victim is protected by sanctuary!\r\n");
else if (MOB_FLAGGED(victim, MOB_NOCHARM))
send_to_char(ch, "Your victim resists!\r\n");
else if (AFF_FLAGGED(ch, AFF_CHARM))
send_to_char(ch, "You can't have any followers of your own!\r\n");
else if (AFF_FLAGGED(victim, AFF_CHARM) || level < GET_LEVEL(victim))
send_to_char(ch, "You fail.\r\n");
/* player charming another player - no legal reason for this */
else if (!CONFIG_PK_ALLOWED && !IS_NPC(victim))
send_to_char(ch, "You fail - shouldn't be doing it anyway.\r\n");
else if (circle_follow(victim, ch))
send_to_char(ch, "Sorry, following in circles is not allowed.\r\n");
2006-12-19 22:56:18 +00:00
else if (mag_savingthrow(victim, SAVING_PARA, 0))
send_to_char(ch, "Your victim resists!\r\n");
else {
if (victim->master)
stop_follower(victim);
add_follower(victim, ch);
af.type = SPELL_CHARM;
af.duration = 24 * 2;
if (GET_CHA(ch))
af.duration *= GET_CHA(ch);
if (GET_INT(victim))
af.duration /= GET_INT(victim);
af.modifier = 0;
af.location = 0;
af.bitvector = AFF_CHARM;
affect_to_char(victim, &af);
act("Isn't $n just such a nice fellow?", FALSE, ch, 0, victim, TO_VICT);
if (IS_NPC(victim))
2007-05-08 15:20:59 +00:00
REMOVE_BIT_AR(MOB_FLAGS(victim), MOB_SPEC);
2006-12-19 22:56:18 +00:00
}
}
ASPELL(spell_identify)
{
int i, found;
size_t len;
if (obj) {
char bitbuf[MAX_STRING_LENGTH];
sprinttype(GET_OBJ_TYPE(obj), item_types, bitbuf, sizeof(bitbuf));
send_to_char(ch, "You feel informed:\r\nObject '%s', Item type: %s\r\n", obj->short_description, bitbuf);
if (GET_OBJ_AFFECT(obj)) {
2007-05-08 15:20:59 +00:00
sprintbitarray(GET_OBJ_AFFECT(obj), affected_bits, AF_ARRAY_MAX, bitbuf);
2006-12-19 22:56:18 +00:00
send_to_char(ch, "Item will give you following abilities: %s\r\n", bitbuf);
}
2007-08-17 22:58:18 +00:00
sprintbitarray(GET_OBJ_EXTRA(obj), extra_bits, EF_ARRAY_MAX, bitbuf);
2006-12-19 22:56:18 +00:00
send_to_char(ch, "Item is: %s\r\n", bitbuf);
send_to_char(ch, "Weight: %d, Value: %d, Rent: %d, Min. level: %d\r\n",
GET_OBJ_WEIGHT(obj), GET_OBJ_COST(obj), GET_OBJ_RENT(obj), GET_OBJ_LEVEL(obj));
switch (GET_OBJ_TYPE(obj)) {
case ITEM_SCROLL:
case ITEM_POTION:
len = i = 0;
if (GET_OBJ_VAL(obj, 1) >= 1) {
i = snprintf(bitbuf + len, sizeof(bitbuf) - len, " %s", skill_name(GET_OBJ_VAL(obj, 1)));
if (i >= 0)
len += i;
}
if (GET_OBJ_VAL(obj, 2) >= 1 && len < sizeof(bitbuf)) {
i = snprintf(bitbuf + len, sizeof(bitbuf) - len, " %s", skill_name(GET_OBJ_VAL(obj, 2)));
if (i >= 0)
len += i;
}
if (GET_OBJ_VAL(obj, 3) >= 1 && len < sizeof(bitbuf)) {
i = snprintf(bitbuf + len, sizeof(bitbuf) - len, " %s", skill_name(GET_OBJ_VAL(obj, 3)));
if (i >= 0)
len += i;
}
send_to_char(ch, "This %s casts: %s\r\n", item_types[(int) GET_OBJ_TYPE(obj)], bitbuf);
break;
case ITEM_WAND:
case ITEM_STAFF:
send_to_char(ch, "This %s casts: %s\r\nIt has %d maximum charge%s and %d remaining.\r\n",
item_types[(int) GET_OBJ_TYPE(obj)], skill_name(GET_OBJ_VAL(obj, 3)),
GET_OBJ_VAL(obj, 1), GET_OBJ_VAL(obj, 1) == 1 ? "" : "s", GET_OBJ_VAL(obj, 2));
break;
case ITEM_WEAPON:
send_to_char(ch, "Damage Dice is '%dD%d' for an average per-round damage of %.1f.\r\n",
GET_OBJ_VAL(obj, 1), GET_OBJ_VAL(obj, 2), ((GET_OBJ_VAL(obj, 2) + 1) / 2.0) * GET_OBJ_VAL(obj, 1));
break;
case ITEM_ARMOR:
send_to_char(ch, "AC-apply is %d\r\n", GET_OBJ_VAL(obj, 0));
break;
}
found = FALSE;
for (i = 0; i < MAX_OBJ_AFFECT; i++) {
if ((obj->affected[i].location != APPLY_NONE) &&
(obj->affected[i].modifier != 0)) {
if (!found) {
send_to_char(ch, "Can affect you as :\r\n");
found = TRUE;
}
sprinttype(obj->affected[i].location, apply_types, bitbuf, sizeof(bitbuf));
send_to_char(ch, " Affects: %s By %d\r\n", bitbuf, obj->affected[i].modifier);
}
}
} else if (victim) { /* victim */
send_to_char(ch, "Name: %s\r\n", GET_NAME(victim));
if (!IS_NPC(victim))
send_to_char(ch, "%s is %d years, %d months, %d days and %d hours old.\r\n",
GET_NAME(victim), age(victim)->year, age(victim)->month,
age(victim)->day, age(victim)->hours);
send_to_char(ch, "Height %d cm, Weight %d pounds\r\n", GET_HEIGHT(victim), GET_WEIGHT(victim));
send_to_char(ch, "Level: %d, Hits: %d, Mana: %d\r\n", GET_LEVEL(victim), GET_HIT(victim), GET_MANA(victim));
send_to_char(ch, "AC: %d, Hitroll: %d, Damroll: %d\r\n", compute_armor_class(victim), GET_HITROLL(victim), GET_DAMROLL(victim));
send_to_char(ch, "Str: %d/%d, Int: %d, Wis: %d, Dex: %d, Con: %d, Cha: %d\r\n",
GET_STR(victim), GET_ADD(victim), GET_INT(victim),
GET_WIS(victim), GET_DEX(victim), GET_CON(victim), GET_CHA(victim));
}
}
/* Cannot use this spell on an equipped object or it will mess up the wielding
* character's hit/dam totals. */
2006-12-19 22:56:18 +00:00
ASPELL(spell_enchant_weapon)
{
int i;
if (ch == NULL || obj == NULL)
return;
/* Either already enchanted or not a weapon. */
if (GET_OBJ_TYPE(obj) != ITEM_WEAPON || OBJ_FLAGGED(obj, ITEM_MAGIC))
return;
/* Make sure no other affections. */
for (i = 0; i < MAX_OBJ_AFFECT; i++)
if (obj->affected[i].location != APPLY_NONE)
return;
2007-05-08 15:20:59 +00:00
SET_BIT_AR(GET_OBJ_EXTRA(obj), ITEM_MAGIC);
2006-12-19 22:56:18 +00:00
obj->affected[0].location = APPLY_HITROLL;
obj->affected[0].modifier = 1 + (level >= 18);
obj->affected[1].location = APPLY_DAMROLL;
obj->affected[1].modifier = 1 + (level >= 20);
if (IS_GOOD(ch)) {
2007-05-08 15:20:59 +00:00
SET_BIT_AR(GET_OBJ_EXTRA(obj), ITEM_ANTI_EVIL);
2006-12-19 22:56:18 +00:00
act("$p glows blue.", FALSE, ch, obj, 0, TO_CHAR);
} else if (IS_EVIL(ch)) {
2007-05-08 15:20:59 +00:00
SET_BIT_AR(GET_OBJ_EXTRA(obj), ITEM_ANTI_GOOD);
2006-12-19 22:56:18 +00:00
act("$p glows red.", FALSE, ch, obj, 0, TO_CHAR);
} else
act("$p glows yellow.", FALSE, ch, obj, 0, TO_CHAR);
}
ASPELL(spell_detect_poison)
{
if (victim) {
if (victim == ch) {
if (AFF_FLAGGED(victim, AFF_POISON))
send_to_char(ch, "You can sense poison in your blood.\r\n");
else
send_to_char(ch, "You feel healthy.\r\n");
} else {
if (AFF_FLAGGED(victim, AFF_POISON))
act("You sense that $E is poisoned.", FALSE, ch, 0, victim, TO_CHAR);
else
act("You sense that $E is healthy.", FALSE, ch, 0, victim, TO_CHAR);
}
}
if (obj) {
switch (GET_OBJ_TYPE(obj)) {
case ITEM_DRINKCON:
case ITEM_FOUNTAIN:
case ITEM_FOOD:
if (GET_OBJ_VAL(obj, 3))
act("You sense that $p has been contaminated.",FALSE,ch,obj,0,TO_CHAR);
else
act("You sense that $p is safe for consumption.", FALSE, ch, obj, 0,
TO_CHAR);
break;
default:
send_to_char(ch, "You sense that it should not be consumed.\r\n");
}
}
}