bast/
bast/area/
bast/backup/
bast/clans/
bast/doc/MSP/
bast/doc/OLC11/
bast/doc/OLC11/doc/
bast/doc/OLC11/options/
bast/log/
bast/mobprogs/
bast/player/
/***************************************************************************
 *  Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,        *
 *  Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe.   *
 *                                                                         *
 *  Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael          *
 *  Chastain, Michael Quan, and Mitchell Tse.                              *
 *                                                                         *
 *  Envy Diku Mud improvements copyright (C) 1994 by Michael Quan, David   *
 *  Love, Guilherme 'Willie' Arnold, and Mitchell Tse.                     *
 *                                                                         *
 *  EnvyMud 2.0 improvements copyright (C) 1995 by Michael Quan and        *
 *  Mitchell Tse.                                                          *
 *                                                                         *
 *  EnvyMud 2.2 improvements copyright (C) 1996, 1997 by Michael Quan.     *
 *                                                                         *
 *  In order to use any part of this Envy Diku Mud, you must comply with   *
 *  the original Diku license in 'license.doc', the Merc license in        *
 *  'license.txt', as well as the Envy license in 'license.nvy'.           *
 *  In particular, you may not remove either of these copyright notices.   *
 *                                                                         *
 *  Much time and thought has gone into this software and you are          *
 *  benefitting.  We hope that you share your changes too.  What goes      *
 *  around, comes around.                                                  *
 *                                                                         *
 *  This code was freely distributed with the The Isles 1.1 source code,   *
 *  and has been used here for OLC - OLC would not be what it is without   *
 *  all the previous coders who released their source code.                *
 ***************************************************************************/

#if defined( macintosh )
#include <types.h>
#else
#include <sys/types.h>
#endif
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "merc.h"
#include "olc.h"



void show_version( CHAR_DATA *ch, char *argument )
{
    send_to_char( VERSION, ch );
    send_to_char( "\n\r",  ch );
    send_to_char( AUTHOR,  ch );
    send_to_char( "\n\r",  ch );
    send_to_char( DATE,    ch );
    send_to_char( "\n\r",  ch );
    send_to_char( CREDITS, ch );
    send_to_char( "\n\r",  ch );
    return;
}

/*
 * Added by Zen. Substitutes the C macros they were making a do_switch bug!
 * Return pointers to what is being edited.
 */
bool is_builder( CHAR_DATA *ch, AREA_DATA *area )
{
    CHAR_DATA *rch;

    rch = get_char( ch );
    if ( ( rch->pcdata->security >= area->security
	  || is_name( rch->name, area->builders )
	  || is_name( "All", area->builders ) ) )
	return TRUE;

    return FALSE;
}

void edit_done( CHAR_DATA *ch, char *argument )
{
    ch->desc->olc_editing = NULL;
    ch->desc->connected   = CON_PLAYING;
    return;
}


bool check_range( int lower, int upper )
{
    AREA_DATA *pArea;
    int        cnt = 0;

    for ( pArea = area_first; pArea; pArea = pArea->next )
    {
	if ( ( lower <= pArea->lvnum && upper >= pArea->lvnum )
	    || ( upper >= pArea->uvnum && lower <= pArea->uvnum ) )
	    cnt++;

	if ( cnt > 1 )
	    return FALSE;
    }
    return TRUE;
}


AREA_DATA *get_vnum_area( int vnum )
{
    AREA_DATA *pArea;

    for ( pArea = area_first; pArea; pArea = pArea->next )
	if ( vnum >= pArea->lvnum && vnum <= pArea->uvnum )
	    return pArea;

    return 0;
}

