/****************************************************************************
* [S]imulated [M]edieval [A]dventure multi[U]ser [G]ame | \\._.// *
* -----------------------------------------------------------| (0...0) *
* SMAUG 1.4 (C) 1994, 1995, 1996, 1998 by Derek Snider | ).:.( *
* -----------------------------------------------------------| {o o} *
* SMAUG code team: Thoric, Altrag, Blodkai, Narn, Haus, | / ' ' \ *
* Scryn, Rennard, Swordbearer, Gorog, Grishnakh, Nivek, |~'~.VxvxV.~'~*
* Tricops and Fireblade | *
*------------------------------------------------------------------------ *
* Shaddai's Polymorph *
****************************************************************************/
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include "mud.h"
#if defined(KEY)
#undef KEY
#endif
#define KEY( literal, field, value ) \
if ( !str_cmp( word, literal ) ) \
{ \
field = value; \
fMatch = TRUE; \
break; \
}
MORPH_DATA *morph_start = NULL;
MORPH_DATA *morph_end = NULL;
int morph_vnum = 0;
/*
* Local functions
*/
void copy_morph args ( ( MORPH_DATA *morph, MORPH_DATA *temp ) );
/*
* Extern prototypes
*/
int get_risflag args( ( char *flag ) );
int get_npc_race args( ( char *type ) );
int get_pc_race args( ( char *type ) );
/*
* Command used to set all the morphing information.
* Must use the morphset save command, to write the commands to file.
* Blood/Hp/Mana/Move/Hitroll/Damroll can be set using variables such
* as 1d2+10. No boundry checks are in place yet on those, so care must
* be taken when using these. --Shaddai
*/
void
do_morphset ( CHAR_DATA *ch, char *argument )
{
char arg1[MAX_INPUT_LENGTH];
char arg2[MAX_INPUT_LENGTH];
char arg3[MAX_INPUT_LENGTH];
char buf[MAX_STRING_LENGTH];
char *origarg = argument;
int value;
MORPH_DATA *morph = NULL;
set_char_color (AT_PLAIN, ch);
if (IS_NPC (ch))
{
send_to_char ("Mob's can't morphset\n\r", ch);
return;
}
if (!ch->desc)
{
send_to_char ("You have no descriptor\n\r", ch);
return;
}
switch( ch->substate )
{
default:
break;
case SUB_MORPH_DESC:
if ( !ch->dest_buf )
{
send_to_char( "Fatal error: report to Shaddai.\n\r", ch );
bug( "do_morphset: sub_morph_desc: NULL ch->dest_buf", 0 );
ch->substate = SUB_NONE;
return;
}
morph = ch->dest_buf;
STRFREE( morph->description );
morph->description = copy_buffer( ch );
stop_editing( ch );
ch->substate = ch->tempnum;
if ( ch->substate == SUB_REPEATCMD )
ch->dest_buf = morph;
return;
case SUB_MORPH_HELP:
if ( !ch->dest_buf )
{
send_to_char( "Fatal error: report to Shaddai.\n\r", ch );
bug( "do_morphset: sub_morph_help: NULL ch->dest_buf", 0 );
ch->substate = SUB_NONE;
return;
}
morph = ch->dest_buf;
STRFREE( morph->help );
morph->help = copy_buffer( ch );
stop_editing( ch );
ch->substate = ch->tempnum;
if ( ch->substate == SUB_REPEATCMD )
ch->dest_buf = morph;
return;
}
morph = NULL;
smash_tilde (argument);
if ( ch->substate == SUB_REPEATCMD )
{
morph = ch->dest_buf;
if ( !morph )
{
send_to_char ("Someone deleted your morph!\n\r", ch);
argument = "done";
}
if (argument[0] == '\0' || !str_cmp (argument, " ") )
{
do_morphstat( ch, morph->name );
return;
}
if ( !str_cmp( argument, "stat" ) )
{
strcpy ( buf, morph->name );
strcat ( buf, " help" );
do_morphstat( ch, buf );
return;
}
if ( !str_cmp (argument, "done") || !str_cmp (argument, "off"))
{
send_to_char ("Morphset mode off.\n\r", ch);
ch->substate = SUB_NONE;
ch->dest_buf = NULL;
if (ch->pcdata && ch->pcdata->subprompt) {
STRFREE (ch->pcdata->subprompt);
ch->pcdata->subprompt = NULL;
}
return;
}
}
if ( morph )
{
strcpy (arg1, morph->name);
argument = one_argument (argument, arg2);
strcpy (arg3, argument);
}
else
{
argument = one_argument (argument, arg1);
argument = one_argument (argument, arg2);
strcpy (arg3, argument);
}
if (!str_cmp (arg1, "on"))
{
send_to_char ("Syntax: morphset <morph> on.\n\r", ch);
return;
}
value = is_number( arg3 ) ? atoi( arg3 ) : -1;
if ( atoi(arg3) < -1 && value == -1 )
value = atoi(arg3);
if ( ch->substate != SUB_REPEATCMD && arg1[0] != '\0' &&
!str_cmp( arg1, "save" ) )
{
save_morphs( );
send_to_char ("Morph data saved.\n\r", ch);
return;
}
if (arg1[0] == '\0' || (arg2[0] == '\0' && ch->substate != SUB_REPEATCMD)
|| !str_cmp (arg1, "?"))
{
if (ch->substate == SUB_REPEATCMD)
{
if (morph)
send_to_char ("Syntax: <field> <value>\n\r", ch);
else
send_to_char ("Syntax: <morph> <field> <value>\n\r", ch);
}
else
send_to_char ("Syntax: morphset <morph> <field> <value>\n\r", ch);
send_to_char ("Syntax: morphset save\n\r", ch);
send_to_char ("\n\r", ch);
send_to_char_color ("&cField being one of:\n\r", ch);
send_to_char_color ("&c-------------------------------------------------\n\r",ch);
send_to_char (" ac, affected, blood, bloodused, cha, class, con, damroll, dayto,\n\r",ch);
send_to_char (" dayfrom, deity, description, defpos, dex, dodge,\n\r",ch);
send_to_char (" favourused, gloryused, help, hitroll, hp, hpused, immune,\n\r",ch);
send_to_char (" int, str, keyword, lck, level, long, mana, manaused,\n\r", ch);
send_to_char (" morphother, morphself, move, moveused, name, noaffected,\n\r",ch);
send_to_char (" nocast, noimmune, noresistant, noskill, nosusceptible,\n\r",ch);
send_to_char (" obj1, obj2, obj3, objuse1, objuse2, objuse3, parry,\n\r", ch);
send_to_char (" pkill, race, resistant, sav1, sav2, sav3, sav4, sav5,\n\r",ch);
send_to_char (" sex, short, skills, susceptible, timefrom, timer, timeto,\n\r", ch);
send_to_char (" tumble, unmorphother, unmorphself, wis.\n\r", ch );
send_to_char_color ("&c-------------------------------------------------\n\r",ch);
return;
}
if ( !morph ) {
if ( !is_number( arg1 ) )
morph = get_morph( arg1 );
else
morph = get_morph_vnum( atoi(arg1) );
if ( morph == NULL ) {
send_to_char ("That morph does not exist.\n\r", ch );
return;
}
}
if (!str_cmp (arg2, "on"))
{
CHECK_SUBRESTRICTED (ch);
ch_printf (ch, "Morphset mode on. (Editing %s).\n\r",
morph->name);
ch->substate = SUB_REPEATCMD;
ch->dest_buf = morph;
if (ch->pcdata)
{
if (ch->pcdata->subprompt) {
STRFREE (ch->pcdata->subprompt);
ch->pcdata->subprompt = NULL;
}
sprintf (buf, "<&CMorphset &W%s&w> %%i", morph->name);
ch->pcdata->subprompt = STRALLOC (buf);
}
return;
}
if (!str_cmp ( arg2, "str" ) )
{
if ( value < -10 || value > 10 )
{
send_to_char("Strength must be a value from -10 to 10.\n\r",ch);
return;
}
morph->str = value;
}
else if (!str_cmp ( arg2, "int" ) )
{
if ( value < -10 || value > 10 )
{
send_to_char("Intelligence must be a value from -10 to 10.\n\r",ch);
return;
}
morph->inte = value;
}
else if (!str_cmp ( arg2, "wis" ) )
{
if ( value < -10 || value > 10 )
{
send_to_char("Wisdom must be a value from -10 to 10.\n\r",ch);
return;
}
morph->wis = value;
}
else if (!str_cmp ( arg2, "defpos" ) )
{
if (value < 0 || value > POS_STANDING)
{
ch_printf (ch, "Position range is 0 to %d.\n\r", POS_STANDING);
return;
}
morph->defpos = value;
}
else if (!str_cmp ( arg2, "dex" ) )
{
if ( value < -10 || value > 10 )
{
send_to_char("Dexterity must be a value from -10 to 10.\n\r",ch);
return;
}
morph->dex = value;
}
else if (!str_cmp ( arg2, "con" ) )
{
if ( value < -10 || value > 10 )
{
send_to_char("Constitution must be a value from -10 to 10.\n\r",ch);
return;
}
morph->con = value;
}
else if (!str_cmp ( arg2, "cha" ) )
{
if ( value < -10 || value > 10 )
{
send_to_char("Charisma must be a value from -10 to 10.\n\r",ch);
return;
}
morph->cha = value;
}
else if (!str_cmp ( arg2, "lck" ) )
{
if ( value < -10 || value > 10 )
{
send_to_char("Luck must be a value from -10 to 10.\n\r",ch);
return;
}
morph->lck = value;
}
else if (!str_cmp ( arg2, "sex") )
{
if ( (value < 0 || value > 2) && value != -1)
{
send_to_char("Sex must be a value from 0 to 2.\n\r", ch );
return;
}
morph->sex = value;
}
else if ( !str_cmp ( arg2, "pkill") )
{
if ( !str_cmp ( arg3, "pkill" ) )
morph->pkill = ONLY_PKILL;
else if ( !str_cmp( arg3, "peace" ) )
morph->pkill = ONLY_PEACEFULL;
else if ( !str_cmp( arg3, "none" ) )
morph->pkill = 0;
else
{
send_to_char("Usuage: morphset <morph> pkill [pkill|peace|none]\n\r", ch );
return;
}
}
else if (!str_cmp ( arg2, "bloodused") )
{
if ( value < 0 || value > 60 )
{
send_to_char("Blood used is a value from 0 to 60.\n\r", ch );
return;
}
morph->bloodused = value;
}
else if (!str_cmp ( arg2, "manaused") )
{
if ( value < 0 || value > 2000 )
{
send_to_char("Mana used is a value from 0 to 2000.\n\r", ch );
return;
}
morph->manaused = value;
}
else if (!str_cmp( arg2, "moveused") )
{
if ( value < 0 || value > 2000 )
{
send_to_char("Move used is a value from 0 to 2000.\n\r", ch );
return;
}
morph->moveused = value;
}
else if (!str_cmp( arg2, "hpused") )
{
if ( value < 0 || value > 2000 )
{
send_to_char("Hp used is a value from 0 to 2000.\n\r", ch );
return;
}
morph->hpused = value;
}
else if ( !str_cmp( arg2, "favourused") )
{
if ( value < 0 || value > 2000 )
{
send_to_char("Favour used is a value from 0 to 2000.\n\r", ch );
return;
}
morph->favourused = value;
}
else if ( !str_cmp( arg2, "gloryused") )
{
if ( value < 0 || value > 2000 )
{
send_to_char("Glory used is a value from 0 to 2000.\n\r",ch);
return;
}
morph->gloryused = value;
}
else if ( !str_cmp( arg2, "timeto") )
{
if ( value < 0 || value > 23 )
{
send_to_char("Timeto is a value from 0 to 23.\n\r", ch );
return;
}
morph->timeto = value;
}
else if ( !str_cmp( arg2, "timefrom") )
{
if ( value < 0 || value > 23 )
{
send_to_char("Timefrom is a value from 0 to 23.\n\r", ch );
return;
}
morph->timefrom = value;
}
else if ( !str_cmp( arg2, "dayto") )
{
if ( value < 0 || value > 31 )
{
send_to_char("Dayto is a value from 0 to 31.\n\r", ch );
return;
}
morph->dayto = value;
}
else if ( !str_cmp( arg2, "dayfrom") )
{
if ( value < 0 || value > 31 )
{
send_to_char("Dayfrom is a value from 0 to 31.\n\r", ch );
return;
}
morph->dayfrom = value;
}
else if (!str_cmp ( arg2, "sav1" ) || !str_cmp( arg2, "savepoison") )
{
if (value < -30 || value > 30)
{
send_to_char ("Saving throw range is -30 to 30.\n\r", ch);
return;
}
morph->saving_poison_death = value;
}
else if (!str_cmp ( arg2, "sav2" ) || !str_cmp( arg2, "savewand") )
{
if (value < -30 || value > 30)
{
send_to_char ("Saving throw range is -30 to 30.\n\r", ch);
return;
}
morph->saving_wand = value;
}
else if (!str_cmp ( arg2, "sav3" ) || !str_cmp( arg2, "savepara") )
{
if (value < -30 || value > 30)
{
send_to_char ("Saving throw range is -30 to 30.\n\r", ch);
return;
}
morph->saving_para_petri = value;
}
else if (!str_cmp ( arg2, "sav4" ) || !str_cmp( arg2, "savebreath") )
{
if (value < -30 || value > 30)
{
send_to_char ("Saving throw range is -30 to 30.\n\r", ch);
return;
}
morph->saving_breath = value;
}
else if (!str_cmp ( arg2, "sav5" ) || !str_cmp( arg2, "savestaff") )
{
if (value < -30 || value > 30)
{
send_to_char ("Saving throw range is -30 to 30.\n\r", ch);
return;
}
morph->saving_spell_staff = value;
}
else if (!str_cmp ( arg2, "timer" ) )
{
if ( value < -1 || value == 0 )
{
send_to_char ("Timer must be -1 (None) or greater than 0.\n\r", ch);
return;
}
morph->timer = value;
}
else if (!str_cmp ( arg2, "hp" ) )
{
argument = one_argument( argument, arg3 );
if ( !str_cmp ( arg3, "0"))
arg3[0] = '\0';
morph->hit = str_dup( arg3 );
}
else if (!str_cmp ( arg2, "mana" ) )
{
argument = one_argument( argument, arg3 );
if ( !str_cmp ( arg3, "0"))
arg3[0] = '\0';
morph->mana = str_dup( arg3 );
}
else if (!str_cmp ( arg2, "move" ) )
{
argument = one_argument( argument, arg3 );
if ( !str_cmp ( arg3, "0"))
arg3[0] = '\0';
morph->move = str_dup( arg3 );
}
else if (!str_cmp ( arg2, "blood" ) )
{
argument = one_argument( argument, arg3 );
if ( !str_cmp ( arg3, "0"))
arg3[0] = '\0';
morph->blood = str_dup( arg3 );
}
else if (!str_cmp ( arg2, "ac" ) )
{
if ( value > 500 || value < -500 )
{
send_to_char("Ac range is -500 to 500.\n\r", ch);
return;
}
morph->ac = value;
}
else if ( !str_cmp ( arg2, "hitroll" ) )
{
argument = one_argument( argument, arg3 );
if ( !str_cmp ( arg3, "0"))
arg3[0] = '\0';
morph->hitroll = str_dup( arg3 );
}
else if ( !str_cmp ( arg2, "damroll" ) )
{
argument = one_argument( argument, arg3 );
if ( !str_cmp ( arg3, "0"))
arg3[0] = '\0';
morph->damroll = str_dup( arg3 );
}
else if ( !str_cmp ( arg2, "dodge" ) )
{
if ( value > 100 || value < -100 )
{
send_to_char ("Dodge range is -100 to 100.\n\r", ch );
return;
}
morph->dodge = value;
}
else if ( !str_prefix( "obj", arg2) )
{
int index;
char temp[MAX_STRING_LENGTH];
if ( arg2[3] == '\0' )
{
send_to_char("Obj 1, 2, or 3.\n\r", ch );
return;
}
temp[0] = arg2[3];
temp[1] = '\0';
index = atoi(temp);
if ( index >3 || index < 1 )
{
send_to_char("Obj 1, 2, or 3.\n\r", ch );
return;
}
if ( ( get_obj_index( value ) ) == NULL )
{
send_to_char("No such vnum.\n\r", ch );
return;
}
morph->obj[index-1] = value;
}
else if ( !str_cmp ( arg2, "parry" ) )
{
if ( value > 100 || value < -100 )
{
send_to_char ("Dodge range is -100 to 100.\n\r", ch );
return;
}
morph->parry = value;
}
else if ( !str_cmp ( arg2, "tumble" ) )
{
if ( value > 100 || value < -100 )
{
send_to_char ("Dodge range is -100 to 100.\n\r", ch );
return;
}
morph->tumble = value;
}
else if ( !str_cmp ( arg2, "level" ) )
{
if ( value < 0 || value > 51 )
{
send_to_char ("Level range is 0 to 51.\n\r", ch);
return;
}
morph->level = value;
}
else if ( !str_prefix ( arg2, "objuse" ) )
{
int index;
char temp[MAX_INPUT_LENGTH];
if ( arg2[6] == '\0' )
{
send_to_char("Objuse 1, 2 or 3?\n\r", ch );
return;
}
temp[0] = arg2[6];
temp[1] = '\0';
index = atoi( temp );
if ( index > 3 || index < 1 )
{
send_to_char("Objuse 1, 2, or 3?\n\r", ch );
return;
}
if ( value )
morph->objuse[index-1] = TRUE;
else
morph->objuse[index-1] = FALSE;
}
else if ( !str_cmp ( arg2, "nocast" ) )
{
if ( value )
morph->no_cast = TRUE;
else
morph->no_cast = FALSE;
}
else if ( !str_cmp ( arg2, "resistant" ) || !str_cmp( arg2, "r") )
{
if ( !argument || argument[0] == '\0' )
{
send_to_char( "Usage: morphset <morph> resistant <flag> [flag]...\n\r", ch );
return;
}
while ( argument[0] != '\0' )
{
argument = one_argument( argument, arg3 );
value = get_risflag( arg3 );
if ( value < 0 || value > 31 )
ch_printf( ch, "Unknown flag: %s\n\r", arg3 );
else
TOGGLE_BIT( morph->resistant, 1 << value );
}
}
else if ( !str_cmp ( arg2, "susceptible" ) || !str_cmp( arg2, "s" ) )
{
if ( !argument || argument[0] == '\0' )
{
send_to_char( "Usage: morphset <morph> susceptible <flag> [flag]...\n\r", ch );
return;
}
while ( argument[0] != '\0' )
{
argument = one_argument( argument, arg3 );
value = get_risflag( arg3 );
if ( value < 0 || value > 31 )
ch_printf( ch, "Unknown flag: %s\n\r", arg3 );
else
TOGGLE_BIT( morph->suscept, 1 << value );
}
}
else if ( !str_cmp ( arg2, "immune" ) || !str_cmp( arg2, "i" ) )
{
if ( !argument || argument[0] == '\0' )
{
send_to_char( "Usage: morphset <morph> immune <flag> [flag]...\n\r", ch );
return;
}
while ( argument[0] != '\0' )
{
argument = one_argument( argument, arg3 );
value = get_risflag( arg3 );
if ( value < 0 || value > 31 )
ch_printf( ch, "Unknown flag: %s\n\r", arg3 );
else
TOGGLE_BIT( morph->immune, 1 << value );
}
}
else if ( !str_cmp ( arg2, "noresistant" ) || !str_cmp( arg2, "nr") )
{
if ( !argument || argument[0] == '\0' )
{
send_to_char( "Usage: morphset <morph> noresistant <flag> [flag]...\n\r", ch );
return;
}
while ( argument[0] != '\0' )
{
argument = one_argument( argument, arg3 );
value = get_risflag( arg3 );
if ( value < 0 || value > 31 )
ch_printf( ch, "Unknown flag: %s\n\r", arg3 );
else
TOGGLE_BIT( morph->no_resistant, 1 << value );
}
}
else if ( !str_cmp ( arg2, "nosusceptible" ) || !str_cmp( arg2, "ns" ) )
{
if ( !argument || argument[0] == '\0' )
{
send_to_char( "Usage: morphset <morph> nosusceptible <flag> [flag]...\n\r", ch );
return;
}
while ( argument[0] != '\0' )
{
argument = one_argument( argument, arg3 );
value = get_risflag( arg3 );
if ( value < 0 || value > 31 )
ch_printf( ch, "Unknown flag: %s\n\r", arg3 );
else
TOGGLE_BIT( morph->no_suscept, 1 << value );
}
}
else if ( !str_cmp ( arg2, "noimmune" ) || !str_cmp( arg2, "ni" ) )
{
if ( !argument || argument[0] == '\0' )
{
send_to_char( "Usage: morphset <morph> noimmune <flag> [flag]...\n\r", ch );
return;
}
while ( argument[0] != '\0' )
{
argument = one_argument( argument, arg3 );
value = get_risflag( arg3 );
if ( value < 0 || value > 31 )
ch_printf( ch, "Unknown flag: %s\n\r", arg3 );
else
TOGGLE_BIT( morph->no_immune, 1 << value );
}
}
else if ( !str_cmp ( arg2, "affected" ) || !str_cmp( arg2, "aff" ) )
{
if ( !argument || argument[0] == '\0' )
{
send_to_char( "Usage: morphset <morph> affected <flag> [flag]...\n\r", ch );
return;
}
while ( argument[0] != '\0' )
{
argument = one_argument( argument, arg3 );
value = get_aflag( arg3 );
if ( value < 0 || value > MAX_BITS )
ch_printf( ch, "Unknown flag: %s\n\r", arg3 );
else
xTOGGLE_BIT( morph->affected_by, value );
}
}
else if ( !str_cmp ( arg2, "noaffected" ) || !str_cmp( arg2, "naff" ) )
{
if ( !argument || argument[0] == '\0' )
{
send_to_char( "Usage: morphset <morph> noaffected <flag> [flag]...\n\r", ch );
return;
}
while ( argument[0] != '\0' )
{
argument = one_argument( argument, arg3 );
value = get_aflag( arg3 );
if ( value < 0 || value > MAX_BITS )
ch_printf( ch, "Unknown flag: %s\n\r", arg3 );
else
xTOGGLE_BIT( morph->no_affected_by, value );
}
}
else if ( !str_cmp( arg2, "short" ) )
{
STRFREE( morph->short_desc );
morph->short_desc = STRALLOC( arg3 );
}
else if ( !str_cmp( arg2, "morphother" ) )
{
STRFREE( morph->morph_other );
morph->morph_other = STRALLOC( arg3 );
}
else if ( !str_cmp( arg2, "morphself" ) )
{
STRFREE( morph->morph_self );
morph->morph_self = STRALLOC( arg3 );
}
else if ( !str_cmp( arg2, "unmorphother" ) )
{
STRFREE( morph->unmorph_other );
morph->unmorph_other = STRALLOC( arg3 );
}
else if ( !str_cmp( arg2, "unmorphself" ) )
{
STRFREE( morph->unmorph_self );
morph->unmorph_self = STRALLOC( arg3 );
}
else if ( !str_cmp( arg2, "keyword" ) )
{
STRFREE( morph->key_words );
morph->key_words = STRALLOC( arg3 );
}
else if ( !str_cmp( arg2, "long" ) )
{
STRFREE( morph->long_desc );
strcpy( buf, arg3 );
strcat( buf, "\n\r" );
morph->long_desc = STRALLOC( buf );
}
else if ( !str_cmp( arg2, "description") || !str_cmp( arg2, "desc" ) )
{
if ( arg3[0] )
{
STRFREE( morph->description );
morph->description = STRALLOC( arg3 );
}
CHECK_SUBRESTRICTED( ch );
if ( ch->substate == SUB_REPEATCMD )
ch->tempnum = SUB_REPEATCMD;
else
ch->tempnum = SUB_NONE;
ch->substate = SUB_MORPH_DESC;
ch->dest_buf = morph;
start_editing( ch, morph->description );
return;
}
else if ( !str_cmp( arg2, "name") )
{
STRFREE( morph->name );
morph->name = STRALLOC( arg3 );
}
else if ( !str_cmp( arg2, "help" ) )
{
if ( arg3[0] )
{
STRFREE( morph->help );
morph->help = STRALLOC( arg3 );
}
CHECK_SUBRESTRICTED( ch );
if ( ch->substate == SUB_REPEATCMD )
ch->tempnum = SUB_REPEATCMD;
else
ch->tempnum = SUB_NONE;
ch->substate = SUB_MORPH_HELP;
ch->dest_buf = morph;
start_editing( ch, morph->help );
return;
}
else if ( !str_cmp ( arg2, "skills" ) )
{
if ( !morph->skills )
morph->skills = str_dup ("");
if ( arg3[0] == '\0' || !str_cmp( arg3, "none" ) )
{
DISPOSE ( morph->skills );
morph->skills = str_dup ("");
return;
}
sprintf ( buf, "%s %s", morph->skills, arg3 );
DISPOSE ( morph->skills );
morph->skills = str_dup ( buf );
}
else if ( !str_cmp ( arg2, "noskills" ) )
{
if ( !morph->no_skills )
morph->no_skills = str_dup ("");
if ( arg3[0] == '\0' || !str_cmp( arg3, "none" ) )
{
DISPOSE ( morph->no_skills );
morph->no_skills = str_dup ("");
return;
}
sprintf ( buf, "%s %s", morph->no_skills, arg3 );
DISPOSE ( morph->no_skills );
morph->no_skills = str_dup ( buf );
}
else if ( !str_cmp ( arg2, "class" ) )
{
if ( !is_number( arg3 ) )
{
int i;
for ( i = 0; i < MAX_PC_CLASS; i++ )
if ( !str_cmp ( class_table[i]->who_name, arg3 ) )
break;
value = i;
}
if (value < 0 || value >= MAX_PC_CLASS)
{
ch_printf (ch, "Class range is 0 to %d.\n", MAX_PC_CLASS);
return;
}
TOGGLE_BIT ( morph->class, ( 1 << value) );
}
else if ( !str_cmp ( arg2, "race" ) )
{
if ( is_number( arg3 ) )
value = atoi (arg3);
else
value = get_pc_race (arg3);
if ( value < 0 && !is_number( arg3 ) )
{
ch_printf (ch, "Unknown race: %s", arg3 );
return;
}
else if ( value < 0 || value >= MAX_PC_RACE )
{
ch_printf (ch, "Race range is 0 to %d.\n", MAX_PC_RACE - 1);
return;
}
TOGGLE_BIT ( morph->race, ( 1 << value) );
}
else if ( ch->substate == SUB_REPEATCMD )
{
ch->substate = SUB_RESTRICTED;
interpret( ch, origarg );
ch->substate = SUB_REPEATCMD;
ch->last_cmd = do_morphset;
}
else
{
do_morphset( ch, "" );
return;
}
send_to_char("Done.\n\r", ch );
return;
}
/*
* Shows morph info on a given morph.
* To see the description and help file, must use morphstat <morph> help
* Shaddai
*/
void
do_morphstat ( CHAR_DATA *ch, char *argument )
{
MORPH_DATA *morph;
char arg[MAX_INPUT_LENGTH];
int count = 1;
set_pager_color( AT_CYAN, ch );
argument = one_argument( argument, arg );
if ( arg[0] == '\0' )
{
send_to_pager( "Morphstat what?\n\r", ch );
return;
}
if (IS_NPC (ch))
{
send_to_char ("Mob's can't morphstat\n\r", ch);
return;
}
if ( !str_cmp ( arg, "list") )
{
if ( !morph_start )
{
send_to_pager( "No morph's currently exist.\n\r", ch );
return;
}
for ( morph = morph_start; morph; morph = morph->next )
{
pager_printf_color ( ch, "&c[&C%2d&c] Name: &C%-13s &cVnum: &C%4d &cUsed: &C%3d\n\r",
count, morph->name, morph->vnum, morph->used );
count++;
}
return;
}
if ( !is_number( arg ) )
morph = get_morph( arg );
else
morph = get_morph_vnum( atoi(arg) );
if ( morph == NULL )
{
send_to_pager( "No such morph exists.\n\r", ch );
return;
}
if ( argument[0] == '\0' )
{
pager_printf_color (ch, " &cMorph Name: &C%-20s Vnum: %4d\n\r", morph->name, morph->vnum );
send_to_pager_color( "&B[----------------------------------------------------------------------------]\n\r", ch );
send_to_pager_color(" &BMorph Restrictions\n\r", ch );
send_to_pager_color( "&B[----------------------------------------------------------------------------]\n\r", ch );
pager_printf_color (ch, " &cClasses Allowed : &w%s\n\r",
class_string (morph->class) );
pager_printf_color (ch, " &cRaces Not Allowed: &w%s\n\r",
race_string (morph->race) );
pager_printf_color (ch, " &cSex: &C%s &cPkill: &C%s &cTime From: &C%d &cTime To: &C%d\n\r",
morph->sex == SEX_MALE ? "male" :
morph->sex == SEX_FEMALE ? "female" : "neutral",
morph->pkill == ONLY_PKILL ? "YES" :
morph->pkill == ONLY_PEACEFULL ? "NO" : "n/a",
morph->timefrom, morph->timeto );
pager_printf_color (ch, " &cDay From: &C%d &cDay To: &C%d\n\r",
morph->dayfrom, morph->dayto );
pager_printf_color (ch, " &cLevel: &C%d &cCasting Allowed : &C%s\n\r",
morph->level, (morph->no_cast)?"NO":"yes" );
pager_printf_color (ch, " &cUSAGES: Mana: &C%d &cMove: &C%d &cHp: &C%d &cFavour: &C%d &cGlory: &C%d\n\r",
morph->manaused, morph->moveused, morph->hpused,
morph->favourused, morph->gloryused );
pager_printf_color (ch, " &cBlood: &C%d\n\r",
morph->bloodused );
pager_printf_color (ch, " &cObj1: &C%d &cObjuse1: &C%s &cObj2: &C%d &cObjuse2: &C%s &cObj3: &C%d &cObjuse3: &c%s\n\r",
morph->obj[0], (morph->objuse[0]?"YES":"no"),
morph->obj[1], (morph->objuse[1]?"YES":"no"),
morph->obj[2], (morph->objuse[2]?"YES":"no"));
pager_printf_color (ch, " &cTimer: &w%d\n\r", morph->timer );
send_to_pager_color( "&B[----------------------------------------------------------------------------]\n\r", ch );
send_to_pager_color( " &BEnhancements to the Player\n\r", ch );
send_to_pager_color( "&B[----------------------------------------------------------------------------]\n\r", ch );
pager_printf_color (ch, " &cStr: &C%2d&c )( Int: &C%2d&c )( Wis: &C%2d&c )( Dex: &C%2d&c )( Con: &C%2d&c )( Cha: &C%2d&c )( Lck: &C%2d&c )\n\r",
morph->str, morph->inte, morph->wis, morph->dex, morph->con,
morph->cha, morph->lck );
pager_printf_color (ch, " &cSave versus: &w%d %d %d %d %d &cDodge: &w%d &cParry: &w%d &cTumble: &w%d\n\r",
morph->saving_poison_death, morph->saving_wand,
morph->saving_para_petri, morph->saving_breath,
morph->saving_spell_staff, morph->dodge, morph->parry,
morph->tumble );
pager_printf_color (ch, " &cHps : &w%s &cBlood : &w%s &cMana : &w%s &cMove : &w%s\n\r",
morph->hit, morph->blood, morph->mana, morph->move );
pager_printf_color (ch, " &cDamroll : &w%s &cHitroll: &w%s &cAC : &w%d\n\r",
morph->damroll, morph->hitroll, morph->ac );
send_to_pager_color( "&B[----------------------------------------------------------------------------]\n\r", ch );
send_to_pager_color( " &BAffects to the Player\n\r", ch );
send_to_pager_color( "&B[----------------------------------------------------------------------------]\n\r", ch );
pager_printf_color (ch, " &cAffected by: &C%s\n\r",
affect_bit_name ( &morph->affected_by) );
pager_printf_color (ch, " &cImmune : &w%s\n\r",
flag_string ( morph->immune, ris_flags ) );
pager_printf_color (ch, " &cSusceptible: &w%s\n\r",
flag_string ( morph->suscept, ris_flags ) );
pager_printf_color (ch, " &cResistant : &w%s\n\r",
flag_string ( morph->resistant, ris_flags ) );
pager_printf_color (ch, " &cSkills : &w%s\n\r", morph->skills );
send_to_pager_color( "&B[----------------------------------------------------------------------------]\n\r", ch );
send_to_pager_color( " &BPrevented affects to the Player\n\r", ch );
send_to_pager_color( "&B[----------------------------------------------------------------------------]\n\r", ch );
pager_printf_color (ch, " &cNot affected by: &C%s\n\r",
affect_bit_name ( &morph->no_affected_by) );
pager_printf_color (ch, " &cNot Immune : &w%s\n\r",
flag_string ( morph->no_immune, ris_flags ) );
pager_printf_color (ch, " &cNot Susceptible: &w%s\n\r",
flag_string ( morph->no_suscept, ris_flags ) );
pager_printf_color (ch, " &cNot Resistant : &w%s\n\r",
flag_string ( morph->no_resistant, ris_flags ) );
pager_printf_color (ch, " &cNot Skills : &w%s\n\r",
morph->no_skills);
send_to_pager_color( "&B[----------------------------------------------------------------------------]\n\r", ch );
send_to_char ("\n\r", ch);
}
else if ( !str_cmp ( argument, "help") || !str_cmp ( argument, "desc") )
{
pager_printf_color(ch," &cMorph Name : &C%-20s\n\r", morph->name );
pager_printf_color(ch," &cDefault Pos : &w%d\n\r", morph->defpos );
pager_printf_color(ch," &cKeywords : &w%s\n\r",morph->key_words );
pager_printf_color(ch," &cShortdesc : &w%s\n\r",
(morph->short_desc[0] == '\0')?"(none set)":morph->short_desc );
pager_printf_color(ch," &cLongdesc : &w%s",
(morph->long_desc[0] == '\0')?"(none set)\n\r":
morph->long_desc );
pager_printf_color(ch," &cMorphself : &w%s\n\r",morph->morph_self );
pager_printf_color(ch," &cMorphother : &w%s\n\r",morph->morph_other );
pager_printf_color(ch," &cUnMorphself : &w%s\n\r",morph->unmorph_self);
pager_printf_color(ch," &cUnMorphother: &w%s\n\r",morph->unmorph_other);
send_to_pager_color( "&B[----------------------------------------------------------------------------]\n\r", ch );
pager_printf_color (ch, " &cHelp:\n\r&w%s\n\r", morph->help );
send_to_pager_color( "&B[----------------------------------------------------------------------------]\n\r", ch );
pager_printf_color (ch, " &cDescription:\n\r&w%s\n\r", morph->description );
send_to_pager_color( "&B[----------------------------------------------------------------------------]\n\r", ch );
}
else
{
send_to_char ("Syntax: morphstat <morph>\n\r", ch );
send_to_char ("Syntax: morphstat <morph> <help/desc>\n\r", ch );
}
return;
}
char *
class_string ( int bitvector )
{
static char buf[MAX_STRING_LENGTH];
int x;
buf[0] = '\0';
for (x = 0; x < MAX_PC_CLASS; x++)
if (IS_SET (bitvector, 1 << x))
{
strcat (buf, class_table[x]->who_name);
strcat (buf, " ");
}
if ((x = strlen (buf)) > 0)
buf[--x] = '\0';
return buf;
}
char *
race_string ( int bitvector )
{
static char buf[MAX_STRING_LENGTH];
int x;
buf[0] = '\0';
for (x = 0; x < MAX_PC_RACE; x++)
if (IS_SET (bitvector, 1 << x))
{
strcat (buf, race_table[x]->race_name);
strcat (buf, " ");
}
if ((x = strlen (buf)) > 0)
buf[--x] = '\0';
return buf;
}
/*
* Given the Morph's name, returns the pointer to the morph structure.
* --Shaddai
*/
MORPH_DATA *
get_morph ( char *arg )
{
MORPH_DATA *morph;
if ( arg[0] == '\0' )
return NULL;
for ( morph = morph_start; morph; morph = morph->next )
if ( !str_cmp ( morph->name, arg ) )
break;
return morph;
}
/*
* Find a morph you can use -- Shaddai
*/
MORPH_DATA *find_morph ( CHAR_DATA *ch, char *target, bool is_cast)
{
MORPH_DATA *morph;
if ( target[0] == '\0' )
return NULL;
for ( morph = morph_start; morph; morph = morph->next )
{
if ( str_cmp( morph->name, target) )
continue;
if ( can_morph( ch, morph, is_cast ) )
break;
}
return morph;
}
/*
* Given the Morph's vnum, returns the pointer to the morph structure.
* --Shaddai
*/
MORPH_DATA *
get_morph_vnum ( int vnum )
{
MORPH_DATA *morph;
if ( vnum < 1 )
return NULL;
for ( morph = morph_start; morph; morph = morph->next )
if ( morph->vnum == vnum )
break;
return morph;
}
/*
* These functions wrap the sending of morph stuff, with morphing the code.
* In most cases this is what should be called in the code when using spells,
* obj morphing, etc... --Shaddai
*/
int
do_morph_char ( CHAR_DATA *ch, MORPH_DATA *morph )
{
bool canmorph = TRUE;
OBJ_DATA *obj;
OBJ_DATA *tmpobj;
if ( ch->morph )
canmorph = FALSE;
if ( morph->obj[0] )
{
if ((obj =get_obj_vnum(ch, morph->obj[0])) == NULL)
canmorph = FALSE;
else if ( morph->objuse[0] )
{
act( AT_OBJECT, "$p disappears in a whisp of smoke!",
obj->carried_by, obj, NULL, TO_CHAR );
if ( obj == get_eq_char( obj->carried_by, WEAR_WIELD )
&& (tmpobj=get_eq_char(obj->carried_by,WEAR_DUAL_WIELD))!=NULL)
tmpobj->wear_loc = WEAR_WIELD;
separate_obj( obj );
extract_obj( obj );
}
}
if ( morph->obj[1] )
{
if ((obj =get_obj_vnum(ch, morph->obj[1])) == NULL)
canmorph = FALSE;
else if ( morph->objuse[1] )
{
act( AT_OBJECT, "$p disappears in a whisp of smoke!",
obj->carried_by, obj, NULL, TO_CHAR );
if ( obj == get_eq_char( obj->carried_by, WEAR_WIELD )
&& (tmpobj=get_eq_char(obj->carried_by,WEAR_DUAL_WIELD))!=NULL)
tmpobj->wear_loc = WEAR_WIELD;
separate_obj( obj );
extract_obj( obj );
}
}
if ( morph->obj[2] )
{
if ((obj =get_obj_vnum(ch, morph->obj[2])) == NULL)
canmorph = FALSE;
else if ( morph->objuse[2] )
{
act( AT_OBJECT, "$p disappears in a whisp of smoke!",
obj->carried_by, obj, NULL, TO_CHAR );
if ( obj == get_eq_char( obj->carried_by, WEAR_WIELD )
&& (tmpobj=get_eq_char(obj->carried_by,WEAR_DUAL_WIELD))!=NULL)
tmpobj->wear_loc = WEAR_WIELD;
separate_obj( obj );
extract_obj( obj );
}
}
if ( morph->hpused )
{
if ( ch->hit < morph->hpused )
canmorph = FALSE;
else
ch->hit -= morph->hpused;
}
if ( morph->moveused )
{
if ( ch->move < morph->moveused )
canmorph = FALSE;
else
ch->move -= morph->moveused;
}
if ( morph->manaused && !IS_VAMPIRE(ch) )
{
if ( ch->mana < morph->manaused )
canmorph = FALSE;
else
ch->mana -= morph->manaused;
}
if ( morph->bloodused && IS_VAMPIRE(ch) )
{
if ( ch->pcdata->condition[COND_BLOODTHIRST] < morph->bloodused )
canmorph = FALSE;
else
ch->pcdata->condition[COND_BLOODTHIRST]-= morph->bloodused;
}
if ( morph->favourused )
{
if ( IS_NPC(ch) || !ch->pcdata->deity ||
ch->pcdata->favor < morph->favourused )
canmorph = FALSE;
else {
ch->pcdata->favor -= morph->favourused;
if ( ch->pcdata->favor < ch->pcdata->deity->susceptnum )
SET_BIT( ch->susceptible, ch->pcdata->deity->suscept );
}
}
if ( morph->gloryused )
{
if ( !IS_NPC(ch) && ch->pcdata->quest_curr < morph->gloryused )
canmorph = FALSE;
else
ch->pcdata->quest_curr -= morph->gloryused;
}
if ( !canmorph )
{
send_to_char ( "You begin to transform, but something goes wrong.\n\r",
ch );
return FALSE;
}
send_morph_message ( ch, morph, TRUE );
do_morph ( ch, morph );
return TRUE;
}
void
do_unmorph_char ( CHAR_DATA *ch )
{
MORPH_DATA *temp;
if ( !ch->morph )
return;
temp = ch->morph->morph;
do_unmorph ( ch );
send_morph_message ( ch, temp, FALSE );
return;
}
/*
* This function sends the morph/unmorph message to the people in the room.
* -- Shaddai
*/
void
send_morph_message ( CHAR_DATA *ch, MORPH_DATA *morph, bool is_morph )
{
if ( morph == NULL )
return;
if ( is_morph )
{
act ( AT_MORPH, morph->morph_other, ch, NULL, NULL, TO_ROOM );
act ( AT_MORPH, morph->morph_self, ch, NULL, NULL, TO_CHAR );
}
else
{
act ( AT_MORPH, morph->unmorph_other, ch, NULL, NULL, TO_ROOM );
act ( AT_MORPH, morph->unmorph_self, ch, NULL, NULL, TO_CHAR );
}
return;
}
/*
* Checks to see if the char meets all the requirements to morph into
* the provided morph. Doesn't Look at NPC's class or race as they
* are different from pc's, but still checks level and if they can
* cast it or not. --Shaddai
*/
bool
can_morph ( CHAR_DATA *ch, MORPH_DATA *morph, bool is_cast )
{
if ( morph == NULL)
return FALSE;
if ( IS_IMMORTAL ( ch ) || IS_NPC(ch) ) /* Let immortals morph to anything
Also NPC can do any morph */
return TRUE;
if ( morph->no_cast && is_cast )
return FALSE;
if ( ch->level < morph->level )
return FALSE;
if ( morph->pkill == ONLY_PKILL && !IS_PKILL(ch) )
return FALSE;
if ( morph->pkill == ONLY_PEACEFULL && IS_PKILL(ch) )
return FALSE;
if ( morph->sex != -1 && morph->sex != ch->sex )
return FALSE;
if ( morph->class != 0 && !IS_SET( morph->class, (1 << ch->class) ) )
return FALSE;
if ( morph->race != 0 && IS_SET( morph->race, (1 << ch->race ) ) )
return FALSE;
if ( morph->deity && ( !ch->pcdata->deity || !get_deity ( morph->deity ) ) )
return FALSE;
if ( morph->timeto != -1 && morph->timefrom != -1 ) {
int tmp,i;
bool found = FALSE;
/* i is a sanity check, just in case things go haywire so it doesn't
* loop forever here. -Shaddai
*/
for ( i=0,tmp=morph->timefrom; i<25&&tmp!=morph->timeto;i++ ){
if ( tmp == time_info.hour ) {
found = TRUE;
break;
}
if ( tmp == 23 ) tmp = 0;
else tmp++;
}
if ( !found ) return FALSE;
}
if ( morph->dayfrom != -1 && morph->dayto != -1 &&
( morph->dayto < (time_info.day+1) || morph->dayfrom > (time_info.day+1)))
return FALSE;
return TRUE;
}
/*
* Workhorse of the polymorph code, this turns the player into the proper
* morph. Doesn't check if you can morph or not so must use can_morph before
* this is called. That is so we can let people morph into things without
* checking. Also, if anything is changed here, make sure it gets changed
* in do_unmorph otherwise you will be giving your player stats for free.
* This also does not send the message to people when you morph good to
* use in save functions.
* --Shaddai
*/
void
do_morph ( CHAR_DATA *ch, MORPH_DATA *morph )
{
CHAR_MORPH *ch_morph;
if ( !morph )
return;
if ( ch->morph )
do_unmorph_char ( ch );
ch_morph = make_char_morph ( morph );
ch->armor += morph->ac;
ch->mod_str += morph->str;
ch->mod_int += morph->inte;
ch->mod_wis += morph->wis;
ch->mod_dex += morph->dex;
ch->mod_cha += morph->cha;
ch->mod_lck += morph->lck;
ch->saving_breath += morph->saving_breath;
ch->saving_para_petri += morph->saving_para_petri;
ch->saving_poison_death += morph->saving_poison_death;
ch->saving_spell_staff += morph->saving_spell_staff;
ch->saving_wand += morph->saving_wand;
ch_morph->hitroll = dice_parse( ch, morph->level, morph->hitroll );
ch->hitroll += ch_morph->hitroll;
ch_morph->damroll = dice_parse( ch, morph->level, morph->damroll );
ch->damroll += ch_morph->damroll;
ch_morph->hit = dice_parse( ch, morph->level, morph->hit );
if ( (ch->hit + ch_morph->hit ) > 32700 )
ch_morph->hit = (32700 - ch->hit);
ch->hit += ch_morph->hit;
ch_morph->move = dice_parse( ch, morph->level, morph->move );
if ( (ch->move + ch_morph->move ) > 32700 )
ch_morph->move = (32700 - ch->move);
ch->move += ch_morph->move;
if ( !IS_NPC(ch) && IS_VAMPIRE ( ch ) )
{
ch_morph->blood = dice_parse(ch,morph->level,morph->blood);
ch->pcdata->condition[COND_BLOODTHIRST] += ch_morph->blood;
}
else
{
ch_morph->mana = dice_parse( ch, morph->level, morph->mana );
if ( (ch->mana + ch_morph->mana ) > 32700 )
ch_morph->mana = (32700 - ch->mana);
ch->mana += ch_morph->mana;
}
xSET_BITS ( ch->affected_by, morph->affected_by );
SET_BIT ( ch->immune, morph->immune );
SET_BIT ( ch->resistant, morph->resistant );
SET_BIT ( ch->susceptible, morph->suscept );
xREMOVE_BITS ( ch->affected_by, morph->no_affected_by );
REMOVE_BIT ( ch->immune, morph->no_immune );
REMOVE_BIT ( ch->resistant, morph->no_resistant );
REMOVE_BIT ( ch->susceptible, morph->no_suscept );
ch->morph = ch_morph;
morph->used++;
return;
}
/*
* This makes sure to take all the affects given to the player by the morph
* away. Several things to keep in mind. If you add something here make
* sure you add it to do_morph as well (Unless you want to charge your players
* for morphing ;) ). Also make sure that their pfile saves with the morph
* affects off, as the morph may not exist when they log back in. This
* function also does not send the message to people when you morph so it is
* good to use in save functions and other places you don't want people to
* see the stuff.
* --Shaddai
*/
void
do_unmorph ( CHAR_DATA *ch )
{
CHAR_MORPH *morph;
if ( (morph = ch->morph) == NULL )
return;
ch->armor -= morph->ac;
ch->mod_str -= morph->str;
ch->mod_int -= morph->inte;
ch->mod_wis -= morph->wis;
ch->mod_dex -= morph->dex;
ch->mod_cha -= morph->cha;
ch->mod_lck -= morph->lck;
ch->saving_breath -= morph->saving_breath;
ch->saving_para_petri -= morph->saving_para_petri;
ch->saving_poison_death -= morph->saving_poison_death;
ch->saving_spell_staff -= morph->saving_spell_staff;
ch->saving_wand -= morph->saving_wand;
ch->hitroll -= morph->hitroll;
ch->damroll -= morph->damroll;
ch->hit -= morph->hit;
ch->move -= morph->move;
if ( !IS_NPC(ch) && IS_VAMPIRE ( ch ) )
ch->pcdata->condition[COND_BLOODTHIRST]-=morph->blood;
else
ch->mana -= morph->mana;
xREMOVE_BITS( ch->affected_by, morph->affected_by );
REMOVE_BIT ( ch->immune, morph->immune );
REMOVE_BIT ( ch->resistant, morph->resistant );
REMOVE_BIT ( ch->susceptible, morph->suscept );
free_char_morph ( ch->morph );
ch->morph = NULL;
update_aris ( ch );
return;
}
/*
* This function saves the morph data. Should be put in on reboot or shutdown
* to make use of the sort algorithim. --Shaddai
*/
void
save_morphs ( )
{
MORPH_DATA *morph;
FILE *fp;
fclose( fpReserve );
if ((fp = fopen (SYSTEM_DIR MORPH_FILE, "w")) == NULL)
{
bug ("Save_morph: fopen", 0);
perror (SYSTEM_DIR MORPH_FILE);
fpReserve = fopen( NULL_FILE, "r" );
return;
}
for ( morph = morph_start; morph; morph = morph->next )
fwrite_morph ( fp, morph );
fprintf ( fp, "#END\n" );
fclose ( fp );
fpReserve = fopen( NULL_FILE, "r" );
return;
}
/*
* Write one morph structure to a file. It doesn't print the variable to file
* if it hasn't been set why waste disk-space :) --Shaddai
*/
void
fwrite_morph ( FILE *fp, MORPH_DATA *morph )
{
if ( !morph )
return;
fprintf (fp, "Morph %s\n", morph->name );
if ( morph->obj[0] != 0 || morph->obj[1] != 0 || morph->obj[2] != 0 )
fprintf (fp, "Objs %d %d %d\n",
morph->obj[0], morph->obj[1], morph->obj[2] );
if ( morph->objuse[0] != 0 || morph->objuse[1] != 0 || morph->objuse[2] != 0 )
fprintf ( fp, "Objuse %d %d %d\n",
morph->objuse[0], morph->objuse[1], morph->objuse[2] );
if ( morph->vnum != 0 )
fprintf (fp, "Vnum %d\n", morph->vnum );
if ( morph->blood[0] != '\0' )
fprintf (fp, "Blood %s~\n", morph->blood );
if ( morph->damroll[0] != '\0' )
fprintf (fp, "Damroll %s~\n", morph->damroll );
if ( morph->defpos != POS_STANDING )
fprintf (fp, "Defpos %d\n", morph->defpos );
if ( morph->description[0] != '\0' )
fprintf (fp, "Description %s~\n", morph->description );
if ( morph->help[0] != '\0' )
fprintf (fp, "Help %s~\n", morph->help );
if ( morph->hit[0] != '\0' )
fprintf (fp, "Hit %s~\n", morph->hit );
if ( morph->hitroll[0] != '\0' )
fprintf (fp, "Hitroll %s~\n", morph->hitroll );
if ( morph->key_words[0] != '\0' )
fprintf (fp, "Keywords %s~\n", morph->key_words );
if ( morph->long_desc[0] != '\0' )
fprintf (fp, "Longdesc %s~\n", morph->long_desc );
if ( morph->mana[0] != '\0' )
fprintf (fp, "Mana %s~\n", morph->mana );
if ( morph->morph_other[0] != '\0' )
fprintf (fp, "MorphOther %s~\n", morph->morph_other );
if ( morph->morph_self[0] != '\0' )
fprintf (fp, "MorphSelf %s~\n", morph->morph_self );
if ( morph->move[0] != '\0' )
fprintf (fp, "Move %s~\n", morph->move );
if ( morph->no_skills[0] != '\0' )
fprintf ( fp, "NoSkills %s~\n", morph->no_skills );
if ( morph->short_desc[0] != '\0' )
fprintf (fp, "ShortDesc %s~\n", morph->short_desc );
if ( morph->skills[0] != '\0' )
fprintf (fp, "Skills %s~\n", morph->skills );
if ( morph->unmorph_other[0] != '\0' )
fprintf (fp, "UnmorphOther %s~\n", morph->unmorph_other );
if ( morph->unmorph_self[0] != '\0' )
fprintf (fp, "UnmorphSelf %s~\n", morph->unmorph_self );
if ( !xIS_EMPTY(morph->affected_by) )
fprintf (fp, "Affected %s\n", print_bitvector(&morph->affected_by) );
if ( morph->class != 0 )
fprintf (fp, "Class %s~\n", class_string(morph->class) );
if ( morph->immune != 0 )
fprintf (fp, "Immune %d\n", morph->immune );
if ( !xIS_EMPTY(morph->no_affected_by) )
fprintf (fp, "NoAffected %s\n", print_bitvector(&morph->no_affected_by) );
if ( morph->no_immune != 0 )
fprintf (fp, "NoImmune %d\n", morph->no_immune );
if ( morph->no_resistant != 0 )
fprintf (fp, "NoResistant %d\n", morph->no_resistant );
if ( morph->no_suscept != 0 )
fprintf (fp, "NoSuscept %d\n", morph->no_suscept );
if ( morph->race != 0 )
fprintf (fp, "Race %s~\n", race_string(morph->race) );
if ( morph->resistant != 0 )
fprintf (fp, "Resistant %d\n", morph->resistant );
if ( morph->suscept != 0 )
fprintf (fp, "Suscept %d\n", morph->suscept );
if ( morph->used != 0 )
fprintf (fp, "Used %d\n", morph->used );
if ( morph->sex != -1 )
fprintf ( fp, "Sex %d\n", morph->sex );
if ( morph->pkill != 0 )
fprintf ( fp, "Pkill %d\n", morph->pkill );
if ( morph->timefrom != -1 )
fprintf ( fp, "TimeFrom %d\n", morph->timefrom );
if ( morph->timeto != -1 )
fprintf ( fp, "TimeTo %d\n", morph->timeto );
if ( morph->dayfrom != -1 )
fprintf ( fp, "DayFrom %d\n", morph->dayfrom );
if ( morph->dayto != -1 )
fprintf ( fp, "DayTo %d\n", morph->dayto );
if ( morph->bloodused != 0 )
fprintf ( fp, "BloodUsed %d\n", morph->bloodused );
if ( morph->manaused != 0 )
fprintf ( fp, "ManaUsed %d\n", morph->manaused );
if ( morph->moveused != 0 )
fprintf ( fp, "MoveUsed %d\n", morph->moveused );
if ( morph->hpused != 0 )
fprintf ( fp, "HpUsed %d\n", morph->hpused );
if ( morph->favourused != 0 )
fprintf ( fp, "FavourUsed %d\n", morph->favourused );
if ( morph->gloryused != 0 )
fprintf ( fp, "GloryUsed %d\n", morph->gloryused );
if ( morph->ac != 0 )
fprintf (fp, "Armor %d\n", morph->ac );
if ( morph->cha != 0 )
fprintf (fp, "Charisma %d\n", morph->cha );
if ( morph->con != 0 )
fprintf (fp, "Constitution %d\n", morph->con );
if ( morph->dex != 0 )
fprintf (fp, "Dexterity %d\n", morph->dex );
if ( morph->dodge != 0 )
fprintf (fp, "Dodge %d\n", morph->dodge );
if ( morph->inte != 0 )
fprintf (fp, "Intelligence %d\n", morph->inte );
if ( morph->lck != 0 )
fprintf (fp, "Luck %d\n", morph->lck );
if ( morph->level != 0 )
fprintf (fp, "Level %d\n", morph->level );
if ( morph->parry != 0 )
fprintf (fp, "Parry %d\n", morph->parry );
if ( morph->saving_breath != 0 )
fprintf (fp, "SaveBreath %d\n", morph->saving_breath );
if ( morph->saving_para_petri != 0 )
fprintf (fp, "SavePara %d\n", morph->saving_para_petri );
if ( morph->saving_poison_death != 0 )
fprintf (fp, "SavePoison %d\n", morph->saving_poison_death );
if ( morph->saving_spell_staff != 0 )
fprintf (fp, "SaveSpell %d\n", morph->saving_spell_staff );
if ( morph->saving_wand != 0 )
fprintf (fp, "SaveWand %d\n", morph->saving_wand );
if ( morph->str != 0 )
fprintf (fp, "Strength %d\n", morph->str );
if ( morph->tumble != 0 )
fprintf (fp, "Tumble %d\n", morph->tumble );
if ( morph->wis != 0 )
fprintf (fp, "Wisdom %d\n", morph->wis );
if ( morph->no_cast )
fprintf (fp, "NoCast %d\n", morph->no_cast );
fprintf (fp, "End\n\n" );
return;
}
/*
* This function loads in the morph data. Note that this function MUST be
* used AFTER the race and class tables have been read in and setup.
* --Shaddai
*/
void
load_morphs ( )
{
MORPH_DATA *morph;
char buf[MAX_INPUT_LENGTH];
char *word;
FILE *fp;
bool my_continue = TRUE;
bool fMatch = FALSE;
if ((fp = fopen (SYSTEM_DIR MORPH_FILE, "r")) == NULL)
{
bug ("Load_morph: fopen", 0);
perror (SYSTEM_DIR MORPH_FILE);
return;
}
while (my_continue)
{
morph = NULL;
word = feof (fp) ? "#END" : fread_word (fp);
fMatch = FALSE;
switch (UPPER (word[0]))
{
case '#':
if (!str_cmp (word, "#END" ) )
{
fclose (fp);
fMatch = TRUE;
my_continue = FALSE;
break;
}
break;
case 'M':
if (!str_cmp (word, "Morph"))
{
morph = fread_morph (fp);
fMatch = TRUE;
}
break;
}
if (!fMatch)
{
sprintf (buf, "Fread_morph: no match: %s", word);
bug (buf, 0);
}
if ( morph )
LINK (morph, morph_start, morph_end, next, prev);
}
if ( sysdata.morph_opt )
{
log_string("Optimizing Morphs.");
sort_morphs ( );
}
setup_morph_vnum ( );
log_string("Done.");
return;
}
/*
* Read in one morph structure
*/
MORPH_DATA *
fread_morph ( FILE *fp )
{
MORPH_DATA *morph;
char buf[MAX_INPUT_LENGTH];
char *arg;
char temp[MAX_STRING_LENGTH];
char *word;
int i;
bool fMatch;
word = feof (fp) ? "End" : fread_word (fp);
if ( !str_cmp ( word, "End" ) )
return NULL;
CREATE ( morph, MORPH_DATA, 1);
morph_defaults ( morph );
morph->name = str_dup ( word );
for (;;)
{
word = feof (fp) ? "End" : fread_word (fp);
fMatch = FALSE;
switch (UPPER (word[0]))
{
case 'A':
KEY ( "Armor", morph->ac, fread_number ( fp ) );
KEY ( "Affected", morph->affected_by, fread_bitvector( fp ) );
break;
case 'B':
KEY ( "Blood", morph->blood, fread_string_nohash ( fp ) );
KEY ( "BloodUsed", morph->bloodused, fread_number ( fp ) );
break;
case 'C':
KEY( "Charisma", morph->cha, fread_number ( fp ) );
if ( !str_cmp ( word, "Class" ) )
{
fMatch = TRUE;
arg = fread_string_nohash ( fp );
arg = one_argument( arg, temp );
while ( temp[0] != '\0' )
{
for ( i=0; i < MAX_PC_CLASS; i++ )
if ( !str_cmp( temp, class_table[i]->who_name ) )
{
SET_BIT( morph->class, (1 << i) );
break;
}
arg = one_argument( arg, temp );
}
}
KEY( "Constitution", morph->con, fread_number ( fp ) );
break;
case 'D':
KEY( "Damroll", morph->damroll, fread_string_nohash(fp));
KEY( "DayFrom", morph->dayfrom, fread_number( fp ) );
KEY( "DayTo", morph->dayto, fread_number( fp ) );
KEY( "Defpos", morph->defpos, fread_number( fp ) );
KEY( "Description",morph->description,fread_string_nohash(fp));
KEY( "Dexterity", morph->dex, fread_number ( fp ) );
KEY( "Dodge", morph->dodge, fread_number( fp ) );
break;
case 'E':
if (!str_cmp (word, "End"))
return morph;
break;
case 'F':
KEY( "FavourUsed", morph->favourused, fread_number( fp ) );
break;
case 'G':
KEY( "GloryUsed", morph->gloryused, fread_number( fp ) );
break;
case 'H':
KEY( "Help", morph->help, fread_string_nohash(fp));
KEY( "Hit", morph->hit, fread_string_nohash(fp));
KEY( "Hitroll", morph->hitroll, fread_string_nohash(fp));
KEY( "HpUsed", morph->hpused, fread_number( fp ) );
break;
case 'I':
KEY( "Intelligence", morph->inte, fread_number( fp ) );
KEY( "Immune", morph->immune, fread_number( fp ) );
break;
case 'K':
KEY( "Keywords", morph->key_words, fread_string_nohash(fp));
break;
case 'L':
KEY( "Level", morph->level, fread_number ( fp ) );
KEY( "Longdesc", morph->long_desc, fread_string_nohash(fp));
KEY( "Luck", morph->lck, fread_number( fp ) );
break;
case 'M':
KEY( "Mana", morph->mana, fread_string_nohash(fp));
KEY( "ManaUsed", morph->manaused, fread_number( fp ) );
KEY( "MorphOther", morph->morph_other,fread_string_nohash(fp));
KEY( "MorphSelf", morph->morph_self, fread_string_nohash(fp));
KEY( "Move", morph->morph_self, fread_string_nohash(fp));
KEY( "MoveUsed", morph->moveused, fread_number( fp ) );
break;
case 'N':
KEY( "NoAffected", morph->no_affected_by, fread_bitvector(fp));
KEY( "NoImmune", morph->no_immune, fread_number( fp ) );
KEY( "NoResistant", morph->no_resistant, fread_number(fp));
KEY( "NoSkills", morph->no_skills, fread_string_nohash(fp));
KEY( "NoSuscept", morph->no_suscept, fread_number(fp));
if ( !str_cmp ( word, "NoCast" ) )
{
fMatch = TRUE;
morph->no_cast = fread_number( fp );
}
break;
case 'O':
if ( !str_cmp( word, "Objs" ) )
{
fMatch = TRUE;
morph->obj[0] = fread_number( fp );
morph->obj[1] = fread_number( fp );
morph->obj[2] = fread_number( fp );
}
if ( !str_cmp( word, "Objuse" ) )
{
fMatch = TRUE;
morph->objuse[0] = fread_number( fp );
morph->objuse[1] = fread_number( fp );
morph->objuse[2] = fread_number( fp );
}
break;
case 'P':
KEY( "Parry", morph->parry, fread_number( fp ) );
KEY( "Pkill", morph->pkill, fread_number( fp ) );
break;
case 'R':
if ( !str_cmp ( word, "Race" ) )
{
fMatch = TRUE;
arg = fread_string_nohash ( fp );
arg = one_argument( arg, temp );
while ( temp[0] != '\0' )
{
for ( i=0; i < MAX_PC_RACE; i++ )
if ( !str_cmp( temp, race_table[i]->race_name ) )
{
SET_BIT( morph->race, (1 << i) );
break;
}
arg = one_argument( arg, temp );
}
}
KEY( "Resistant", morph->resistant, fread_number( fp ) );
break;
case 'S':
KEY("SaveBreath", morph->saving_breath, fread_number( fp ) );
KEY("SavePara", morph->saving_para_petri, fread_number( fp ) );
KEY("SavePoison", morph->saving_poison_death,fread_number(fp));
KEY("SaveSpell", morph->saving_spell_staff, fread_number(fp));
KEY("SaveWand", morph->saving_wand, fread_number(fp));
KEY("Sex", morph->sex, fread_number( fp ) );
KEY("ShortDesc",morph->short_desc, fread_string_nohash(fp));
KEY("Skills", morph->skills, fread_string_nohash(fp));
KEY("Strength", morph->str, fread_number( fp ) );
KEY("Suscept", morph->suscept, fread_number( fp ) );
break;
case 'T':
KEY("TimeFrom", morph->timefrom, fread_number( fp ) );
KEY("TimeTo", morph->timeto, fread_number( fp ) );
KEY("Tumble", morph->tumble, fread_number( fp ) );
break;
case 'U':
KEY("UnmorphOther",morph->unmorph_other,fread_string_nohash(fp));
KEY("UnmorphSelf",morph->unmorph_self,fread_string_nohash(fp));
KEY("Used", morph->used, fread_number( fp ) );
break;
case 'V':
KEY("Vnum", morph->vnum, fread_number( fp ) );
break;
case 'W':
KEY("Wisdom", morph->wis, fread_number( fp ) );
break;
}
if (!fMatch)
{
sprintf (buf, "Fread_morph: no match: %s", word);
bug (buf, 0);
/* Bailing out on this morph as something may be messed up
* this is going to have lots of bugs from the load_morphs this
* way, but it is better than possibly having the memory messed
* up! --Shaddai
*/
free_morph( morph );
return NULL;
}
}
}
/*
* Function that releases all the memory for a morph struct. Carefull not
* to use the memory afterwards as it doesn't exist.
* --Shaddai
*/
void
free_morph ( MORPH_DATA *morph )
{
if ( !morph )
return;
if ( morph->blood )
DISPOSE ( morph->blood );
if ( morph->damroll )
DISPOSE ( morph->damroll );
if ( morph->description )
DISPOSE ( morph->description );
if ( morph->help )
DISPOSE ( morph->help );
if ( morph->hit )
DISPOSE ( morph->hit );
if ( morph->hitroll )
DISPOSE ( morph->hitroll );
if ( morph->key_words )
DISPOSE ( morph->key_words );
if ( morph->long_desc )
DISPOSE ( morph->long_desc );
if ( morph->mana )
DISPOSE ( morph->mana );
if ( morph->morph_other )
DISPOSE ( morph->morph_other );
if ( morph->morph_self )
DISPOSE ( morph->morph_self );
if ( morph->move )
DISPOSE ( morph->move );
if ( morph->name )
DISPOSE ( morph->name );
if ( morph->short_desc )
DISPOSE ( morph->short_desc );
if ( morph->skills )
DISPOSE ( morph->skills );
if ( morph->no_skills )
DISPOSE ( morph->no_skills );
if ( morph->unmorph_other )
DISPOSE ( morph->unmorph_other );
if ( morph->unmorph_self )
DISPOSE ( morph->unmorph_self );
DISPOSE ( morph );
return;
}
/*
* This function set's up all the default values for a morph
*/
void
morph_defaults ( MORPH_DATA *morph )
{
morph->blood = str_dup ( "" );
morph->damroll = str_dup ( "" );
morph->description = str_dup ( "" );
morph->help = str_dup ( "" );
morph->hit = str_dup ( "" );
morph->hitroll = str_dup ( "" );
morph->key_words = str_dup ( "" );
morph->long_desc = str_dup ( "" );
morph->mana = str_dup ( "" );
morph->morph_other = str_dup ( "" );
morph->morph_self = str_dup ( "" );
morph->move = str_dup ( "" );
morph->name = str_dup ( "" );
morph->short_desc = str_dup ( "" );
morph->skills = str_dup ( "" );
morph->no_skills = str_dup ( "" );
morph->unmorph_other = str_dup ( "" );
morph->unmorph_self = str_dup ( "" );
xCLEAR_BITS(morph->affected_by);
morph->class = 0;
morph->sex = -1;
morph->timefrom = -1;
morph->timeto = -1;
morph->dayfrom = -1;
morph->dayto = -1;
morph->pkill = 0;
morph->bloodused = 0;
morph->manaused = 0;
morph->moveused = 0;
morph->hpused = 0;
morph->favourused = 0;
morph->gloryused = 0;
morph->immune = 0;
xCLEAR_BITS(morph->no_affected_by);
morph->no_immune = 0;
morph->no_resistant = 0;
morph->no_suscept = 0;
morph->obj[0] = 0;
morph->obj[1] = 0;
morph->obj[2] = 0;
morph->objuse[0] = FALSE;
morph->objuse[1] = FALSE;
morph->objuse[2] = FALSE;
morph->race = 0;
morph->resistant = 0;
morph->suscept = 0;
morph->used = 0;
morph->ac = 0;
morph->defpos = POS_STANDING;
morph->dex = 0;
morph->dodge = 0;
morph->cha = 0;
morph->con = 0;
morph->inte = 0;
morph->lck = 0;
morph->level = 0;
morph->parry = 0;
morph->saving_breath = 0;
morph->saving_para_petri = 0;
morph->saving_poison_death = 0;
morph->saving_spell_staff = 0;
morph->saving_wand = 0;
morph->str = 0;
morph->tumble = 0;
morph->wis = 0;
morph->no_cast = FALSE;
morph->timer = -1;
morph->vnum = 0;
return;
}
/*
* This function copys one morph structure to another
*/
void
copy_morph ( MORPH_DATA *morph, MORPH_DATA *temp )
{
morph->blood = str_dup ( temp->blood );
morph->damroll = str_dup ( temp->damroll );
morph->description = str_dup ( temp->description );
morph->help = str_dup ( temp->help );
morph->hit = str_dup ( temp->hit );
morph->hitroll = str_dup ( temp->hitroll );
morph->key_words = str_dup ( temp->key_words );
morph->long_desc = str_dup ( temp->long_desc );
morph->mana = str_dup ( temp->mana );
morph->morph_other = str_dup ( temp->morph_other );
morph->morph_self = str_dup ( temp->morph_self );
morph->move = str_dup ( temp->move );
morph->name = str_dup ( temp->name );
morph->short_desc = str_dup ( temp->short_desc );
morph->skills = str_dup ( temp->skills );
morph->no_skills = str_dup ( temp->no_skills );
morph->unmorph_other = str_dup ( temp->unmorph_other );
morph->unmorph_self = str_dup ( temp->unmorph_self );
morph->affected_by = temp->affected_by;
morph->class = temp->class;
morph->sex = temp->sex;
morph->timefrom = temp->timefrom;
morph->timeto = temp->timeto;
morph->timefrom = temp->timefrom;
morph->dayfrom = temp->dayfrom;
morph->dayto = temp->dayto;
morph->pkill = temp->pkill;
morph->manaused = temp->manaused;
morph->bloodused = temp->bloodused;
morph->moveused = temp->moveused;
morph->hpused = temp->hpused;
morph->favourused = temp->favourused;
morph->gloryused = temp->gloryused;
morph->immune = temp->immune;
morph->no_affected_by = temp->no_affected_by;
morph->no_immune = temp->no_immune;
morph->no_resistant = temp->no_resistant;
morph->no_suscept = temp->no_suscept;
morph->obj[0] = temp->obj[0];
morph->obj[1] = temp->obj[1];
morph->obj[2] = temp->obj[2];
morph->objuse[0] = temp->objuse[0];
morph->objuse[1] = temp->objuse[1];
morph->objuse[2] = temp->objuse[2];
morph->race = temp->race;
morph->resistant = temp->resistant;
morph->suscept = temp->suscept;
morph->ac = temp->ac;
morph->defpos = temp->defpos;
morph->dex = temp->dex;
morph->dodge = temp->dodge;
morph->cha = temp->cha;
morph->con = temp->con;
morph->inte = temp->inte;
morph->lck = temp->lck;
morph->level = temp->level;
morph->parry = temp->parry;
morph->saving_breath = temp->saving_breath;
morph->saving_para_petri = temp->saving_para_petri;
morph->saving_poison_death = temp->saving_poison_death;
morph->saving_spell_staff = temp->saving_spell_staff;
morph->saving_wand = temp->saving_wand;
morph->str = temp->str;
morph->tumble = temp->tumble;
morph->wis = temp->wis;
morph->no_cast = temp->no_cast;
morph->timer = temp->timer;
return;
}
/*
* This is to move the more used morphs to the beginning hopefully saving
* that .000000001 second ;) --Shaddai
*/
void
sort_morphs ( )
{
MORPH_DATA *morph, *temp;
int fMatch;
/* This is slow and the wrong way to code it but I am tired and have more
* Important things to-do :) Also it is only done at boot-up so who cares
* if it is slow or not. --Shaddai
*/
do {
fMatch = FALSE;
if ( morph_start == NULL )
return;
for ( morph = morph_start, temp = morph->next;morph && temp;
morph = morph->next, temp = temp->next)
{
if ( morph->used < temp->used )
{
if ( morph == morph_start )
morph_start = temp;
if ( temp == morph_end )
morph_end = morph;
if ( morph->prev )
morph->prev->next = temp;
if ( temp->next )
temp->next->prev = morph;
temp->prev = morph->prev;
morph->next = temp->next;
temp->next = morph;
morph->prev = temp;
fMatch = TRUE;
break;
}
}
} while (fMatch);
return;
}
/*
* Create new player morph, a scailed down version of original morph
* so if morph gets changed stats don't get messed up.
*/
CHAR_MORPH *
make_char_morph ( MORPH_DATA *morph )
{
CHAR_MORPH *ch_morph;
if ( morph == NULL )
return NULL;
CREATE ( ch_morph, CHAR_MORPH, 1);
ch_morph->morph = morph;
ch_morph->ac = morph->ac;
ch_morph->str = morph->str;
ch_morph->inte = morph->inte;
ch_morph->wis = morph->wis;
ch_morph->dex = morph->dex;
ch_morph->cha = morph->cha;
ch_morph->lck = morph->lck;
ch_morph->saving_breath = morph->saving_breath;
ch_morph->saving_para_petri = morph->saving_para_petri;
ch_morph->saving_poison_death = morph->saving_poison_death;
ch_morph->saving_spell_staff = morph->saving_spell_staff;
ch_morph->saving_wand = morph->saving_wand;
ch_morph->timer = morph->timer;
ch_morph->hitroll = 0;
ch_morph->damroll = 0;
ch_morph->hit = 0;
ch_morph->mana = 0;
ch_morph->move = 0;
ch_morph->blood = 0;
ch_morph->affected_by = morph->affected_by;
ch_morph->immune = morph->immune;
ch_morph->resistant = morph->resistant;
ch_morph->suscept = morph->suscept;
ch_morph->no_affected_by = morph->no_affected_by;
ch_morph->no_immune = morph->no_immune;
ch_morph->no_resistant = morph->no_resistant;
ch_morph->no_suscept = morph->no_suscept;
return ch_morph;
}
/*
* Player command to create a new morph
*/
void
do_morphcreate ( CHAR_DATA *ch, char *argument )
{
MORPH_DATA *morph;
MORPH_DATA *temp = NULL;
char arg1[MAX_INPUT_LENGTH];
char arg2[MAX_INPUT_LENGTH];
argument = one_argument( argument, arg1 );
argument = one_argument( argument, arg2 );
if ( arg1[0] == '\0' )
{
send_to_char( "Usage: morphcreate <name>\n\r", ch);
send_to_char( "Usage: morphcreate <name/vnum> copy\n\r", ch );
return;
}
if ( arg2[0] != '\0' && !str_cmp( arg2, "copy" ) )
{
if ( is_number( arg1 ) )
{
if ( (temp = get_morph_vnum( atoi( arg1 ) ) ) == NULL )
{
ch_printf(ch, "No such morph vnum %d exists.\n\r", atoi(arg1) );
return;
}
}
else if ( (temp = get_morph( arg1 ) ) == NULL )
{
ch_printf(ch, "No such morph %s exists.\n\r", arg1 );
return;
}
}
smash_tilde( arg1 );
CREATE( morph, MORPH_DATA, 1);
morph_defaults ( morph );
if ( morph->name )
DISPOSE( morph->name );
if ( arg2[0] != '\0' && !str_cmp( arg2, "copy" ) && temp )
copy_morph ( morph, temp );
else
morph->name = str_dup( arg1 );
morph->vnum = morph_vnum;
morph_vnum++;
LINK (morph, morph_start, morph_end, next, prev);
ch_printf (ch, "Morph %s created with vnum %d.\n\r",morph->name,morph->vnum);
return;
}
/*
* Player function to delete a morph. --Shaddai
* NOTE Need to check all players and force them to unmorph first
*/
void
do_morphdestroy ( CHAR_DATA *ch, char *argument )
{
MORPH_DATA *morph;
char arg[MAX_INPUT_LENGTH];
one_argument( argument, arg );
if ( is_number( arg ) )
morph = get_morph_vnum ( atoi(arg) );
else
morph = get_morph ( arg );
if ( !morph )
{
ch_printf(ch, "Unkown morph %s.\n\r", arg );
return;
}
unmorph_all ( morph );
UNLINK( morph, morph_start, morph_end, next, prev );
free_morph( morph );
send_to_char( "Morph deleted.\n\r", ch );
return;
}
void
free_char_morph ( CHAR_MORPH *morph )
{
/* Boy this is easy but better to keep it a seperate function for later
* possible complications. --Shaddai
*/
DISPOSE ( morph );
return;
}
void
fwrite_morph_data ( CHAR_DATA *ch, FILE *fp )
{
CHAR_MORPH *morph;
if ( ch->morph == NULL )
return;
morph = ch->morph;
fprintf ( fp, "#MorphData\n" );
/* Only Print Out what is necessary */
if ( morph->morph != NULL )
{
fprintf ( fp, "Vnum %d\n", morph->morph->vnum );
fprintf ( fp, "Name %s~\n", morph->morph->name );
}
if ( !xIS_EMPTY(morph->affected_by) )
fprintf ( fp, "Affect %s\n", print_bitvector(&morph->affected_by) );
if ( morph->immune != 0 )
fprintf ( fp, "Immune %d\n", morph->immune );
if ( morph->resistant != 0 )
fprintf ( fp, "Resistant %d\n", morph->resistant );
if ( morph->suscept != 0 )
fprintf ( fp, "Suscept %d\n", morph->suscept );
if ( !xIS_EMPTY(morph->no_affected_by) )
fprintf ( fp, "NoAffect %s\n", print_bitvector(&morph->no_affected_by) );
if ( morph->no_immune != 0 )
fprintf ( fp, "NoImmune %d\n", morph->no_immune );
if ( morph->no_resistant != 0 )
fprintf ( fp, "NoResistant %d\n", morph->no_resistant );
if ( morph->no_suscept != 0 )
fprintf ( fp, "NoSuscept %d\n", morph->no_suscept );
if ( morph->ac != 0 )
fprintf ( fp, "Armor %d\n", morph->ac );
if ( morph->blood != 0 )
fprintf ( fp, "Blood %d\n", morph->blood );
if ( morph->cha != 0 )
fprintf ( fp, "Charisma %d\n", morph->cha );
if ( morph->con != 0 )
fprintf ( fp, "Constitution %d\n", morph->con );
if ( morph->damroll != 0 )
fprintf ( fp, "Damroll %d\n", morph->damroll );
if ( morph->dex != 0 )
fprintf ( fp, "Dexterity %d\n", morph->dex );
if ( morph->dodge != 0 )
fprintf ( fp, "Dodge %d\n", morph->dodge );
if ( morph->hit != 0 )
fprintf ( fp, "Hit %d\n", morph->hit );
if ( morph->hitroll != 0 )
fprintf ( fp, "Hitroll %d\n", morph->hitroll );
if ( morph->inte != 0 )
fprintf ( fp, "Intelligence %d\n", morph->inte );
if ( morph->lck != 0 )
fprintf ( fp, "Luck %d\n", morph->lck );
if ( morph->mana != 0 )
fprintf ( fp, "Mana %d\n", morph->mana );
if ( morph->move != 0 )
fprintf ( fp, "Move %d\n", morph->move );
if ( morph->parry != 0 )
fprintf ( fp, "Parry %d\n", morph->parry );
if ( morph->saving_breath != 0 )
fprintf ( fp, "Save1 %d\n", morph->saving_breath );
if ( morph->saving_para_petri != 0 )
fprintf ( fp, "Save2 %d\n", morph->saving_para_petri );
if ( morph->saving_poison_death != 0 )
fprintf ( fp, "Save3 %d\n", morph->saving_poison_death );
if ( morph->saving_spell_staff != 0 )
fprintf ( fp, "Save4 %d\n", morph->saving_spell_staff );
if ( morph->saving_wand != 0 )
fprintf ( fp, "Save5 %d\n", morph->saving_wand );
if ( morph->str != 0 )
fprintf ( fp, "Strength %d\n", morph->str );
if ( morph->timer != -1 )
fprintf ( fp, "Timer %d\n", morph->timer );
if ( morph->tumble != 0 )
fprintf ( fp, "Tumble %d\n", morph->tumble );
if ( morph->wis != 0 )
fprintf ( fp, "Wisdom %d\n", morph->wis );
fprintf ( fp, "End\n" );
return;
}
void
fread_morph_data ( CHAR_DATA *ch, FILE *fp )
{
CHAR_MORPH *morph;
bool fMatch;
char *word;
char buf[MAX_STRING_LENGTH];
CREATE ( morph, CHAR_MORPH, 1);
clear_char_morph ( morph );
ch->morph = morph;
for ( ; ; )
{
word = feof ( fp ) ? "End" : fread_word (fp);
fMatch = FALSE;
switch ( UPPER ( word[0] ) )
{
case 'A':
KEY ( "Affect", morph->affected_by, fread_bitvector( fp ) );
KEY ( "Armor", morph->ac, fread_number( fp ) );
break;
case 'B':
KEY ( "Blood", morph->blood, fread_number( fp ) );
break;
case 'C':
KEY ( "Charisma", morph->cha, fread_number( fp ) );
KEY ( "Constitution", morph->con, fread_number( fp ) );
break;
case 'D':
KEY ( "Damroll", morph->damroll, fread_number( fp ) );
KEY ( "Dexterity", morph->dex, fread_number( fp ) );
KEY ( "Dodge", morph->dodge, fread_number( fp ) );
break;
case 'E':
if ( !str_cmp ( "End", word ) )
return;
break;
case 'H':
KEY ( "Hit", morph->hit, fread_number( fp ) );
KEY ( "Hitroll", morph->hitroll, fread_number( fp ) );
break;
case 'I':
KEY ( "Immune", morph->immune, fread_number( fp ) );
KEY ( "Intelligence", morph->inte, fread_number( fp ) );
break;
case 'L':
KEY ( "Luck", morph->lck, fread_number( fp ) );
break;
case 'M':
KEY ( "Mana", morph->mana, fread_number( fp ) );
KEY ( "Move", morph->move, fread_number( fp ) );
break;
case 'N':
if ( !str_cmp ( "Name", word ) )
{
fMatch = TRUE;
if ( morph->morph )
if ( str_cmp ( morph->morph->name, fread_string( fp )))
bug ( "Morph Name doesn't match vnum %d.",
morph->morph->vnum );
}
KEY ( "NoAffect", morph->no_affected_by, fread_bitvector( fp ) );
KEY ( "NoImmune", morph->no_immune, fread_number( fp ) );
KEY ( "NoResistant", morph->no_resistant, fread_number( fp ) );
KEY ( "NoSuscept", morph->no_suscept, fread_number( fp ) );
break;
case 'P':
KEY ( "Parry", morph->parry, fread_number( fp ) );
break;
case 'R':
KEY ( "Resistant", morph->resistant, fread_number( fp ) );
break;
case 'S':
KEY ( "Save1", morph->saving_breath, fread_number( fp ) );
KEY ( "Save2", morph->saving_para_petri, fread_number( fp ) );
KEY ( "Save3", morph->saving_poison_death, fread_number( fp ) );
KEY ( "Save4", morph->saving_spell_staff, fread_number( fp ) );
KEY ( "Save5", morph->saving_wand, fread_number( fp ) );
KEY ( "Strength", morph->str, fread_number( fp ) );
KEY ( "Suscept", morph->suscept, fread_number( fp ) );
break;
case 'T':
KEY ( "Timer", morph->timer, fread_number( fp ) );
KEY ( "Tumble", morph->tumble, fread_number( fp ) );
break;
case 'V':
if ( !str_cmp ( "Vnum", word ) )
{
fMatch = TRUE;
morph->morph = get_morph_vnum ( fread_number( fp ) );
}
break;
case 'W':
KEY ( "Wisdom", morph->wis, fread_number( fp ) );
break;
}
if (!fMatch)
{
sprintf (buf, "Fread_morph_data: no match: %s", word);
bug (buf, 0);
}
}
return;
}
void
clear_char_morph ( CHAR_MORPH *morph )
{
morph->timer = -1;
xCLEAR_BITS(morph->affected_by);
xCLEAR_BITS(morph->no_affected_by);
morph->immune = 0;
morph->no_immune = 0;
morph->no_resistant = 0;
morph->no_suscept = 0;
morph->resistant = 0;
morph->suscept = 0;
morph->ac = 0;
morph->blood = 0;
morph->cha = 0;
morph->con = 0;
morph->damroll = 0;
morph->dex = 0;
morph->dodge = 0;
morph->hit = 0;
morph->hitroll = 0;
morph->inte = 0;
morph->lck = 0;
morph->mana = 0;
morph->parry = 0;
morph->saving_breath = 0;
morph->saving_para_petri = 0;
morph->saving_poison_death = 0;
morph->saving_spell_staff = 0;
morph->saving_wand = 0;
morph->str = 0;
morph->tumble = 0;
morph->wis = 0;
morph->morph = NULL;
return;
}
void
setup_morph_vnum( void )
{
MORPH_DATA *morph;
int vnum;
vnum = morph_vnum;
for ( morph = morph_start; morph; morph = morph->next )
if ( morph->vnum > vnum )
vnum = morph->vnum;
if ( vnum < 1000 )
vnum = 1000;
else
vnum++;
for ( morph = morph_start; morph; morph = morph->next )
if ( morph->vnum == 0 )
{
morph->vnum = vnum;
vnum++;
}
morph_vnum = vnum;
return;
}
void
unmorph_all ( MORPH_DATA *morph )
{
CHAR_DATA *vch;
for (vch = first_char; vch; vch = vch->next )
{
if ( IS_NPC(vch) )
continue;
if ( vch->morph == NULL || vch->morph->morph == NULL ||
vch->morph->morph != morph )
continue;
do_unmorph_char ( vch );
}
return;
}
/*
* Following functions are for immortal testing purposes.
*/
void
do_imm_morph ( CHAR_DATA *ch, char *argument )
{
MORPH_DATA *morph;
CHAR_DATA *victim = NULL;
char arg[MAX_INPUT_LENGTH];
char arg2[MAX_INPUT_LENGTH];
int vnum;
if ( IS_NPC(ch) )
{
send_to_char("Only player characters can use this command.\n\r", ch );
return;
}
argument = one_argument( argument, arg );
one_argument( argument, arg2 );
if ( !is_number(arg) )
{
send_to_char("Syntax: morph <vnum>\n\r", ch );
return;
}
vnum = atoi( arg );
morph = get_morph_vnum ( vnum );
if ( morph == NULL )
{
ch_printf(ch, "No such morph %d exists.\n\r", vnum );
return;
}
if ( arg2[0] == '\0' )
do_morph_char ( ch, morph );
else if ( ( victim = get_char_world ( ch, arg2 ) ) == NULL )
{
send_to_char ("No one like that in all the realms.\n\r", ch);
return;
}
if ( victim!= NULL && get_trust (ch) < get_trust (victim)
&& !IS_NPC (victim))
{
send_to_char ("You can't do that!\n\r", ch);
return;
}
else if ( victim != NULL )
do_morph_char ( victim, morph );
send_to_char("Done.\n\r", ch );
return;
}
/*
* This is just a wrapper. --Shaddai
*/
void
do_imm_unmorph( CHAR_DATA *ch , char *argument)
{
CHAR_DATA *victim = NULL;
char arg[MAX_INPUT_LENGTH];
one_argument( argument, arg );
if ( arg[0] == '\0' )
do_unmorph_char ( ch );
else if ( ( victim = get_char_world ( ch, arg ) ) == NULL )
{
send_to_char ("No one like that in all the realms.\n\r", ch);
return;
}
if ( victim!= NULL && get_trust (ch) < get_trust (victim)
&& !IS_NPC (victim))
{
send_to_char ("You can't do that!\n\r", ch);
return;
}
else if ( victim != NULL )
do_unmorph_char ( victim );
send_to_char("Done.\n\r", ch );
return;
}