// $Id: command.inc,v 1.17 2001/05/11 14:25:08 druid Exp $ {$F+} { The complete quit procedure, which even logs off NPCs! - Grimlord } procedure do_quit(ch : GCharacter; param : string); var timer : GTimer; begin if (ch.IS_NPC) then exit; if (ch.position = POS_FIGHTING) then begin ch.sendBuffer('You are fighting! You can''t quit!'#13#10); exit; end; timer := hasTimer(ch, TIMER_COMBAT); if (timer <> nil) then begin ch.sendBuffer('You have recently fled out of combat or have encountered a member'#13#10); ch.sendBuffer('of the opposite alignment. Therefor you are not allowed to quit.'#13#10); ch.sendBuffer('Please wait another '+inttostr(round(timer.counter / CPULSE_TICK))+' gameticks to quit.'#13#10); exit; end; if (auction_good.seller = ch) or (auction_good.buyer = ch) or (auction_evil.seller = ch) or (auction_evil.buyer = ch) then begin ch.sendBuffer('Please wait till the current auction has been concluded.'#13#10); exit; end; if (ch.snooped_by <> nil) then interpret(ch.snooped_by, 'snoop self'); act(AT_REPORT, '$n has logged off.', false, ch, nil, nil, TO_ROOM); if (ch.conn <> nil) then GConnection(ch.conn).send('Thanks for playing! Please visit this MUD again!'#13#10); GPlayer(ch).quit; end; procedure do_save(ch : GCharacter; param : string); begin if (ch.IS_NPC) then exit; GPlayer(ch).save(ch.name^); ch.sendBuffer('Ok.'#13#10); end; procedure do_afk(ch : GCharacter; param : string); begin GConnection(ch.conn).afk := true; ch.sendBuffer('You are now listed as AFK. Hitting ENTER will cease this.'#13#10); end; type THelpKeyword = class keyword : string; phelp : GHelp; constructor Create(str : string; p : GHelp); end; constructor THelpKeyword.Create(str : string; p : GHelp); begin inherited Create(); keyword := str; phelp := p; end; { Xenon 22/Apr/2001: helper function for do_help() and do_apropos() } procedure insertAlphabetical(var ll : GDLinkedList; hk : THelpKeyword); var node, ins : GListNode; s : THelpKeyword; begin ins := nil; node := ll.head; if (ll.head = nil) then begin ll.insertLast(hk); exit; end; while (node <> nil) do begin s := node.element; if (AnsiCompareStr(hk.keyword, s.keyword) > 0) then begin ins := node; end else begin ll.insertBefore(node, hk); exit; end; node := node.next; end; ll.insertAfter(ins, hk) end; { Revised help - Nemesis } { Xenon 16/Apr/2001: - help without arguments now gives sorted keywordlist - help with an arg that matches multiple keywords will show matching keywords} procedure do_help(ch : GCharacter; param : string); var buf, s, keyword : string; help : GHelp; counter : integer; node : GListNode; keywordlist : GDLinkedList; hk : THelpKeyword; done : boolean; begin keywordlist := nil; hk := nil; done := false; counter := 0; if (length(param) = 0) then begin buf := ch.ansiColor(3) + ' ' + add_chars(78, '---- Available help keywords ', '-') + ch.ansiColor(7) + #13#10#13#10; keywordlist := GDLinkedList.Create(); node := help_files.head; while (node <> nil) do begin help := node.element; keyword := help.keywords; while (length(keyword) > 0) do begin keyword := one_argument(keyword, s); if ((s[length(s)] <> '_') and (help.level <= ch.level)) then begin hk := THelpKeyword.Create(lowercase(s), help); insertAlphabetical(keywordlist, hk); end; end; node := node.next; end; node := keywordlist.head; while (node <> nil) do begin buf := buf + pad_string(THelpKeyword(node.element).keyword, 19); inc(counter); if (counter = 4) then begin buf := buf + #13#10; counter := 0; end; node := node.next; end; keywordlist.Clean(); keywordlist.Free(); ch.sendPager(buf + #13#10); exit; end; keywordlist := GDLinkedList.Create(); node := help_files.head; while (node <> nil) do begin help := node.element; keyword := help.keywords; while (length(keyword) > 0) do begin keyword := one_argument(keyword, s); if (s[length(s)] <> '_') then begin if ((pos(uppercase(param), s) = 1) and (help.level <= ch.level)) then begin hk := THelpKeyword.Create(lowercase(s), help); insertAlphabetical(keywordlist, hk); end; if ((uppercase(param) = s) and (help.level <= ch.level)) then // if it's a 1-on-1 match, stop right away begin keywordlist.Clean(); keywordlist.Free(); keywordlist := GDLinkedList.Create(); keywordlist.insertLast(THelpKeyword.Create(lowercase(s), help)); done := true; break; end; end; end; if (done) then break; node := node.next; end; if (keywordlist.getSize() = 0) then begin ch.sendBuffer('No help on that word.'#13#10) end else if (keywordlist.getSize() = 1) then begin help := THelpKeyword(keywordlist.head.element).phelp; buf := '$A$3 ' + add_chars(78, '---- Help topic ', '-') + '$A$7'#13#10#13#10 + 'Name: $A$3' + help.keywords + #13#10 + '$A$7' + 'Type: $A$3' + help.helptype + #13#10 + '$A$7' + 'Syntax: $A$3' + help.syntax + #13#10 + '$A$7' + 'Related: $A$3' + help.related + #13#10 + '$A$7' + #13#10 + help.text; ch.sendPager(act_string(buf, ch, nil, nil, nil)); end else if (keywordlist.getSize() > 1) then begin buf := Format('Your help query ''$B$7%s$A$7'' matched $B$7%d$A$7 keywords:'#13#10#13#10, [param, keywordlist.getSize()]); node := keywordlist.head; while (node <> nil) do begin buf := buf + Format(' $B$7%s$A$7'#13#10, [THelpKeyword(node.element).keyword]); node := node.next; end; ch.sendPager(act_string(buf, ch, nil, nil, nil)); end; keywordlist.Clean(); keywordlist.Free(); end; procedure do_remort(ch : GCharacter; param : string); begin ch.sendBuffer('Disfunctional. Sorry.'#13#10); end; { Revised - Nemesis } procedure do_delete(ch: GCharacter; param : string); var f:file; begin if (ch.IS_NPC) then begin ch.sendBuffer('NPCs cannot delete.'#13#10); exit; end; if (not MD5Match(GPlayer(ch).md5_password, MD5String(param))) then begin ch.sendBuffer('Type DELETE <password> to delete. WARNING: This is irreversible!'#13#10); exit; end; GConnection(ch.conn).send('You feel yourself dissolving, atom by atom...'#13#10); write_console(ch.name^ + ' has deleted'); GPlayer(ch).quit; assignfile(f, 'players\' + ch.name^ + '.usr'); rename(f, 'backup\' + ch.name^ + '.usr'); end; procedure do_wimpy(ch : GCharacter; param : string); var wimpy:integer; begin if (length(param) = 0) or (ch.IS_NPC) then begin ch.sendBuffer('Set wimpy to what?'#13#10); exit; end; try wimpy := strtoint(param); except ch.sendBuffer('That is not a valid number.'#13#10); exit; end; if (wimpy > ch.max_hp div 3) then ch.sendBuffer('Your wimpy cannot be higher than 1/3 of your total hps!'#13#10) else begin GPlayer(ch).wimpy := wimpy; ch.sendBuffer('Wimpy set to '+inttostr(wimpy)+'.'+#13#10); end; end; { Allow players to lock their keyboard - Nemesis } procedure do_keylock(ch : GCharacter; param: string); begin GConnection(ch.conn).afk := true; GConnection(ch.conn).keylock := true; ch.sendBuffer('You are now away from keyboard.'#13#10); ch.sendBuffer('Enter your password to unlock.'#13#10); end; // Handle Notes - Nemesis procedure do_note(ch : GCharacter; param : string); var arg1, arg2, buf : string; number, counter : integer; note : GNote; node : GListNode; begin if (ch.IS_NPC) then exit; param := one_argument(param, arg1); one_argument(param, arg2); if (length(arg1) = 0) then begin ch.sendBuffer('Usage: NOTE READ <number>'#13#10); ch.sendBuffer(' NOTE WRITE'#13#10); ch.sendBuffer(' NOTE LIST'#13#10); if (ch.IS_IMMORT) then ch.sendBuffer(' NOTE DELETE <number>'#13#10); exit; end else if (uppercase(arg1) = 'WRITE') then begin ch.substate := SUB_SUBJECT; ch.sendBuffer('You are now away from keyboard.'#13#10#13#10); act(AT_REPORT,'$n has left $s keyboard and starts writing a note.',false,ch,nil,nil,to_room); ch.sendBuffer('You start writing a note on the ' + board_names[GPlayer(ch).active_board] + ' board.'#13#10); GPlayer(ch).startEditing(''); exit; end else if (uppercase(arg1) = 'LIST') then begin counter := 0; node := notes.head; if (node = nil) then begin ch.sendBuffer('There are no notes on this board.'#13#10); exit; end; while (node <> nil) do begin note := node.element; if (note.board = GPlayer(ch).active_board) then begin inc(counter); buf := buf + ch.ansiColor(15) + ' ' + pad_integer_front(note.number,3) + ch.ansiColor(7) + '> ' + pad_string(note.author,20) + ' ' + note.subject + #13#10; end; node := node.next; end; if (counter = 0) then buf := ch.ansiColor(7) + 'There are no notes on this board.' + #13#10; buf := ch.ansiColor(8) + '[' + ch.ansiColor(9) + 'Num ' + ch.ansiColor(8) + '] ' + ch.ansiColor(8) + '[' + ch.ansiColor(9) + 'Author ' + ch.ansiColor(8) + '] ' + ch.ansiColor(8) + '[' + ch.ansiColor(9) + 'Subject ' + ch.ansiColor(8) + ']' + #13#10 + #13#10 + buf; ch.sendPager(buf); exit; end else if (uppercase(arg1) = 'READ') then begin if (length(arg2) = 0) then begin ch.sendBuffer('Usage: NOTE READ <number>'#13#10); exit; end; try number := strtoint(arg2); except ch.sendBuffer('Usage: NOTE READ <number>'#13#10); exit; end; note := findNote(GPlayer(ch).active_board, number); if (note = nil) then begin ch.sendBuffer('That is not a valid number.'#13#10); exit; end; buf := ch.ansiColor(3) + add_chars(76, '---- Note by ' + note.author, '-') + #13#10 + ch.ansiColor(7) + 'Date: ' + ch.ansiColor(7) + note.date + #13#10 + ch.ansiColor(7) + 'Subject: ' + ch.ansiColor(7) + note.subject + #13#10 + ch.ansiColor(3) + add_chars(76, '', '-') + #13#10#13#10 + ch.ansiColor(7) + note.text + ch.ansiColor(3) + add_chars(76, '', '-') + #13#10; ch.sendPager(buf); GPlayer(ch).boards[GPlayer(ch).active_board] := number; exit; end else if (uppercase(arg1) = 'DELETE') then begin if (length(arg2) = 0) then begin ch.sendBuffer('Usage: NOTE DELETE <number>'#13#10); exit; end; try number := strtoint(arg2); except ch.sendBuffer('Usage: NOTE DELETE <number>'#13#10); exit; end; node := notes.head; if (node = nil) then begin ch.sendBuffer('There are no notes to delete.'#13#10); exit; end; while (node <> nil) do begin note := node.element; if (note.board = GPlayer(ch).active_board) and (note.number = number) then begin notes.remove(node); save_notes; ch.sendBuffer('Note succesfully deleted.'#13#10); exit; end; node := node.next; end; ch.sendBuffer('Not a valid number.'#13#10); exit; end else begin ch.sendBuffer('Usage: NOTE READ <number>'#13#10); ch.sendBuffer(' NOTE WRITE'#13#10); ch.sendBuffer(' NOTE LIST'#13#10); if (ch.IS_IMMORT) then ch.sendBuffer(' NOTE DELETE <number>'#13#10); exit; end end; // Bulletinboard - Nemesis procedure do_board(ch : GCharacter; param : string); var node : GListNode; i, counter, boardnumber : integer; note : GNote; arg1 : string; begin if (ch.IS_NPC) then exit; param := one_argument(param, arg1); if (length(arg1) > 0) then begin try boardnumber := strtoint(arg1); if (boardnumber < BOARD1) or (boardnumber >= BOARD_MAX) or ((boardnumber = BOARD_IMM) and (not ch.IS_IMMORT)) then begin ch.sendBuffer('That board is not available.'#13#10); exit; end; GPlayer(ch).active_board := boardnumber; ch.sendBuffer('Current board changed to ' + board_names[GPlayer(ch).active_board] + '.'#13#10); exit; except arg1 := ''; end; end; if (length(arg1) = 0) then begin act(AT_REPORT, '$8[$B$1Num$A$8] [$B$1Name $A$8] [$B$1New$A$8] [$B$1Description$A$8]'#13#10,false,ch,nil,nil,TO_CHAR); for i:=1 to BOARD_MAX-1 do begin counter := 0; node := notes.head; while (node <> nil) do begin note := node.element; if (note.board = i) then begin if (note.number > counter) then counter := note.number; end; node := node.next; end; counter := counter - GPlayer(ch).boards[i]; if (i = BOARD_IMM) then begin if (ch.IS_IMMORT) then act(AT_REPORT, '$B$7 ' + pad_integer_front(i, 2) + '$A$7> ' + pad_string(board_names[i],10) + ' ' + pad_integer(counter,3) + ' ' + board_descr[i],false,ch,nil,nil,TO_CHAR); end else act(AT_REPORT, '$B$7 ' + pad_integer_front(i, 2) + '$A$7> ' + pad_string(board_names[i],10) + ' ' + pad_integer(counter,3) + ' ' + board_descr[i],false,ch,nil,nil,TO_CHAR); end; ch.sendBuffer(#13#10 + ch.ansiColor(7) + 'Your current board is ' + board_names[GPlayer(ch).active_board] + '.'#13#10); if (GPlayer(ch).active_board = BOARD_NEWS) and (not ch.IS_IMMORT) then ch.sendBuffer(ch.ansiColor(7) + 'You can only read from this board.'#13#10) else ch.sendBuffer(ch.ansiColor(7) + 'You can both read and write on this board.'#13#10); end; end; { Xenon 23/Apr/2001: apropos searches through all helpfiles for a match on user input } procedure do_apropos(ch : GCharacter; param : string); var node : GListNode; help : GHelp; matchlist : GDLinkedList; hk : THelpKeyword; s : string; begin if (ch.IS_NPC) then exit; if (length(param) = 0) then begin ch.sendBuffer('Usage: APROPOS <text>'#13#10#13#10); ch.sendBuffer('Apropos searches for ''text'' in the online helpfiles.'#13#10); exit; end; matchlist := GDLinkedList.Create(); node := help_files.head; while (node <> nil) do begin help := node.element; s := help.keywords; if ((s[length(s)] <> '_') and (pos(param, help.text) > 0) and (help.level <= ch.level)) then begin hk := THelpKeyword.Create(lowercase(s), help); insertAlphabetical(matchlist, hk); end; node := node.next; end; if (matchlist.getSize() = 0) then begin ch.sendBuffer(Format('No matches found for your query ''%s''.'#13#10, [param])); exit; end else begin ch.sendPager(act_string(Format('Found $B$7%d$A$7 helpfiles that match your query ''$B$7%s$A$7'':'#13#10#13#10, [matchlist.getSize(), param]), ch, nil, nil, nil)); node := matchlist.head; while (node <> nil) do begin hk := node.element; ch.sendPager(act_string(Format(' $B$7%s$A$7'#13#10, [hk.keyword]), ch, nil, nil, nil)); node := node.next; end; end; matchlist.Clean(); matchlist.Free(); end; {$I include\cmd_imm.inc} {$I include\cmd_info.inc} {$I include\cmd_move.inc} {$I include\cmd_fight.inc} {$I include\cmd_magic.inc} {$I include\cmd_skill.inc} {$I include\cmd_comm.inc} {$I include\cmd_obj.inc} {$I include\cmd_shops.inc} {$I include\cmd_build.inc}