void show_flag_cmds( CHAR_DATA *ch, const struct flag_type *flag_table )
{
    char buf  [ MAX_STRING_LENGTH ];
    char buf1 [ MAX_STRING_LENGTH ];
    int  flag;
    int  col;

    buf1[0] = '\0';
    col = 0;
    for ( flag = 0; *flag_table[flag].name; flag++ )
    {
	if ( flag_table[flag].settable )
	{
	    sprintf( buf, "%-19.18s", flag_table[flag].name );
	    strcat( buf1, buf );

	    if ( ++col % 4 == 0 )
		strcat( buf1, "\n\r" );
	}
    }

    if ( col % 4 != 0 )
	strcat( buf1, "\n\r" );

    send_to_char( buf1, ch );
    return;
}

// skills only, not spells.
void show_skill_cmds( CHAR_DATA *ch )
{
    char buf  [MAX_STRING_LENGTH];
    char buf1 [MAX_STRING_LENGTH*2];
    int  sn;
    int  col;

    buf1[0] = '\0';
    col = 0;
    for ( sn = 0; sn < MAX_SKILL; sn++ )
    {
	if ( !skills_table[sn].name )
	    break;

	if ( !str_cmp( skills_table[sn].name, "reserved" ) )
	    continue;

	sprintf( buf, "%-19.18s", skills_table[sn].name );
	strcat( buf1, buf );

	if ( ++col % 4 == 0 )
	   strcat( buf1, "\n\r" );
    }

    if ( col % 4 != 0 )
	strcat( buf1, "\n\r" );

    send_to_char( buf1, ch );
    return;
}

void show_spell_cmds( CHAR_DATA *ch, int tar )
{
    char buf  [MAX_STRING_LENGTH];
    char buf1 [MAX_STRING_LENGTH*2];
    int  sn;
    int  col;

    buf1[0] = '\0';
    col = 0;
    for ( sn = 0; sn < MAX_SPELL; sn++ )
    {
	if ( !spells_table[sn].name )
	    break;

	if ( !str_cmp( spells_table[sn].name, "reserved" )
	    || spells_table[sn].spell_fun == spell_null )
	    continue;

	if ( tar == -1 || spells_table[sn].target == tar )
	{
	    sprintf( buf, "%-19.18s", spells_table[sn].name );
	    strcat( buf1, buf );

	    if ( ++col % 4 == 0 )
		strcat( buf1, "\n\r" );
	}
    }

    if ( col % 4 != 0 )
	strcat( buf1, "\n\r" );

    send_to_char( buf1, ch );
    return;
}


void show_spec_mob_cmds( CHAR_DATA *ch )
{
    char buf  [MAX_STRING_LENGTH];
    char buf1 [MAX_STRING_LENGTH];
    int  spec;
    int  col;

    buf1[0] = '\0';
    col = 0;
    send_to_char( "SPEC MOB FUN's (preceed with spec_):\n\r\n\r", ch );
    for ( spec = 0; *spec_mob_table[spec].spec_fun; spec++ )
    {
	sprintf( buf, "%-19.18s", &spec_mob_table[spec].spec_name[5] );
	strcat( buf1, buf );
	if ( ++col % 4 == 0 )
	    strcat( buf1, "\n\r" );
    }

    if ( col % 4 != 0 )
	strcat( buf1, "\n\r" );

    send_to_char( buf1, ch );
    return;
}


void show_game_cmds( CHAR_DATA *ch )
{
    char buf  [MAX_STRING_LENGTH];
    char buf1 [MAX_STRING_LENGTH];
    int  game;
    int  col;

    buf1[0] = '\0';
    col = 0;
    send_to_char( "GAME FUN's (preceed with game_):\n\r", ch );
    for ( game = 0; *game_table[game].game_fun; game++ )
    {
	sprintf( buf, "%-19.18s", &game_table[game].game_name[5] );
	strcat( buf1, buf );
	if ( ++col % 4 == 0 )
	    strcat( buf1, "\n\r" );
    }

    if ( col % 4 != 0 )
	strcat( buf1, "\n\r" );

    send_to_char( buf1, ch );
    return;
}


