dawn/notes/
dawn/src/
dawn/src/docs/
/**************************************************************************/
// olc_ex.cpp - Extended commands for olc - Dawn only code in here :)
/***************************************************************************
 * The Dawn of Time v1.69r (c)1997-2004 Michael Garratt                    *
 * >> A number of people have contributed to the Dawn codebase, with the   *
 *    majority of code written by Michael Garratt - www.dawnoftime.org     *
 * >> To use this source code, you must fully comply with the dawn license *
 *    in licenses.txt... In particular, you may not remove this copyright  *
 *    notice.                                                              *
 **************************************************************************/
#include "include.h"
#include "olc_ex.h"
#include "olc.h"
#include "help.h"

/**************************************************************************/
// Lookup a spell by name - exact match - Kal
int spell_exact_lookup( const char *name )
{
    int sn;

    for( sn = FIRST_SPELL; sn < LAST_SPELL; sn++ )
    {
		if( IS_NULLSTR(skill_table[sn].name))
			break;
		if( !str_cmp( name, skill_table[sn].name ) )
			return sn;
    }

    return -1;
}

/**************************************************************************/
// Lookup a spell by name - Kal
int spell_lookup( const char *name )
{
    int sn;

	sn=spell_exact_lookup(name);

	if(sn>-1){
		return sn;
	}
    for( sn = FIRST_SPELL; sn < LAST_SPELL; sn++ )
    {
	if( IS_NULLSTR(skill_table[sn].name))
	    break;
	if( LOWER(name[0]) == LOWER(skill_table[sn].name[0])
	&&   !str_prefix( name, skill_table[sn].name ) )
	    return sn;
    }

    return -1;
}
/**************************************************************************/
// Returns the name of a skill without crashing if sn is out of bounds - Kal
char * safe_skill_name(int sn)
{
	if(sn==-1){
		return "unassigned";
	}
	if(sn<-1 || sn>MAX_SKILL-1){
		return "unknown!";
	}
	return skill_table[sn].name;
}