void show_obj_values( CHAR_DATA *ch, OBJ_INDEX_DATA *obj )
{
    char buf [ MAX_STRING_LENGTH ];

    buf[0] = '\0';

    switch ( obj->item_type )
    {
    default:								break;
    case TYPE_LIGHT:
	if ( obj->value[2] == -1 )
	    sprintf( buf, "v2 light infinite.  -1,\n\r" );
	else
	    sprintf( buf, "v2 light %d.\n\r", obj->value[2] );
	break;
    case TYPE_WAND:
    case TYPE_STAFF:
	sprintf( buf,
		"v0 level         %d.\n\r"
		"v1 charges total %d.\n\r"
		"v2 charges left  %d.\n\r"
		"v3 spell         %s.\n\r",
		obj->value[0],
		obj->value[1],
		obj->value[2],
		obj->value[3] != -1
		  ? spells_table[obj->value[3]].name : "none" );
	break;
    case TYPE_SCROLL:
    case TYPE_POTION:
    case TYPE_PILL:
	sprintf( buf,
		"v0 level %d.\n\r"
		"v1 spell %s.\n\r"
		"v2 spell %s.\n\r"
		"v3 spell %s.\n\r"
		"v4 spell %s.\n\r",
		obj->value[0],
		obj->value[1] != -1 ? spells_table[obj->value[1]].name : "none",
		obj->value[2] != -1 ? spells_table[obj->value[2]].name : "none",
		obj->value[3] != -1 ? spells_table[obj->value[3]].name : "none",
		obj->value[4] != -1 ? spells_table[obj->value[4]].name : "none"
		);
	break;
    case TYPE_WEAPON:
	sprintf( buf,
		"v1 damage minimum %d.\n\r"
		"v2 damage maximum %d.\n\r"
		"v3 type           %s.\n\r",
		obj->value[1],
		obj->value[2],
		flag_string( weapon_flags, obj->value[3] ) );
	break;
    case TYPE_CONTAINER:
	sprintf( buf,
		"v0 weight %d kg.\n\r"
		"v1 flags  %s.\n\r"
		"v2 key    %s.  %d.\n\r",
		obj->value[0],
		flag_string( container_flags, obj->value[1] ),
		get_obj_index( obj->value[2] )
		  ? get_obj_index( obj->value[2] )->short_descr : "none",
		obj->value[2] );
	break;
    case TYPE_DRINK_CON:
	sprintf( buf,
		"v0 liquid total %d.\n\r"
		"v1 liquid left  %d.\n\r"
		"v2 liquid       %s.\n\r"
		"v3 poisoned     %s.\n\r",
		obj->value[0],
		obj->value[1],
		flag_string( liquid_flags, obj->value[2] ),
		obj->value[3] != 0 ? "yes" : "no" );
	break;
    case TYPE_FOOD:
	sprintf( buf,
		"v0 food hours %d.\n\r"
		"v3 poisoned   %s.\n\r",
		obj->value[0],
		obj->value[3] != 0 ? "yes" : "no" );
	break;
    case TYPE_MONEY:
	sprintf( buf, "v0 gold %d.\n\r", obj->value[0] );
	break;
    case TYPE_PORTAL:
	sprintf( buf,
		"v0 charges %d.\n\r"
		"v1 flags   %s.\n\r"
		"v2 key     %s.  %d.\n\r"
		"v3 flags   %s.\n\r"
		"v4 destiny %d.\n\r",
		obj->value[0],
		flag_string( portal_door_flags, obj->value[1] ),
		get_obj_index( obj->value[2] )
		  ? get_obj_index( obj->value[2] )->short_descr
		  : "none", obj->value[2],
		flag_string( portal_flags, obj->value[3] ),
		obj->value[4] );
	break;
    }

    send_to_char( buf, ch );
    return;
}


int mprog_count( MOB_INDEX_DATA * pMob )
{
    MPROG_DATA *mprg;
    int         count;

    for ( count = 0, mprg = pMob->mobprogs; mprg; mprg = mprg->next, count++ )
	;
    return count;
}

MPROG_DATA *edit_mprog( CHAR_DATA * ch, MOB_INDEX_DATA * pMob )
{
    MPROG_DATA *mprg;
    int         mprog_num;
    int         count = 0;

    mprog_num = ch->pcdata->mprog_edit;
    for ( mprg = pMob->mobprogs; mprg && count < mprog_num; mprg = mprg->next )
	count++;

    return mprg;
}

void show_mprog( CHAR_DATA * ch, MPROG_DATA * pMobProg )
{
    char buf [ MAX_STRING_LENGTH ];

    sprintf( buf, ">%s %s~\n\r",
	    mprog_type_to_name( pMobProg->type ),
	    pMobProg->arglist ? pMobProg->arglist : "NULL" );
    send_to_char( buf, ch );

    sprintf( buf, "%s~\n\r", pMobProg->comlist ? pMobProg->comlist
	    : "NULL\n\r" );
    send_to_char( buf, ch );
}

void delete_mprog( CHAR_DATA * ch, int pnum )
{
    MPROG_DATA     *mprg;
    MPROG_DATA     *mprg_prev;
    MOB_INDEX_DATA *pMob;
    char            buf	[ MAX_INPUT_LENGTH ];
    int             count;

    pMob = ( MOB_INDEX_DATA * ) ch->desc->olc_editing;

    if ( pnum < 0 )
	return;

    if ( pnum == 0 )
    {
	free_string( pMob->mobprogs->arglist );
	free_string( pMob->mobprogs->comlist );
	mprg = pMob->mobprogs->next;
	/*
	 * Here is where we would recycle the memory of pMob->mobprogs...
	 * no such mechanism yet so this actually IS a sort of memory leak
	 * since memory allocated with alloc_perm cannot be freed.  Walker 
	 */
	pMob->mobprogs	= mprg;
    }
    else
    {
	mprg_prev	= pMob->mobprogs;
	mprg		= mprg_prev->next;

	for ( count = 1; mprg && count < pnum; count++ )
	{
	    mprg_prev	= mprg;
	    mprg	= mprg->next;
	}
	if ( mprg )
	{
	    free_string( mprg->arglist );
	    free_string( mprg->comlist );
	    mprg_prev->next = mprg->next;
	    /*
	     * Here is where we would recycle the memory of mprg...
	     * no such mechanism yet so this actually IS a sort of memory leak
	     * since memory allocated with alloc_perm cannot be freed.  Walker
	     */
	}
    }

    sprintf( buf, "MOBProg %d Deleted.\n\r", pnum + 1 );
    send_to_char( buf, ch );
    return;
}

void mpedit_show( CHAR_DATA *ch, char *argument )
{
    MPROG_DATA     *pMobProg;
    MOB_INDEX_DATA *pMob;
    char            buf [MAX_STRING_LENGTH];

    pMob	= (MOB_INDEX_DATA *) ch->desc->olc_editing;
    pMobProg	= edit_mprog( ch, pMob );

    if ( argument[0] == '\0' )
	show_mprog( ch, pMobProg );
    else
    if ( is_number( argument ) )
    {
	MPROG_DATA *mprg;
	int         prg = atoi( argument );
	int         cnt = mprog_count( pMob );

	if ( prg < 1 || prg > cnt )
	{
	    sprintf( buf, "Valid range is 1 to %d.\n\r", cnt );
	    send_to_char( buf, ch );
	    return;
	}

	for ( mprg = pMob->mobprogs; mprg && prg-- > 1; mprg = mprg->next )
	    ;
	show_mprog( ch, mprg );
    }
    else if ( !str_cmp( argument, "all" ) )
    {
	for ( pMobProg = pMob->mobprogs; pMobProg; pMobProg = pMobProg->next )
	    show_mprog( ch, pMobProg );
	send_to_char( "|\n\r", ch );
    }
    else
	send_to_char( "Syntax: show <all>\n\r", ch );

    return;
}