/**************************************************************************/
// return true if changed - Kal
bool olc_generic_skill_assignment_to_int(char_data *ch, int *field, const char *argument, 
	bool spell_only, bool extra_lf, 
	const char *command_name, const char *description_of_field_sprintf, ...)
{
	// format the description_of_field_sprintf into description
    char description[MSL]; 
	va_list args;
	va_start(args, description_of_field_sprintf);
	vsnprintf(description, MSL-10, description_of_field_sprintf, args);
	va_end(args);

	if(IS_NULLSTR(argument)){
		ch->printlnf("`Bsyntax:`x %s <%s>  - to change/assign %s to %s", 
			command_name, spell_only?"spell":"skill/spell",
			spell_only?"spell":"skill/spell", description);
		ch->printlnf("`Bsyntax:`x %s clear - to clear %s", 
			command_name, description);
		ch->printlnf("`x%s is currently assigned as: %s`x", 
			capitalize(description), safe_skill_name(*field));
		if(extra_lf) ch->println("");
		return false;
	}

	if(!str_cmp(argument,"clear")){
		if(*field==-1){
			ch->printlnf("`Y%s is already unassigned!`x", capitalize(description));
			if(extra_lf) ch->println("");
			return false;
		}

		ch->printlnf("`G%s cleared, was originally set to %s.`x", 
			capitalize(description), safe_skill_name(*field));
		*field=-1;
		if(extra_lf) ch->println("");
		return true;
	}

	int value;
	if(spell_only){
		value=spell_lookup( argument );
	}else{
		value=skill_lookup( argument );
	}

	if(value==-1){
		ch->printlnf("`RNo such %s '`x%s`R' found!`x", spell_only?"spell":"skill/spell", argument);
		olc_generic_skill_assignment_to_int(ch, field, "", spell_only, extra_lf, 
				command_name, description);
		return false;
	}
	
	if(*field==value){
		ch->printlnf("`Y%s is already assigned to `x%s!", 
			capitalize(description), safe_skill_name(value));
		if(extra_lf) ch->println("");
		return false;
	}
	
	ch->printlnf( "`G%s changed from `x%s `Gto `x%s.",
		capitalize(description), safe_skill_name(*field), safe_skill_name(value));
	*field= value;
	if(extra_lf) ch->println("");
	return true;
}
/**************************************************************************/
// turns the list of all flags in a table
char *flagtable_names( const struct flag_type *flag_table)
{
	static int i;
    static char buf[5][512];
    int flag;
	// rotate buffers
	++i= i%5;
    buf[i][0] = '\0';

    for(flag = 0; flag_table[flag].name != NULL; flag++){
		strcat( buf[i], " " );
		strcat( buf[i], flag_table[flag].name );
	}
    return buf[i]+1;
}
/**************************************************************************/
bool is_stat( const struct flag_type *flag_table );
/**************************************************************************/
// Kal - Jan 2001
void show_olc_flags_types(char_data *ch, const struct flag_type *flag_table)
{
	int count=0;

    for(int flag = 0; !IS_NULLSTR(flag_table[flag].name); flag++)
    {
		if(flag_table[flag].settable){
			count++;
			ch->printf("`=R   %-34s`x%s", flag_table[flag].name,
				count%2==0?"\r\n":"");
		}
	}
	ch->println("");		
}					  
/**************************************************************************/
// Kal - Jan 2001
void show_olc_flags_types_value(char_data *ch, const struct flag_type *flag_table, 
											const char *command_name, long value)
{
	int count=0;
	bool type_table=is_stat(flag_table);

	char c;
    for(int flag = 0; !IS_NULLSTR(flag_table[flag].name); flag++)
    {
		if(flag_table[flag].settable){
			count++;
			int l=34-str_len(flag_table[flag].name);
			bool match=false;
			if(type_table){
				if(value==flag_table[flag].bit){
					match=true;
				}
			}else{
				if(IS_SET(value,flag_table[flag].bit)){
					match=true;
				}
			}
			if(flag_table[flag].settable){
				c=match?'\'':'$';
			}else{
				if(match){
					c='R';
				}else{
					// we dont show these flags
					continue;
				}
			}			
			if(type_table && match){
				c='/'; // selected option code
			}

			const char *suffix;
			if(count%2==0){
				suffix="\r\n";
			}else{
				suffix="";
			}
	                        // "{=R    %s%20s{x\r\n"
			ch->printf(FORMATF("`=%c   %%s%%%ds`x%s", c, l, suffix), 
				mxp_create_send(ch, FORMATF("sca %s %s %s", command_name, 
					command_name, flag_table[flag].name), 
				flag_table[flag].name), "");
		}
	}
	ch->println("");
}					  
/**************************************************************************/
// Kal - Dec 2000
void show_olc_options(char_data *ch, const struct flag_type *flag_table, 
			const char *command_name, const char *descript, long flags)
{
	if(is_stat(flag_table)){
		ch->printlnf("Syntax: %s <%s type>", command_name, descript);
		ch->printlnf("Valid %s types include (pick one):", descript);
	}else{
		ch->printlnf("Syntax: %s <%s flag(s)>", command_name, descript);
		ch->printlnf("Valid %s flags include:", descript);		
	};
	show_olc_flags_types_value(ch, flag_table, command_name, flags);
}
/**************************************************************************/
int mxp_display_olc_flags_ex(char_data *ch, const struct flag_type *flag_table, 
		long value, char *command, char *heading, 
		int max_width /*77*/,int first_indent /*16*/, int indent /*5*/)
{
	int width;
	int found_count=0;
	bool type_table=is_stat(flag_table);
	char *flag_start="";
	int lines=0;

	char openbracket='[';
	char closebracket=']';
	if(type_table){
		openbracket='(';
		closebracket=')';
	}

	char buf[MSL];
	int l=first_indent-1-str_len(heading);
	l=UMAX(l,0);
	sprintf(buf, FORMATF("`=r%%s%%%ds%c",l, openbracket),
		mxp_create_send(ch,command, heading), "");
	width=first_indent;

	char flagbuf[MSL];
	if(!IS_SET(ch->dyn,DYN_SHOWFLAGS)){
		strcat(buf,"`=R");
		flag_start=&buf[str_len(buf)-1]; // record where the flags start so we can
										// strip the mxp later
		flagbuf[0]='\0';
	};

	bool match;
    for(int flag = 0; !IS_NULLSTR(flag_table[flag].name); flag++)
    {
		match=false;
		if(type_table){
			if(value==flag_table[flag].bit){
				match=true;
			}
		}else{
			if(IS_SET(value,flag_table[flag].bit)){
				match=true;
			}
		}

		if(IS_SET(ch->dyn,DYN_SHOWFLAGS)){
			if(flag_table[flag].settable){
				if(match){
					strcpy(flagbuf,"`='");
				}else{
					strcpy(flagbuf,"`=$");
				}
			}else{
				if(match){
					strcpy(flagbuf,"`=\x98");
				}else{
					// we dont show these flags
					continue;
				}
			}			
			if(type_table && match){
				strcpy(flagbuf,"`=/"); // selected option code
			}
		}else{
			if(!match){ // if they arent using 'showflags', we dont show unset flags
				continue;
			}
		}

		found_count++;
		width+= str_len(flag_table[flag].name)+1;
		if(width>max_width){
			strcat(buf,"\r\n");
			lines++;
			strcat(buf,FORMATF(FORMATF("%%%ds", indent), ""));
			width=indent + str_len(flag_table[flag].name) +1;
		}

		strcat(buf, flagbuf);
		if(flag_table[flag].settable){
			strcat(buf, mxp_create_send(ch,
							 FORMATF("sfa %s %s", command, flag_table[flag].name)
							,flag_table[flag].name));
		}else{
			strcat(buf, flag_table[flag].name);
		}
		strcat(buf," ");
	}
	if(found_count==0){
		strcat(buf,"none ");
	}
	buf[str_len(buf)-1]='\0';
	strcat(buf,FORMATF("`=r%c", closebracket));

	if(IS_SET(ch->dyn,DYN_SHOWFLAGS)){
		ch->println(buf);
	}else{
		*flag_start='\0';
		ch->printlnf("%sR%s", buf, flag_start+1); 
		lines++;
	}
	return lines;
}
/**************************************************************************/
int mxp_display_olc_flags(char_data *ch, const struct flag_type *flag_table, 
						   long value, char *command, char *heading)
{
	return mxp_display_olc_flags_ex(ch, flag_table, value, command, heading, 
		77 /*max_width*/, 16 /*first_indent*/, 5 /*indent*/);
}

/**************************************************************************/
bool olcex_showflags(char_data *ch, char *)
{
	SET_BIT(ch->dyn,DYN_SHOWFLAGS);
	run_olc_editor_for_connection(ch->desc, "show");
	REMOVE_BIT(ch->dyn,DYN_SHOWFLAGS);
	return false;
}
/**************************************************************************/
// does a show after putting argument thru medit()
bool olcex_showafter(char_data *ch, char *argument)
{
	if(IS_NULLSTR(argument)){
		ch->println("ShowAfter: Shows olc info after the argument is run as a command.");
		return false;
	}
	if(IS_SET(ch->dyn, DYN_USING_OLCAFTER)){
		ch->println("No run after loops!");
		return false;
	}
	SET_BIT(ch->dyn, DYN_USING_OLCAFTER);
	run_olc_editor_for_connection(ch->desc, argument);
	REMOVE_BIT(ch->dyn, DYN_USING_OLCAFTER);
	run_olc_editor_for_connection(ch->desc, "show");
	return false;
}
/**************************************************************************/
// does a command (first arg) after putting argument thru medit()
bool olcex_showcommandafter(char_data *ch, char *argument)
{
	char arg[MIL];
	argument=one_argument(argument, arg);
	if(IS_NULLSTR(argument)){
		ch->println("ShowCommandAfter: shows a command after all but the first arg is run as a command.");
		return false;
	}
	if(IS_SET(ch->dyn, DYN_USING_OLCAFTER)){
		ch->println("No run after loops!");
		return false;
	}
	SET_BIT(ch->dyn, DYN_USING_OLCAFTER);
	run_olc_editor_for_connection(ch->desc, argument);
	REMOVE_BIT(ch->dyn, DYN_USING_OLCAFTER);
	run_olc_editor_for_connection(ch->desc, arg);
	return false;
}
/**************************************************************************/
// does a show after putting argument thru medit()
bool olcex_showflagsafter(char_data *ch, char *argument)
{
	if(IS_NULLSTR(argument)){
		ch->println("ShowFlagsAfter: ShowsFlags after the argument is run as a command.");
		return false;
	}
	if(IS_SET(ch->dyn, DYN_USING_OLCAFTER)){
		ch->println("No run after loops!");
		return false;
	}
	SET_BIT(ch->dyn, DYN_USING_OLCAFTER);
	run_olc_editor_for_connection(ch->desc, argument);
	REMOVE_BIT(ch->dyn, DYN_USING_OLCAFTER);
	olcex_showflags(ch,"");
	return false;
}
/**************************************************************************/
// Kal - Apr 01
char *olcex_get_editor_name( int edit_mode)
{
    switch (edit_mode){
		case ED_AREA:		return "AEdit";
		case ED_ROOM:		return "REdit";
		case ED_OBJECT:		return "OEdit";
		case ED_MOBILE:		return "MEdit";
		case ED_MPCODE:		return "MPEdit";
		case ED_HELP:		return "HEdit";
		case ED_BAN:		return "BanEdit";
		case ED_RACE:		return "RaceEdit";
		case ED_CLASS:		return "ClassEdit";
		case ED_SPELLSKILL:	return "Spell/SkillEdit";
		case ED_COMMAND:	return "comEdit";
		case ED_DEITY:		return "dEdit";
		case ED_QUEST:		return "qEdit";
		case ED_GAME:		return "GameEdit";
		case ED_SOCIAL:		return "SocialEdit";
		case ED_HERB:		return "HerbEdit";
		case ED_MIX:		return "MixEdit";
		case ED_CLAN:		return "ClanEdit";
		case ED_SKILLGROUP:	return "SkillGroupEdit";
		case ED_LANGUAGE:	return "LangEdit";
		default:			return "";
	}
}
/**************************************************************************/
// Kal - Apr 01
const olc_cmd_type *olcex_get_editor_command_table( int edit_mode)
{
    switch (edit_mode){
		case ED_AREA:		return aedit_table;
		case ED_ROOM:		return redit_table;
		case ED_OBJECT:		return oedit_table;
		case ED_MOBILE:		return medit_table;
		case ED_MPCODE:		return mpedit_table;
		case ED_HELP:		return hedit_table;
		case ED_BAN:		return banedit_table;
		case ED_RACE:		return raceedit_table;
		case ED_CLASS:		return classedit_table;
		case ED_SPELLSKILL:	return sedit_table;
		case ED_COMMAND:	return comedit_table;
		case ED_DEITY:		return dedit_table;
		case ED_QUEST:		return qedit_table;
		case ED_GAME:		return gameedit_table;
		case ED_SOCIAL:		return socedit_table;
		case ED_HERB:		return herbedit_table;
		case ED_MIX:		return mixedit_table;
		case ED_CLAN:		return clanedit_table;
		case ED_SKILLGROUP:	return skillgroupedit_table;
		case ED_LANGUAGE:	return langedit_table;
		default:			return NULL;
	}
}
/**************************************************************************/
// Show the commands in an olc editor... display mxp help links for
// all entries - Kal, Apr 01
void show_olc_cmds( char_data *ch, const struct olc_cmd_type *olc_table )
{
	if(!olc_table){
		ch->println("show_olc_cmds() given NULL olc_table");
		ch->println("- this function is typically called by show_commands()");
		return;
	}

	int i;
	int count=0;
	for(i=0; !IS_NULLSTR(olc_table[i].name); i++){
		if(olc_table[i].hidden){
			continue;
		}
		if(HAS_MXP(ch) && ch->desc){
			// automatically make the entries helplinks if a help exists
			// if not run the command
			char keyword[MIL];
			bool found=false;
			sprintf(keyword,"OLC%s-%s", 
				uppercase(olcex_get_editor_name(ch->desc->editor)),
				uppercase(olc_table[i].name));

			// search for our generated keyword
			if(help_get_by_keyword(keyword, ch, false)){
				found=true;
			}
			// if we have _ in the keyword and we didn't find a help try 
			// converting the _ to a - and see if the help then exists
			if(!found && count_char(keyword, '_')){
				char *p=keyword;
				while(*p){
					if(*p=='_'){
						*p='-';
					}
					p++;
				}
				// search for modified keyword
				if(help_get_by_keyword(keyword, ch, false)){
					found=true;
				}
			}

			if(found){ // generate the mxp help link
				ch->printf("`=; %s `x", mxp_create_send(ch,
						FORMATF("help %s|%s\" hint=\"help %s|%s"
							,keyword, olc_table[i].name, keyword, olc_table[i].name)
						,FORMATF("%-18.18s", olc_table[i].name)) // text see on screen underlined						
					);
			}else{ // generate MXP command links
				ch->printf("`=: %s `x", mxp_create_send(ch,
								FORMATF("%s", olc_table[i].name)
								,FORMATF("%-18.18s", olc_table[i].name))
						 );
			}
		}else{
			ch->printf(" %-18.18s ", olc_table[i].name);
		}

		if(++count%4==0){
			ch->println("");
		}
	}
	if(count%4!=0){
		ch->println("");
	}
}
/**************************************************************************/
// Kal - Apr 01
bool show_commands( char_data *ch, char *)
{
	char *line=	"========================================================"
				"========================================================";

	char *editorname=uppercase(olcex_get_editor_name(ch->desc->editor));

	if(IS_NULLSTR(editorname)){
		editorname="[Unknown editor mode name - update olcex_get_editor_name()]";
	}

	ch->titlebarf("%s COMMANDS", editorname);
	show_olc_cmds( ch,	olcex_get_editor_command_table(ch->desc->editor));

	char mhelp[MIL];
	sprintf(mhelp,"MASTER HELP: `=_OLC-%s. ", uppercase(olcex_get_editor_name(ch->desc->editor)));
	int len=str_len(mhelp);
	 
	ch->printlnf("`=t%s[`=T %s`=t]=-`x", 
		(FORMATF(FORMATF("-%%.%ds", 74-len), line)),// the line
		mhelp);
    return false;
}
/**************************************************************************/
bool olcex_tab( char_data *ch, char *argument)
{
	if(IS_NPC(ch)){
		ch->println("Players only.");
		return false;
	}
	if(IS_NULLSTR(argument)){
		ch->println("syntax: tab <tab number>");
		return false;
	}

	int value =atoi(argument);
	if(value>0){
//		ch->printlnf("olc tab changed from %d to %d",ch->pcdata->olc_tab+1, value);
		ch->pcdata->olc_tab=value-1;
	}else{
		ch->println("The tab must be 1 or higher");
	}

	olcex_showflags(ch,"");
	return false;
}
/**************************************************************************/
void continents_show( char_data *ch )
{
	continent_type *c;

    ch->println( "Current Continental Land Masses" );
	ch->println( "===============================" );

	int col=0;
	for( c=continent_list; c; c=c->next){
		ch->printf(" %-40s`x", c->name );
		if ( ++col % 2 == 0 ){
			ch->print_blank_lines(1);
		}
	}
	if ( ++col % 2 == 0 ){
		ch->print_blank_lines(1);
	}
	return;
}
/**************************************************************************/
void do_ownerlist( char_data *ch, char *argument )
{
	char buf[MSL],sbuf[MIL];
	int count=0;
    BUFFER *output;
	bool all_owners=false;
	bool search=false;

	if (!HAS_SECURITY(ch,1))
	{
		ch->println("The ownerlist command is an olc command, you dont have olc permissions.");
		return;
	}

    output= new_buf();

	argument =one_argument( argument, sbuf );

	if (!IS_NULLSTR(sbuf))
	{
		if (!str_cmp("all", sbuf))
		{
			all_owners=true;
		}
		else
		{
			search=true;
		}
	}


	// now list all rooms with lockers in them
	int minvnum=1;
	int maxvnum=top_vnum_room;


	// if we arent searching, nor listing all areas reduce the 
	// searching range to the current area
	if(!search  && !all_owners){
		minvnum=ch->in_room->area->min_vnum;
		maxvnum=ch->in_room->area->max_vnum;
	}

	int i;
	ROOM_INDEX_DATA *r;
	for(i=minvnum; i<=maxvnum; i++){
		r=get_room_index(i);

		if(!r || IS_NULLSTR(r->owner)){
			continue;
		}

		if(search // filter if specifed
			&& !is_name( sbuf, r->owner ) 
			&& !is_name( sbuf, r->invite_list)){
			continue;
		}

		sprintf( buf, "`x%3d`S[`=R%5d`S-%s%-8.8s`S] `g%s:`w%s`x\r\n", 
			++count, r->vnum, 
			colour_table[(r->area->vnum%14)+1].code,
			r->area->short_name,
			r->owner,
			r->invite_list);
	    add_buf(output,buf);
    }

	if(!count){
		add_buf(output,"No rooms with owners/invites found.\r\n");
	}

	if(!search  && !all_owners){
		add_buf(output,"you can also search this list, or use 'all' to see all matching rooms.\r\n");		
	}
 
	if(GAMESETTING4(GAMESET4_ROOM_INVITES_DISABLED)){
		add_buf(output,"Note: the room invites system is disabled in gameedit.\r\n");
	}

	ch->sendpage( buf_string(output));
	free_buf(output);
}
/**************************************************************************/
// Kal, Sept 02 - Count the number of bits set to 1 a long
int count_bits(long value)
{
	int count=0;
	for(int i=0; i<(int)sizeof(long)*8; i++){
		if(value&1<<i){
			count++;
		}
	}
	return count;
}
/**************************************************************************/
// Kal, Sept 02 - Finally wrote a generic flag toggling/type setting  handler :)
bool olc_generic_flag_toggle(char_data *ch, char *argument,
	const char *command_name, const char *descript, 
	const struct flag_type *flag_table, long *value)
{
    if(!IS_NULLSTR(argument)){
		long flags_to_toggle=flag_value( flag_table, argument);

		if(flags_to_toggle!=NO_FLAG){
			if(is_stat(flag_table)){
				// types for setting
				if(*value==flags_to_toggle){
					ch->printlnf("The %s type is already set to %s.", 
						descript,
						flag_string(flag_table, flags_to_toggle));
					return false;
				}else{
					ch->printlnf("%s type changed from %s to %s", 
						capitalize(descript),
						flag_string(flag_table, *value),
						flag_string(flag_table, flags_to_toggle));
					*value=flags_to_toggle;
					return true;
				}
			}else{ 
				// flags for toggling
				*value^= flags_to_toggle; // do the toggle
				// see what was toggled on 
				long on=flags_to_toggle & (*value); 
				if(on){
					ch->printlnf("%d %s flag%s toggled on: %s", 
						count_bits(on),
						descript,
						count_bits(on)==1?"":"s",
						flag_string(flag_table,on));
				}
				// see what was toggled off 
				long off=flags_to_toggle & (~(*value));
				if(off){
					ch->printlnf("%d %s flag%s toggled off: %s", 
						count_bits(off),
						descript,
						count_bits(off)==1?"":"s",
						flag_string(flag_table,off));
				}
			}
		}else{
			ch->printlnf("`=X'%s' wasn't recognised as a valid %s flag.`x", argument, descript);
			show_olc_options(ch, flag_table, command_name, descript, *value);
		}
		return true;
    }
	show_olc_options(ch, flag_table, command_name, descript, *value);
	return false;
}
/**************************************************************************/
// Kal, April 03 - support 'int *', as well as 'long *' above
bool olc_generic_flag_toggle(char_data *ch, char *argument,
	const char *command_name, const char *descript, 
	const struct flag_type *flag_table, int *value)
{
	long lng=(long)*value;
	bool result=olc_generic_flag_toggle(ch, argument, command_name, descript, flag_table, &lng);
	*value=(int)lng;
	return result;
}

/**************************************************************************/
/**************************************************************************/